Commit 9f481cea authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'ksz-dcb-dscp'



Oleksij Rempel says:

====================
add DCB and DSCP support for KSZ switches

This patch series is aimed at improving support for DCB (Data Center
Bridging) and DSCP (Differentiated Services Code Point) on KSZ switches.

The main goal is to introduce global DSCP and PCP (Priority Code Point)
mapping support, addressing the limitation of KSZ switches not having
per-port DSCP priority mapping. This involves extending the DSA
framework with new callbacks for managing trust settings for global DSCP
and PCP maps. Additionally, we introduce IEEE 802.1q helpers for default
configurations, benefiting other drivers too.

Change logs are in separate patches.

Compared to v6 this series includes some new patches for DSCP global
mapping support and QoS selftest script for KSZ9477 switches.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 09ca9940 cbc7afff
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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 −1
Original line number Diff line number Diff line
# 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
+1 −0
Original line number Diff line number Diff line
@@ -58,5 +58,6 @@ void ksz8_phylink_mac_link_up(struct phylink_config *config,
			      struct phy_device *phydev, unsigned int mode,
			      phy_interface_t interface, int speed, int duplex,
			      bool tx_pause, bool rx_pause);
int ksz8_all_queues_split(struct ksz_device *dev, int queues);

#endif
+71 −35
Original line number Diff line number Diff line
@@ -127,37 +127,71 @@ int ksz8_change_mtu(struct ksz_device *dev, int port, int mtu)
	return -EOPNOTSUPP;
}

static void ksz8795_set_prio_queue(struct ksz_device *dev, int port, int queue)
static int ksz8_port_queue_split(struct ksz_device *dev, int port, int queues)
{
	u8 hi, lo;
	u8 mask_4q, mask_2q;
	u8 reg_4q, reg_2q;
	u8 data_4q = 0;
	u8 data_2q = 0;
	int ret;

	/* Number of queues can only be 1, 2, or 4. */
	switch (queue) {
	case 4:
	case 3:
		queue = PORT_QUEUE_SPLIT_4;
		break;
	case 2:
		queue = PORT_QUEUE_SPLIT_2;
		break;
	default:
		queue = PORT_QUEUE_SPLIT_1;
	if (ksz_is_ksz88x3(dev)) {
		mask_4q = KSZ8873_PORT_4QUEUE_SPLIT_EN;
		mask_2q = KSZ8873_PORT_2QUEUE_SPLIT_EN;
		reg_4q = REG_PORT_CTRL_0;
		reg_2q = REG_PORT_CTRL_2;

		/* KSZ8795 family switches have Weighted Fair Queueing (WFQ)
		 * enabled by default. Enable it for KSZ8873 family switches
		 * too. Default value for KSZ8873 family is strict priority,
		 * which should be enabled by using TC_SETUP_QDISC_ETS, not
		 * by default.
		 */
		ret = ksz_rmw8(dev, REG_SW_CTRL_3, WEIGHTED_FAIR_QUEUE_ENABLE,
			       WEIGHTED_FAIR_QUEUE_ENABLE);
		if (ret)
			return ret;
	} else {
		mask_4q = KSZ8795_PORT_4QUEUE_SPLIT_EN;
		mask_2q = KSZ8795_PORT_2QUEUE_SPLIT_EN;
		reg_4q = REG_PORT_CTRL_13;
		reg_2q = REG_PORT_CTRL_0;

		/* TODO: this is legacy from initial KSZ8795 driver, should be
		 * moved to appropriate place in the future.
		 */
		ret = ksz_rmw8(dev, REG_SW_CTRL_19,
			       SW_OUT_RATE_LIMIT_QUEUE_BASED,
			       SW_OUT_RATE_LIMIT_QUEUE_BASED);
		if (ret)
			return ret;
	}
	ksz_pread8(dev, port, REG_PORT_CTRL_0, &lo);
	ksz_pread8(dev, port, P_DROP_TAG_CTRL, &hi);
	lo &= ~PORT_QUEUE_SPLIT_L;
	if (queue & PORT_QUEUE_SPLIT_2)
		lo |= PORT_QUEUE_SPLIT_L;
	hi &= ~PORT_QUEUE_SPLIT_H;
	if (queue & PORT_QUEUE_SPLIT_4)
		hi |= PORT_QUEUE_SPLIT_H;
	ksz_pwrite8(dev, port, REG_PORT_CTRL_0, lo);
	ksz_pwrite8(dev, port, P_DROP_TAG_CTRL, hi);

	/* Default is port based for egress rate limit. */
	if (queue != PORT_QUEUE_SPLIT_1)
		ksz_cfg(dev, REG_SW_CTRL_19, SW_OUT_RATE_LIMIT_QUEUE_BASED,
			true);
	if (queues == 4)
		data_4q = mask_4q;
	else if (queues == 2)
		data_2q = mask_2q;

	ret = ksz_prmw8(dev, port, reg_4q, mask_4q, data_4q);
	if (ret)
		return ret;

	return ksz_prmw8(dev, port, reg_2q, mask_2q, data_2q);
}

int ksz8_all_queues_split(struct ksz_device *dev, int queues)
{
	struct dsa_switch *ds = dev->ds;
	const struct dsa_port *dp;

	dsa_switch_for_each_port(dp, ds) {
		int ret = ksz8_port_queue_split(dev, dp->index, queues);

		if (ret)
			return ret;
	}

	return 0;
}

void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt)
@@ -1513,6 +1547,7 @@ void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port)
{
	struct dsa_switch *ds = dev->ds;
	const u32 *masks;
	int queues;
	u8 member;

	masks = dev->info->masks;
@@ -1520,19 +1555,20 @@ void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port)
	/* enable broadcast storm limit */
	ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true);

	if (!ksz_is_ksz88x3(dev))
		ksz8795_set_prio_queue(dev, port, 4);
	/* For KSZ88x3 enable only one queue by default, otherwise we won't
	 * be able to get rid of PCP prios on Port 2.
	 */
	if (ksz_is_ksz88x3(dev))
		queues = 1;
	else
		queues = dev->info->num_tx_queues;

	/* disable DiffServ priority */
	ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_DIFFSERV_ENABLE, false);
	ksz8_port_queue_split(dev, port, queues);

	/* replace priority */
	ksz_port_cfg(dev, port, P_802_1P_CTRL,
		     masks[PORT_802_1P_REMAPPING], false);

	/* enable 802.1p priority */
	ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_ENABLE, true);

	if (cpu_port)
		member = dsa_user_ports(ds);
	else
+4 −5
Original line number Diff line number Diff line
@@ -124,7 +124,8 @@
#define PORT_BASED_PRIO_3		3
#define PORT_INSERT_TAG			BIT(2)
#define PORT_REMOVE_TAG			BIT(1)
#define PORT_QUEUE_SPLIT_L		BIT(0)
#define KSZ8795_PORT_2QUEUE_SPLIT_EN	BIT(0)
#define KSZ8873_PORT_4QUEUE_SPLIT_EN	BIT(0)

#define REG_PORT_1_CTRL_1		0x11
#define REG_PORT_2_CTRL_1		0x21
@@ -143,6 +144,7 @@
#define REG_PORT_4_CTRL_2		0x42
#define REG_PORT_5_CTRL_2		0x52

#define KSZ8873_PORT_2QUEUE_SPLIT_EN	BIT(7)
#define PORT_INGRESS_FILTER		BIT(6)
#define PORT_DISCARD_NON_VID		BIT(5)
#define PORT_FORCE_FLOW_CTRL		BIT(4)
@@ -463,10 +465,7 @@
#define REG_PORT_4_CTRL_13		0xE1
#define REG_PORT_5_CTRL_13		0xF1

#define PORT_QUEUE_SPLIT_H		BIT(1)
#define PORT_QUEUE_SPLIT_1		0
#define PORT_QUEUE_SPLIT_2		1
#define PORT_QUEUE_SPLIT_4		2
#define KSZ8795_PORT_4QUEUE_SPLIT_EN	BIT(1)
#define PORT_DROP_TAG			BIT(0)

#define REG_PORT_1_CTRL_14		0xB2
Loading