Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
0002 /* Copyright (C) 2019 Netronome Systems, Inc. */
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  * struct nfp_devlink_param_u8_arg - Devlink u8 parameter get/set arguments
0012  * @hwinfo_name:    HWinfo key name
0013  * @default_hi_val: Default HWinfo value if HWinfo doesn't exist
0014  * @invalid_dl_val: Devlink value to use if HWinfo is unknown/invalid.
0015  *          -errno if there is no unknown/invalid value available
0016  * @hi_to_dl:   HWinfo to devlink value mapping
0017  * @dl_to_hi:   Devlink to hwinfo value mapping
0018  * @max_dl_val: Maximum devlink value supported, for validation only
0019  * @max_hi_val: Maximum HWinfo value supported, for validation only
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     /* Note the value has already been validated. */
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 }