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