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

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's 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
...@@ -128,6 +128,16 @@ static void hellcreek_select_prio(struct hellcreek *hellcreek, int prio) ...@@ -128,6 +128,16 @@ static void hellcreek_select_prio(struct hellcreek *hellcreek, int prio)
hellcreek_write(hellcreek, val, HR_PSEL); 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) static void hellcreek_select_counter(struct hellcreek *hellcreek, int counter)
{ {
u16 val = counter << HR_CSEL_SHIFT; u16 val = counter << HR_CSEL_SHIFT;
...@@ -1537,6 +1547,45 @@ hellcreek_port_prechangeupper(struct dsa_switch *ds, int port, ...@@ -1537,6 +1547,45 @@ hellcreek_port_prechangeupper(struct dsa_switch *ds, int port,
return ret; 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, static void hellcreek_setup_gcl(struct hellcreek *hellcreek, int port,
const struct tc_taprio_qopt_offload *schedule) const struct tc_taprio_qopt_offload *schedule)
{ {
...@@ -1720,7 +1769,10 @@ static int hellcreek_port_set_schedule(struct dsa_switch *ds, int port, ...@@ -1720,7 +1769,10 @@ static int hellcreek_port_set_schedule(struct dsa_switch *ds, int port,
} }
hellcreek_port->current_schedule = taprio_offload_get(taprio); 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); hellcreek_select_tgd(hellcreek, port);
/* Enable gating and keep defaults */ /* Enable gating and keep defaults */
...@@ -1772,7 +1824,10 @@ static int hellcreek_port_del_schedule(struct dsa_switch *ds, int port) ...@@ -1772,7 +1824,10 @@ static int hellcreek_port_del_schedule(struct dsa_switch *ds, int port)
hellcreek_port->current_schedule = NULL; hellcreek_port->current_schedule = NULL;
} }
/* Then select port */ /* Reset max sdu */
hellcreek_reset_maxsdu(hellcreek, port);
/* Select tgd */
hellcreek_select_tgd(hellcreek, port); hellcreek_select_tgd(hellcreek, port);
/* Disable gating and return to regular switching flow */ /* Disable gating and return to regular switching flow */
...@@ -1809,12 +1864,29 @@ static bool hellcreek_validate_schedule(struct hellcreek *hellcreek, ...@@ -1809,12 +1864,29 @@ static bool hellcreek_validate_schedule(struct hellcreek *hellcreek,
return true; 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, static int hellcreek_port_setup_tc(struct dsa_switch *ds, int port,
enum tc_setup_type type, void *type_data) enum tc_setup_type type, void *type_data)
{ {
struct hellcreek *hellcreek = ds->priv; struct hellcreek *hellcreek = ds->priv;
switch (type) { switch (type) {
case TC_QUERY_CAPS:
return hellcreek_tc_query_caps(type_data);
case TC_SETUP_QDISC_TAPRIO: { case TC_SETUP_QDISC_TAPRIO: {
struct tc_taprio_qopt_offload *taprio = type_data; struct tc_taprio_qopt_offload *taprio = type_data;
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#define HELLCREEK_VLAN_UNTAGGED_MEMBER 0x1 #define HELLCREEK_VLAN_UNTAGGED_MEMBER 0x1
#define HELLCREEK_VLAN_TAGGED_MEMBER 0x3 #define HELLCREEK_VLAN_TAGGED_MEMBER 0x3
#define HELLCREEK_NUM_EGRESS_QUEUES 8 #define HELLCREEK_NUM_EGRESS_QUEUES 8
#define HELLCREEK_DEFAULT_MAX_SDU 1536
/* Register definitions */ /* Register definitions */
#define HR_MODID_C (0 * 2) #define HR_MODID_C (0 * 2)
...@@ -72,6 +73,12 @@ ...@@ -72,6 +73,12 @@
#define HR_PRTCCFG_PCP_TC_MAP_SHIFT 0 #define HR_PRTCCFG_PCP_TC_MAP_SHIFT 0
#define HR_PRTCCFG_PCP_TC_MAP_MASK GENMASK(2, 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 (0x8d * 2)
#define HR_CSEL_SHIFT 0 #define HR_CSEL_SHIFT 0
#define HR_CSEL_MASK GENMASK(7, 0) #define HR_CSEL_MASK GENMASK(7, 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment