xref: /linux/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c (revision cdd30ebb1b9f36159d66f088b61aee264e649d7a)
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 	otx2_alloc_mcam_entries(pfvf, ctx->val.vu16);
45 
46 	return 0;
47 }
48 
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 
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 
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 
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
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 
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 
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 
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