0001
0002
0003
0004 #include <net/devlink.h>
0005
0006 #include "nfpcore/nfp.h"
0007 #include "nfpcore/nfp_nsp.h"
0008 #include "nfp_main.h"
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 struct nfp_devlink_param_u8_arg {
0022 const char *hwinfo_name;
0023 const char *default_hi_val;
0024 int invalid_dl_val;
0025 u8 hi_to_dl[4];
0026 u8 dl_to_hi[4];
0027 u8 max_dl_val;
0028 u8 max_hi_val;
0029 };
0030
0031 static const struct nfp_devlink_param_u8_arg nfp_devlink_u8_args[] = {
0032 [DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY] = {
0033 .hwinfo_name = "app_fw_from_flash",
0034 .default_hi_val = NFP_NSP_APP_FW_LOAD_DEFAULT,
0035 .invalid_dl_val =
0036 DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_UNKNOWN,
0037 .hi_to_dl = {
0038 [NFP_NSP_APP_FW_LOAD_DISK] =
0039 DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DISK,
0040 [NFP_NSP_APP_FW_LOAD_FLASH] =
0041 DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH,
0042 [NFP_NSP_APP_FW_LOAD_PREF] =
0043 DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER,
0044 },
0045 .dl_to_hi = {
0046 [DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER] =
0047 NFP_NSP_APP_FW_LOAD_PREF,
0048 [DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH] =
0049 NFP_NSP_APP_FW_LOAD_FLASH,
0050 [DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DISK] =
0051 NFP_NSP_APP_FW_LOAD_DISK,
0052 },
0053 .max_dl_val = DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DISK,
0054 .max_hi_val = NFP_NSP_APP_FW_LOAD_PREF,
0055 },
0056 [DEVLINK_PARAM_GENERIC_ID_RESET_DEV_ON_DRV_PROBE] = {
0057 .hwinfo_name = "abi_drv_reset",
0058 .default_hi_val = NFP_NSP_DRV_RESET_DEFAULT,
0059 .invalid_dl_val =
0060 DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_UNKNOWN,
0061 .hi_to_dl = {
0062 [NFP_NSP_DRV_RESET_ALWAYS] =
0063 DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_ALWAYS,
0064 [NFP_NSP_DRV_RESET_NEVER] =
0065 DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_NEVER,
0066 [NFP_NSP_DRV_RESET_DISK] =
0067 DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_DISK,
0068 },
0069 .dl_to_hi = {
0070 [DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_ALWAYS] =
0071 NFP_NSP_DRV_RESET_ALWAYS,
0072 [DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_NEVER] =
0073 NFP_NSP_DRV_RESET_NEVER,
0074 [DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_DISK] =
0075 NFP_NSP_DRV_RESET_DISK,
0076 },
0077 .max_dl_val = DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_DISK,
0078 .max_hi_val = NFP_NSP_DRV_RESET_NEVER,
0079 }
0080 };
0081
0082 static int
0083 nfp_devlink_param_u8_get(struct devlink *devlink, u32 id,
0084 struct devlink_param_gset_ctx *ctx)
0085 {
0086 const struct nfp_devlink_param_u8_arg *arg;
0087 struct nfp_pf *pf = devlink_priv(devlink);
0088 struct nfp_nsp *nsp;
0089 char hwinfo[32];
0090 long value;
0091 int err;
0092
0093 if (id >= ARRAY_SIZE(nfp_devlink_u8_args))
0094 return -EOPNOTSUPP;
0095
0096 arg = &nfp_devlink_u8_args[id];
0097
0098 nsp = nfp_nsp_open(pf->cpp);
0099 if (IS_ERR(nsp)) {
0100 err = PTR_ERR(nsp);
0101 nfp_warn(pf->cpp, "can't access NSP: %d\n", err);
0102 return err;
0103 }
0104
0105 snprintf(hwinfo, sizeof(hwinfo), arg->hwinfo_name);
0106 err = nfp_nsp_hwinfo_lookup_optional(nsp, hwinfo, sizeof(hwinfo),
0107 arg->default_hi_val);
0108 if (err) {
0109 nfp_warn(pf->cpp, "HWinfo lookup failed: %d\n", err);
0110 goto exit_close_nsp;
0111 }
0112
0113 err = kstrtol(hwinfo, 0, &value);
0114 if (err || value < 0 || value > arg->max_hi_val) {
0115 nfp_warn(pf->cpp, "HWinfo '%s' value %li invalid\n",
0116 arg->hwinfo_name, value);
0117
0118 if (arg->invalid_dl_val >= 0)
0119 ctx->val.vu8 = arg->invalid_dl_val;
0120 else
0121 err = arg->invalid_dl_val;
0122
0123 goto exit_close_nsp;
0124 }
0125
0126 ctx->val.vu8 = arg->hi_to_dl[value];
0127
0128 exit_close_nsp:
0129 nfp_nsp_close(nsp);
0130 return err;
0131 }
0132
0133 static int
0134 nfp_devlink_param_u8_set(struct devlink *devlink, u32 id,
0135 struct devlink_param_gset_ctx *ctx)
0136 {
0137 const struct nfp_devlink_param_u8_arg *arg;
0138 struct nfp_pf *pf = devlink_priv(devlink);
0139 struct nfp_nsp *nsp;
0140 char hwinfo[32];
0141 int err;
0142
0143 if (id >= ARRAY_SIZE(nfp_devlink_u8_args))
0144 return -EOPNOTSUPP;
0145
0146 arg = &nfp_devlink_u8_args[id];
0147
0148 nsp = nfp_nsp_open(pf->cpp);
0149 if (IS_ERR(nsp)) {
0150 err = PTR_ERR(nsp);
0151 nfp_warn(pf->cpp, "can't access NSP: %d\n", err);
0152 return err;
0153 }
0154
0155
0156 snprintf(hwinfo, sizeof(hwinfo), "%s=%u",
0157 arg->hwinfo_name, arg->dl_to_hi[ctx->val.vu8]);
0158 err = nfp_nsp_hwinfo_set(nsp, hwinfo, sizeof(hwinfo));
0159 if (err) {
0160 nfp_warn(pf->cpp, "HWinfo set failed: %d\n", err);
0161 goto exit_close_nsp;
0162 }
0163
0164 exit_close_nsp:
0165 nfp_nsp_close(nsp);
0166 return err;
0167 }
0168
0169 static int
0170 nfp_devlink_param_u8_validate(struct devlink *devlink, u32 id,
0171 union devlink_param_value val,
0172 struct netlink_ext_ack *extack)
0173 {
0174 const struct nfp_devlink_param_u8_arg *arg;
0175
0176 if (id >= ARRAY_SIZE(nfp_devlink_u8_args))
0177 return -EOPNOTSUPP;
0178
0179 arg = &nfp_devlink_u8_args[id];
0180
0181 if (val.vu8 > arg->max_dl_val) {
0182 NL_SET_ERR_MSG_MOD(extack, "parameter out of range");
0183 return -EINVAL;
0184 }
0185
0186 if (val.vu8 == arg->invalid_dl_val) {
0187 NL_SET_ERR_MSG_MOD(extack, "unknown/invalid value specified");
0188 return -EINVAL;
0189 }
0190
0191 return 0;
0192 }
0193
0194 static const struct devlink_param nfp_devlink_params[] = {
0195 DEVLINK_PARAM_GENERIC(FW_LOAD_POLICY,
0196 BIT(DEVLINK_PARAM_CMODE_PERMANENT),
0197 nfp_devlink_param_u8_get,
0198 nfp_devlink_param_u8_set,
0199 nfp_devlink_param_u8_validate),
0200 DEVLINK_PARAM_GENERIC(RESET_DEV_ON_DRV_PROBE,
0201 BIT(DEVLINK_PARAM_CMODE_PERMANENT),
0202 nfp_devlink_param_u8_get,
0203 nfp_devlink_param_u8_set,
0204 nfp_devlink_param_u8_validate),
0205 };
0206
0207 static int nfp_devlink_supports_params(struct nfp_pf *pf)
0208 {
0209 struct nfp_nsp *nsp;
0210 bool supported;
0211 int err;
0212
0213 nsp = nfp_nsp_open(pf->cpp);
0214 if (IS_ERR(nsp)) {
0215 err = PTR_ERR(nsp);
0216 dev_err(&pf->pdev->dev, "Failed to access the NSP: %d\n", err);
0217 return err;
0218 }
0219
0220 supported = nfp_nsp_has_hwinfo_lookup(nsp) &&
0221 nfp_nsp_has_hwinfo_set(nsp);
0222
0223 nfp_nsp_close(nsp);
0224 return supported;
0225 }
0226
0227 int nfp_devlink_params_register(struct nfp_pf *pf)
0228 {
0229 struct devlink *devlink = priv_to_devlink(pf);
0230 int err;
0231
0232 err = nfp_devlink_supports_params(pf);
0233 if (err <= 0)
0234 return err;
0235
0236 return devlink_params_register(devlink, nfp_devlink_params,
0237 ARRAY_SIZE(nfp_devlink_params));
0238 }
0239
0240 void nfp_devlink_params_unregister(struct nfp_pf *pf)
0241 {
0242 int err;
0243
0244 err = nfp_devlink_supports_params(pf);
0245 if (err <= 0)
0246 return;
0247
0248 devlink_params_unregister(priv_to_devlink(pf), nfp_devlink_params,
0249 ARRAY_SIZE(nfp_devlink_params));
0250 }