linux/drivers/net/ethernet/netronome/nfp/devlink_param.c
<<
>>
Prefs
   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        err = devlink_params_register(devlink, nfp_devlink_params,
 237                                      ARRAY_SIZE(nfp_devlink_params));
 238        if (err)
 239                return err;
 240
 241        devlink_params_publish(devlink);
 242        return 0;
 243}
 244
 245void nfp_devlink_params_unregister(struct nfp_pf *pf)
 246{
 247        int err;
 248
 249        err = nfp_devlink_supports_params(pf);
 250        if (err <= 0)
 251                return;
 252
 253        devlink_params_unregister(priv_to_devlink(pf), nfp_devlink_params,
 254                                  ARRAY_SIZE(nfp_devlink_params));
 255}
 256