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