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 */
otx2_dl_mcam_count_validate(struct devlink * devlink,u32 id,union devlink_param_value val,struct netlink_ext_ack * extack)10 static 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
otx2_dl_mcam_count_set(struct devlink * devlink,u32 id,struct devlink_param_gset_ctx * ctx,struct netlink_ext_ack * extack)34 static int otx2_dl_mcam_count_set(struct devlink *devlink, u32 id,
35 struct devlink_param_gset_ctx *ctx,
36 struct netlink_ext_ack *extack)
37 {
38 struct otx2_devlink *otx2_dl = devlink_priv(devlink);
39 struct otx2_nic *pfvf = otx2_dl->pfvf;
40
41 if (!pfvf->flow_cfg)
42 return 0;
43
44 pfvf->flow_cfg->ntuple_cnt = ctx->val.vu16;
45 otx2_alloc_mcam_entries(pfvf, ctx->val.vu16);
46
47 return 0;
48 }
49
otx2_dl_mcam_count_get(struct devlink * devlink,u32 id,struct devlink_param_gset_ctx * ctx)50 static int otx2_dl_mcam_count_get(struct devlink *devlink, u32 id,
51 struct devlink_param_gset_ctx *ctx)
52 {
53 struct otx2_devlink *otx2_dl = devlink_priv(devlink);
54 struct otx2_nic *pfvf = otx2_dl->pfvf;
55 struct otx2_flow_config *flow_cfg;
56
57 if (!pfvf->flow_cfg) {
58 ctx->val.vu16 = 0;
59 return 0;
60 }
61
62 flow_cfg = pfvf->flow_cfg;
63 ctx->val.vu16 = flow_cfg->max_flows;
64
65 return 0;
66 }
67
otx2_dl_ucast_flt_cnt_set(struct devlink * devlink,u32 id,struct devlink_param_gset_ctx * ctx,struct netlink_ext_ack * extack)68 static int otx2_dl_ucast_flt_cnt_set(struct devlink *devlink, u32 id,
69 struct devlink_param_gset_ctx *ctx,
70 struct netlink_ext_ack *extack)
71 {
72 struct otx2_devlink *otx2_dl = devlink_priv(devlink);
73 struct otx2_nic *pfvf = otx2_dl->pfvf;
74 int err;
75
76 pfvf->flow_cfg->ucast_flt_cnt = ctx->val.vu8;
77
78 otx2_mcam_flow_del(pfvf);
79 err = otx2_mcam_entry_init(pfvf);
80 if (err)
81 return err;
82
83 return 0;
84 }
85
otx2_dl_ucast_flt_cnt_get(struct devlink * devlink,u32 id,struct devlink_param_gset_ctx * ctx)86 static int otx2_dl_ucast_flt_cnt_get(struct devlink *devlink, u32 id,
87 struct devlink_param_gset_ctx *ctx)
88 {
89 struct otx2_devlink *otx2_dl = devlink_priv(devlink);
90 struct otx2_nic *pfvf = otx2_dl->pfvf;
91
92 ctx->val.vu8 = pfvf->flow_cfg ? pfvf->flow_cfg->ucast_flt_cnt : 0;
93
94 return 0;
95 }
96
otx2_dl_ucast_flt_cnt_validate(struct devlink * devlink,u32 id,union devlink_param_value val,struct netlink_ext_ack * extack)97 static int otx2_dl_ucast_flt_cnt_validate(struct devlink *devlink, u32 id,
98 union devlink_param_value val,
99 struct netlink_ext_ack *extack)
100 {
101 struct otx2_devlink *otx2_dl = devlink_priv(devlink);
102 struct otx2_nic *pfvf = otx2_dl->pfvf;
103
104 /* Check for UNICAST filter support*/
105 if (!(pfvf->flags & OTX2_FLAG_UCAST_FLTR_SUPPORT)) {
106 NL_SET_ERR_MSG_MOD(extack,
107 "Unicast filter not enabled");
108 return -EINVAL;
109 }
110
111 if (!pfvf->flow_cfg) {
112 NL_SET_ERR_MSG_MOD(extack,
113 "pfvf->flow_cfg not initialized");
114 return -EINVAL;
115 }
116
117 if (pfvf->flow_cfg->nr_flows) {
118 NL_SET_ERR_MSG_MOD(extack,
119 "Cannot modify count when there are active rules");
120 return -EINVAL;
121 }
122
123 return 0;
124 }
125
126 enum otx2_dl_param_id {
127 OTX2_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
128 OTX2_DEVLINK_PARAM_ID_MCAM_COUNT,
129 OTX2_DEVLINK_PARAM_ID_UCAST_FLT_CNT,
130 };
131
132 static const struct devlink_param otx2_dl_params[] = {
133 DEVLINK_PARAM_DRIVER(OTX2_DEVLINK_PARAM_ID_MCAM_COUNT,
134 "mcam_count", DEVLINK_PARAM_TYPE_U16,
135 BIT(DEVLINK_PARAM_CMODE_RUNTIME),
136 otx2_dl_mcam_count_get, otx2_dl_mcam_count_set,
137 otx2_dl_mcam_count_validate),
138 DEVLINK_PARAM_DRIVER(OTX2_DEVLINK_PARAM_ID_UCAST_FLT_CNT,
139 "unicast_filter_count", DEVLINK_PARAM_TYPE_U8,
140 BIT(DEVLINK_PARAM_CMODE_RUNTIME),
141 otx2_dl_ucast_flt_cnt_get, otx2_dl_ucast_flt_cnt_set,
142 otx2_dl_ucast_flt_cnt_validate),
143 };
144
145 #ifdef CONFIG_RVU_ESWITCH
otx2_devlink_eswitch_mode_get(struct devlink * devlink,u16 * mode)146 static int otx2_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
147 {
148 struct otx2_devlink *otx2_dl = devlink_priv(devlink);
149 struct otx2_nic *pfvf = otx2_dl->pfvf;
150
151 if (!otx2_rep_dev(pfvf->pdev))
152 return -EOPNOTSUPP;
153
154 *mode = pfvf->esw_mode;
155
156 return 0;
157 }
158
otx2_devlink_eswitch_mode_set(struct devlink * devlink,u16 mode,struct netlink_ext_ack * extack)159 static int otx2_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
160 struct netlink_ext_ack *extack)
161 {
162 struct otx2_devlink *otx2_dl = devlink_priv(devlink);
163 struct otx2_nic *pfvf = otx2_dl->pfvf;
164 int ret = 0;
165
166 if (!otx2_rep_dev(pfvf->pdev))
167 return -EOPNOTSUPP;
168
169 if (pfvf->esw_mode == mode)
170 return 0;
171
172 switch (mode) {
173 case DEVLINK_ESWITCH_MODE_LEGACY:
174 rvu_rep_destroy(pfvf);
175 break;
176 case DEVLINK_ESWITCH_MODE_SWITCHDEV:
177 ret = rvu_rep_create(pfvf, extack);
178 break;
179 default:
180 return -EINVAL;
181 }
182
183 if (!ret)
184 pfvf->esw_mode = mode;
185
186 return ret;
187 }
188 #endif
189
190 static const struct devlink_ops otx2_devlink_ops = {
191 #ifdef CONFIG_RVU_ESWITCH
192 .eswitch_mode_get = otx2_devlink_eswitch_mode_get,
193 .eswitch_mode_set = otx2_devlink_eswitch_mode_set,
194 #endif
195 };
196
otx2_register_dl(struct otx2_nic * pfvf)197 int otx2_register_dl(struct otx2_nic *pfvf)
198 {
199 struct otx2_devlink *otx2_dl;
200 struct devlink *dl;
201 int err;
202
203 dl = devlink_alloc(&otx2_devlink_ops,
204 sizeof(struct otx2_devlink), pfvf->dev);
205 if (!dl) {
206 dev_warn(pfvf->dev, "devlink_alloc failed\n");
207 return -ENOMEM;
208 }
209
210 otx2_dl = devlink_priv(dl);
211 otx2_dl->dl = dl;
212 otx2_dl->pfvf = pfvf;
213 pfvf->dl = otx2_dl;
214
215 err = devlink_params_register(dl, otx2_dl_params,
216 ARRAY_SIZE(otx2_dl_params));
217 if (err) {
218 dev_err(pfvf->dev,
219 "devlink params register failed with error %d", err);
220 goto err_dl;
221 }
222
223 devlink_register(dl);
224 return 0;
225
226 err_dl:
227 devlink_free(dl);
228 return err;
229 }
230 EXPORT_SYMBOL(otx2_register_dl);
231
otx2_unregister_dl(struct otx2_nic * pfvf)232 void otx2_unregister_dl(struct otx2_nic *pfvf)
233 {
234 struct otx2_devlink *otx2_dl = pfvf->dl;
235 struct devlink *dl = otx2_dl->dl;
236
237 devlink_unregister(dl);
238 devlink_params_unregister(dl, otx2_dl_params,
239 ARRAY_SIZE(otx2_dl_params));
240 devlink_free(dl);
241 }
242 EXPORT_SYMBOL(otx2_unregister_dl);
243