820 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (c) 2024 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>3 4#include <linux/dsa/ksz_common.h>5#include <net/dsa.h>6#include <net/dscp.h>7#include <net/ieee8021q.h>8 9#include "ksz_common.h"10#include "ksz_dcb.h"11#include "ksz8.h"12 13#define KSZ8_REG_PORT_1_CTRL_0 0x1014#define KSZ8_PORT_DIFFSERV_ENABLE BIT(6)15#define KSZ8_PORT_802_1P_ENABLE BIT(5)16#define KSZ8_PORT_BASED_PRIO_M GENMASK(4, 3)17 18#define KSZ88X3_REG_TOS_DSCP_CTRL 0x6019#define KSZ8765_REG_TOS_DSCP_CTRL 0x9020 21#define KSZ9477_REG_SW_MAC_TOS_CTRL 0x033e22#define KSZ9477_SW_TOS_DSCP_REMAP BIT(0)23#define KSZ9477_SW_TOS_DSCP_DEFAULT_PRIO_M GENMASK(5, 3)24 25#define KSZ9477_REG_DIFFSERV_PRIO_MAP 0x034026 27#define KSZ9477_REG_PORT_MRI_PRIO_CTRL 0x080128#define KSZ9477_PORT_HIGHEST_PRIO BIT(7)29#define KSZ9477_PORT_OR_PRIO BIT(6)30#define KSZ9477_PORT_MAC_PRIO_ENABLE BIT(4)31#define KSZ9477_PORT_VLAN_PRIO_ENABLE BIT(3)32#define KSZ9477_PORT_802_1P_PRIO_ENABLE BIT(2)33#define KSZ9477_PORT_DIFFSERV_PRIO_ENABLE BIT(1)34#define KSZ9477_PORT_ACL_PRIO_ENABLE BIT(0)35 36#define KSZ9477_REG_PORT_MRI_MAC_CTRL 0x080237#define KSZ9477_PORT_BASED_PRIO_M GENMASK(2, 0)38 39struct ksz_apptrust_map {40 u8 apptrust;41 u8 bit;42};43 44static const struct ksz_apptrust_map ksz8_apptrust_map_to_bit[] = {45 { DCB_APP_SEL_PCP, KSZ8_PORT_802_1P_ENABLE },46 { IEEE_8021QAZ_APP_SEL_DSCP, KSZ8_PORT_DIFFSERV_ENABLE },47};48 49static const struct ksz_apptrust_map ksz9477_apptrust_map_to_bit[] = {50 { DCB_APP_SEL_PCP, KSZ9477_PORT_802_1P_PRIO_ENABLE },51 { IEEE_8021QAZ_APP_SEL_DSCP, KSZ9477_PORT_DIFFSERV_PRIO_ENABLE },52};53 54/* ksz_supported_apptrust[] - Supported apptrust selectors and Priority Order55 * of Internal Priority Map (IPM) sources.56 *57 * This array defines the apptrust selectors supported by the hardware, where58 * the index within the array indicates the priority of the selector - lower59 * indices correspond to higher priority. This fixed priority scheme is due to60 * the hardware's design, which does not support configurable priority among61 * different priority sources.62 *63 * The priority sources, including Tail Tag, ACL, VLAN PCP and DSCP are ordered64 * by the hardware's fixed logic, as detailed below. The order reflects a65 * non-configurable precedence where certain types of priority information66 * override others:67 *68 * 1. Tail Tag - Highest priority, overrides ACL, VLAN PCP, and DSCP priorities.69 * 2. ACL - Overrides VLAN PCP and DSCP priorities.70 * 3. VLAN PCP - Overrides DSCP priority.71 * 4. DSCP - Lowest priority, does not override any other priority source.72 *73 * In this context, the array's lower index (higher priority) for74 * 'DCB_APP_SEL_PCP' suggests its relative priority over75 * 'IEEE_8021QAZ_APP_SEL_DSCP' within the system's fixed priority scheme.76 *77 * DCB_APP_SEL_PCP - Priority Code Point selector78 * IEEE_8021QAZ_APP_SEL_DSCP - Differentiated Services Code Point selector79 */80static const u8 ksz_supported_apptrust[] = {81 DCB_APP_SEL_PCP,82 IEEE_8021QAZ_APP_SEL_DSCP,83};84 85static const char * const ksz_supported_apptrust_variants[] = {86 "empty", "dscp", "pcp", "dscp pcp"87};88 89static void ksz_get_default_port_prio_reg(struct ksz_device *dev, int *reg,90 u8 *mask, int *shift)91{92 if (is_ksz8(dev)) {93 *reg = KSZ8_REG_PORT_1_CTRL_0;94 *mask = KSZ8_PORT_BASED_PRIO_M;95 *shift = __bf_shf(KSZ8_PORT_BASED_PRIO_M);96 } else {97 *reg = KSZ9477_REG_PORT_MRI_MAC_CTRL;98 *mask = KSZ9477_PORT_BASED_PRIO_M;99 *shift = __bf_shf(KSZ9477_PORT_BASED_PRIO_M);100 }101}102 103/**104 * ksz_get_dscp_prio_reg - Retrieves the DSCP-to-priority-mapping register105 * @dev: Pointer to the KSZ switch device structure106 * @reg: Pointer to the register address to be set107 * @per_reg: Pointer to the number of DSCP values per register108 * @mask: Pointer to the mask to be set109 *110 * This function retrieves the DSCP to priority mapping register, the number of111 * DSCP values per register, and the mask to be set.112 */113static void ksz_get_dscp_prio_reg(struct ksz_device *dev, int *reg,114 int *per_reg, u8 *mask)115{116 if (ksz_is_ksz87xx(dev) || ksz_is_8895_family(dev)) {117 *reg = KSZ8765_REG_TOS_DSCP_CTRL;118 *per_reg = 4;119 *mask = GENMASK(1, 0);120 } else if (ksz_is_ksz88x3(dev)) {121 *reg = KSZ88X3_REG_TOS_DSCP_CTRL;122 *per_reg = 4;123 *mask = GENMASK(1, 0);124 } else {125 *reg = KSZ9477_REG_DIFFSERV_PRIO_MAP;126 *per_reg = 2;127 *mask = GENMASK(2, 0);128 }129}130 131/**132 * ksz_get_apptrust_map_and_reg - Retrieves the apptrust map and register133 * @dev: Pointer to the KSZ switch device structure134 * @map: Pointer to the apptrust map to be set135 * @reg: Pointer to the register address to be set136 * @mask: Pointer to the mask to be set137 *138 * This function retrieves the apptrust map and register address for the139 * apptrust configuration.140 */141static void ksz_get_apptrust_map_and_reg(struct ksz_device *dev,142 const struct ksz_apptrust_map **map,143 int *reg, u8 *mask)144{145 if (is_ksz8(dev)) {146 *map = ksz8_apptrust_map_to_bit;147 *reg = KSZ8_REG_PORT_1_CTRL_0;148 *mask = KSZ8_PORT_DIFFSERV_ENABLE | KSZ8_PORT_802_1P_ENABLE;149 } else {150 *map = ksz9477_apptrust_map_to_bit;151 *reg = KSZ9477_REG_PORT_MRI_PRIO_CTRL;152 *mask = KSZ9477_PORT_802_1P_PRIO_ENABLE |153 KSZ9477_PORT_DIFFSERV_PRIO_ENABLE;154 }155}156 157/**158 * ksz_port_get_default_prio - Retrieves the default priority for a port on a159 * KSZ switch160 * @ds: Pointer to the DSA switch structure161 * @port: Port number from which to get the default priority162 *163 * This function fetches the default priority for the specified port on a KSZ164 * switch.165 *166 * Return: The default priority of the port on success, or a negative error167 * code on failure.168 */169int ksz_port_get_default_prio(struct dsa_switch *ds, int port)170{171 struct ksz_device *dev = ds->priv;172 int ret, reg, shift;173 u8 data, mask;174 175 ksz_get_default_port_prio_reg(dev, ®, &mask, &shift);176 177 ret = ksz_pread8(dev, port, reg, &data);178 if (ret)179 return ret;180 181 return (data & mask) >> shift;182}183 184/**185 * ksz88x3_port_set_default_prio_quirks - Quirks for default priority186 * @dev: Pointer to the KSZ switch device structure187 * @port: Port number for which to set the default priority188 * @prio: Priority value to set189 *190 * This function implements quirks for setting the default priority on KSZ88x3191 * devices. On Port 2, no other priority providers are working192 * except of PCP. So, configuring default priority on Port 2 is not possible.193 * On Port 1, it is not possible to configure port priority if PCP194 * apptrust on Port 2 is disabled. Since we disable multiple queues on the195 * switch to disable PCP on Port 2, we need to ensure that the default priority196 * configuration on Port 1 is in agreement with the configuration on Port 2.197 *198 * Return: 0 on success, or a negative error code on failure199 */200static int ksz88x3_port_set_default_prio_quirks(struct ksz_device *dev, int port,201 u8 prio)202{203 if (!prio)204 return 0;205 206 if (port == KSZ_PORT_2) {207 dev_err(dev->dev, "Port priority configuration is not working on Port 2\n");208 return -EINVAL;209 } else if (port == KSZ_PORT_1) {210 u8 port2_data;211 int ret;212 213 ret = ksz_pread8(dev, KSZ_PORT_2, KSZ8_REG_PORT_1_CTRL_0,214 &port2_data);215 if (ret)216 return ret;217 218 if (!(port2_data & KSZ8_PORT_802_1P_ENABLE)) {219 dev_err(dev->dev, "Not possible to configure port priority on Port 1 if PCP apptrust on Port 2 is disabled\n");220 return -EINVAL;221 }222 }223 224 return 0;225}226 227/**228 * ksz_port_set_default_prio - Sets the default priority for a port on a KSZ229 * switch230 * @ds: Pointer to the DSA switch structure231 * @port: Port number for which to set the default priority232 * @prio: Priority value to set233 *234 * This function sets the default priority for the specified port on a KSZ235 * switch.236 *237 * Return: 0 on success, or a negative error code on failure.238 */239int ksz_port_set_default_prio(struct dsa_switch *ds, int port, u8 prio)240{241 struct ksz_device *dev = ds->priv;242 int reg, shift, ret;243 u8 mask;244 245 if (prio >= dev->info->num_ipms)246 return -EINVAL;247 248 if (ksz_is_ksz88x3(dev)) {249 ret = ksz88x3_port_set_default_prio_quirks(dev, port, prio);250 if (ret)251 return ret;252 }253 254 ksz_get_default_port_prio_reg(dev, ®, &mask, &shift);255 256 return ksz_prmw8(dev, port, reg, mask, (prio << shift) & mask);257}258 259/**260 * ksz_port_get_dscp_prio - Retrieves the priority for a DSCP value on a KSZ261 * switch262 * @ds: Pointer to the DSA switch structure263 * @port: Port number for which to get the priority264 * @dscp: DSCP value for which to get the priority265 *266 * This function fetches the priority value from switch global DSCP-to-priorty267 * mapping table for the specified DSCP value.268 *269 * Return: The priority value for the DSCP on success, or a negative error270 * code on failure.271 */272int ksz_port_get_dscp_prio(struct dsa_switch *ds, int port, u8 dscp)273{274 struct ksz_device *dev = ds->priv;275 int reg, per_reg, ret, shift;276 u8 data, mask;277 278 ksz_get_dscp_prio_reg(dev, ®, &per_reg, &mask);279 280 /* If DSCP remapping is disabled, DSCP bits 3-5 are used as Internal281 * Priority Map (IPM)282 */283 if (!is_ksz8(dev)) {284 ret = ksz_read8(dev, KSZ9477_REG_SW_MAC_TOS_CTRL, &data);285 if (ret)286 return ret;287 288 /* If DSCP remapping is disabled, DSCP bits 3-5 are used as289 * Internal Priority Map (IPM)290 */291 if (!(data & KSZ9477_SW_TOS_DSCP_REMAP))292 return FIELD_GET(KSZ9477_SW_TOS_DSCP_DEFAULT_PRIO_M,293 dscp);294 }295 296 /* In case DSCP remapping is enabled, we need to write the DSCP to297 * priority mapping table.298 */299 reg += dscp / per_reg;300 ret = ksz_read8(dev, reg, &data);301 if (ret)302 return ret;303 304 shift = (dscp % per_reg) * (8 / per_reg);305 306 return (data >> shift) & mask;307}308 309/**310 * ksz_set_global_dscp_entry - Sets the global DSCP-to-priority mapping entry311 * @dev: Pointer to the KSZ switch device structure312 * @dscp: DSCP value for which to set the priority313 * @ipm: Priority value to set314 *315 * This function sets the global DSCP-to-priority mapping entry for the316 * specified DSCP value.317 *318 * Return: 0 on success, or a negative error code on failure.319 */320static int ksz_set_global_dscp_entry(struct ksz_device *dev, u8 dscp, u8 ipm)321{322 int reg, per_reg, shift;323 u8 mask;324 325 ksz_get_dscp_prio_reg(dev, ®, &per_reg, &mask);326 327 shift = (dscp % per_reg) * (8 / per_reg);328 329 return ksz_rmw8(dev, reg + (dscp / per_reg), mask << shift,330 ipm << shift);331}332 333/**334 * ksz_init_global_dscp_map - Initializes the global DSCP-to-priority mapping335 * @dev: Pointer to the KSZ switch device structure336 *337 * This function initializes the global DSCP-to-priority mapping table for the338 * switch.339 *340 * Return: 0 on success, or a negative error code on failure341 */342static int ksz_init_global_dscp_map(struct ksz_device *dev)343{344 int ret, dscp;345 346 /* On KSZ9xxx variants, DSCP remapping is disabled by default.347 * Enable to have, predictable and reproducible behavior across348 * different devices.349 */350 if (!is_ksz8(dev)) {351 ret = ksz_rmw8(dev, KSZ9477_REG_SW_MAC_TOS_CTRL,352 KSZ9477_SW_TOS_DSCP_REMAP,353 KSZ9477_SW_TOS_DSCP_REMAP);354 if (ret)355 return ret;356 }357 358 for (dscp = 0; dscp < DSCP_MAX; dscp++) {359 int ipm, tt;360 361 /* Map DSCP to Traffic Type, which is corresponding to the362 * Internal Priority Map (IPM) in the switch.363 */364 if (!is_ksz8(dev)) {365 ipm = ietf_dscp_to_ieee8021q_tt(dscp);366 } else {367 /* On KSZ8xxx variants we do not have IPM to queue368 * remapping table. We need to convert DSCP to Traffic369 * Type and then to queue.370 */371 tt = ietf_dscp_to_ieee8021q_tt(dscp);372 if (tt < 0)373 return tt;374 375 ipm = ieee8021q_tt_to_tc(tt, dev->info->num_tx_queues);376 }377 378 if (ipm < 0)379 return ipm;380 381 ret = ksz_set_global_dscp_entry(dev, dscp, ipm);382 }383 384 return 0;385}386 387/**388 * ksz_port_add_dscp_prio - Adds a DSCP-to-priority mapping entry for a port on389 * a KSZ switch.390 * @ds: Pointer to the DSA switch structure391 * @port: Port number for which to add the DSCP-to-priority mapping entry392 * @dscp: DSCP value for which to add the priority393 * @prio: Priority value to set394 *395 * Return: 0 on success, or a negative error code on failure396 */397int ksz_port_add_dscp_prio(struct dsa_switch *ds, int port, u8 dscp, u8 prio)398{399 struct ksz_device *dev = ds->priv;400 401 if (prio >= dev->info->num_ipms)402 return -ERANGE;403 404 return ksz_set_global_dscp_entry(dev, dscp, prio);405}406 407/**408 * ksz_port_del_dscp_prio - Deletes a DSCP-to-priority mapping entry for a port409 * on a KSZ switch.410 * @ds: Pointer to the DSA switch structure411 * @port: Port number for which to delete the DSCP-to-priority mapping entry412 * @dscp: DSCP value for which to delete the priority413 * @prio: Priority value to delete414 *415 * Return: 0 on success, or a negative error code on failure416 */417int ksz_port_del_dscp_prio(struct dsa_switch *ds, int port, u8 dscp, u8 prio)418{419 struct ksz_device *dev = ds->priv;420 int ipm;421 422 if (ksz_port_get_dscp_prio(ds, port, dscp) != prio)423 return 0;424 425 if (is_ksz8(dev)) {426 ipm = ieee8021q_tt_to_tc(IEEE8021Q_TT_BE,427 dev->info->num_tx_queues);428 if (ipm < 0)429 return ipm;430 } else {431 ipm = IEEE8021Q_TT_BE;432 }433 434 return ksz_set_global_dscp_entry(dev, dscp, ipm);435}436 437/**438 * ksz_apptrust_error - Prints an error message for an invalid apptrust selector439 * @dev: Pointer to the KSZ switch device structure440 *441 * This function prints an error message when an invalid apptrust selector is442 * provided.443 */444static void ksz_apptrust_error(struct ksz_device *dev)445{446 char supported_apptrust_variants[64];447 int i;448 449 supported_apptrust_variants[0] = '\0';450 for (i = 0; i < ARRAY_SIZE(ksz_supported_apptrust_variants); i++) {451 if (i > 0)452 strlcat(supported_apptrust_variants, ", ",453 sizeof(supported_apptrust_variants));454 strlcat(supported_apptrust_variants,455 ksz_supported_apptrust_variants[i],456 sizeof(supported_apptrust_variants));457 }458 459 dev_err(dev->dev, "Invalid apptrust selector or priority order. Supported: %s\n",460 supported_apptrust_variants);461}462 463/**464 * ksz_port_set_apptrust_validate - Validates the apptrust selectors465 * @dev: Pointer to the KSZ switch device structure466 * @port: Port number for which to set the apptrust selectors467 * @sel: Array of apptrust selectors to validate468 * @nsel: Number of apptrust selectors in the array469 *470 * This function validates the apptrust selectors provided and ensures that471 * they are in the correct order.472 *473 * This family of switches supports two apptrust selectors: DCB_APP_SEL_PCP and474 * IEEE_8021QAZ_APP_SEL_DSCP. The priority order of the selectors is fixed and475 * cannot be changed. The order is as follows:476 * 1. DCB_APP_SEL_PCP - Priority Code Point selector (highest priority)477 * 2. IEEE_8021QAZ_APP_SEL_DSCP - Differentiated Services Code Point selector478 * (lowest priority)479 *480 * Return: 0 on success, or a negative error code on failure481 */482static int ksz_port_set_apptrust_validate(struct ksz_device *dev, int port,483 const u8 *sel, int nsel)484{485 int i, j, found;486 int j_prev = 0;487 488 /* Iterate through the requested selectors */489 for (i = 0; i < nsel; i++) {490 found = 0;491 492 /* Check if the current selector is supported by the hardware */493 for (j = 0; j < sizeof(ksz_supported_apptrust); j++) {494 if (sel[i] != ksz_supported_apptrust[j])495 continue;496 497 found = 1;498 499 /* Ensure that no higher priority selector (lower index)500 * precedes a lower priority one501 */502 if (i > 0 && j <= j_prev)503 goto err_sel_not_vaild;504 505 j_prev = j;506 break;507 }508 509 if (!found)510 goto err_sel_not_vaild;511 }512 513 return 0;514 515err_sel_not_vaild:516 ksz_apptrust_error(dev);517 518 return -EINVAL;519}520 521/**522 * ksz88x3_port1_apptrust_quirk - Quirk for apptrust configuration on Port 1523 * of KSZ88x3 devices524 * @dev: Pointer to the KSZ switch device structure525 * @port: Port number for which to set the apptrust selectors526 * @reg: Register address for the apptrust configuration527 * @port1_data: Data to set for the apptrust configuration528 *529 * This function implements a quirk for apptrust configuration on Port 1 of530 * KSZ88x3 devices. It ensures that apptrust configuration on Port 1 is not531 * possible if PCP apptrust on Port 2 is disabled. This is because the Port 2532 * seems to be permanently hardwired to PCP classification, so we need to533 * do Port 1 configuration always in agreement with Port 2 configuration.534 *535 * Return: 0 on success, or a negative error code on failure536 */537static int ksz88x3_port1_apptrust_quirk(struct ksz_device *dev, int port,538 int reg, u8 port1_data)539{540 u8 port2_data;541 int ret;542 543 /* If no apptrust is requested for Port 1, no need to care about Port 2544 * configuration.545 */546 if (!(port1_data & (KSZ8_PORT_802_1P_ENABLE | KSZ8_PORT_DIFFSERV_ENABLE)))547 return 0;548 549 /* We got request to enable any apptrust on Port 1. To make it possible,550 * we need to enable multiple queues on the switch. If we enable551 * multiqueue support, PCP classification on Port 2 will be552 * automatically activated by HW.553 */554 ret = ksz_pread8(dev, KSZ_PORT_2, reg, &port2_data);555 if (ret)556 return ret;557 558 /* If KSZ8_PORT_802_1P_ENABLE bit is set on Port 2, the driver showed559 * the interest in PCP classification on Port 2. In this case,560 * multiqueue support is enabled and we can enable any apptrust on561 * Port 1.562 * If KSZ8_PORT_802_1P_ENABLE bit is not set on Port 2, the PCP563 * classification on Port 2 is still active, but the driver disabled564 * multiqueue support and made frame prioritization inactive for565 * all ports. In this case, we can't enable any apptrust on Port 1.566 */567 if (!(port2_data & KSZ8_PORT_802_1P_ENABLE)) {568 dev_err(dev->dev, "Not possible to enable any apptrust on Port 1 if PCP apptrust on Port 2 is disabled\n");569 return -EINVAL;570 }571 572 return 0;573}574 575/**576 * ksz88x3_port2_apptrust_quirk - Quirk for apptrust configuration on Port 2577 * of KSZ88x3 devices578 * @dev: Pointer to the KSZ switch device structure579 * @port: Port number for which to set the apptrust selectors580 * @reg: Register address for the apptrust configuration581 * @port2_data: Data to set for the apptrust configuration582 *583 * This function implements a quirk for apptrust configuration on Port 2 of584 * KSZ88x3 devices. It ensures that DSCP apptrust is not working on Port 2 and585 * that it is not possible to disable PCP on Port 2. The only way to disable PCP586 * on Port 2 is to disable multiple queues on the switch.587 *588 * Return: 0 on success, or a negative error code on failure589 */590static int ksz88x3_port2_apptrust_quirk(struct ksz_device *dev, int port,591 int reg, u8 port2_data)592{593 struct dsa_switch *ds = dev->ds;594 u8 port1_data;595 int ret;596 597 /* First validate Port 2 configuration. DiffServ/DSCP is not working598 * on this port.599 */600 if (port2_data & KSZ8_PORT_DIFFSERV_ENABLE) {601 dev_err(dev->dev, "DSCP apptrust is not working on Port 2\n");602 return -EINVAL;603 }604 605 /* If PCP support is requested, we need to enable all queues on the606 * switch to make PCP priority working on Port 2.607 */608 if (port2_data & KSZ8_PORT_802_1P_ENABLE)609 return ksz8_all_queues_split(dev, dev->info->num_tx_queues);610 611 /* We got request to disable PCP priority on Port 2.612 * Now, we need to compare Port 2 configuration with Port 1613 * configuration.614 */615 ret = ksz_pread8(dev, KSZ_PORT_1, reg, &port1_data);616 if (ret)617 return ret;618 619 /* If Port 1 has any apptrust enabled, we can't disable multiple queues620 * on the switch, so we can't disable PCP on Port 2.621 */622 if (port1_data & (KSZ8_PORT_802_1P_ENABLE | KSZ8_PORT_DIFFSERV_ENABLE)) {623 dev_err(dev->dev, "Not possible to disable PCP on Port 2 if any apptrust is enabled on Port 1\n");624 return -EINVAL;625 }626 627 /* Now we need to ensure that default priority on Port 1 is set to 0628 * otherwise we can't disable multiqueue support on the switch.629 */630 ret = ksz_port_get_default_prio(ds, KSZ_PORT_1);631 if (ret < 0) {632 return ret;633 } else if (ret) {634 dev_err(dev->dev, "Not possible to disable PCP on Port 2 if non zero default priority is set on Port 1\n");635 return -EINVAL;636 }637 638 /* Port 1 has no apptrust or default priority set and we got request to639 * disable PCP on Port 2. We can disable multiqueue support to disable640 * PCP on Port 2.641 */642 return ksz8_all_queues_split(dev, 1);643}644 645/**646 * ksz88x3_port_apptrust_quirk - Quirk for apptrust configuration on KSZ88x3647 * devices648 * @dev: Pointer to the KSZ switch device structure649 * @port: Port number for which to set the apptrust selectors650 * @reg: Register address for the apptrust configuration651 * @data: Data to set for the apptrust configuration652 *653 * This function implements a quirk for apptrust configuration on KSZ88x3654 * devices. It ensures that apptrust configuration on Port 1 and655 * Port 2 is done in agreement with each other.656 *657 * Return: 0 on success, or a negative error code on failure658 */659static int ksz88x3_port_apptrust_quirk(struct ksz_device *dev, int port,660 int reg, u8 data)661{662 if (port == KSZ_PORT_1)663 return ksz88x3_port1_apptrust_quirk(dev, port, reg, data);664 else if (port == KSZ_PORT_2)665 return ksz88x3_port2_apptrust_quirk(dev, port, reg, data);666 667 return 0;668}669 670/**671 * ksz_port_set_apptrust - Sets the apptrust selectors for a port on a KSZ672 * switch673 * @ds: Pointer to the DSA switch structure674 * @port: Port number for which to set the apptrust selectors675 * @sel: Array of apptrust selectors to set676 * @nsel: Number of apptrust selectors in the array677 *678 * This function sets the apptrust selectors for the specified port on a KSZ679 * switch.680 *681 * Return: 0 on success, or a negative error code on failure682 */683int ksz_port_set_apptrust(struct dsa_switch *ds, int port,684 const u8 *sel, int nsel)685{686 const struct ksz_apptrust_map *map;687 struct ksz_device *dev = ds->priv;688 int reg, i, ret;689 u8 data = 0;690 u8 mask;691 692 ret = ksz_port_set_apptrust_validate(dev, port, sel, nsel);693 if (ret)694 return ret;695 696 ksz_get_apptrust_map_and_reg(dev, &map, ®, &mask);697 698 for (i = 0; i < nsel; i++) {699 int j;700 701 for (j = 0; j < ARRAY_SIZE(ksz_supported_apptrust); j++) {702 if (sel[i] != ksz_supported_apptrust[j])703 continue;704 705 data |= map[j].bit;706 break;707 }708 }709 710 if (ksz_is_ksz88x3(dev)) {711 ret = ksz88x3_port_apptrust_quirk(dev, port, reg, data);712 if (ret)713 return ret;714 }715 716 return ksz_prmw8(dev, port, reg, mask, data);717}718 719/**720 * ksz_port_get_apptrust - Retrieves the apptrust selectors for a port on a KSZ721 * switch722 * @ds: Pointer to the DSA switch structure723 * @port: Port number for which to get the apptrust selectors724 * @sel: Array to store the apptrust selectors725 * @nsel: Number of apptrust selectors in the array726 *727 * This function fetches the apptrust selectors for the specified port on a KSZ728 * switch.729 *730 * Return: 0 on success, or a negative error code on failure731 */732int ksz_port_get_apptrust(struct dsa_switch *ds, int port, u8 *sel, int *nsel)733{734 const struct ksz_apptrust_map *map;735 struct ksz_device *dev = ds->priv;736 int reg, i, ret;737 u8 data;738 u8 mask;739 740 ksz_get_apptrust_map_and_reg(dev, &map, ®, &mask);741 742 ret = ksz_pread8(dev, port, reg, &data);743 if (ret)744 return ret;745 746 *nsel = 0;747 for (i = 0; i < ARRAY_SIZE(ksz_supported_apptrust); i++) {748 if (data & map[i].bit)749 sel[(*nsel)++] = ksz_supported_apptrust[i];750 }751 752 return 0;753}754 755/**756 * ksz_dcb_init_port - Initializes the DCB configuration for a port on a KSZ757 * @dev: Pointer to the KSZ switch device structure758 * @port: Port number for which to initialize the DCB configuration759 *760 * This function initializes the DCB configuration for the specified port on a761 * KSZ switch. Particular DCB configuration is set for the port, including the762 * default priority and apptrust selectors.763 * The default priority is set to Best Effort, and the apptrust selectors are764 * set to all supported selectors.765 *766 * Return: 0 on success, or a negative error code on failure767 */768int ksz_dcb_init_port(struct ksz_device *dev, int port)769{770 const u8 ksz_default_apptrust[] = { DCB_APP_SEL_PCP };771 int ret, ipm;772 773 if (is_ksz8(dev)) {774 ipm = ieee8021q_tt_to_tc(IEEE8021Q_TT_BE,775 dev->info->num_tx_queues);776 if (ipm < 0)777 return ipm;778 } else {779 ipm = IEEE8021Q_TT_BE;780 }781 782 /* Set the default priority for the port to Best Effort */783 ret = ksz_port_set_default_prio(dev->ds, port, ipm);784 if (ret)785 return ret;786 787 return ksz_port_set_apptrust(dev->ds, port, ksz_default_apptrust,788 ARRAY_SIZE(ksz_default_apptrust));789}790 791/**792 * ksz_dcb_init - Initializes the DCB configuration for a KSZ switch793 * @dev: Pointer to the KSZ switch device structure794 *795 * This function initializes the DCB configuration for a KSZ switch. The global796 * DSCP-to-priority mapping table is initialized.797 *798 * Return: 0 on success, or a negative error code on failure799 */800int ksz_dcb_init(struct ksz_device *dev)801{802 int ret;803 804 ret = ksz_init_global_dscp_map(dev);805 if (ret)806 return ret;807 808 /* Enable 802.1p priority control on Port 2 during switch initialization.809 * This setup is critical for the apptrust functionality on Port 1, which810 * relies on the priority settings of Port 2. Note: Port 1 is naturally811 * configured before Port 2, necessitating this configuration order.812 */813 if (ksz_is_ksz88x3(dev))814 return ksz_prmw8(dev, KSZ_PORT_2, KSZ8_REG_PORT_1_CTRL_0,815 KSZ8_PORT_802_1P_ENABLE,816 KSZ8_PORT_802_1P_ENABLE);817 818 return 0;819}820