brintos

brintos / linux-shallow public Read only

0
0
Text · 6.5 KiB · 0e1a380 Raw
252 lines · c
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 arguments12 * @hwinfo_name:	HWinfo key name13 * @default_hi_val:	Default HWinfo value if HWinfo doesn't exist14 * @invalid_dl_val:	Devlink value to use if HWinfo is unknown/invalid.15 *			-errno if there is no unknown/invalid value available16 * @hi_to_dl:	HWinfo to devlink value mapping17 * @dl_to_hi:	Devlink to hwinfo value mapping18 * @max_dl_val:	Maximum devlink value supported, for validation only19 * @max_hi_val:	Maximum HWinfo value supported, for validation only20 */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 int83nfp_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		else121			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 int134nfp_devlink_param_u8_set(struct devlink *devlink, u32 id,135			 struct devlink_param_gset_ctx *ctx,136			 struct netlink_ext_ack *extack)137{138	const struct nfp_devlink_param_u8_arg *arg;139	struct nfp_pf *pf = devlink_priv(devlink);140	struct nfp_nsp *nsp;141	char hwinfo[32];142	int err;143 144	if (id >= ARRAY_SIZE(nfp_devlink_u8_args))145		return -EOPNOTSUPP;146 147	arg = &nfp_devlink_u8_args[id];148 149	nsp = nfp_nsp_open(pf->cpp);150	if (IS_ERR(nsp)) {151		err = PTR_ERR(nsp);152		nfp_warn(pf->cpp, "can't access NSP: %d\n", err);153		return err;154	}155 156	/* Note the value has already been validated. */157	snprintf(hwinfo, sizeof(hwinfo), "%s=%u",158		 arg->hwinfo_name, arg->dl_to_hi[ctx->val.vu8]);159	err = nfp_nsp_hwinfo_set(nsp, hwinfo, sizeof(hwinfo));160	if (err) {161		nfp_warn(pf->cpp, "HWinfo set failed: %d\n", err);162		goto exit_close_nsp;163	}164 165exit_close_nsp:166	nfp_nsp_close(nsp);167	return err;168}169 170static int171nfp_devlink_param_u8_validate(struct devlink *devlink, u32 id,172			      union devlink_param_value val,173			      struct netlink_ext_ack *extack)174{175	const struct nfp_devlink_param_u8_arg *arg;176 177	if (id >= ARRAY_SIZE(nfp_devlink_u8_args))178		return -EOPNOTSUPP;179 180	arg = &nfp_devlink_u8_args[id];181 182	if (val.vu8 > arg->max_dl_val) {183		NL_SET_ERR_MSG_MOD(extack, "parameter out of range");184		return -EINVAL;185	}186 187	if (val.vu8 == arg->invalid_dl_val) {188		NL_SET_ERR_MSG_MOD(extack, "unknown/invalid value specified");189		return -EINVAL;190	}191 192	return 0;193}194 195static const struct devlink_param nfp_devlink_params[] = {196	DEVLINK_PARAM_GENERIC(FW_LOAD_POLICY,197			      BIT(DEVLINK_PARAM_CMODE_PERMANENT),198			      nfp_devlink_param_u8_get,199			      nfp_devlink_param_u8_set,200			      nfp_devlink_param_u8_validate),201	DEVLINK_PARAM_GENERIC(RESET_DEV_ON_DRV_PROBE,202			      BIT(DEVLINK_PARAM_CMODE_PERMANENT),203			      nfp_devlink_param_u8_get,204			      nfp_devlink_param_u8_set,205			      nfp_devlink_param_u8_validate),206};207 208static int nfp_devlink_supports_params(struct nfp_pf *pf)209{210	struct nfp_nsp *nsp;211	bool supported;212	int err;213 214	nsp = nfp_nsp_open(pf->cpp);215	if (IS_ERR(nsp)) {216		err = PTR_ERR(nsp);217		dev_err(&pf->pdev->dev, "Failed to access the NSP: %d\n", err);218		return err;219	}220 221	supported = nfp_nsp_has_hwinfo_lookup(nsp) &&222		    nfp_nsp_has_hwinfo_set(nsp);223 224	nfp_nsp_close(nsp);225	return supported;226}227 228int nfp_devlink_params_register(struct nfp_pf *pf)229{230	struct devlink *devlink = priv_to_devlink(pf);231	int err;232 233	err = nfp_devlink_supports_params(pf);234	if (err <= 0)235		return err;236 237	return devl_params_register(devlink, nfp_devlink_params,238				    ARRAY_SIZE(nfp_devlink_params));239}240 241void nfp_devlink_params_unregister(struct nfp_pf *pf)242{243	int err;244 245	err = nfp_devlink_supports_params(pf);246	if (err <= 0)247		return;248 249	devl_params_unregister(priv_to_devlink(pf), nfp_devlink_params,250			       ARRAY_SIZE(nfp_devlink_params));251}252