1// SPDX-License-Identifier: GPL-2.0
2/* Marvell RVU PF/VF Netdev Devlink
3 *
4 * Copyright (C) 2021 Marvell.
5 */
6
7#include "otx2_common.h"
8
9/* Devlink Params APIs */
10static int otx2_dl_mcam_count_validate(struct devlink *devlink, u32 id,
11				       union devlink_param_value val,
12				       struct netlink_ext_ack *extack)
13{
14	struct otx2_devlink *otx2_dl = devlink_priv(devlink);
15	struct otx2_nic *pfvf = otx2_dl->pfvf;
16	struct otx2_flow_config *flow_cfg;
17
18	if (!pfvf->flow_cfg) {
19		NL_SET_ERR_MSG_MOD(extack,
20				   "pfvf->flow_cfg not initialized");
21		return -EINVAL;
22	}
23
24	flow_cfg = pfvf->flow_cfg;
25	if (flow_cfg && flow_cfg->nr_flows) {
26		NL_SET_ERR_MSG_MOD(extack,
27				   "Cannot modify count when there are active rules");
28		return -EINVAL;
29	}
30
31	return 0;
32}
33
34static int otx2_dl_mcam_count_set(struct devlink *devlink, u32 id,
35				  struct devlink_param_gset_ctx *ctx)
36{
37	struct otx2_devlink *otx2_dl = devlink_priv(devlink);
38	struct otx2_nic *pfvf = otx2_dl->pfvf;
39
40	if (!pfvf->flow_cfg)
41		return 0;
42
43	otx2_alloc_mcam_entries(pfvf, ctx->val.vu16);
44
45	return 0;
46}
47
48static int otx2_dl_mcam_count_get(struct devlink *devlink, u32 id,
49				  struct devlink_param_gset_ctx *ctx)
50{
51	struct otx2_devlink *otx2_dl = devlink_priv(devlink);
52	struct otx2_nic *pfvf = otx2_dl->pfvf;
53	struct otx2_flow_config *flow_cfg;
54
55	if (!pfvf->flow_cfg) {
56		ctx->val.vu16 = 0;
57		return 0;
58	}
59
60	flow_cfg = pfvf->flow_cfg;
61	ctx->val.vu16 = flow_cfg->max_flows;
62
63	return 0;
64}
65
66enum otx2_dl_param_id {
67	OTX2_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
68	OTX2_DEVLINK_PARAM_ID_MCAM_COUNT,
69};
70
71static const struct devlink_param otx2_dl_params[] = {
72	DEVLINK_PARAM_DRIVER(OTX2_DEVLINK_PARAM_ID_MCAM_COUNT,
73			     "mcam_count", DEVLINK_PARAM_TYPE_U16,
74			     BIT(DEVLINK_PARAM_CMODE_RUNTIME),
75			     otx2_dl_mcam_count_get, otx2_dl_mcam_count_set,
76			     otx2_dl_mcam_count_validate),
77};
78
79static const struct devlink_ops otx2_devlink_ops = {
80};
81
82int otx2_register_dl(struct otx2_nic *pfvf)
83{
84	struct otx2_devlink *otx2_dl;
85	struct devlink *dl;
86	int err;
87
88	dl = devlink_alloc(&otx2_devlink_ops,
89			   sizeof(struct otx2_devlink), pfvf->dev);
90	if (!dl) {
91		dev_warn(pfvf->dev, "devlink_alloc failed\n");
92		return -ENOMEM;
93	}
94
95	otx2_dl = devlink_priv(dl);
96	otx2_dl->dl = dl;
97	otx2_dl->pfvf = pfvf;
98	pfvf->dl = otx2_dl;
99
100	err = devlink_params_register(dl, otx2_dl_params,
101				      ARRAY_SIZE(otx2_dl_params));
102	if (err) {
103		dev_err(pfvf->dev,
104			"devlink params register failed with error %d", err);
105		goto err_dl;
106	}
107
108	devlink_register(dl);
109	return 0;
110
111err_dl:
112	devlink_free(dl);
113	return err;
114}
115
116void otx2_unregister_dl(struct otx2_nic *pfvf)
117{
118	struct otx2_devlink *otx2_dl = pfvf->dl;
119	struct devlink *dl = otx2_dl->dl;
120
121	devlink_unregister(dl);
122	devlink_params_unregister(dl, otx2_dl_params,
123				  ARRAY_SIZE(otx2_dl_params));
124	devlink_free(dl);
125}
126