xref: /linux/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c (revision 8f7aa3d3c7323f4ca2768a9e74ebbe359c4f8f88)
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 */
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 
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 
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 
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 
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 
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
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 
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 
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 
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