1 // SPDX-License-Identifier: GPL-2.0+
2 /* Microchip Sparx5 Switch driver
4 * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
9 #include "sparx5_port.h"
11 enum sparx5_dcb_apptrust_values
{
12 SPARX5_DCB_APPTRUST_EMPTY
,
13 SPARX5_DCB_APPTRUST_DSCP
,
14 SPARX5_DCB_APPTRUST_PCP
,
15 SPARX5_DCB_APPTRUST_DSCP_PCP
,
16 __SPARX5_DCB_APPTRUST_MAX
19 static const struct sparx5_dcb_apptrust
{
20 u8 selectors
[IEEE_8021QAZ_APP_SEL_MAX
+ 1];
22 } *sparx5_port_apptrust
[SPX5_PORTS
];
24 static const char *sparx5_dcb_apptrust_names
[__SPARX5_DCB_APPTRUST_MAX
] = {
25 [SPARX5_DCB_APPTRUST_EMPTY
] = "empty",
26 [SPARX5_DCB_APPTRUST_DSCP
] = "dscp",
27 [SPARX5_DCB_APPTRUST_PCP
] = "pcp",
28 [SPARX5_DCB_APPTRUST_DSCP_PCP
] = "dscp pcp"
31 /* Sparx5 supported apptrust policies */
32 static const struct sparx5_dcb_apptrust
33 sparx5_dcb_apptrust_policies
[__SPARX5_DCB_APPTRUST_MAX
] = {
34 /* Empty *must* be first */
35 [SPARX5_DCB_APPTRUST_EMPTY
] = { { 0 }, 0 },
36 [SPARX5_DCB_APPTRUST_DSCP
] = { { IEEE_8021QAZ_APP_SEL_DSCP
}, 1 },
37 [SPARX5_DCB_APPTRUST_PCP
] = { { DCB_APP_SEL_PCP
}, 1 },
38 [SPARX5_DCB_APPTRUST_DSCP_PCP
] = { { IEEE_8021QAZ_APP_SEL_DSCP
,
39 DCB_APP_SEL_PCP
}, 2 },
42 /* Validate app entry.
44 * Check for valid selectors and valid protocol and priority ranges.
46 static int sparx5_dcb_app_validate(struct net_device
*dev
,
47 const struct dcb_app
*app
)
51 switch (app
->selector
) {
52 /* Default priority checks */
53 case IEEE_8021QAZ_APP_SEL_ETHERTYPE
:
54 if (app
->protocol
!= 0)
56 else if (app
->priority
>= SPX5_PRIOS
)
60 case IEEE_8021QAZ_APP_SEL_DSCP
:
61 if (app
->protocol
>= SPARX5_PORT_QOS_DSCP_COUNT
)
63 else if (app
->priority
>= SPX5_PRIOS
)
68 if (app
->protocol
>= SPARX5_PORT_QOS_PCP_DEI_COUNT
)
70 else if (app
->priority
>= SPX5_PRIOS
)
79 netdev_err(dev
, "Invalid entry: %d:%d\n", app
->protocol
,
85 /* Validate apptrust configuration.
87 * Return index of supported apptrust configuration if valid, otherwise return
90 static int sparx5_dcb_apptrust_validate(struct net_device
*dev
, u8
*selectors
,
91 int nselectors
, int *err
)
96 for (i
= 0; i
< ARRAY_SIZE(sparx5_dcb_apptrust_policies
); i
++) {
97 if (sparx5_dcb_apptrust_policies
[i
].nselectors
!= nselectors
)
100 for (ii
= 0; ii
< nselectors
; ii
++) {
101 if (sparx5_dcb_apptrust_policies
[i
].selectors
[ii
] !=
111 /* Requested trust configuration is not supported */
113 netdev_err(dev
, "Valid apptrust configurations are:\n");
114 for (i
= 0; i
< ARRAY_SIZE(sparx5_dcb_apptrust_names
); i
++)
115 pr_info("order: %s\n", sparx5_dcb_apptrust_names
[i
]);
122 static bool sparx5_dcb_apptrust_contains(int portno
, u8 selector
)
124 const struct sparx5_dcb_apptrust
*conf
= sparx5_port_apptrust
[portno
];
127 for (i
= 0; i
< conf
->nselectors
; i
++)
128 if (conf
->selectors
[i
] == selector
)
134 static int sparx5_dcb_app_update(struct net_device
*dev
)
136 struct dcb_ieee_app_prio_map dscp_rewr_map
= {0};
137 struct dcb_rewr_prio_pcp_map pcp_rewr_map
= {0};
138 struct sparx5_port
*port
= netdev_priv(dev
);
139 struct sparx5_port_qos_dscp_map
*dscp_map
;
140 struct sparx5_port_qos_pcp_map
*pcp_map
;
141 struct sparx5_port_qos qos
= {0};
142 struct dcb_app app_itr
= {0};
143 int portno
= port
->portno
;
144 bool dscp_rewr
= false;
145 bool pcp_rewr
= false;
149 dscp_map
= &qos
.dscp
.map
;
150 pcp_map
= &qos
.pcp
.map
;
152 /* Get default prio. */
153 qos
.default_prio
= dcb_ieee_getapp_default_prio_mask(dev
);
154 if (qos
.default_prio
)
155 qos
.default_prio
= fls(qos
.default_prio
) - 1;
157 /* Get dscp ingress mapping */
158 for (i
= 0; i
< ARRAY_SIZE(dscp_map
->map
); i
++) {
159 app_itr
.selector
= IEEE_8021QAZ_APP_SEL_DSCP
;
160 app_itr
.protocol
= i
;
161 dscp_map
->map
[i
] = dcb_getapp(dev
, &app_itr
);
164 /* Get pcp ingress mapping */
165 for (i
= 0; i
< ARRAY_SIZE(pcp_map
->map
); i
++) {
166 app_itr
.selector
= DCB_APP_SEL_PCP
;
167 app_itr
.protocol
= i
;
168 pcp_map
->map
[i
] = dcb_getapp(dev
, &app_itr
);
171 /* Get pcp rewrite mapping */
172 dcb_getrewr_prio_pcp_mask_map(dev
, &pcp_rewr_map
);
173 for (i
= 0; i
< ARRAY_SIZE(pcp_rewr_map
.map
); i
++) {
174 if (!pcp_rewr_map
.map
[i
])
177 qos
.pcp_rewr
.map
.map
[i
] = fls(pcp_rewr_map
.map
[i
]) - 1;
180 /* Get dscp rewrite mapping */
181 dcb_getrewr_prio_dscp_mask_map(dev
, &dscp_rewr_map
);
182 for (i
= 0; i
< ARRAY_SIZE(dscp_rewr_map
.map
); i
++) {
183 if (!dscp_rewr_map
.map
[i
])
186 /* The rewrite table of the switch has 32 entries; one for each
187 * priority for each DP level. Currently, the rewrite map does
188 * not indicate DP level, so we map classified QoS class to
189 * classified DSCP, for each classified DP level. Rewrite of
190 * DSCP is only enabled, if we have active mappings.
193 dscp
= fls64(dscp_rewr_map
.map
[i
]) - 1;
194 qos
.dscp_rewr
.map
.map
[i
] = dscp
; /* DP 0 */
195 qos
.dscp_rewr
.map
.map
[i
+ 8] = dscp
; /* DP 1 */
196 qos
.dscp_rewr
.map
.map
[i
+ 16] = dscp
; /* DP 2 */
197 qos
.dscp_rewr
.map
.map
[i
+ 24] = dscp
; /* DP 3 */
200 /* Enable use of pcp for queue classification ? */
201 if (sparx5_dcb_apptrust_contains(portno
, DCB_APP_SEL_PCP
)) {
202 qos
.pcp
.qos_enable
= true;
203 qos
.pcp
.dp_enable
= qos
.pcp
.qos_enable
;
204 /* Enable rewrite of PCP and DEI if PCP is trusted *and* rewrite
205 * table is not empty.
208 qos
.pcp_rewr
.enable
= true;
211 /* Enable use of dscp for queue classification ? */
212 if (sparx5_dcb_apptrust_contains(portno
, IEEE_8021QAZ_APP_SEL_DSCP
)) {
213 qos
.dscp
.qos_enable
= true;
214 qos
.dscp
.dp_enable
= qos
.dscp
.qos_enable
;
216 /* Do not enable rewrite if no mappings are active, as
217 * classified DSCP will then be zero for all classified
218 * QoS class and DP combinations.
220 qos
.dscp_rewr
.enable
= true;
223 return sparx5_port_qos_set(port
, &qos
);
226 /* Set or delete DSCP app entry.
228 * DSCP mapping is global for all ports, so set and delete app entries are
229 * replicated for each port.
231 static int sparx5_dcb_ieee_dscp_setdel(struct net_device
*dev
,
233 int (*setdel
)(struct net_device
*,
236 struct sparx5_port
*port
= netdev_priv(dev
);
237 struct sparx5
*sparx5
= port
->sparx5
;
238 struct sparx5_port
*port_itr
;
241 for (i
= 0; i
< sparx5
->data
->consts
->n_ports
; i
++) {
242 port_itr
= port
->sparx5
->ports
[i
];
245 err
= setdel(port_itr
->ndev
, app
);
253 static int sparx5_dcb_ieee_delapp(struct net_device
*dev
, struct dcb_app
*app
)
257 if (app
->selector
== IEEE_8021QAZ_APP_SEL_DSCP
)
258 err
= sparx5_dcb_ieee_dscp_setdel(dev
, app
, dcb_ieee_delapp
);
260 err
= dcb_ieee_delapp(dev
, app
);
265 return sparx5_dcb_app_update(dev
);
268 static int sparx5_dcb_ieee_setapp(struct net_device
*dev
, struct dcb_app
*app
)
270 struct dcb_app app_itr
;
274 err
= sparx5_dcb_app_validate(dev
, app
);
278 /* Delete current mapping, if it exists */
279 prio
= dcb_getapp(dev
, app
);
282 app_itr
.priority
= prio
;
283 sparx5_dcb_ieee_delapp(dev
, &app_itr
);
286 if (app
->selector
== IEEE_8021QAZ_APP_SEL_DSCP
)
287 err
= sparx5_dcb_ieee_dscp_setdel(dev
, app
, dcb_ieee_setapp
);
289 err
= dcb_ieee_setapp(dev
, app
);
294 sparx5_dcb_app_update(dev
);
300 static int sparx5_dcb_setapptrust(struct net_device
*dev
, u8
*selectors
,
303 struct sparx5_port
*port
= netdev_priv(dev
);
306 idx
= sparx5_dcb_apptrust_validate(dev
, selectors
, nselectors
, &err
);
310 sparx5_port_apptrust
[port
->portno
] = &sparx5_dcb_apptrust_policies
[idx
];
312 return sparx5_dcb_app_update(dev
);
315 static int sparx5_dcb_getapptrust(struct net_device
*dev
, u8
*selectors
,
318 struct sparx5_port
*port
= netdev_priv(dev
);
319 const struct sparx5_dcb_apptrust
*trust
;
321 trust
= sparx5_port_apptrust
[port
->portno
];
323 memcpy(selectors
, trust
->selectors
, trust
->nselectors
);
324 *nselectors
= trust
->nselectors
;
329 static int sparx5_dcb_delrewr(struct net_device
*dev
, struct dcb_app
*app
)
333 if (app
->selector
== IEEE_8021QAZ_APP_SEL_DSCP
)
334 err
= sparx5_dcb_ieee_dscp_setdel(dev
, app
, dcb_delrewr
);
336 err
= dcb_delrewr(dev
, app
);
341 return sparx5_dcb_app_update(dev
);
344 static int sparx5_dcb_setrewr(struct net_device
*dev
, struct dcb_app
*app
)
346 struct dcb_app app_itr
;
350 err
= sparx5_dcb_app_validate(dev
, app
);
354 /* Delete current mapping, if it exists. */
355 proto
= dcb_getrewr(dev
, app
);
358 app_itr
.protocol
= proto
;
359 sparx5_dcb_delrewr(dev
, &app_itr
);
362 if (app
->selector
== IEEE_8021QAZ_APP_SEL_DSCP
)
363 err
= sparx5_dcb_ieee_dscp_setdel(dev
, app
, dcb_setrewr
);
365 err
= dcb_setrewr(dev
, app
);
370 sparx5_dcb_app_update(dev
);
376 const struct dcbnl_rtnl_ops sparx5_dcbnl_ops
= {
377 .ieee_setapp
= sparx5_dcb_ieee_setapp
,
378 .ieee_delapp
= sparx5_dcb_ieee_delapp
,
379 .dcbnl_setapptrust
= sparx5_dcb_setapptrust
,
380 .dcbnl_getapptrust
= sparx5_dcb_getapptrust
,
381 .dcbnl_setrewr
= sparx5_dcb_setrewr
,
382 .dcbnl_delrewr
= sparx5_dcb_delrewr
,
385 int sparx5_dcb_init(struct sparx5
*sparx5
)
387 struct sparx5_port
*port
;
390 for (i
= 0; i
< sparx5
->data
->consts
->n_ports
; i
++) {
391 port
= sparx5
->ports
[i
];
394 port
->ndev
->dcbnl_ops
= &sparx5_dcbnl_ops
;
395 /* Initialize [dscp, pcp] default trust */
396 sparx5_port_apptrust
[port
->portno
] =
397 &sparx5_dcb_apptrust_policies
398 [SPARX5_DCB_APPTRUST_DSCP_PCP
];
400 /* Enable DSCP classification based on classified QoS class and
401 * DP, for all DSCP values, for all ports.
403 sparx5_port_qos_dscp_rewr_mode_set(port
,
404 SPARX5_PORT_REW_DSCP_ALL
);