1 // SPDX-License-Identifier: GPL-2.0+ 2 /* Microchip Sparx5 Switch driver 3 * 4 * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries. 5 */ 6 7 #include <net/dcbnl.h> 8 9 #include "sparx5_port.h" 10 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 17 }; 18 19 static const struct sparx5_dcb_apptrust { 20 u8 selectors[IEEE_8021QAZ_APP_SEL_MAX + 1]; 21 int nselectors; 22 } *sparx5_port_apptrust[SPX5_PORTS]; 23 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" 29 }; 30 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 }, 40 }; 41 42 /* Validate app entry. 43 * 44 * Check for valid selectors and valid protocol and priority ranges. 45 */ 46 static int sparx5_dcb_app_validate(struct net_device *dev, 47 const struct dcb_app *app) 48 { 49 int err = 0; 50 51 switch (app->selector) { 52 /* Default priority checks */ 53 case IEEE_8021QAZ_APP_SEL_ETHERTYPE: 54 if (app->protocol != 0) 55 err = -EINVAL; 56 else if (app->priority >= SPX5_PRIOS) 57 err = -ERANGE; 58 break; 59 /* Dscp checks */ 60 case IEEE_8021QAZ_APP_SEL_DSCP: 61 if (app->protocol >= SPARX5_PORT_QOS_DSCP_COUNT) 62 err = -EINVAL; 63 else if (app->priority >= SPX5_PRIOS) 64 err = -ERANGE; 65 break; 66 /* Pcp checks */ 67 case DCB_APP_SEL_PCP: 68 if (app->protocol >= SPARX5_PORT_QOS_PCP_DEI_COUNT) 69 err = -EINVAL; 70 else if (app->priority >= SPX5_PRIOS) 71 err = -ERANGE; 72 break; 73 default: 74 err = -EINVAL; 75 break; 76 } 77 78 if (err) 79 netdev_err(dev, "Invalid entry: %d:%d\n", app->protocol, 80 app->priority); 81 82 return err; 83 } 84 85 /* Validate apptrust configuration. 86 * 87 * Return index of supported apptrust configuration if valid, otherwise return 88 * error. 89 */ 90 static int sparx5_dcb_apptrust_validate(struct net_device *dev, u8 *selectors, 91 int nselectors, int *err) 92 { 93 bool match = false; 94 int i, ii; 95 96 for (i = 0; i < ARRAY_SIZE(sparx5_dcb_apptrust_policies); i++) { 97 if (sparx5_dcb_apptrust_policies[i].nselectors != nselectors) 98 continue; 99 match = true; 100 for (ii = 0; ii < nselectors; ii++) { 101 if (sparx5_dcb_apptrust_policies[i].selectors[ii] != 102 *(selectors + ii)) { 103 match = false; 104 break; 105 } 106 } 107 if (match) 108 break; 109 } 110 111 /* Requested trust configuration is not supported */ 112 if (!match) { 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]); 116 *err = -EOPNOTSUPP; 117 } 118 119 return i; 120 } 121 122 static bool sparx5_dcb_apptrust_contains(int portno, u8 selector) 123 { 124 const struct sparx5_dcb_apptrust *conf = sparx5_port_apptrust[portno]; 125 int i; 126 127 for (i = 0; i < conf->nselectors; i++) 128 if (conf->selectors[i] == selector) 129 return true; 130 131 return false; 132 } 133 134 static int sparx5_dcb_app_update(struct net_device *dev) 135 { 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; 146 u16 dscp; 147 int i; 148 149 dscp_map = &qos.dscp.map; 150 pcp_map = &qos.pcp.map; 151 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; 156 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); 162 } 163 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); 169 } 170 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]) 175 continue; 176 pcp_rewr = true; 177 qos.pcp_rewr.map.map[i] = fls(pcp_rewr_map.map[i]) - 1; 178 } 179 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]) 184 continue; 185 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. 191 */ 192 dscp_rewr = true; 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 */ 198 } 199 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. 206 */ 207 if (pcp_rewr) 208 qos.pcp_rewr.enable = true; 209 } 210 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; 215 if (dscp_rewr) 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. 219 */ 220 qos.dscp_rewr.enable = true; 221 } 222 223 return sparx5_port_qos_set(port, &qos); 224 } 225 226 /* Set or delete DSCP app entry. 227 * 228 * DSCP mapping is global for all ports, so set and delete app entries are 229 * replicated for each port. 230 */ 231 static int sparx5_dcb_ieee_dscp_setdel(struct net_device *dev, 232 struct dcb_app *app, 233 int (*setdel)(struct net_device *, 234 struct dcb_app *)) 235 { 236 struct sparx5_port *port = netdev_priv(dev); 237 struct sparx5 *sparx5 = port->sparx5; 238 struct sparx5_port *port_itr; 239 int err, i; 240 241 for (i = 0; i < sparx5->data->consts->n_ports; i++) { 242 port_itr = port->sparx5->ports[i]; 243 if (!port_itr) 244 continue; 245 err = setdel(port_itr->ndev, app); 246 if (err) 247 return err; 248 } 249 250 return 0; 251 } 252 253 static int sparx5_dcb_ieee_delapp(struct net_device *dev, struct dcb_app *app) 254 { 255 int err; 256 257 if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) 258 err = sparx5_dcb_ieee_dscp_setdel(dev, app, dcb_ieee_delapp); 259 else 260 err = dcb_ieee_delapp(dev, app); 261 262 if (err < 0) 263 return err; 264 265 return sparx5_dcb_app_update(dev); 266 } 267 268 static int sparx5_dcb_ieee_setapp(struct net_device *dev, struct dcb_app *app) 269 { 270 struct dcb_app app_itr; 271 int err = 0; 272 u8 prio; 273 274 err = sparx5_dcb_app_validate(dev, app); 275 if (err) 276 goto out; 277 278 /* Delete current mapping, if it exists */ 279 prio = dcb_getapp(dev, app); 280 if (prio) { 281 app_itr = *app; 282 app_itr.priority = prio; 283 sparx5_dcb_ieee_delapp(dev, &app_itr); 284 } 285 286 if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) 287 err = sparx5_dcb_ieee_dscp_setdel(dev, app, dcb_ieee_setapp); 288 else 289 err = dcb_ieee_setapp(dev, app); 290 291 if (err) 292 goto out; 293 294 sparx5_dcb_app_update(dev); 295 296 out: 297 return err; 298 } 299 300 static int sparx5_dcb_setapptrust(struct net_device *dev, u8 *selectors, 301 int nselectors) 302 { 303 struct sparx5_port *port = netdev_priv(dev); 304 int err = 0, idx; 305 306 idx = sparx5_dcb_apptrust_validate(dev, selectors, nselectors, &err); 307 if (err < 0) 308 return err; 309 310 sparx5_port_apptrust[port->portno] = &sparx5_dcb_apptrust_policies[idx]; 311 312 return sparx5_dcb_app_update(dev); 313 } 314 315 static int sparx5_dcb_getapptrust(struct net_device *dev, u8 *selectors, 316 int *nselectors) 317 { 318 struct sparx5_port *port = netdev_priv(dev); 319 const struct sparx5_dcb_apptrust *trust; 320 321 trust = sparx5_port_apptrust[port->portno]; 322 323 memcpy(selectors, trust->selectors, trust->nselectors); 324 *nselectors = trust->nselectors; 325 326 return 0; 327 } 328 329 static int sparx5_dcb_delrewr(struct net_device *dev, struct dcb_app *app) 330 { 331 int err; 332 333 if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) 334 err = sparx5_dcb_ieee_dscp_setdel(dev, app, dcb_delrewr); 335 else 336 err = dcb_delrewr(dev, app); 337 338 if (err < 0) 339 return err; 340 341 return sparx5_dcb_app_update(dev); 342 } 343 344 static int sparx5_dcb_setrewr(struct net_device *dev, struct dcb_app *app) 345 { 346 struct dcb_app app_itr; 347 int err = 0; 348 u16 proto; 349 350 err = sparx5_dcb_app_validate(dev, app); 351 if (err) 352 goto out; 353 354 /* Delete current mapping, if it exists. */ 355 proto = dcb_getrewr(dev, app); 356 if (proto) { 357 app_itr = *app; 358 app_itr.protocol = proto; 359 sparx5_dcb_delrewr(dev, &app_itr); 360 } 361 362 if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) 363 err = sparx5_dcb_ieee_dscp_setdel(dev, app, dcb_setrewr); 364 else 365 err = dcb_setrewr(dev, app); 366 367 if (err) 368 goto out; 369 370 sparx5_dcb_app_update(dev); 371 372 out: 373 return err; 374 } 375 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, 383 }; 384 385 int sparx5_dcb_init(struct sparx5 *sparx5) 386 { 387 struct sparx5_port *port; 388 int i; 389 390 for (i = 0; i < sparx5->data->consts->n_ports; i++) { 391 port = sparx5->ports[i]; 392 if (!port) 393 continue; 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]; 399 400 /* Enable DSCP classification based on classified QoS class and 401 * DP, for all DSCP values, for all ports. 402 */ 403 sparx5_port_qos_dscp_rewr_mode_set(port, 404 SPARX5_PORT_REW_DSCP_ALL); 405 } 406 407 return 0; 408 } 409