[golan] Add Connect-IB, ConnectX-4 and ConnectX-4 Lx (Infiniband) support
[ipxe.git] / src / drivers / infiniband / mlx_utils / mlx_lib / mlx_nvconfig / mlx_nvconfig.c
1 /*
2 * Copyright (C) 2015 Mellanox Technologies Ltd.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 */
19
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 #include "../../mlx_lib/mlx_nvconfig/mlx_nvconfig.h"
23 #include "../../include/public/mlx_memory.h"
24 #include "../../include/public/mlx_bail.h"
25
26 #define TlvMappingEntry( _tlv_type, _real_tlv_type, _class_code, _fw_reset_needed) { \
27 .tlv_type = _tlv_type, \
28 .real_tlv_type = _real_tlv_type, \
29 .class_code = _class_code, \
30 .fw_reset_needed = _fw_reset_needed, \
31 }
32
33 struct nvconfig_tlv_mapping nvconfig_tlv_mapping[] = {
34 TlvMappingEntry(0x10, 0x10, NVRAM_TLV_CLASS_HOST, TRUE),
35 TlvMappingEntry(0x12, 0x12, NVRAM_TLV_CLASS_PHYSICAL_PORT, TRUE),
36 TlvMappingEntry(0x80, 0x80, NVRAM_TLV_CLASS_GLOBAL, TRUE),
37 TlvMappingEntry(0x81, 0x81, NVRAM_TLV_CLASS_GLOBAL, TRUE),
38 TlvMappingEntry(0x100, 0x100, NVRAM_TLV_CLASS_GLOBAL, TRUE),
39 TlvMappingEntry(0x2001, 0x195, NVRAM_TLV_CLASS_HOST, FALSE),
40 TlvMappingEntry(0x2010, 0x210, NVRAM_TLV_CLASS_HOST, FALSE),
41 TlvMappingEntry(0x2011, 0x211, NVRAM_TLV_CLASS_GLOBAL, FALSE),
42 TlvMappingEntry(0x2020, 0x2020, NVRAM_TLV_CLASS_PHYSICAL_PORT, FALSE),
43 TlvMappingEntry(0x2021, 0x221, NVRAM_TLV_CLASS_HOST, FALSE),
44 TlvMappingEntry(0x2023, 0x223, NVRAM_TLV_CLASS_HOST, FALSE),
45 TlvMappingEntry(0x2100, 0x230, NVRAM_TLV_CLASS_HOST, FALSE),
46 TlvMappingEntry(0x2101, 0x231, NVRAM_TLV_CLASS_HOST, FALSE),
47 TlvMappingEntry(0x2102, 0x232, NVRAM_TLV_CLASS_HOST, FALSE),
48 TlvMappingEntry(0x2103, 0x233, NVRAM_TLV_CLASS_HOST, FALSE),
49 TlvMappingEntry(0x2104, 0x234, NVRAM_TLV_CLASS_HOST, FALSE),
50 TlvMappingEntry(0x2105, 0x235, NVRAM_TLV_CLASS_HOST, FALSE),
51 TlvMappingEntry(0x2106, 0x236, NVRAM_TLV_CLASS_HOST, FALSE),
52 TlvMappingEntry(0x2107, 0x237, NVRAM_TLV_CLASS_HOST, FALSE),
53 TlvMappingEntry(0x2108, 0x238, NVRAM_TLV_CLASS_HOST, FALSE),
54 TlvMappingEntry(0x2109, 0x239, NVRAM_TLV_CLASS_HOST, FALSE),
55 TlvMappingEntry(0x210A, 0x23A, NVRAM_TLV_CLASS_HOST, FALSE),
56 TlvMappingEntry(0x2200, 0x240, NVRAM_TLV_CLASS_HOST, FALSE),
57 TlvMappingEntry(0x2201, 0x241, NVRAM_TLV_CLASS_HOST, FALSE),
58 TlvMappingEntry(0x2202, 0x242, NVRAM_TLV_CLASS_HOST, FALSE),
59 TlvMappingEntry(0x2203, 0x243, NVRAM_TLV_CLASS_HOST, FALSE),
60 TlvMappingEntry(0x2204, 0x244, NVRAM_TLV_CLASS_HOST, FALSE),
61 TlvMappingEntry(0x2205, 0x245, NVRAM_TLV_CLASS_HOST, FALSE),
62 TlvMappingEntry(0x2207, 0x247, NVRAM_TLV_CLASS_HOST, FALSE),
63 TlvMappingEntry(0, 0, 0, 0),
64 };
65
66 static
67 mlx_status
68 nvconfig_set_fw_reset_level(
69 IN mlx_utils *utils,
70 IN mlx_uint16 tlv_type
71 )
72 {
73 #define WARM_REBOOT_RESET ((mlx_uint64)0x1 << 38)
74 mlx_status status = MLX_SUCCESS;
75 mlx_uint32 reg_status;
76 mlx_uint64 mfrl = WARM_REBOOT_RESET ;
77 mlx_uint8 index = 0;
78 mlx_boolean reset_needed = FALSE;
79
80 for (index = 0 ; nvconfig_tlv_mapping[index].tlv_type != 0 ; index++) {
81 if (nvconfig_tlv_mapping[index].tlv_type == tlv_type) {
82 reset_needed = nvconfig_tlv_mapping[index].fw_reset_needed;
83 }
84 }
85
86 if (reset_needed == FALSE) {
87 goto no_fw_reset_needed;
88 }
89 status = mlx_reg_access(utils, REG_ID_MFRL, REG_ACCESS_WRITE, &mfrl, sizeof(mfrl),
90 &reg_status);
91 MLX_CHECK_STATUS(utils, status, reg_err, "mlx_reg_access failed ");
92
93 if (reg_status != 0) {
94 MLX_DEBUG_ERROR(utils,"nvconfig_set_fw_reset_level failed with status = %d\n", reg_status);
95 status = MLX_FAILED;
96 goto reg_err;
97 }
98 reg_err:
99 no_fw_reset_needed:
100 return status;
101 }
102
103
104 static
105 mlx_status
106 nvconfig_get_tlv_type_and_class(
107 IN mlx_uint16 tlv_type,
108 OUT mlx_uint16 *real_tlv_type,
109 OUT NVRAM_CLASS_CODE *class_code
110 )
111 {
112 mlx_uint8 index = 0;
113 for ( ; nvconfig_tlv_mapping[index].tlv_type != 0 ; index ++) {
114 if ( nvconfig_tlv_mapping[index].tlv_type == tlv_type) {
115 *real_tlv_type = nvconfig_tlv_mapping[index].real_tlv_type;
116 *class_code = nvconfig_tlv_mapping[index].class_code;
117 return MLX_SUCCESS;
118 }
119 }
120 return MLX_NOT_FOUND;
121 }
122 static
123 void
124 nvconfig_fill_tlv_type(
125 IN mlx_uint8 port,
126 IN NVRAM_CLASS_CODE class_code,
127 IN mlx_uint16 tlv_type,
128 OUT union nvconfig_tlv_type *nvconfig_tlv_type
129 )
130 {
131 switch (class_code) {
132 case NVRAM_TLV_CLASS_GLOBAL:
133 nvconfig_tlv_type->global.param_class = NVRAM_TLV_CLASS_GLOBAL;
134 nvconfig_tlv_type->global.param_idx = tlv_type;
135 break;
136 case NVRAM_TLV_CLASS_HOST:
137 nvconfig_tlv_type->per_host.param_class = NVRAM_TLV_CLASS_HOST;
138 nvconfig_tlv_type->per_host.param_idx = tlv_type;
139 break;
140 case NVRAM_TLV_CLASS_PHYSICAL_PORT:
141 nvconfig_tlv_type->per_port.param_class = NVRAM_TLV_CLASS_PHYSICAL_PORT;
142 nvconfig_tlv_type->per_port.param_idx = tlv_type;
143 nvconfig_tlv_type->per_port.port = port;
144 break;
145 }
146 }
147 mlx_status
148 nvconfig_query_capability(
149 IN mlx_utils *utils,
150 IN mlx_uint8 port,
151 IN mlx_uint16 tlv_type,
152 OUT mlx_boolean *read_supported,
153 OUT mlx_boolean *write_supported
154 )
155 {
156 mlx_status status = MLX_SUCCESS;
157 struct nvconfig_nvqc nvqc;
158 mlx_uint32 reg_status;
159 NVRAM_CLASS_CODE class_code;
160 mlx_uint16 real_tlv_type;
161
162 if (utils == NULL || read_supported == NULL || write_supported == NULL) {
163 status = MLX_INVALID_PARAMETER;
164 goto bad_param;
165 }
166
167 status = nvconfig_get_tlv_type_and_class(tlv_type, &real_tlv_type, &class_code);
168 MLX_CHECK_STATUS(utils, status, tlv_not_supported, "tlv not supported");
169
170 mlx_memory_set(utils, &nvqc, 0, sizeof(nvqc));
171 nvconfig_fill_tlv_type(port, class_code, real_tlv_type, &nvqc.tlv_type);
172
173 status = mlx_reg_access(utils, REG_ID_NVQC, REG_ACCESS_READ, &nvqc, sizeof(nvqc),
174 &reg_status);
175 MLX_CHECK_STATUS(utils, status, reg_err, "mlx_reg_access failed ");
176 if (reg_status != 0) {
177 MLX_DEBUG_ERROR(utils,"mlx_reg_access failed with status = %d\n", reg_status);
178 status = MLX_FAILED;
179 goto reg_err;
180 }
181 *read_supported = nvqc.support_rd;
182 *write_supported = nvqc.support_wr;
183 reg_err:
184 tlv_not_supported:
185 bad_param:
186 return status;
187 }
188
189 mlx_status
190 nvconfig_nvdata_invalidate(
191 IN mlx_utils *utils,
192 IN mlx_uint8 port,
193 IN mlx_uint16 tlv_type
194 )
195 {
196 mlx_status status = MLX_SUCCESS;
197 struct nvconfig_header nv_header;
198 mlx_uint32 reg_status;
199 NVRAM_CLASS_CODE class_code;
200 mlx_uint16 real_tlv_type;
201
202 if (utils == NULL) {
203 status = MLX_INVALID_PARAMETER;
204 goto bad_param;
205 }
206
207 status = nvconfig_get_tlv_type_and_class(tlv_type, &real_tlv_type, &class_code);
208 MLX_CHECK_STATUS(utils, status, tlv_not_supported, "tlv not supported");
209
210 mlx_memory_set(utils, &nv_header, 0, sizeof(nv_header));
211 nvconfig_fill_tlv_type(port, class_code, real_tlv_type, &nv_header.tlv_type);
212
213 status = mlx_reg_access(utils, REG_ID_NVDI, REG_ACCESS_WRITE, &nv_header, sizeof(nv_header),
214 &reg_status);
215 MLX_CHECK_STATUS(utils, status, reg_err, "mlx_reg_access failed ");
216 if (reg_status != 0) {
217 MLX_DEBUG_ERROR(utils,"mlx_reg_access failed with status = %d\n", reg_status);
218 status = MLX_FAILED;
219 goto reg_err;
220 }
221 reg_err:
222 tlv_not_supported:
223 bad_param:
224 return status;
225 }
226
227 mlx_status
228 nvconfig_nvdata_access(
229 IN mlx_utils *utils,
230 IN mlx_uint8 port,
231 IN mlx_uint16 tlv_type,
232 IN REG_ACCESS_OPT opt,
233 IN mlx_size data_size,
234 IN NV_DEFAULT_OPT def_en,
235 IN OUT mlx_uint8 *version,
236 IN OUT mlx_void *data
237 )
238 {
239 mlx_status status = MLX_SUCCESS;
240 struct nvconfig_nvda nvda;
241 mlx_uint32 reg_status;
242 mlx_uint32 real_size_to_read;
243 mlx_uint32 index;
244 NVRAM_CLASS_CODE class_code;
245 mlx_uint16 real_tlv_type;
246 mlx_size data_size_align_to_dword;
247
248 if (utils == NULL || data == NULL || data_size > NVCONFIG_MAX_TLV_SIZE) {
249 status = MLX_INVALID_PARAMETER;
250 goto bad_param;
251 }
252
253 status = nvconfig_get_tlv_type_and_class(tlv_type, &real_tlv_type, &class_code);
254 MLX_CHECK_STATUS(utils, status, tlv_not_supported, "tlv not supported");
255
256 data_size_align_to_dword = ((data_size + 3) / sizeof(mlx_uint32)) * sizeof(mlx_uint32);
257 mlx_memory_set(utils, &nvda, 0, sizeof(nvda));
258 nvda.nv_header.length = data_size_align_to_dword;
259 nvda.nv_header.rd_en = 0;
260 nvda.nv_header.def_en = def_en;
261 nvda.nv_header.over_en = 1;
262 nvda.nv_header.version = *version;
263
264 nvconfig_fill_tlv_type(port, class_code, real_tlv_type, &nvda.nv_header.tlv_type);
265
266 mlx_memory_cpy(utils, nvda.data, data, data_size);
267 for (index = 0 ; index * 4 < NVCONFIG_MAX_TLV_SIZE ; index++) {
268 mlx_memory_be32_to_cpu(utils,(((mlx_uint32 *)nvda.data)[index]), ((mlx_uint32 *)nvda.data) + index);
269 }
270 status = mlx_reg_access(utils, REG_ID_NVDA, opt, &nvda,
271 data_size_align_to_dword + sizeof(nvda.nv_header), &reg_status);
272 MLX_CHECK_STATUS(utils, status, reg_err, "mlx_reg_access failed ");
273 if (reg_status != 0) {
274 MLX_DEBUG_ERROR(utils,"mlx_reg_access failed with status = %d\n", reg_status);
275 status = MLX_FAILED;
276 goto reg_err;
277 }
278 for (index = 0 ; index * 4 < NVCONFIG_MAX_TLV_SIZE ; index++) {
279 mlx_memory_cpu_to_be32(utils,(((mlx_uint32 *)nvda.data)[index]), ((mlx_uint32 *)nvda.data) + index);
280 }
281 if (opt == REG_ACCESS_READ) {
282 real_size_to_read = (nvda.nv_header.length > data_size) ? data_size :
283 nvda.nv_header.length;
284 mlx_memory_cpy(utils, data, nvda.data, real_size_to_read);
285 *version = nvda.nv_header.version;
286 } else {
287 nvconfig_set_fw_reset_level(utils, tlv_type);
288 }
289 reg_err:
290 tlv_not_supported:
291 bad_param:
292 return status;
293 }
294
295