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: Kurt Kanzenbach <kurt@linutronix.de>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Kurt Kanzenbach 2022-09-28 12:52:01 +03:00 committed by Jakub Kicinski
parent 248376b1b1
commit a745c69783
2 changed files with 81 additions and 2 deletions

View file

@ -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;

View file

@ -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)