Add DCB support to configure app trust sources and default port priority.
Following commands can be used for testing:
dcb apptrust set dev lan1 order pcp dscp
dcb app replace dev lan1 default-prio 3
Since it is not possible to configure DSCP-Prio mapping per port, this
patch provide only ability to read switch global dscp-prio mapping and
way to enable/disable app trust for DSCP.
Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/dsa/microchip/Kconfig | 2 +
drivers/net/dsa/microchip/Makefile | 2 +-
drivers/net/dsa/microchip/ksz_common.c | 12 +-
drivers/net/dsa/microchip/ksz_common.h | 5 +
drivers/net/dsa/microchip/ksz_dcb.c | 533 +++++++++++++++++++++++++
drivers/net/dsa/microchip/ksz_dcb.h | 21 +
6 files changed, 573 insertions(+), 2 deletions(-)
create mode 100644 drivers/net/dsa/microchip/ksz_dcb.c
create mode 100644 drivers/net/dsa/microchip/ksz_dcb.h
diff --git a/drivers/net/dsa/microchip/Kconfig b/drivers/net/dsa/microchip/Kconfig
index 394ca8678d2ba..c1b906c05a025 100644
--- a/drivers/net/dsa/microchip/Kconfig
+++ b/drivers/net/dsa/microchip/Kconfig
@@ -4,6 +4,8 @@ menuconfig NET_DSA_MICROCHIP_KSZ_COMMON
depends on NET_DSA
select NET_DSA_TAG_KSZ
select NET_DSA_TAG_NONE
+ select NET_IEEE8021Q_HELPERS
+ select DCB
help
This driver adds support for Microchip KSZ9477 series switch and
KSZ8795/KSZ88x3 switch chips.
diff --git a/drivers/net/dsa/microchip/Makefile b/drivers/net/dsa/microchip/Makefile
index 49459a50dbc81..1cfba1ec9355a 100644
--- a/drivers/net/dsa/microchip/Makefile
+++ b/drivers/net/dsa/microchip/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON) += ksz_switch.o
-ksz_switch-objs := ksz_common.o
+ksz_switch-objs := ksz_common.o ksz_dcb.o
ksz_switch-objs += ksz9477.o ksz9477_acl.o ksz9477_tc_flower.o
ksz_switch-objs += ksz8795.o
ksz_switch-objs += lan937x_main.o
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index cf81739d91dae..ea2d6f8d381bc 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -28,6 +28,7 @@
#include <net/switchdev.h>
#include "ksz_common.h"
+#include "ksz_dcb.h"
#include "ksz_ptp.h"
#include "ksz8.h"
#include "ksz9477.h"
@@ -2371,6 +2372,10 @@ static int ksz_setup(struct dsa_switch *ds)
goto out_ptp_clock_unregister;
}
+ ret = ksz_dcb_init(dev);
+ if (ret)
+ goto out_ptp_clock_unregister;
+
/* start switch */
regmap_update_bits(ksz_regmap_8(dev), regs[S_START_CTRL],
SW_START, SW_START);
@@ -2698,7 +2703,7 @@ static int ksz_port_setup(struct dsa_switch *ds, int port)
* there is no need to do anything.
*/
- return 0;
+ return ksz_dcb_init_port(dev, port);
}
void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
@@ -3950,6 +3955,11 @@ static const struct dsa_switch_ops ksz_switch_ops = {
.port_setup_tc = ksz_setup_tc,
.get_mac_eee = ksz_get_mac_eee,
.set_mac_eee = ksz_set_mac_eee,
+ .port_get_default_prio = ksz_port_get_default_prio,
+ .port_set_default_prio = ksz_port_set_default_prio,
+ .port_get_dscp_prio = ksz_port_get_dscp_prio,
+ .port_set_apptrust = ksz_port_set_apptrust,
+ .port_get_apptrust = ksz_port_get_apptrust,
};
struct ksz_device *ksz_switch_alloc(struct device *base, void *priv)
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 1bedd240cbbe4..4f48a8347e5de 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -621,6 +621,11 @@ static inline bool ksz_is_ksz88x3(struct ksz_device *dev)
return dev->chip_id == KSZ8830_CHIP_ID;
}
+static inline bool is_ksz8(struct ksz_device *dev)
+{
+ return ksz_is_ksz87xx(dev) || ksz_is_ksz88x3(dev);
+}
+
static inline int is_lan937x(struct ksz_device *dev)
{
return dev->chip_id == LAN9370_CHIP_ID ||
diff --git a/drivers/net/dsa/microchip/ksz_dcb.c b/drivers/net/dsa/microchip/ksz_dcb.c
new file mode 100644
index 0000000000000..527bf10d35dd3
--- /dev/null
+++ b/drivers/net/dsa/microchip/ksz_dcb.c
@@ -0,0 +1,533 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2024 Pengutronix, Oleksij Rempel <[email protected]>
+
+#include <linux/dsa/ksz_common.h>
+#include <net/dsa.h>
+#include <net/dscp.h>
+#include <net/ieee8021q.h>
+
+#include "ksz_common.h"
+#include "ksz_dcb.h"
+#include "ksz8.h"
+
+#define KSZ8_REG_PORT_1_CTRL_0 0x10
+#define KSZ8_PORT_DIFFSERV_ENABLE BIT(6)
+#define KSZ8_PORT_802_1P_ENABLE BIT(5)
+#define KSZ8_PORT_BASED_PRIO_M GENMASK(4, 3)
+
+#define KSZ88X3_REG_TOS_DSCP_CTRL 0x60
+#define KSZ8765_REG_TOS_DSCP_CTRL 0x90
+
+#define KSZ9477_REG_SW_MAC_TOS_CTRL 0x033e
+#define KSZ9477_SW_TOS_DSCP_REMAP BIT(0)
+#define KSZ9477_SW_TOS_DSCP_DEFAULT_PRIO_M GENMASK(5, 3)
+
+#define KSZ9477_REG_DIFFSERV_PRIO_MAP 0x0340
+
+#define KSZ9477_REG_PORT_MRI_PRIO_CTRL 0x0801
+#define KSZ9477_PORT_HIGHEST_PRIO BIT(7)
+#define KSZ9477_PORT_OR_PRIO BIT(6)
+#define KSZ9477_PORT_MAC_PRIO_ENABLE BIT(4)
+#define KSZ9477_PORT_VLAN_PRIO_ENABLE BIT(3)
+#define KSZ9477_PORT_802_1P_PRIO_ENABLE BIT(2)
+#define KSZ9477_PORT_DIFFSERV_PRIO_ENABLE BIT(1)
+#define KSZ9477_PORT_ACL_PRIO_ENABLE BIT(0)
+
+#define KSZ9477_REG_PORT_MRI_MAC_CTRL 0x0802
+#define KSZ9477_PORT_BASED_PRIO_M GENMASK(2, 0)
+
+struct ksz_apptrust_map {
+ u8 apptrust;
+ u8 bit;
+};
+
+static const struct ksz_apptrust_map ksz8_apptrust_map_to_bit[] = {
+ { DCB_APP_SEL_PCP, KSZ8_PORT_802_1P_ENABLE },
+ { IEEE_8021QAZ_APP_SEL_DSCP, KSZ8_PORT_DIFFSERV_ENABLE },
+};
+
+static const struct ksz_apptrust_map ksz9477_apptrust_map_to_bit[] = {
+ { DCB_APP_SEL_PCP, KSZ9477_PORT_802_1P_PRIO_ENABLE },
+ { IEEE_8021QAZ_APP_SEL_DSCP, KSZ9477_PORT_DIFFSERV_PRIO_ENABLE },
+};
+
+/**
+ * ksz_supported_apptrust[] - Supported apptrust selectors and Priority Order
+ * of Internal Priority Value (IPV) sources.
+ *
+ * This array defines the apptrust selectors supported by the hardware, where
+ * the index within the array indicates the priority of the selector - lower
+ * indices correspond to higher priority. This fixed priority scheme is due to
+ * the hardware's design, which does not support configurable priority among
+ * different priority sources.
+ *
+ * The priority sources, including Tail Tag, ACL, VLAN PCP and DSCP are ordered
+ * by the hardware's fixed logic, as detailed below. The order reflects a
+ * non-configurable precedence where certain types of priority information
+ * override others:
+ *
+ * 1. Tail Tag - Highest priority, overrides ACL, VLAN PCP, and DSCP priorities.
+ * 2. ACL - Overrides VLAN PCP and DSCP priorities.
+ * 3. VLAN PCP - Overrides DSCP priority.
+ * 4. DSCP - Lowest priority, does not override any other priority source.
+ *
+ * In this context, the array's lower index (higher priority) for
+ * 'DCB_APP_SEL_PCP' suggests its relative priority over
+ * 'IEEE_8021QAZ_APP_SEL_DSCP' within the system's fixed priority scheme.
+ *
+ * DCB_APP_SEL_PCP - Priority Code Point selector
+ * IEEE_8021QAZ_APP_SEL_DSCP - Differentiated Services Code Point selector
+ */
+static const u8 ksz_supported_apptrust[] = {
+ DCB_APP_SEL_PCP,
+ IEEE_8021QAZ_APP_SEL_DSCP,
+};
+
+static const u8 ksz8_port2_supported_apptrust[] = {
+ DCB_APP_SEL_PCP,
+};
+
+static const char * const ksz_supported_apptrust_variants[] = {
+ "empty", "dscp", "pcp", "dscp pcp"
+};
+
+static void ksz_get_defult_port_prio_reg(struct ksz_device *dev, int *reg,
+ u8 *mask, int *shift)
+{
+ if (is_ksz8(dev)) {
+ *reg = KSZ8_REG_PORT_1_CTRL_0;
+ *mask = KSZ8_PORT_BASED_PRIO_M;
+ *shift = __bf_shf(KSZ8_PORT_BASED_PRIO_M);
+ } else {
+ *reg = KSZ9477_REG_PORT_MRI_MAC_CTRL;
+ *mask = KSZ9477_PORT_BASED_PRIO_M;
+ *shift = __bf_shf(KSZ9477_PORT_BASED_PRIO_M);
+ }
+}
+
+/**
+ * ksz_port_get_default_prio - Retrieves the default priority for a port on a
+ * KSZ switch
+ * @ds: Pointer to the DSA switch structure
+ * @port: Port number from which to get the default priority
+ *
+ * This function fetches the default priority for the specified port on a KSZ
+ * switch.
+ *
+ * Return: The default priority of the port on success, or a negative error
+ * code on failure.
+ */
+int ksz_port_get_default_prio(struct dsa_switch *ds, int port)
+{
+ struct ksz_device *dev = ds->priv;
+ int ret, reg, shift;
+ u8 data, mask;
+
+ ksz_get_defult_port_prio_reg(dev, ®, &mask, &shift);
+
+ ret = ksz_pread8(dev, port, reg, &data);
+ if (ret)
+ return ret;
+
+ return (data & mask) >> shift;
+}
+
+/**
+ * ksz_port_set_default_prio - Sets the default priority for a port on a KSZ
+ * switch
+ * @ds: Pointer to the DSA switch structure
+ * @port: Port number for which to set the default priority
+ * @prio: Priority value to set
+ *
+ * This function sets the default priority for the specified port on a KSZ
+ * switch.
+ *
+ * Return: 0 on success, or a negative error code on failure.
+ */
+int ksz_port_set_default_prio(struct dsa_switch *ds, int port, u8 prio)
+{
+ struct ksz_device *dev = ds->priv;
+ int reg, shift;
+ u8 mask;
+
+ if (prio >= dev->info->num_tx_queues)
+ return -EINVAL;
+
+ ksz_get_defult_port_prio_reg(dev, ®, &mask, &shift);
+
+ return ksz_prmw8(dev, port, reg, mask, (prio << shift) & mask);
+}
+
+/**
+ * ksz_get_dscp_prio_reg - Retrieves the DSCP-to-priority-mapping register
+ * @dev: Pointer to the KSZ switch device structure
+ * @reg: Pointer to the register address to be set
+ * @per_reg: Pointer to the number of DSCP values per register
+ * @mask: Pointer to the mask to be set
+ *
+ * This function retrieves the DSCP to priority mapping register, the number of
+ * DSCP values per register, and the mask to be set.
+ */
+static void ksz_get_dscp_prio_reg(struct ksz_device *dev, int *reg,
+ int *per_reg, u8 *mask)
+{
+ if (ksz_is_ksz87xx(dev)) {
+ *reg = KSZ8765_REG_TOS_DSCP_CTRL;
+ *per_reg = 4;
+ *mask = GENMASK(1, 0);
+ } else if (ksz_is_ksz88x3(dev)) {
+ *reg = KSZ88X3_REG_TOS_DSCP_CTRL;
+ *per_reg = 4;
+ *mask = GENMASK(1, 0);
+ } else {
+ *reg = KSZ9477_REG_DIFFSERV_PRIO_MAP;
+ *per_reg = 2;
+ *mask = GENMASK(2, 0);
+ }
+}
+
+/**
+ * ksz_port_get_dscp_prio - Retrieves the priority for a DSCP value on a KSZ
+ * switch
+ * @ds: Pointer to the DSA switch structure
+ * @port: Port number for which to get the priority
+ * @dscp: DSCP value for which to get the priority
+ *
+ * This function fetches the priority value from switch global DSCP-to-priorty
+ * mapping table for the specified DSCP value.
+ *
+ * Return: The priority value for the DSCP on success, or a negative error
+ * code on failure.
+ */
+int ksz_port_get_dscp_prio(struct dsa_switch *ds, int port, u8 dscp)
+{
+ struct ksz_device *dev = ds->priv;
+ int reg, per_reg, ret, shift;
+ u8 data, mask;
+
+ ksz_get_dscp_prio_reg(dev, ®, &per_reg, &mask);
+
+ /* If DSCP remapping is disabled, DSCP bits 3-5 are used as Internal
+ * Priority Value (IPV)
+ */
+ if (!is_ksz8(dev)) {
+ ret = ksz_read8(dev, KSZ9477_REG_SW_MAC_TOS_CTRL, &data);
+ if (ret)
+ return ret;
+
+ /* If DSCP remapping is disabled, DSCP bits 3-5 are used as
+ * Internal Priority Value (IPV)
+ */
+ if (!(data & KSZ9477_SW_TOS_DSCP_REMAP))
+ return FIELD_GET(KSZ9477_SW_TOS_DSCP_DEFAULT_PRIO_M,
+ dscp);
+ }
+
+ /* In case DSCP remapping is enabled, we need to write the DSCP to
+ * priority mapping table.
+ */
+ reg += dscp / per_reg;
+ ret = ksz_read8(dev, reg, &data);
+ if (ret)
+ return ret;
+
+ shift = (dscp % per_reg) * (8 / per_reg);
+
+ return (data >> shift) & mask;
+}
+
+/**
+ * ksz_init_global_dscp_map - Initializes the global DSCP-to-priority mapping
+ * @dev: Pointer to the KSZ switch device structure
+ *
+ * This function initializes the global DSCP-to-priority mapping table for the
+ * switch.
+ *
+ * Return: 0 on success, or a negative error code on failure
+ */
+static int ksz_init_global_dscp_map(struct ksz_device *dev)
+{
+ int reg, per_reg, ret, dscp;
+ u8 data = 0;
+ u8 mask;
+
+ /* On KSZ9xxx variants, DSCP remapping is disabled by default.
+ * Enable to have, predictable and reproducible behavior across
+ * different devices.
+ */
+ if (!is_ksz8(dev)) {
+ ret = ksz_rmw8(dev, KSZ9477_REG_SW_MAC_TOS_CTRL,
+ KSZ9477_SW_TOS_DSCP_REMAP,
+ KSZ9477_SW_TOS_DSCP_REMAP);
+ if (ret)
+ return ret;
+ }
+
+ ksz_get_dscp_prio_reg(dev, ®, &per_reg, &mask);
+
+ for (dscp = 0; dscp < DSCP_MAX; dscp++) {
+ int ipv, shift;
+
+ /* Map DSCP to Traffic Type, which is corresponding to the
+ * Internal Priority Value (IPV) in the switch.
+ */
+ if (!is_ksz8(dev)) {
+ ipv = ietf_dscp_to_ieee8021q_tt(dscp);
+ } else {
+ ipv = ieee8021q_tt_to_tc(ietf_dscp_to_ieee8021q_tt(dscp),
+ dev->info->num_tx_queues);
+ }
+ shift = (dscp % per_reg) * (8 / per_reg);
+ data |= (ipv & mask) << shift;
+
+ if (dscp % per_reg == per_reg - 1) {
+ ret = ksz_write8(dev, reg + (dscp / per_reg), data);
+ if (ret)
+ return ret;
+
+ data = 0;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * ksz_apptrust_error - Prints an error message for an invalid apptrust selector
+ * @dev: Pointer to the KSZ switch device structure
+ *
+ * This function prints an error message when an invalid apptrust selector is
+ * provided.
+ */
+static void ksz_apptrust_error(struct ksz_device *dev)
+{
+ char supported_apptrust_variants[64];
+ int i;
+
+ supported_apptrust_variants[0] = '\0';
+ for (i = 0; i < ARRAY_SIZE(ksz_supported_apptrust_variants); i++) {
+ if (i > 0)
+ strlcat(supported_apptrust_variants, ", ",
+ sizeof(supported_apptrust_variants));
+ strlcat(supported_apptrust_variants,
+ ksz_supported_apptrust_variants[i],
+ sizeof(supported_apptrust_variants));
+ }
+
+ dev_err(dev->dev, "Invalid apptrust selector or priority order. Supported: %s\n",
+ supported_apptrust_variants);
+}
+
+/**
+ * ksz_port_set_apptrust_validate - Validates the apptrust selectors
+ * @dev: Pointer to the KSZ switch device structure
+ * @port: Port number for which to set the apptrust selectors
+ * @sel: Array of apptrust selectors to validate
+ * @nsel: Number of apptrust selectors in the array
+ *
+ * This function validates the apptrust selectors provided and ensures that
+ * they are in the correct order.
+ *
+ * This family of switches supports two apptrust selectors: DCB_APP_SEL_PCP and
+ * IEEE_8021QAZ_APP_SEL_DSCP. The priority order of the selectors is fixed and
+ * cannot be changed. The order is as follows:
+ * 1. DCB_APP_SEL_PCP - Priority Code Point selector (highest priority)
+ * 2. IEEE_8021QAZ_APP_SEL_DSCP - Differentiated Services Code Point selector
+ * (lowest priority)
+ *
+ * Return: 0 on success, or a negative error code on failure
+ */
+static int ksz_port_set_apptrust_validate(struct ksz_device *dev, int port,
+ const u8 *sel, int nsel)
+{
+ int i, j, j_prev, found;
+
+ /* Iterate through the requested selectors */
+ for (i = 0; i < nsel; i++) {
+ found = 0;
+
+ /* Check if the current selector is supported by the hardware */
+ for (j = 0; j < sizeof(ksz_supported_apptrust); j++) {
+ if (sel[i] != ksz_supported_apptrust[j])
+ continue;
+
+ found = 1;
+
+ /* Ensure that no higher priority selector (lower index)
+ * precedes a lower priority one
+ */
+ if (i > 0 && j <= j_prev)
+ goto invalid;
+
+ j_prev = j;
+ break;
+ }
+
+ if (!found)
+ goto invalid;
+ }
+
+ return 0;
+
+invalid:
+ ksz_apptrust_error(dev);
+
+ return -EINVAL;
+}
+
+/**
+ * ksz_get_apptrus_map_and_reg - Retrieves the apptrust map and register
+ * @dev: Pointer to the KSZ switch device structure
+ * @map: Pointer to the apptrust map to be set
+ * @reg: Pointer to the register address to be set
+ * @mask: Pointer to the mask to be set
+ *
+ * This function retrieves the apptrust map and register address for the
+ * apptrust configuration.
+ */
+static void ksz_get_apptrus_map_and_reg(struct ksz_device *dev,
+ const struct ksz_apptrust_map **map,
+ int *reg, u8 *mask)
+{
+ if (is_ksz8(dev)) {
+ *map = ksz8_apptrust_map_to_bit;
+ *reg = KSZ8_REG_PORT_1_CTRL_0;
+ *mask = KSZ8_PORT_DIFFSERV_ENABLE | KSZ8_PORT_802_1P_ENABLE;
+ } else {
+ *map = ksz9477_apptrust_map_to_bit;
+ *reg = KSZ9477_REG_PORT_MRI_PRIO_CTRL;
+ *mask = KSZ9477_PORT_802_1P_PRIO_ENABLE |
+ KSZ9477_PORT_DIFFSERV_PRIO_ENABLE;
+ }
+}
+
+/**
+ * ksz_port_set_apptrust - Sets the apptrust selectors for a port on a KSZ
+ * switch
+ * @ds: Pointer to the DSA switch structure
+ * @port: Port number for which to set the apptrust selectors
+ * @sel: Array of apptrust selectors to set
+ * @nsel: Number of apptrust selectors in the array
+ *
+ * This function sets the apptrust selectors for the specified port on a KSZ
+ * switch.
+ *
+ * Return: 0 on success, or a negative error code on failure
+ */
+int ksz_port_set_apptrust(struct dsa_switch *ds, int port,
+ const u8 *sel, int nsel)
+{
+ const struct ksz_apptrust_map *map;
+ struct ksz_device *dev = ds->priv;
+ int reg, i, ret;
+ u8 data = 0;
+ u8 mask;
+
+ ret = ksz_port_set_apptrust_validate(dev, port, sel, nsel);
+ if (ret)
+ return ret;
+
+ ksz_get_apptrus_map_and_reg(dev, &map, ®, &mask);
+
+ for (i = 0; i < nsel; i++) {
+ int j;
+
+ for (j = 0; j < ARRAY_SIZE(ksz_supported_apptrust); j++) {
+ if (sel[i] != ksz_supported_apptrust[j])
+ continue;
+
+ data |= map[j].bit;
+ break;
+ }
+ }
+
+ return ksz_prmw8(dev, port, reg, mask, data);
+}
+
+/**
+ * ksz_port_get_apptrust - Retrieves the apptrust selectors for a port on a KSZ
+ * switch
+ * @ds: Pointer to the DSA switch structure
+ * @port: Port number for which to get the apptrust selectors
+ * @sel: Array to store the apptrust selectors
+ * @nsel: Number of apptrust selectors in the array
+ *
+ * This function fetches the apptrust selectors for the specified port on a KSZ
+ * switch.
+ *
+ * Return: 0 on success, or a negative error code on failure
+ */
+int ksz_port_get_apptrust(struct dsa_switch *ds, int port, u8 *sel, int *nsel)
+{
+ const struct ksz_apptrust_map *map;
+ struct ksz_device *dev = ds->priv;
+ int reg, i, ret;
+ u8 data;
+ u8 mask;
+
+ ksz_get_apptrus_map_and_reg(dev, &map, ®, &mask);
+
+ ret = ksz_pread8(dev, port, reg, &data);
+ if (ret)
+ return ret;
+
+ *nsel = 0;
+ for (i = 0; i < ARRAY_SIZE(ksz_supported_apptrust); i++) {
+ if (data & map[i].bit)
+ sel[(*nsel)++] = ksz_supported_apptrust[i];
+ }
+
+ return 0;
+}
+
+/**
+ * ksz_dcb_init_port - Initializes the DCB configuration for a port on a KSZ
+ * @dev: Pointer to the KSZ switch device structure
+ * @port: Port number for which to initialize the DCB configuration
+ *
+ * This function initializes the DCB configuration for the specified port on a
+ * KSZ switch. Particular DCB configuration is set for the port, including the
+ * default priority and apptrust selectors.
+ * The default priority is set to Best Effort, and the apptrust selectors are
+ * set to all supported selectors.
+ *
+ * Return: 0 on success, or a negative error code on failure
+ */
+int ksz_dcb_init_port(struct ksz_device *dev, int port)
+{
+ int ret, ipv;
+
+ if (is_ksz8(dev))
+ ipv = ieee8021q_tt_to_tc(IEEE8021Q_TT_BE,
+ dev->info->num_tx_queues);
+ else
+ ipv = IEEE8021Q_TT_BE;
+
+ /* Set the default priority for the port to Best Effort */
+ ret = ksz_port_set_default_prio(dev->ds, port, ipv);
+ if (ret)
+ return ret;
+
+ return ksz_port_set_apptrust(dev->ds, port, ksz_supported_apptrust,
+ ARRAY_SIZE(ksz_supported_apptrust));
+}
+
+/**
+ * ksz_dcb_init - Initializes the DCB configuration for a KSZ switch
+ * @dev: Pointer to the KSZ switch device structure
+ *
+ * This function initializes the DCB configuration for a KSZ switch. The global
+ * DSCP-to-priority mapping table is initialized.
+ *
+ * Return: 0 on success, or a negative error code on failure
+ */
+int ksz_dcb_init(struct ksz_device *dev)
+{
+ int ret;
+
+ ret = ksz_init_global_dscp_map(dev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
diff --git a/drivers/net/dsa/microchip/ksz_dcb.h b/drivers/net/dsa/microchip/ksz_dcb.h
new file mode 100644
index 0000000000000..254c0e7bdafca
--- /dev/null
+++ b/drivers/net/dsa/microchip/ksz_dcb.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2024 Pengutronix, Oleksij Rempel <[email protected]> */
+
+#ifndef __KSZ_DCB_H
+#define __KSZ_DCB_H
+
+#include <net/dsa.h>
+
+#include "ksz_common.h"
+
+int ksz_port_get_default_prio(struct dsa_switch *ds, int port);
+int ksz_port_set_default_prio(struct dsa_switch *ds, int port, u8 prio);
+int ksz_port_get_dscp_prio(struct dsa_switch *ds, int port, u8 dscp);
+int ksz_port_set_apptrust(struct dsa_switch *ds, int port,
+ const unsigned char *sel,
+ int nsel);
+int ksz_port_get_apptrust(struct dsa_switch *ds, int port, u8 *sel, int *nsel);
+int ksz_dcb_init_port(struct ksz_device *dev, int port);
+int ksz_dcb_init(struct ksz_device *dev);
+
+#endif /* __KSZ_DCB_H */
--
2.39.2
> -----Original Message-----
> From: Oleksij Rempel <[email protected]>
> Sent: Thursday, March 28, 2024 9:35 PM
> To: David S. Miller <[email protected]>; Andrew Lunn <[email protected]>;
> Eric Dumazet <[email protected]>; Florian Fainelli <[email protected]>;
> Jakub Kicinski <[email protected]>; Paolo Abeni <[email protected]>; Vladimir
> Oltean <[email protected]>; Woojung Huh <[email protected]>;
> Arun Ramadoss <[email protected]>
> Cc: Oleksij Rempel <[email protected]>; [email protected]; linux-
> [email protected]; [email protected];
> [email protected]; David Ahern <[email protected]>; Simon
> Horman <[email protected]>; Willem de Bruijn <[email protected]>; S?ren
> Andersen <[email protected]>
> Subject: [PATCH net-next v1 5/9] net: dsa: microchip: add support
> for different DCB app configurations
>
> Add DCB support to configure app trust sources and default port priority.
>
> Following commands can be used for testing:
> dcb apptrust set dev lan1 order pcp dscp dcb app replace dev lan1 default-prio 3
>
> Since it is not possible to configure DSCP-Prio mapping per port, this patch
> provide only ability to read switch global dscp-prio mapping and way to
> enable/disable app trust for DSCP.
>
> Signed-off-by: Oleksij Rempel <[email protected]>
> ---
> drivers/net/dsa/microchip/Kconfig | 2 +
> drivers/net/dsa/microchip/Makefile | 2 +-
> drivers/net/dsa/microchip/ksz_common.c | 12 +-
> drivers/net/dsa/microchip/ksz_common.h | 5 +
> drivers/net/dsa/microchip/ksz_dcb.c | 533 +++++++++++++++++++++++++
> drivers/net/dsa/microchip/ksz_dcb.h | 21 +
> 6 files changed, 573 insertions(+), 2 deletions(-) create mode 100644
> drivers/net/dsa/microchip/ksz_dcb.c
> create mode 100644 drivers/net/dsa/microchip/ksz_dcb.h
>
> diff --git a/drivers/net/dsa/microchip/Kconfig b/drivers/net/dsa/microchip/Kconfig
> index 394ca8678d2ba..c1b906c05a025 100644
> --- a/drivers/net/dsa/microchip/Kconfig
> +++ b/drivers/net/dsa/microchip/Kconfig
> @@ -4,6 +4,8 @@ menuconfig NET_DSA_MICROCHIP_KSZ_COMMON
> depends on NET_DSA
> select NET_DSA_TAG_KSZ
> select NET_DSA_TAG_NONE
> + select NET_IEEE8021Q_HELPERS
> + select DCB
> help
> This driver adds support for Microchip KSZ9477 series switch and
> KSZ8795/KSZ88x3 switch chips.
> diff --git a/drivers/net/dsa/microchip/Makefile b/drivers/net/dsa/microchip/Makefile
> index 49459a50dbc81..1cfba1ec9355a 100644
> --- a/drivers/net/dsa/microchip/Makefile
> +++ b/drivers/net/dsa/microchip/Makefile
> @@ -1,6 +1,6 @@
> # SPDX-License-Identifier: GPL-2.0-only
> obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON) += ksz_switch.o
> -ksz_switch-objs := ksz_common.o
> +ksz_switch-objs := ksz_common.o ksz_dcb.o
> ksz_switch-objs += ksz9477.o ksz9477_acl.o ksz9477_tc_flower.o ksz_switch-
> objs += ksz8795.o ksz_switch-objs += lan937x_main.o diff --git
> a/drivers/net/dsa/microchip/ksz_common.c
> b/drivers/net/dsa/microchip/ksz_common.c
> index cf81739d91dae..ea2d6f8d381bc 100644
> --- a/drivers/net/dsa/microchip/ksz_common.c
> +++ b/drivers/net/dsa/microchip/ksz_common.c
> @@ -28,6 +28,7 @@
> #include <net/switchdev.h>
>
> #include "ksz_common.h"
> +#include "ksz_dcb.h"
> #include "ksz_ptp.h"
> #include "ksz8.h"
> #include "ksz9477.h"
> @@ -2371,6 +2372,10 @@ static int ksz_setup(struct dsa_switch *ds)
> goto out_ptp_clock_unregister;
> }
>
> + ret = ksz_dcb_init(dev);
> + if (ret)
> + goto out_ptp_clock_unregister;
> +
> /* start switch */
> regmap_update_bits(ksz_regmap_8(dev), regs[S_START_CTRL],
> SW_START, SW_START);
> @@ -2698,7 +2703,7 @@ static int ksz_port_setup(struct dsa_switch *ds, int
> port)
> * there is no need to do anything.
> */
>
> - return 0;
> + return ksz_dcb_init_port(dev, port);
> }
>
> void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) @@ -
> 3950,6 +3955,11 @@ static const struct dsa_switch_ops ksz_switch_ops = {
> .port_setup_tc = ksz_setup_tc,
> .get_mac_eee = ksz_get_mac_eee,
> .set_mac_eee = ksz_set_mac_eee,
> + .port_get_default_prio = ksz_port_get_default_prio,
> + .port_set_default_prio = ksz_port_set_default_prio,
> + .port_get_dscp_prio = ksz_port_get_dscp_prio,
> + .port_set_apptrust = ksz_port_set_apptrust,
> + .port_get_apptrust = ksz_port_get_apptrust,
> };
>
> struct ksz_device *ksz_switch_alloc(struct device *base, void *priv) diff --git
> a/drivers/net/dsa/microchip/ksz_common.h
> b/drivers/net/dsa/microchip/ksz_common.h
> index 1bedd240cbbe4..4f48a8347e5de 100644
> --- a/drivers/net/dsa/microchip/ksz_common.h
> +++ b/drivers/net/dsa/microchip/ksz_common.h
> @@ -621,6 +621,11 @@ static inline bool ksz_is_ksz88x3(struct ksz_device
> *dev)
> return dev->chip_id == KSZ8830_CHIP_ID; }
>
> +static inline bool is_ksz8(struct ksz_device *dev) {
> + return ksz_is_ksz87xx(dev) || ksz_is_ksz88x3(dev); }
> +
> static inline int is_lan937x(struct ksz_device *dev) {
> return dev->chip_id == LAN9370_CHIP_ID || diff --git
> a/drivers/net/dsa/microchip/ksz_dcb.c b/drivers/net/dsa/microchip/ksz_dcbc
> new file mode 100644
> index 0000000000000..527bf10d35dd3
> --- /dev/null
> +++ b/drivers/net/dsa/microchip/ksz_dcb.c
> @@ -0,0 +1,533 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (c) 2024 Pengutronix, Oleksij Rempel
> +<[email protected]>
> +
> +#include <linux/dsa/ksz_common.h>
> +#include <net/dsa.h>
> +#include <net/dscp.h>
> +#include <net/ieee8021q.h>
> +
> +#include "ksz_common.h"
> +#include "ksz_dcb.h"
> +#include "ksz8.h"
> +
> +#define KSZ8_REG_PORT_1_CTRL_0 0x10
> +#define KSZ8_PORT_DIFFSERV_ENABLE BIT(6)
> +#define KSZ8_PORT_802_1P_ENABLE BIT(5)
> +#define KSZ8_PORT_BASED_PRIO_M GENMASK(4, 3)
> +
> +#define KSZ88X3_REG_TOS_DSCP_CTRL 0x60
> +#define KSZ8765_REG_TOS_DSCP_CTRL 0x90
> +
> +#define KSZ9477_REG_SW_MAC_TOS_CTRL 0x033e
> +#define KSZ9477_SW_TOS_DSCP_REMAP BIT(0)
> +#define KSZ9477_SW_TOS_DSCP_DEFAULT_PRIO_M GENMASK(5, 3)
> +
> +#define KSZ9477_REG_DIFFSERV_PRIO_MAP 0x0340
> +
> +#define KSZ9477_REG_PORT_MRI_PRIO_CTRL 0x0801
> +#define KSZ9477_PORT_HIGHEST_PRIO BIT(7)
> +#define KSZ9477_PORT_OR_PRIO BIT(6)
> +#define KSZ9477_PORT_MAC_PRIO_ENABLE BIT(4)
> +#define KSZ9477_PORT_VLAN_PRIO_ENABLE BIT(3)
> +#define KSZ9477_PORT_802_1P_PRIO_ENABLE BIT(2)
> +#define KSZ9477_PORT_DIFFSERV_PRIO_ENABLE BIT(1)
> +#define KSZ9477_PORT_ACL_PRIO_ENABLE BIT(0)
> +
> +#define KSZ9477_REG_PORT_MRI_MAC_CTRL 0x0802
> +#define KSZ9477_PORT_BASED_PRIO_M GENMASK(2, 0)
> +
> +struct ksz_apptrust_map {
> + u8 apptrust;
> + u8 bit;
> +};
> +
> +static const struct ksz_apptrust_map ksz8_apptrust_map_to_bit[] = {
> + { DCB_APP_SEL_PCP, KSZ8_PORT_802_1P_ENABLE },
> + { IEEE_8021QAZ_APP_SEL_DSCP, KSZ8_PORT_DIFFSERV_ENABLE },
> };
> +
> +static const struct ksz_apptrust_map ksz9477_apptrust_map_to_bit[] = {
> + { DCB_APP_SEL_PCP, KSZ9477_PORT_802_1P_PRIO_ENABLE },
> + { IEEE_8021QAZ_APP_SEL_DSCP,
> KSZ9477_PORT_DIFFSERV_PRIO_ENABLE }, };
> +
> +/**
> + * ksz_supported_apptrust[] - Supported apptrust selectors and Priority Order
> + * of Internal Priority Value (IPV) sources.
> + *
> + * This array defines the apptrust selectors supported by the hardware,
> +where
> + * the index within the array indicates the priority of the selector -
> +lower
> + * indices correspond to higher priority. This fixed priority scheme is
> +due to
> + * the hardware's design, which does not support configurable priority
> +among
> + * different priority sources.
> + *
> + * The priority sources, including Tail Tag, ACL, VLAN PCP and DSCP are
> +ordered
> + * by the hardware's fixed logic, as detailed below. The order reflects
> +a
> + * non-configurable precedence where certain types of priority
> +information
> + * override others:
> + *
> + * 1. Tail Tag - Highest priority, overrides ACL, VLAN PCP, and DSCP priorities.
> + * 2. ACL - Overrides VLAN PCP and DSCP priorities.
> + * 3. VLAN PCP - Overrides DSCP priority.
> + * 4. DSCP - Lowest priority, does not override any other priority source.
> + *
> + * In this context, the array's lower index (higher priority) for
> + * 'DCB_APP_SEL_PCP' suggests its relative priority over
> + * 'IEEE_8021QAZ_APP_SEL_DSCP' within the system's fixed priority scheme.
> + *
> + * DCB_APP_SEL_PCP - Priority Code Point selector
> + * IEEE_8021QAZ_APP_SEL_DSCP - Differentiated Services Code Point
> +selector */ static const u8 ksz_supported_apptrust[] = {
> + DCB_APP_SEL_PCP,
> + IEEE_8021QAZ_APP_SEL_DSCP,
> +};
> +
> +static const u8 ksz8_port2_supported_apptrust[] = {
> + DCB_APP_SEL_PCP,
> +};
> +
> +static const char * const ksz_supported_apptrust_variants[] = {
> + "empty", "dscp", "pcp", "dscp pcp"
> +};
> +
> +static void ksz_get_defult_port_prio_reg(struct ksz_device *dev, int *reg,
> + u8 *mask, int *shift)
> +{
> + if (is_ksz8(dev)) {
> + *reg = KSZ8_REG_PORT_1_CTRL_0;
> + *mask = KSZ8_PORT_BASED_PRIO_M;
> + *shift = __bf_shf(KSZ8_PORT_BASED_PRIO_M);
> + } else {
> + *reg = KSZ9477_REG_PORT_MRI_MAC_CTRL;
> + *mask = KSZ9477_PORT_BASED_PRIO_M;
> + *shift = __bf_shf(KSZ9477_PORT_BASED_PRIO_M);
> + }
> +}
> +
> +/**
> + * ksz_port_get_default_prio - Retrieves the default priority for a port on a
> + * KSZ switch
> + * @ds: Pointer to the DSA switch structure
> + * @port: Port number from which to get the default priority
> + *
> + * This function fetches the default priority for the specified port on
> +a KSZ
> + * switch.
> + *
> + * Return: The default priority of the port on success, or a negative
> +error
> + * code on failure.
> + */
> +int ksz_port_get_default_prio(struct dsa_switch *ds, int port) {
> + struct ksz_device *dev = ds->priv;
> + int ret, reg, shift;
> + u8 data, mask;
> +
> + ksz_get_defult_port_prio_reg(dev, ®, &mask, &shift);
> +
> + ret = ksz_pread8(dev, port, reg, &data);
> + if (ret)
> + return ret;
> +
> + return (data & mask) >> shift;
> +}
> +
> +/**
> + * ksz_port_set_default_prio - Sets the default priority for a port on a KSZ
> + * switch
> + * @ds: Pointer to the DSA switch structure
> + * @port: Port number for which to set the default priority
> + * @prio: Priority value to set
> + *
> + * This function sets the default priority for the specified port on a
> +KSZ
> + * switch.
> + *
> + * Return: 0 on success, or a negative error code on failure.
> + */
> +int ksz_port_set_default_prio(struct dsa_switch *ds, int port, u8 prio)
> +{
> + struct ksz_device *dev = ds->priv;
> + int reg, shift;
> + u8 mask;
> +
> + if (prio >= dev->info->num_tx_queues)
> + return -EINVAL;
> +
> + ksz_get_defult_port_prio_reg(dev, ®, &mask, &shift);
> +
> + return ksz_prmw8(dev, port, reg, mask, (prio << shift) & mask); }
> +
> +/**
> + * ksz_get_dscp_prio_reg - Retrieves the DSCP-to-priority-mapping
> +register
> + * @dev: Pointer to the KSZ switch device structure
> + * @reg: Pointer to the register address to be set
> + * @per_reg: Pointer to the number of DSCP values per register
> + * @mask: Pointer to the mask to be set
> + *
> + * This function retrieves the DSCP to priority mapping register, the
> +number of
> + * DSCP values per register, and the mask to be set.
> + */
> +static void ksz_get_dscp_prio_reg(struct ksz_device *dev, int *reg,
> + int *per_reg, u8 *mask)
> +{
> + if (ksz_is_ksz87xx(dev)) {
> + *reg = KSZ8765_REG_TOS_DSCP_CTRL;
> + *per_reg = 4;
> + *mask = GENMASK(1, 0);
> + } else if (ksz_is_ksz88x3(dev)) {
> + *reg = KSZ88X3_REG_TOS_DSCP_CTRL;
> + *per_reg = 4;
> + *mask = GENMASK(1, 0);
> + } else {
> + *reg = KSZ9477_REG_DIFFSERV_PRIO_MAP;
> + *per_reg = 2;
> + *mask = GENMASK(2, 0);
> + }
> +}
> +
> +/**
> + * ksz_port_get_dscp_prio - Retrieves the priority for a DSCP value on a KSZ
> + * switch
> + * @ds: Pointer to the DSA switch structure
> + * @port: Port number for which to get the priority
> + * @dscp: DSCP value for which to get the priority
> + *
> + * This function fetches the priority value from switch global
> +DSCP-to-priorty
> + * mapping table for the specified DSCP value.
> + *
> + * Return: The priority value for the DSCP on success, or a negative
> +error
> + * code on failure.
> + */
> +int ksz_port_get_dscp_prio(struct dsa_switch *ds, int port, u8 dscp) {
> + struct ksz_device *dev = ds->priv;
> + int reg, per_reg, ret, shift;
> + u8 data, mask;
> +
> + ksz_get_dscp_prio_reg(dev, ®, &per_reg, &mask);
> +
> + /* If DSCP remapping is disabled, DSCP bits 3-5 are used as Internal
> + * Priority Value (IPV)
> + */
> + if (!is_ksz8(dev)) {
> + ret = ksz_read8(dev, KSZ9477_REG_SW_MAC_TOS_CTRL,
> &data);
> + if (ret)
> + return ret;
> +
> + /* If DSCP remapping is disabled, DSCP bits 3-5 are used as
> + * Internal Priority Value (IPV)
> + */
> + if (!(data & KSZ9477_SW_TOS_DSCP_REMAP))
> + return
> FIELD_GET(KSZ9477_SW_TOS_DSCP_DEFAULT_PRIO_M,
> + dscp);
> + }
> +
> + /* In case DSCP remapping is enabled, we need to write the DSCP to
> + * priority mapping table.
> + */
> + reg += dscp / per_reg;
> + ret = ksz_read8(dev, reg, &data);
> + if (ret)
> + return ret;
> +
> + shift = (dscp % per_reg) * (8 / per_reg);
> +
> + return (data >> shift) & mask;
> +}
> +
> +/**
> + * ksz_init_global_dscp_map - Initializes the global DSCP-to-priority
> +mapping
> + * @dev: Pointer to the KSZ switch device structure
> + *
> + * This function initializes the global DSCP-to-priority mapping table
> +for the
> + * switch.
> + *
> + * Return: 0 on success, or a negative error code on failure */ static
> +int ksz_init_global_dscp_map(struct ksz_device *dev) {
> + int reg, per_reg, ret, dscp;
> + u8 data = 0;
> + u8 mask;
> +
> + /* On KSZ9xxx variants, DSCP remapping is disabled by default.
> + * Enable to have, predictable and reproducible behavior across
> + * different devices.
> + */
> + if (!is_ksz8(dev)) {
> + ret = ksz_rmw8(dev, KSZ9477_REG_SW_MAC_TOS_CTRL,
> + KSZ9477_SW_TOS_DSCP_REMAP,
> + KSZ9477_SW_TOS_DSCP_REMAP);
> + if (ret)
> + return ret;
> + }
> +
> + ksz_get_dscp_prio_reg(dev, ®, &per_reg, &mask);
> +
> + for (dscp = 0; dscp < DSCP_MAX; dscp++) {
> + int ipv, shift;
> +
> + /* Map DSCP to Traffic Type, which is corresponding to the
> + * Internal Priority Value (IPV) in the switch.
> + */
> + if (!is_ksz8(dev)) {
> + ipv = ietf_dscp_to_ieee8021q_tt(dscp);
> + } else {
> + ipv =
> ieee8021q_tt_to_tc(ietf_dscp_to_ieee8021q_tt(dscp),
> + dev->info->num_tx_queues);
> + }
No need for braces for single statement.
> + shift = (dscp % per_reg) * (8 / per_reg);
> + data |= (ipv & mask) << shift;
> +
> + if (dscp % per_reg == per_reg - 1) {
> + ret = ksz_write8(dev, reg + (dscp / per_reg), data);
> + if (ret)
> + return ret;
> +
> + data = 0;
> + }
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * ksz_apptrust_error - Prints an error message for an invalid apptrust
> +selector
> + * @dev: Pointer to the KSZ switch device structure
> + *
> + * This function prints an error message when an invalid apptrust
> +selector is
> + * provided.
> + */
> +static void ksz_apptrust_error(struct ksz_device *dev) {
> + char supported_apptrust_variants[64];
> + int i;
> +
> + supported_apptrust_variants[0] = '\0';
> + for (i = 0; i < ARRAY_SIZE(ksz_supported_apptrust_variants); i++) {
> + if (i > 0)
> + strlcat(supported_apptrust_variants, ", ",
> + sizeof(supported_apptrust_variants));
> + strlcat(supported_apptrust_variants,
> + ksz_supported_apptrust_variants[i],
> + sizeof(supported_apptrust_variants));
> + }
> +
> + dev_err(dev->dev, "Invalid apptrust selector or priority order. Supported:
> %s\n",
> + supported_apptrust_variants);
> +}
> +
> +/**
> + * ksz_port_set_apptrust_validate - Validates the apptrust selectors
> + * @dev: Pointer to the KSZ switch device structure
> + * @port: Port number for which to set the apptrust selectors
> + * @sel: Array of apptrust selectors to validate
> + * @nsel: Number of apptrust selectors in the array
> + *
> + * This function validates the apptrust selectors provided and ensures
> +that
> + * they are in the correct order.
> + *
> + * This family of switches supports two apptrust selectors:
> +DCB_APP_SEL_PCP and
> + * IEEE_8021QAZ_APP_SEL_DSCP. The priority order of the selectors is
> +fixed and
> + * cannot be changed. The order is as follows:
> + * 1. DCB_APP_SEL_PCP - Priority Code Point selector (highest priority)
> + * 2. IEEE_8021QAZ_APP_SEL_DSCP - Differentiated Services Code Point
> selector
> + * (lowest priority)
> + *
> + * Return: 0 on success, or a negative error code on failure */ static
> +int ksz_port_set_apptrust_validate(struct ksz_device *dev, int port,
> + const u8 *sel, int nsel)
> +{
> + int i, j, j_prev, found;
> +
> + /* Iterate through the requested selectors */
> + for (i = 0; i < nsel; i++) {
> + found = 0;
> +
> + /* Check if the current selector is supported by the hardware */
> + for (j = 0; j < sizeof(ksz_supported_apptrust); j++) {
> + if (sel[i] != ksz_supported_apptrust[j])
> + continue;
> +
> + found = 1;
> +
> + /* Ensure that no higher priority selector (lower index)
> + * precedes a lower priority one
> + */
> + if (i > 0 && j <= j_prev)
j_prev is uninitialized. It may contain garbage value.
> + goto invalid;
> +
> + j_prev = j;
> + break;
> + }
> +
> + if (!found)
> + goto invalid;
> + }
> +
> + return 0;
> +
> +invalid:
> + ksz_apptrust_error(dev);
> +
> + return -EINVAL;
> +}
> +
> +/**
> + * ksz_get_apptrus_map_and_reg - Retrieves the apptrust map and
> +register
> + * @dev: Pointer to the KSZ switch device structure
> + * @map: Pointer to the apptrust map to be set
> + * @reg: Pointer to the register address to be set
> + * @mask: Pointer to the mask to be set
> + *
> + * This function retrieves the apptrust map and register address for
> +the
> + * apptrust configuration.
> + */
> +static void ksz_get_apptrus_map_and_reg(struct ksz_device *dev,
> + const struct ksz_apptrust_map **map,
> + int *reg, u8 *mask)
> +{
> + if (is_ksz8(dev)) {
> + *map = ksz8_apptrust_map_to_bit;
> + *reg = KSZ8_REG_PORT_1_CTRL_0;
> + *mask = KSZ8_PORT_DIFFSERV_ENABLE |
> KSZ8_PORT_802_1P_ENABLE;
> + } else {
> + *map = ksz9477_apptrust_map_to_bit;
> + *reg = KSZ9477_REG_PORT_MRI_PRIO_CTRL;
> + *mask = KSZ9477_PORT_802_1P_PRIO_ENABLE |
> + KSZ9477_PORT_DIFFSERV_PRIO_ENABLE;
> + }
> +}
> +
> +/**
> + * ksz_port_set_apptrust - Sets the apptrust selectors for a port on a KSZ
> + * switch
> + * @ds: Pointer to the DSA switch structure
> + * @port: Port number for which to set the apptrust selectors
> + * @sel: Array of apptrust selectors to set
> + * @nsel: Number of apptrust selectors in the array
> + *
> + * This function sets the apptrust selectors for the specified port on
> +a KSZ
> + * switch.
> + *
> + * Return: 0 on success, or a negative error code on failure */ int
> +ksz_port_set_apptrust(struct dsa_switch *ds, int port,
> + const u8 *sel, int nsel)
> +{
> + const struct ksz_apptrust_map *map;
> + struct ksz_device *dev = ds->priv;
> + int reg, i, ret;
> + u8 data = 0;
> + u8 mask;
> +
> + ret = ksz_port_set_apptrust_validate(dev, port, sel, nsel);
> + if (ret)
> + return ret;
> +
> + ksz_get_apptrus_map_and_reg(dev, &map, ®, &mask);
> +
> + for (i = 0; i < nsel; i++) {
> + int j;
> +
> + for (j = 0; j < ARRAY_SIZE(ksz_supported_apptrust); j++) {
> + if (sel[i] != ksz_supported_apptrust[j])
> + continue;
> +
> + data |= map[j].bit;
> + break;
> + }
> + }
> +
> + return ksz_prmw8(dev, port, reg, mask, data); }
> +
> +/**
> + * ksz_port_get_apptrust - Retrieves the apptrust selectors for a port on a KSZ
> + * switch
> + * @ds: Pointer to the DSA switch structure
> + * @port: Port number for which to get the apptrust selectors
> + * @sel: Array to store the apptrust selectors
> + * @nsel: Number of apptrust selectors in the array
> + *
> + * This function fetches the apptrust selectors for the specified port
> +on a KSZ
> + * switch.
> + *
> + * Return: 0 on success, or a negative error code on failure */ int
> +ksz_port_get_apptrust(struct dsa_switch *ds, int port, u8 *sel, int
> +*nsel) {
> + const struct ksz_apptrust_map *map;
> + struct ksz_device *dev = ds->priv;
> + int reg, i, ret;
> + u8 data;
> + u8 mask;
> +
> + ksz_get_apptrus_map_and_reg(dev, &map, ®, &mask);
> +
> + ret = ksz_pread8(dev, port, reg, &data);
> + if (ret)
> + return ret;
> +
> + *nsel = 0;
> + for (i = 0; i < ARRAY_SIZE(ksz_supported_apptrust); i++) {
> + if (data & map[i].bit)
> + sel[(*nsel)++] = ksz_supported_apptrust[i];
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * ksz_dcb_init_port - Initializes the DCB configuration for a port on
> +a KSZ
> + * @dev: Pointer to the KSZ switch device structure
> + * @port: Port number for which to initialize the DCB configuration
> + *
> + * This function initializes the DCB configuration for the specified
> +port on a
> + * KSZ switch. Particular DCB configuration is set for the port,
> +including the
> + * default priority and apptrust selectors.
> + * The default priority is set to Best Effort, and the apptrust
> +selectors are
> + * set to all supported selectors.
> + *
> + * Return: 0 on success, or a negative error code on failure */ int
> +ksz_dcb_init_port(struct ksz_device *dev, int port) {
> + int ret, ipv;
> +
> + if (is_ksz8(dev))
> + ipv = ieee8021q_tt_to_tc(IEEE8021Q_TT_BE,
> + dev->info->num_tx_queues);
> + else
> + ipv = IEEE8021Q_TT_BE;
> +
> + /* Set the default priority for the port to Best Effort */
> + ret = ksz_port_set_default_prio(dev->ds, port, ipv);
> + if (ret)
> + return ret;
> +
> + return ksz_port_set_apptrust(dev->ds, port, ksz_supported_apptrust,
> + ARRAY_SIZE(ksz_supported_apptrust));
> +}
> +
> +/**
> + * ksz_dcb_init - Initializes the DCB configuration for a KSZ switch
> + * @dev: Pointer to the KSZ switch device structure
> + *
> + * This function initializes the DCB configuration for a KSZ switch.
> +The global
> + * DSCP-to-priority mapping table is initialized.
> + *
> + * Return: 0 on success, or a negative error code on failure */ int
> +ksz_dcb_init(struct ksz_device *dev) {
> + int ret;
> +
> + ret = ksz_init_global_dscp_map(dev);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> diff --git a/drivers/net/dsa/microchip/ksz_dcb.h
> b/drivers/net/dsa/microchip/ksz_dcb.h
> new file mode 100644
> index 0000000000000..254c0e7bdafca
> --- /dev/null
> +++ b/drivers/net/dsa/microchip/ksz_dcb.h
> @@ -0,0 +1,21 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (c) 2024 Pengutronix, Oleksij Rempel
> +<[email protected]> */
> +
> +#ifndef __KSZ_DCB_H
> +#define __KSZ_DCB_H
> +
> +#include <net/dsa.h>
> +
> +#include "ksz_common.h"
> +
> +int ksz_port_get_default_prio(struct dsa_switch *ds, int port); int
> +ksz_port_set_default_prio(struct dsa_switch *ds, int port, u8 prio);
> +int ksz_port_get_dscp_prio(struct dsa_switch *ds, int port, u8 dscp);
> +int ksz_port_set_apptrust(struct dsa_switch *ds, int port,
> + const unsigned char *sel,
> + int nsel);
> +int ksz_port_get_apptrust(struct dsa_switch *ds, int port, u8 *sel, int
> +*nsel); int ksz_dcb_init_port(struct ksz_device *dev, int port); int
> +ksz_dcb_init(struct ksz_device *dev);
> +
> +#endif /* __KSZ_DCB_H */
> --
> 2.39.2
>
Hi Oleksij,
kernel test robot noticed the following build warnings:
[auto build test WARNING on net-next/main]
url: https://github.com/intel-lab-lkp/linux/commits/Oleksij-Rempel/net-dsa-add-support-for-DCB-get-set-apptrust-configuration/20240329-000847
base: net-next/main
patch link: https://lore.kernel.org/r/20240328160518.2396238-6-o.rempel%40pengutronix.de
patch subject: [PATCH net-next v1 5/9] net: dsa: microchip: add support for different DCB app configurations
config: sh-allmodconfig (https://download.01.org/0day-ci/archive/20240329/[email protected]/config)
compiler: sh4-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240329/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All warnings (new ones prefixed by >>):
>> drivers/net/dsa/microchip/ksz_dcb.c:81: warning: cannot understand function prototype: 'const u8 ksz_supported_apptrust[] = '
vim +81 drivers/net/dsa/microchip/ksz_dcb.c
53
54 /**
55 * ksz_supported_apptrust[] - Supported apptrust selectors and Priority Order
56 * of Internal Priority Value (IPV) sources.
57 *
58 * This array defines the apptrust selectors supported by the hardware, where
59 * the index within the array indicates the priority of the selector - lower
60 * indices correspond to higher priority. This fixed priority scheme is due to
61 * the hardware's design, which does not support configurable priority among
62 * different priority sources.
63 *
64 * The priority sources, including Tail Tag, ACL, VLAN PCP and DSCP are ordered
65 * by the hardware's fixed logic, as detailed below. The order reflects a
66 * non-configurable precedence where certain types of priority information
67 * override others:
68 *
69 * 1. Tail Tag - Highest priority, overrides ACL, VLAN PCP, and DSCP priorities.
70 * 2. ACL - Overrides VLAN PCP and DSCP priorities.
71 * 3. VLAN PCP - Overrides DSCP priority.
72 * 4. DSCP - Lowest priority, does not override any other priority source.
73 *
74 * In this context, the array's lower index (higher priority) for
75 * 'DCB_APP_SEL_PCP' suggests its relative priority over
76 * 'IEEE_8021QAZ_APP_SEL_DSCP' within the system's fixed priority scheme.
77 *
78 * DCB_APP_SEL_PCP - Priority Code Point selector
79 * IEEE_8021QAZ_APP_SEL_DSCP - Differentiated Services Code Point selector
80 */
> 81 static const u8 ksz_supported_apptrust[] = {
82 DCB_APP_SEL_PCP,
83 IEEE_8021QAZ_APP_SEL_DSCP,
84 };
85
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Hi Oleksij,
kernel test robot noticed the following build errors:
[auto build test ERROR on net-next/main]
url: https://github.com/intel-lab-lkp/linux/commits/Oleksij-Rempel/net-dsa-add-support-for-DCB-get-set-apptrust-configuration/20240329-000847
base: net-next/main
patch link: https://lore.kernel.org/r/20240328160518.2396238-6-o.rempel%40pengutronix.de
patch subject: [PATCH net-next v1 5/9] net: dsa: microchip: add support for different DCB app configurations
config: i386-randconfig-012-20240330 (https://download.01.org/0day-ci/archive/20240330/[email protected]/config)
compiler: gcc-12 (Ubuntu 12.3.0-9ubuntu2) 12.3.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240330/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>, old ones prefixed by <<):
WARNING: modpost: missing MODULE_DESCRIPTION() in kernel/rcu/rcuscale.o
WARNING: modpost: missing MODULE_DESCRIPTION() in kernel/rcu/refscale.o
WARNING: modpost: missing MODULE_DESCRIPTION() in kernel/time/time_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in kernel/trace/preemptirq_delay_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in kernel/torture.o
WARNING: modpost: missing MODULE_DESCRIPTION() in mm/dmapool_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_cp737.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_cp860.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_cp862.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_cp866.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_cp936.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_cp949.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_cp950.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_iso8859-2.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_iso8859-5.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_iso8859-7.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_iso8859-13.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/mac-cyrillic.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/mac-gaelic.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/mac-roman.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/nls/nls_ucs2_utils.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/bcachefs/mean_and_variance_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/binfmt_misc.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/minix/minix.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/efs/efs.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/qnx4/qnx4.o
WARNING: modpost: missing MODULE_DESCRIPTION() in fs/qnx6/qnx6.o
WARNING: modpost: missing MODULE_DESCRIPTION() in security/keys/trusted-keys/trusted.o
WARNING: modpost: missing MODULE_DESCRIPTION() in crypto/algif_hash.o
WARNING: modpost: missing MODULE_DESCRIPTION() in block/t10-pi.o
WARNING: modpost: missing MODULE_DESCRIPTION() in lib/kunit/kunit.o
WARNING: modpost: missing MODULE_DESCRIPTION() in lib/kunit/kunit-test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in lib/kunit/kunit-example-test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in lib/crypto/libarc4.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpio/gpio-gw-pld.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/video/backlight/rt4831-backlight.o
WARNING: modpost: drivers/acpi/apei/einj: section mismatch in reference: einj_driver+0x8 (section: .data) -> einj_remove (section: .exit.text)
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/clk/clk-gate_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/virtio/virtio.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/virtio/virtio_ring.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/regulator/max20411-regulator.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/tty/n_hdlc.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/char/lp.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/char/nvram.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/char/ppdev.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tests/drm_kunit_helpers.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tests/drm_buddy_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tests/drm_cmdline_parser_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tests/drm_connector_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tests/drm_damage_helper_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tests/drm_dp_mst_helper_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tests/drm_exec_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tests/drm_format_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tests/drm_framebuffer_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tests/drm_gem_shmem_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tests/drm_managed_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tests/drm_mm_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tests/drm_modes_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tests/drm_plane_helper_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tests/drm_probe_helper_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tests/drm_rect_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/bridge/sil-sii8620.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/tiny/gm12u320.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/base/regmap/regmap-kunit.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/base/regmap/regmap-ram.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/base/regmap/regmap-raw-ram.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/misc/open-dice.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/scsi/scsi_common.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/scsi/aha1740.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/auxdisplay/charlcd.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/auxdisplay/hd44780_common.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/host/xhci-pci-renesas.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/mon/usbmon.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/serial/usb_debug.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/serial/mxuport.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/serial/usb-serial-simple.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/usb/serial/symbolserial.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/input/tests/input_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/media/tuners/tda9887.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/media/rc/rc-core.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/media/v4l2-core/v4l2-async.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/media/v4l2-core/v4l2-fwnode.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/hwmon/mr75203.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/watchdog/twl4030_wdt.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/mmc/core/pwrseq_simple.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/mmc/core/pwrseq_sd8787.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/mmc/core/pwrseq_emmc.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/mmc/core/sdio_uart.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/firmware/google/gsmi.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/of/of_test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/devfreq/governor_simpleondemand.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/devfreq/governor_performance.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/fsi/fsi-master-gpio.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/parport/parport.o
WARNING: modpost: missing MODULE_DESCRIPTION() in samples/vfio-mdev/mdpy.o
WARNING: modpost: missing MODULE_DESCRIPTION() in samples/vfio-mdev/mbochs.o
WARNING: modpost: missing MODULE_DESCRIPTION() in samples/kobject/kobject-example.o
WARNING: modpost: missing MODULE_DESCRIPTION() in samples/kobject/kset-example.o
WARNING: modpost: missing MODULE_DESCRIPTION() in samples/kprobes/kprobe_example.o
WARNING: modpost: missing MODULE_DESCRIPTION() in samples/kprobes/kretprobe_example.o
>> ERROR: modpost: "ietf_dscp_to_ieee8021q_tt" [drivers/net/dsa/microchip/ksz_switch.ko] undefined!
>> ERROR: modpost: "ieee8021q_tt_to_tc" [drivers/net/dsa/microchip/ksz_switch.ko] undefined!
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
On Fri, Mar 29, 2024 at 09:29:32AM +0000, Naveen Mamindlapalli wrote:
>
> > +int ksz_init_global_dscp_map(struct ksz_device *dev) {
> > + int reg, per_reg, ret, dscp;
> > + u8 data = 0;
> > + u8 mask;
> > +
> > + /* On KSZ9xxx variants, DSCP remapping is disabled by default.
> > + * Enable to have, predictable and reproducible behavior across
> > + * different devices.
> > + */
> > + if (!is_ksz8(dev)) {
> > + ret = ksz_rmw8(dev, KSZ9477_REG_SW_MAC_TOS_CTRL,
> > + KSZ9477_SW_TOS_DSCP_REMAP,
> > + KSZ9477_SW_TOS_DSCP_REMAP);
> > + if (ret)
> > + return ret;
> > + }
> > +
> > + ksz_get_dscp_prio_reg(dev, ®, &per_reg, &mask);
> > +
> > + for (dscp = 0; dscp < DSCP_MAX; dscp++) {
> > + int ipv, shift;
> > +
> > + /* Map DSCP to Traffic Type, which is corresponding to the
> > + * Internal Priority Value (IPV) in the switch.
> > + */
> > + if (!is_ksz8(dev)) {
> > + ipv = ietf_dscp_to_ieee8021q_tt(dscp);
> > + } else {
> > + ipv =
> > ieee8021q_tt_to_tc(ietf_dscp_to_ieee8021q_tt(dscp),
> > + dev->info->num_tx_queues);
> > + }
>
> No need for braces for single statement.
Please trim the email when replying. It is very easy to miss comments
when it is 99% quoted text with a couple of one-liners mixed in.
Andrew