brintos

brintos / linux-shallow public Read only

0
0
Text · 24.4 KiB · 30b4a61 Raw
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, &reg, &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, &reg, &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, &reg, &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, &reg, &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, &reg, &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, &reg, &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