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 <o.rempel@pengutronix.de> Acked-by: Arun Ramadoss <arun.ramadoss@microchip.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
328de4671d
commit
a16efc61d2
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
@ -2411,6 +2412,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);
|
||||
@ -2739,7 +2744,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)
|
||||
@ -3982,6 +3987,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_get_apptrust = ksz_port_get_apptrust,
|
||||
.port_set_apptrust = ksz_port_set_apptrust,
|
||||
};
|
||||
|
||||
struct ksz_device *ksz_switch_alloc(struct device *base, void *priv)
|
||||
|
@ -620,6 +620,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 ||
|
||||
|
543
drivers/net/dsa/microchip/ksz_dcb.c
Normal file
543
drivers/net/dsa/microchip/ksz_dcb.c
Normal file
@ -0,0 +1,543 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2024 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
|
||||
|
||||
#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 char * const ksz_supported_apptrust_variants[] = {
|
||||
"empty", "dscp", "pcp", "dscp pcp"
|
||||
};
|
||||
|
||||
static void ksz_get_default_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_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_get_apptrust_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_apptrust_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_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_default_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_ipvs)
|
||||
return -EINVAL;
|
||||
|
||||
ksz_get_default_port_prio_reg(dev, ®, &mask, &shift);
|
||||
|
||||
return ksz_prmw8(dev, port, reg, mask, (prio << shift) & mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, tt;
|
||||
|
||||
/* 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 {
|
||||
/* On KSZ8xxx variants we do not have IPV to queue
|
||||
* remapping table. We need to convert DSCP to Traffic
|
||||
* Type and then to queue.
|
||||
*/
|
||||
tt = ietf_dscp_to_ieee8021q_tt(dscp);
|
||||
if (tt < 0)
|
||||
return tt;
|
||||
|
||||
ipv = ieee8021q_tt_to_tc(tt, dev->info->num_tx_queues);
|
||||
}
|
||||
|
||||
if (ipv < 0)
|
||||
return ipv;
|
||||
|
||||
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, found;
|
||||
int j_prev = 0;
|
||||
|
||||
/* 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 err_sel_not_vaild;
|
||||
|
||||
j_prev = j;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
goto err_sel_not_vaild;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_sel_not_vaild:
|
||||
ksz_apptrust_error(dev);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_apptrust_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_apptrust_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);
|
||||
if (ipv < 0)
|
||||
return ipv;
|
||||
} 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;
|
||||
}
|
21
drivers/net/dsa/microchip/ksz_dcb.h
Normal file
21
drivers/net/dsa/microchip/ksz_dcb.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2024 Pengutronix, Oleksij Rempel <kernel@pengutronix.de> */
|
||||
|
||||
#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 */
|
Loading…
x
Reference in New Issue
Block a user