iPXE
mlx_nvconfig.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2015 Mellanox Technologies Ltd.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  */
00019 
00020 FILE_LICENCE ( GPL2_OR_LATER );
00021 
00022 #include "../../mlx_lib/mlx_nvconfig/mlx_nvconfig.h"
00023 #include "../../include/public/mlx_memory.h"
00024 #include "../../include/public/mlx_bail.h"
00025 
00026 #define TlvMappingEntry( _tlv_type, _real_tlv_type, _class_code, _fw_reset_needed) { \
00027   .tlv_type = _tlv_type,                     \
00028   .real_tlv_type = _real_tlv_type,                   \
00029   .class_code = _class_code,                  \
00030   .fw_reset_needed = _fw_reset_needed,        \
00031   }
00032 
00033 struct nvconfig_tlv_mapping nvconfig_tlv_mapping[] = {
00034                 TlvMappingEntry(0x10, 0x10, NVRAM_TLV_CLASS_HOST, TRUE),
00035                 TlvMappingEntry(0x12, 0x12, NVRAM_TLV_CLASS_PHYSICAL_PORT, TRUE),
00036                 TlvMappingEntry(0x80, 0x80, NVRAM_TLV_CLASS_GLOBAL, TRUE),
00037                 TlvMappingEntry(0x81, 0x81, NVRAM_TLV_CLASS_GLOBAL, TRUE),
00038                 TlvMappingEntry(0x100, 0x100, NVRAM_TLV_CLASS_GLOBAL, TRUE),
00039                 TlvMappingEntry(0x2001, 0x195, NVRAM_TLV_CLASS_HOST, FALSE),
00040                 TlvMappingEntry(0x2010, 0x210, NVRAM_TLV_CLASS_HOST, FALSE),
00041                 TlvMappingEntry(0x2011, 0x211, NVRAM_TLV_CLASS_GLOBAL, FALSE),
00042                 TlvMappingEntry(0x2021, 0x221, NVRAM_TLV_CLASS_HOST, FALSE),
00043                 TlvMappingEntry(0x2023, 0x223, NVRAM_TLV_CLASS_HOST, FALSE),
00044                 TlvMappingEntry(0x2006, 0x206, NVRAM_TLV_CLASS_HOST, FALSE),
00045                 TlvMappingEntry(0x2100, 0x230, NVRAM_TLV_CLASS_HOST, FALSE),
00046                 TlvMappingEntry(0x2101, 0x231, NVRAM_TLV_CLASS_HOST, FALSE),
00047                 TlvMappingEntry(0x2102, 0x232, NVRAM_TLV_CLASS_HOST, FALSE),
00048                 TlvMappingEntry(0x2103, 0x233, NVRAM_TLV_CLASS_HOST, FALSE),
00049                 TlvMappingEntry(0x2104, 0x234, NVRAM_TLV_CLASS_HOST, FALSE),
00050                 TlvMappingEntry(0x2105, 0x235, NVRAM_TLV_CLASS_HOST, FALSE),
00051                 TlvMappingEntry(0x2106, 0x236, NVRAM_TLV_CLASS_HOST, FALSE),
00052                 TlvMappingEntry(0x2107, 0x237, NVRAM_TLV_CLASS_HOST, FALSE),
00053                 TlvMappingEntry(0x2108, 0x238, NVRAM_TLV_CLASS_HOST, FALSE),
00054                 TlvMappingEntry(0x2109, 0x239, NVRAM_TLV_CLASS_HOST, FALSE),
00055                 TlvMappingEntry(0x210A, 0x23A, NVRAM_TLV_CLASS_HOST, FALSE),
00056                 TlvMappingEntry(0x2022, 0x222, NVRAM_TLV_CLASS_HOST, FALSE),
00057                 TlvMappingEntry(0x2200, 0x240, NVRAM_TLV_CLASS_HOST, FALSE),
00058                 TlvMappingEntry(0x2201, 0x241, NVRAM_TLV_CLASS_HOST, FALSE),
00059                 TlvMappingEntry(0x2202, 0x242, NVRAM_TLV_CLASS_HOST, FALSE),
00060                 TlvMappingEntry(0x2203, 0x243, NVRAM_TLV_CLASS_HOST, FALSE),
00061                 TlvMappingEntry(0x2204, 0x244, NVRAM_TLV_CLASS_HOST, FALSE),
00062                 TlvMappingEntry(0x2205, 0x245, NVRAM_TLV_CLASS_HOST, FALSE),
00063                 TlvMappingEntry(0x2207, 0x247, NVRAM_TLV_CLASS_HOST, FALSE),
00064                 TlvMappingEntry(0x2002, 0x202, NVRAM_TLV_CLASS_HOST, FALSE),
00065                 TlvMappingEntry(0x2004, 0x204, NVRAM_TLV_CLASS_HOST, FALSE),
00066                 TlvMappingEntry(0x110, 0x110, NVRAM_TLV_CLASS_HOST, FALSE),
00067                 TlvMappingEntry(0x192, 0x192, NVRAM_TLV_CLASS_GLOBAL, FALSE),
00068                 TlvMappingEntry(0x101, 0x101, NVRAM_TLV_CLASS_GLOBAL, TRUE),
00069                 TlvMappingEntry(0x194, 0x194, NVRAM_TLV_CLASS_GLOBAL, FALSE),
00070                 TlvMappingEntry(0, 0, 0, 0),
00071 };
00072 
00073 static
00074 mlx_status
00075 nvconfig_set_fw_reset_level(
00076                 IN mlx_utils *utils,
00077                 IN      mlx_uint16      tlv_type
00078                 )
00079 {
00080 #define WARM_REBOOT_RESET ((mlx_uint64)0x1 << 38)
00081         mlx_status status = MLX_SUCCESS;
00082         mlx_uint32 reg_status;
00083         mlx_uint64 mfrl = WARM_REBOOT_RESET ;
00084         mlx_uint8 index = 0;
00085         mlx_boolean reset_needed = FALSE;
00086 
00087         for (index = 0 ; nvconfig_tlv_mapping[index].tlv_type != 0 ; index++) {
00088                 if (nvconfig_tlv_mapping[index].tlv_type == tlv_type) {
00089                         reset_needed = nvconfig_tlv_mapping[index].fw_reset_needed;
00090                 }
00091         }
00092 
00093         if (reset_needed == FALSE) {
00094                 goto no_fw_reset_needed;
00095         }
00096         status = mlx_reg_access(utils, REG_ID_MFRL, REG_ACCESS_WRITE, &mfrl, sizeof(mfrl),
00097                                 &reg_status);
00098         MLX_CHECK_STATUS(utils, status, reg_err, "mlx_reg_access failed ");
00099 
00100         if (reg_status != 0) {
00101                 MLX_DEBUG_ERROR(utils,"nvconfig_set_fw_reset_level failed with status = %d\n", reg_status);
00102                 status = MLX_FAILED;
00103                 goto reg_err;
00104         }
00105 reg_err:
00106 no_fw_reset_needed:
00107         return status;
00108 }
00109 
00110 
00111 static
00112 mlx_status
00113 nvconfig_get_tlv_type_and_class(
00114                 IN      mlx_uint16      tlv_type,
00115                 OUT mlx_uint16  *real_tlv_type,
00116                 OUT NVRAM_CLASS_CODE *class_code
00117                 )
00118 {
00119         mlx_uint8 index = 0;
00120         for ( ; nvconfig_tlv_mapping[index].tlv_type != 0 ; index ++) {
00121                 if ( nvconfig_tlv_mapping[index].tlv_type == tlv_type) {
00122                         *real_tlv_type = nvconfig_tlv_mapping[index].real_tlv_type;
00123                         *class_code = nvconfig_tlv_mapping[index].class_code;
00124                         return MLX_SUCCESS;
00125                 }
00126         }
00127         return MLX_NOT_FOUND;
00128 }
00129 static
00130 void
00131 nvconfig_fill_tlv_type(
00132                 IN mlx_uint8 port,
00133                 IN NVRAM_CLASS_CODE class_code,
00134                 IN mlx_uint16 tlv_type,
00135                 OUT union nvconfig_tlv_type *nvconfig_tlv_type
00136                 )
00137 {
00138         switch (class_code) {
00139         case NVRAM_TLV_CLASS_GLOBAL:
00140                 nvconfig_tlv_type->global.param_class = NVRAM_TLV_CLASS_GLOBAL;
00141                 nvconfig_tlv_type->global.param_idx = tlv_type;
00142                 break;
00143         case NVRAM_TLV_CLASS_HOST:
00144                 nvconfig_tlv_type->per_host.param_class = NVRAM_TLV_CLASS_HOST;
00145                 nvconfig_tlv_type->per_host.param_idx = tlv_type;
00146                 break;
00147         case NVRAM_TLV_CLASS_PHYSICAL_PORT:
00148                 nvconfig_tlv_type->per_port.param_class = NVRAM_TLV_CLASS_PHYSICAL_PORT;
00149                 nvconfig_tlv_type->per_port.param_idx = tlv_type;
00150                 nvconfig_tlv_type->per_port.port = port;
00151                 break;
00152         }
00153 }
00154 mlx_status
00155 nvconfig_query_capability(
00156                 IN mlx_utils *utils,
00157                 IN mlx_uint8 port,
00158                 IN mlx_uint16 tlv_type,
00159                 OUT mlx_boolean *read_supported,
00160                 OUT mlx_boolean *write_supported
00161                 )
00162 {
00163         mlx_status status = MLX_SUCCESS;
00164         struct nvconfig_nvqc nvqc;
00165         mlx_uint32 reg_status;
00166         NVRAM_CLASS_CODE class_code;
00167         mlx_uint16 real_tlv_type;
00168 
00169         if (utils == NULL || read_supported == NULL || write_supported == NULL) {
00170                 status = MLX_INVALID_PARAMETER;
00171                 goto bad_param;
00172         }
00173 
00174         status = nvconfig_get_tlv_type_and_class(tlv_type, &real_tlv_type, &class_code);
00175         MLX_CHECK_STATUS(utils, status, tlv_not_supported, "tlv not supported");
00176 
00177         mlx_memory_set(utils, &nvqc, 0, sizeof(nvqc));
00178         nvconfig_fill_tlv_type(port, class_code, real_tlv_type, &nvqc.tlv_type);
00179 
00180         status = mlx_reg_access(utils, REG_ID_NVQC, REG_ACCESS_READ, &nvqc, sizeof(nvqc),
00181                         &reg_status);
00182         MLX_CHECK_STATUS(utils, status, reg_err, "mlx_reg_access failed ");
00183         if (reg_status != 0) {
00184                 MLX_DEBUG_ERROR(utils,"mlx_reg_access failed with status = %d\n", reg_status);
00185                 status = MLX_FAILED;
00186                 goto reg_err;
00187         }
00188         *read_supported = nvqc.support_rd;
00189         *write_supported = nvqc.support_wr;
00190 reg_err:
00191 tlv_not_supported:
00192 bad_param:
00193         return status;
00194 }
00195 
00196 mlx_status
00197 nvconfig_nvdata_invalidate(
00198                 IN mlx_utils *utils,
00199                 IN mlx_uint8 port,
00200                 IN mlx_uint16 tlv_type
00201                 )
00202 {
00203         mlx_status status = MLX_SUCCESS;
00204         struct nvconfig_header nv_header;
00205         mlx_uint32 reg_status;
00206         NVRAM_CLASS_CODE class_code;
00207         mlx_uint16 real_tlv_type;
00208 
00209         if (utils == NULL) {
00210                 status = MLX_INVALID_PARAMETER;
00211                 goto bad_param;
00212         }
00213 
00214         status = nvconfig_get_tlv_type_and_class(tlv_type, &real_tlv_type, &class_code);
00215         MLX_CHECK_STATUS(utils, status, tlv_not_supported, "tlv not supported");
00216 
00217         mlx_memory_set(utils, &nv_header, 0, sizeof(nv_header));
00218         nvconfig_fill_tlv_type(port, class_code, real_tlv_type, &nv_header.tlv_type);
00219 
00220         status = mlx_reg_access(utils, REG_ID_NVDI, REG_ACCESS_WRITE, &nv_header, sizeof(nv_header),
00221                         &reg_status);
00222         MLX_CHECK_STATUS(utils, status, reg_err, "mlx_reg_access failed ");
00223         if (reg_status != 0) {
00224                 MLX_DEBUG_ERROR(utils,"mlx_reg_access failed with status = %d\n", reg_status);
00225                 status = MLX_FAILED;
00226                 goto reg_err;
00227         }
00228 reg_err:
00229 tlv_not_supported:
00230 bad_param:
00231         return status;
00232 }
00233 
00234 mlx_status
00235 nvconfig_nvdata_access(
00236                 IN mlx_utils *utils,
00237                 IN mlx_uint8 port,
00238                 IN mlx_uint16 tlv_type,
00239                 IN REG_ACCESS_OPT opt,
00240                 IN mlx_size data_size,
00241                 IN NV_DEFAULT_OPT def_en,
00242                 IN NVDA_WRITER_ID writer_id,
00243                 IN OUT mlx_uint8 *version,
00244                 IN OUT mlx_void *data
00245                 )
00246 {
00247         mlx_status status = MLX_SUCCESS;
00248         struct nvconfig_nvda nvda;
00249         mlx_uint32 reg_status;
00250         mlx_uint32 real_size_to_read;
00251         mlx_uint32 index;
00252         NVRAM_CLASS_CODE class_code;
00253         mlx_uint16 real_tlv_type;
00254         mlx_size data_size_align_to_dword;
00255 
00256         if (utils == NULL || data == NULL || data_size > NVCONFIG_MAX_TLV_SIZE) {
00257                 status = MLX_INVALID_PARAMETER;
00258                 goto bad_param;
00259         }
00260 
00261         status = nvconfig_get_tlv_type_and_class(tlv_type, &real_tlv_type, &class_code);
00262         MLX_CHECK_STATUS(utils, status, tlv_not_supported, "tlv not supported");
00263 
00264         data_size_align_to_dword = ((data_size + 3) / sizeof(mlx_uint32)) * sizeof(mlx_uint32);
00265         mlx_memory_set(utils, &nvda, 0, sizeof(nvda));
00266         nvda.nv_header.length = data_size_align_to_dword;
00267         nvda.nv_header.access_mode = def_en;
00268         nvda.nv_header.version = *version;
00269         nvda.nv_header.writer_id = writer_id;
00270 
00271         nvconfig_fill_tlv_type(port, class_code, real_tlv_type, &nvda.nv_header.tlv_type);
00272 
00273         mlx_memory_cpy(utils, nvda.data, data, data_size);
00274         for (index = 0 ; index * 4 < NVCONFIG_MAX_TLV_SIZE ; index++) {
00275                 mlx_memory_be32_to_cpu(utils,(((mlx_uint32 *)nvda.data)[index]), ((mlx_uint32 *)nvda.data) + index);
00276         }
00277         status = mlx_reg_access(utils, REG_ID_NVDA, opt, &nvda,
00278                         data_size_align_to_dword + sizeof(nvda.nv_header), &reg_status);
00279         MLX_CHECK_STATUS(utils, status, reg_err, "mlx_reg_access failed ");
00280         if (reg_status != 0) {
00281                 MLX_DEBUG_ERROR(utils,"mlx_reg_access failed with status = %d\n", reg_status);
00282                 status = MLX_FAILED;
00283                 goto reg_err;
00284         }
00285         for (index = 0 ; index * 4 < NVCONFIG_MAX_TLV_SIZE ; index++) {
00286                 mlx_memory_cpu_to_be32(utils,(((mlx_uint32 *)nvda.data)[index]), ((mlx_uint32 *)nvda.data) + index);
00287         }
00288         if (opt == REG_ACCESS_READ) {
00289                 real_size_to_read = (nvda.nv_header.length > data_size) ? data_size :
00290                                 nvda.nv_header.length;
00291                 mlx_memory_cpy(utils, data, nvda.data, real_size_to_read);
00292                 *version = nvda.nv_header.version;
00293         } else {
00294                 nvconfig_set_fw_reset_level(utils, tlv_type);
00295         }
00296 reg_err:
00297 tlv_not_supported:
00298 bad_param:
00299         return status;
00300 }
00301 
00302