Commit a745c697 authored by Kurt Kanzenbach's avatar Kurt Kanzenbach Committed by Jakub Kicinski
Browse files

net: dsa: hellcreek: Offload per-tc max SDU from tc-taprio



Add support for configuring the max SDU per priority and per port. If not
specified, keep the default.

Signed-off-by: default avatarKurt Kanzenbach <kurt@linutronix.de>
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 248376b1
Loading
Loading
Loading
Loading
+74 −2
Original line number Diff line number Diff line
@@ -128,6 +128,16 @@ static void hellcreek_select_prio(struct hellcreek *hellcreek, int prio)
	hellcreek_write(hellcreek, val, HR_PSEL);
}

static void hellcreek_select_port_prio(struct hellcreek *hellcreek, int port,
				       int prio)
{
	u16 val = port << HR_PSEL_PTWSEL_SHIFT;

	val |= prio << HR_PSEL_PRTCWSEL_SHIFT;

	hellcreek_write(hellcreek, val, HR_PSEL);
}

static void hellcreek_select_counter(struct hellcreek *hellcreek, int counter)
{
	u16 val = counter << HR_CSEL_SHIFT;
@@ -1537,6 +1547,45 @@ hellcreek_port_prechangeupper(struct dsa_switch *ds, int port,
	return ret;
}

static void hellcreek_setup_maxsdu(struct hellcreek *hellcreek, int port,
				   const struct tc_taprio_qopt_offload *schedule)
{
	int tc;

	for (tc = 0; tc < 8; ++tc) {
		u32 max_sdu = schedule->max_sdu[tc] + VLAN_ETH_HLEN - ETH_FCS_LEN;
		u16 val;

		if (!schedule->max_sdu[tc])
			continue;

		dev_dbg(hellcreek->dev, "Configure max-sdu %u for tc %d on port %d\n",
			max_sdu, tc, port);

		hellcreek_select_port_prio(hellcreek, port, tc);

		val = (max_sdu & HR_PTPRTCCFG_MAXSDU_MASK) << HR_PTPRTCCFG_MAXSDU_SHIFT;

		hellcreek_write(hellcreek, val, HR_PTPRTCCFG);
	}
}

static void hellcreek_reset_maxsdu(struct hellcreek *hellcreek, int port)
{
	int tc;

	for (tc = 0; tc < 8; ++tc) {
		u16 val;

		hellcreek_select_port_prio(hellcreek, port, tc);

		val = (HELLCREEK_DEFAULT_MAX_SDU & HR_PTPRTCCFG_MAXSDU_MASK)
			<< HR_PTPRTCCFG_MAXSDU_SHIFT;

		hellcreek_write(hellcreek, val, HR_PTPRTCCFG);
	}
}

static void hellcreek_setup_gcl(struct hellcreek *hellcreek, int port,
				const struct tc_taprio_qopt_offload *schedule)
{
@@ -1720,7 +1769,10 @@ static int hellcreek_port_set_schedule(struct dsa_switch *ds, int port,
	}
	hellcreek_port->current_schedule = taprio_offload_get(taprio);

	/* Then select port */
	/* Configure max sdu */
	hellcreek_setup_maxsdu(hellcreek, port, hellcreek_port->current_schedule);

	/* Select tdg */
	hellcreek_select_tgd(hellcreek, port);

	/* Enable gating and keep defaults */
@@ -1772,7 +1824,10 @@ static int hellcreek_port_del_schedule(struct dsa_switch *ds, int port)
		hellcreek_port->current_schedule = NULL;
	}

	/* Then select port */
	/* Reset max sdu */
	hellcreek_reset_maxsdu(hellcreek, port);

	/* Select tgd */
	hellcreek_select_tgd(hellcreek, port);

	/* Disable gating and return to regular switching flow */
@@ -1809,12 +1864,29 @@ static bool hellcreek_validate_schedule(struct hellcreek *hellcreek,
	return true;
}

static int hellcreek_tc_query_caps(struct tc_query_caps_base *base)
{
	switch (base->type) {
	case TC_SETUP_QDISC_TAPRIO: {
		struct tc_taprio_caps *caps = base->caps;

		caps->supports_queue_max_sdu = true;

		return 0;
	}
	default:
		return -EOPNOTSUPP;
	}
}

static int hellcreek_port_setup_tc(struct dsa_switch *ds, int port,
				   enum tc_setup_type type, void *type_data)
{
	struct hellcreek *hellcreek = ds->priv;

	switch (type) {
	case TC_QUERY_CAPS:
		return hellcreek_tc_query_caps(type_data);
	case TC_SETUP_QDISC_TAPRIO: {
		struct tc_taprio_qopt_offload *taprio = type_data;

+7 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#define HELLCREEK_VLAN_UNTAGGED_MEMBER	0x1
#define HELLCREEK_VLAN_TAGGED_MEMBER	0x3
#define HELLCREEK_NUM_EGRESS_QUEUES	8
#define HELLCREEK_DEFAULT_MAX_SDU	1536

/* Register definitions */
#define HR_MODID_C			(0 * 2)
@@ -72,6 +73,12 @@
#define HR_PRTCCFG_PCP_TC_MAP_SHIFT	0
#define HR_PRTCCFG_PCP_TC_MAP_MASK	GENMASK(2, 0)

#define HR_PTPRTCCFG			(0xa9 * 2)
#define HR_PTPRTCCFG_SET_QTRACK		BIT(15)
#define HR_PTPRTCCFG_REJECT		BIT(14)
#define HR_PTPRTCCFG_MAXSDU_SHIFT	0
#define HR_PTPRTCCFG_MAXSDU_MASK	GENMASK(10, 0)

#define HR_CSEL				(0x8d * 2)
#define HR_CSEL_SHIFT			0
#define HR_CSEL_MASK			GENMASK(7, 0)