devlink_param.c (6631B)
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2/* Copyright (C) 2019 Netronome Systems, Inc. */ 3 4#include <net/devlink.h> 5 6#include "nfpcore/nfp.h" 7#include "nfpcore/nfp_nsp.h" 8#include "nfp_main.h" 9 10/** 11 * struct nfp_devlink_param_u8_arg - Devlink u8 parameter get/set arguments 12 * @hwinfo_name: HWinfo key name 13 * @default_hi_val: Default HWinfo value if HWinfo doesn't exist 14 * @invalid_dl_val: Devlink value to use if HWinfo is unknown/invalid. 15 * -errno if there is no unknown/invalid value available 16 * @hi_to_dl: HWinfo to devlink value mapping 17 * @dl_to_hi: Devlink to hwinfo value mapping 18 * @max_dl_val: Maximum devlink value supported, for validation only 19 * @max_hi_val: Maximum HWinfo value supported, for validation only 20 */ 21struct nfp_devlink_param_u8_arg { 22 const char *hwinfo_name; 23 const char *default_hi_val; 24 int invalid_dl_val; 25 u8 hi_to_dl[4]; 26 u8 dl_to_hi[4]; 27 u8 max_dl_val; 28 u8 max_hi_val; 29}; 30 31static const struct nfp_devlink_param_u8_arg nfp_devlink_u8_args[] = { 32 [DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY] = { 33 .hwinfo_name = "app_fw_from_flash", 34 .default_hi_val = NFP_NSP_APP_FW_LOAD_DEFAULT, 35 .invalid_dl_val = 36 DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_UNKNOWN, 37 .hi_to_dl = { 38 [NFP_NSP_APP_FW_LOAD_DISK] = 39 DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DISK, 40 [NFP_NSP_APP_FW_LOAD_FLASH] = 41 DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH, 42 [NFP_NSP_APP_FW_LOAD_PREF] = 43 DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER, 44 }, 45 .dl_to_hi = { 46 [DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER] = 47 NFP_NSP_APP_FW_LOAD_PREF, 48 [DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH] = 49 NFP_NSP_APP_FW_LOAD_FLASH, 50 [DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DISK] = 51 NFP_NSP_APP_FW_LOAD_DISK, 52 }, 53 .max_dl_val = DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DISK, 54 .max_hi_val = NFP_NSP_APP_FW_LOAD_PREF, 55 }, 56 [DEVLINK_PARAM_GENERIC_ID_RESET_DEV_ON_DRV_PROBE] = { 57 .hwinfo_name = "abi_drv_reset", 58 .default_hi_val = NFP_NSP_DRV_RESET_DEFAULT, 59 .invalid_dl_val = 60 DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_UNKNOWN, 61 .hi_to_dl = { 62 [NFP_NSP_DRV_RESET_ALWAYS] = 63 DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_ALWAYS, 64 [NFP_NSP_DRV_RESET_NEVER] = 65 DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_NEVER, 66 [NFP_NSP_DRV_RESET_DISK] = 67 DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_DISK, 68 }, 69 .dl_to_hi = { 70 [DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_ALWAYS] = 71 NFP_NSP_DRV_RESET_ALWAYS, 72 [DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_NEVER] = 73 NFP_NSP_DRV_RESET_NEVER, 74 [DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_DISK] = 75 NFP_NSP_DRV_RESET_DISK, 76 }, 77 .max_dl_val = DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_DISK, 78 .max_hi_val = NFP_NSP_DRV_RESET_NEVER, 79 } 80}; 81 82static int 83nfp_devlink_param_u8_get(struct devlink *devlink, u32 id, 84 struct devlink_param_gset_ctx *ctx) 85{ 86 const struct nfp_devlink_param_u8_arg *arg; 87 struct nfp_pf *pf = devlink_priv(devlink); 88 struct nfp_nsp *nsp; 89 char hwinfo[32]; 90 long value; 91 int err; 92 93 if (id >= ARRAY_SIZE(nfp_devlink_u8_args)) 94 return -EOPNOTSUPP; 95 96 arg = &nfp_devlink_u8_args[id]; 97 98 nsp = nfp_nsp_open(pf->cpp); 99 if (IS_ERR(nsp)) { 100 err = PTR_ERR(nsp); 101 nfp_warn(pf->cpp, "can't access NSP: %d\n", err); 102 return err; 103 } 104 105 snprintf(hwinfo, sizeof(hwinfo), arg->hwinfo_name); 106 err = nfp_nsp_hwinfo_lookup_optional(nsp, hwinfo, sizeof(hwinfo), 107 arg->default_hi_val); 108 if (err) { 109 nfp_warn(pf->cpp, "HWinfo lookup failed: %d\n", err); 110 goto exit_close_nsp; 111 } 112 113 err = kstrtol(hwinfo, 0, &value); 114 if (err || value < 0 || value > arg->max_hi_val) { 115 nfp_warn(pf->cpp, "HWinfo '%s' value %li invalid\n", 116 arg->hwinfo_name, value); 117 118 if (arg->invalid_dl_val >= 0) 119 ctx->val.vu8 = arg->invalid_dl_val; 120 else 121 err = arg->invalid_dl_val; 122 123 goto exit_close_nsp; 124 } 125 126 ctx->val.vu8 = arg->hi_to_dl[value]; 127 128exit_close_nsp: 129 nfp_nsp_close(nsp); 130 return err; 131} 132 133static int 134nfp_devlink_param_u8_set(struct devlink *devlink, u32 id, 135 struct devlink_param_gset_ctx *ctx) 136{ 137 const struct nfp_devlink_param_u8_arg *arg; 138 struct nfp_pf *pf = devlink_priv(devlink); 139 struct nfp_nsp *nsp; 140 char hwinfo[32]; 141 int err; 142 143 if (id >= ARRAY_SIZE(nfp_devlink_u8_args)) 144 return -EOPNOTSUPP; 145 146 arg = &nfp_devlink_u8_args[id]; 147 148 nsp = nfp_nsp_open(pf->cpp); 149 if (IS_ERR(nsp)) { 150 err = PTR_ERR(nsp); 151 nfp_warn(pf->cpp, "can't access NSP: %d\n", err); 152 return err; 153 } 154 155 /* Note the value has already been validated. */ 156 snprintf(hwinfo, sizeof(hwinfo), "%s=%u", 157 arg->hwinfo_name, arg->dl_to_hi[ctx->val.vu8]); 158 err = nfp_nsp_hwinfo_set(nsp, hwinfo, sizeof(hwinfo)); 159 if (err) { 160 nfp_warn(pf->cpp, "HWinfo set failed: %d\n", err); 161 goto exit_close_nsp; 162 } 163 164exit_close_nsp: 165 nfp_nsp_close(nsp); 166 return err; 167} 168 169static int 170nfp_devlink_param_u8_validate(struct devlink *devlink, u32 id, 171 union devlink_param_value val, 172 struct netlink_ext_ack *extack) 173{ 174 const struct nfp_devlink_param_u8_arg *arg; 175 176 if (id >= ARRAY_SIZE(nfp_devlink_u8_args)) 177 return -EOPNOTSUPP; 178 179 arg = &nfp_devlink_u8_args[id]; 180 181 if (val.vu8 > arg->max_dl_val) { 182 NL_SET_ERR_MSG_MOD(extack, "parameter out of range"); 183 return -EINVAL; 184 } 185 186 if (val.vu8 == arg->invalid_dl_val) { 187 NL_SET_ERR_MSG_MOD(extack, "unknown/invalid value specified"); 188 return -EINVAL; 189 } 190 191 return 0; 192} 193 194static const struct devlink_param nfp_devlink_params[] = { 195 DEVLINK_PARAM_GENERIC(FW_LOAD_POLICY, 196 BIT(DEVLINK_PARAM_CMODE_PERMANENT), 197 nfp_devlink_param_u8_get, 198 nfp_devlink_param_u8_set, 199 nfp_devlink_param_u8_validate), 200 DEVLINK_PARAM_GENERIC(RESET_DEV_ON_DRV_PROBE, 201 BIT(DEVLINK_PARAM_CMODE_PERMANENT), 202 nfp_devlink_param_u8_get, 203 nfp_devlink_param_u8_set, 204 nfp_devlink_param_u8_validate), 205}; 206 207static int nfp_devlink_supports_params(struct nfp_pf *pf) 208{ 209 struct nfp_nsp *nsp; 210 bool supported; 211 int err; 212 213 nsp = nfp_nsp_open(pf->cpp); 214 if (IS_ERR(nsp)) { 215 err = PTR_ERR(nsp); 216 dev_err(&pf->pdev->dev, "Failed to access the NSP: %d\n", err); 217 return err; 218 } 219 220 supported = nfp_nsp_has_hwinfo_lookup(nsp) && 221 nfp_nsp_has_hwinfo_set(nsp); 222 223 nfp_nsp_close(nsp); 224 return supported; 225} 226 227int nfp_devlink_params_register(struct nfp_pf *pf) 228{ 229 struct devlink *devlink = priv_to_devlink(pf); 230 int err; 231 232 err = nfp_devlink_supports_params(pf); 233 if (err <= 0) 234 return err; 235 236 return devlink_params_register(devlink, nfp_devlink_params, 237 ARRAY_SIZE(nfp_devlink_params)); 238} 239 240void nfp_devlink_params_unregister(struct nfp_pf *pf) 241{ 242 int err; 243 244 err = nfp_devlink_supports_params(pf); 245 if (err <= 0) 246 return; 247 248 devlink_params_unregister(priv_to_devlink(pf), nfp_devlink_params, 249 ARRAY_SIZE(nfp_devlink_params)); 250}