mirror of
https://github.com/torvalds/linux.git
synced 2026-07-29 10:41:49 +02:00
Merge branch 'net-dsa-yt921x-add-port-tbf-support'
David Yang says: ==================== net: dsa: yt921x: Add port TBF support ==================== Link: https://patch.msgid.link/20260521010320.208138-1-mmyangfl@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
24822968aa
|
|
@ -24,6 +24,7 @@
|
|||
#include <net/dsa.h>
|
||||
#include <net/dscp.h>
|
||||
#include <net/ieee8021q.h>
|
||||
#include <net/pkt_cls.h>
|
||||
|
||||
#include "yt921x.h"
|
||||
|
||||
|
|
@ -1272,6 +1273,17 @@ yt921x_marker_tfm_police(struct yt921x_marker *marker,
|
|||
priv, port, extack);
|
||||
}
|
||||
|
||||
static int
|
||||
yt921x_marker_tfm_shape(struct yt921x_marker *marker, u64 rate, u64 burst,
|
||||
unsigned int flags, struct yt921x_priv *priv, int port,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
return yt921x_marker_tfm(marker, rate, burst, flags,
|
||||
priv->port_shape_slot_ns, YT921X_SHAPE_CIR_MAX,
|
||||
YT921X_SHAPE_CBS_MAX, YT921X_SHAPE_UNIT_MAX,
|
||||
priv, port, extack);
|
||||
}
|
||||
|
||||
static int
|
||||
yt921x_police_validate(const struct flow_action_police *police,
|
||||
const struct flow_action *action,
|
||||
|
|
@ -1378,6 +1390,73 @@ yt921x_dsa_port_policer_add(struct dsa_switch *ds, int port,
|
|||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
yt921x_dsa_port_setup_tc_tbf_port(struct dsa_switch *ds, int port,
|
||||
const struct tc_tbf_qopt_offload *qopt)
|
||||
{
|
||||
struct yt921x_priv *priv = to_yt921x_priv(ds);
|
||||
struct netlink_ext_ack *extack = qopt->extack;
|
||||
u32 ctrls[2];
|
||||
int res;
|
||||
|
||||
if (qopt->parent != TC_H_ROOT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (qopt->command) {
|
||||
case TC_TBF_STATS:
|
||||
/* Unfortunately the convention for TC_*_STATS is a mess,
|
||||
* neither 0 nor -EOPNOTSUPP is perfect here.
|
||||
*/
|
||||
return -EOPNOTSUPP;
|
||||
case TC_TBF_DESTROY:
|
||||
ctrls[0] = 0;
|
||||
ctrls[1] = 0;
|
||||
break;
|
||||
case TC_TBF_REPLACE: {
|
||||
const struct tc_tbf_qopt_offload_replace_params *p;
|
||||
struct yt921x_marker marker;
|
||||
|
||||
p = &qopt->replace_params;
|
||||
|
||||
res = yt921x_marker_tfm_shape(&marker, p->rate.rate_bytes_ps,
|
||||
p->max_size,
|
||||
YT921X_MARKER_SINGLE_BUCKET,
|
||||
priv, port, extack);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
ctrls[0] = YT921X_PORT_SHAPE_CTRLa_CIR(marker.cir) |
|
||||
YT921X_PORT_SHAPE_CTRLa_CBS(marker.cbs);
|
||||
ctrls[1] = YT921X_PORT_SHAPE_CTRLb_UNIT(marker.unit) |
|
||||
YT921X_PORT_SHAPE_CTRLb_EN;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
mutex_lock(&priv->reg_lock);
|
||||
res = yt921x_reg64_write(priv, YT921X_PORTn_SHAPE_CTRL(port), ctrls);
|
||||
mutex_unlock(&priv->reg_lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
yt921x_dsa_port_setup_tc(struct dsa_switch *ds, int port,
|
||||
enum tc_setup_type type, void *type_data)
|
||||
{
|
||||
switch (type) {
|
||||
case TC_SETUP_QDISC_TBF: {
|
||||
const struct tc_tbf_qopt_offload *qopt = type_data;
|
||||
|
||||
return yt921x_dsa_port_setup_tc_tbf_port(ds, port, qopt);
|
||||
}
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
yt921x_mirror_del(struct yt921x_priv *priv, int port, bool ingress)
|
||||
{
|
||||
|
|
@ -3523,6 +3602,13 @@ static int yt921x_chip_setup_tc(struct yt921x_priv *priv)
|
|||
return res;
|
||||
priv->meter_slot_ns = ctrl * op_ns;
|
||||
|
||||
ctrl = max(priv->port_shape_slot_ns / op_ns,
|
||||
YT921X_PORT_SHAPE_SLOT_MIN);
|
||||
res = yt921x_reg_write(priv, YT921X_PORT_SHAPE_SLOT, ctrl);
|
||||
if (res)
|
||||
return res;
|
||||
priv->port_shape_slot_ns = ctrl * op_ns;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3679,6 +3765,7 @@ static const struct dsa_switch_ops yt921x_dsa_switch_ops = {
|
|||
/* rate */
|
||||
.port_policer_del = yt921x_dsa_port_policer_del,
|
||||
.port_policer_add = yt921x_dsa_port_policer_add,
|
||||
.port_setup_tc = yt921x_dsa_port_setup_tc,
|
||||
/* hsr */
|
||||
.port_hsr_leave = dsa_port_simple_hsr_leave,
|
||||
.port_hsr_join = dsa_port_simple_hsr_join,
|
||||
|
|
|
|||
|
|
@ -531,6 +531,19 @@ enum yt921x_app_selector {
|
|||
#define YT921X_MIRROR_PORT_M GENMASK(3, 0)
|
||||
#define YT921X_MIRROR_PORT(x) FIELD_PREP(YT921X_MIRROR_PORT_M, (x))
|
||||
|
||||
#define YT921X_PORT_SHAPE_SLOT 0x34000c
|
||||
#define YT921X_PORT_SHAPE_SLOT_SLOT_M GENMASK(11, 0)
|
||||
#define YT921X_PORTn_SHAPE_CTRL(port) (0x354000 + 8 * (port))
|
||||
#define YT921X_PORT_SHAPE_CTRLb_EN BIT(4)
|
||||
#define YT921X_PORT_SHAPE_CTRLb_PKT_MODE BIT(3) /* 0: byte rate mode */
|
||||
#define YT921X_PORT_SHAPE_CTRLb_UNIT_M GENMASK(2, 0)
|
||||
#define YT921X_PORT_SHAPE_CTRLb_UNIT(x) FIELD_PREP(YT921X_PORT_SHAPE_CTRLb_UNIT_M, (x))
|
||||
#define YT921X_PORT_SHAPE_CTRLa_CBS_M GENMASK(31, 18)
|
||||
#define YT921X_PORT_SHAPE_CTRLa_CBS(x) FIELD_PREP(YT921X_PORT_SHAPE_CTRLa_CBS_M, (x))
|
||||
#define YT921X_PORT_SHAPE_CTRLa_CIR_M GENMASK(17, 0)
|
||||
#define YT921X_PORT_SHAPE_CTRLa_CIR(x) FIELD_PREP(YT921X_PORT_SHAPE_CTRLa_CIR_M, (x))
|
||||
#define YT921X_PORTn_SHAPE_STAT(port) (0x356000 + 4 * (port))
|
||||
|
||||
#define YT921X_EDATA_EXTMODE 0xfb
|
||||
#define YT921X_EDATA_LEN 0x100
|
||||
|
||||
|
|
@ -556,6 +569,10 @@ enum yt921x_fdb_entry_status {
|
|||
#define YT921X_METER_UNIT_MAX ((1 << 3) - 1)
|
||||
#define YT921X_METER_CIR_MAX ((1 << 18) - 1)
|
||||
#define YT921X_METER_CBS_MAX ((1 << 16) - 1)
|
||||
#define YT921X_PORT_SHAPE_SLOT_MIN 80
|
||||
#define YT921X_SHAPE_UNIT_MAX ((1 << 3) - 1)
|
||||
#define YT921X_SHAPE_CIR_MAX ((1 << 18) - 1)
|
||||
#define YT921X_SHAPE_CBS_MAX ((1 << 14) - 1)
|
||||
|
||||
#define YT921X_LAG_NUM 2
|
||||
#define YT921X_LAG_PORT_NUM 4
|
||||
|
|
@ -652,6 +669,7 @@ struct yt921x_priv {
|
|||
|
||||
const struct yt921x_info *info;
|
||||
unsigned int meter_slot_ns;
|
||||
unsigned int port_shape_slot_ns;
|
||||
/* cache of dsa_cpu_ports(ds) */
|
||||
u16 cpu_ports_mask;
|
||||
unsigned char cycle_ns;
|
||||
|
|
|
|||
|
|
@ -1046,6 +1046,7 @@ struct tc_tbf_qopt_offload_replace_params {
|
|||
};
|
||||
|
||||
struct tc_tbf_qopt_offload {
|
||||
struct netlink_ext_ack *extack;
|
||||
enum tc_tbf_command command;
|
||||
u32 handle;
|
||||
u32 parent;
|
||||
|
|
|
|||
|
|
@ -859,7 +859,7 @@ void qdisc_offload_graft_helper(struct net_device *dev, struct Qdisc *sch,
|
|||
any_qdisc_is_offloaded |= old && old->flags & TCQ_F_OFFLOADED;
|
||||
|
||||
if (any_qdisc_is_offloaded)
|
||||
NL_SET_ERR_MSG(extack, "Offloading graft operation failed.");
|
||||
NL_SET_ERR_MSG_WEAK(extack, "Offloading graft operation failed.");
|
||||
}
|
||||
EXPORT_SYMBOL(qdisc_offload_graft_helper);
|
||||
|
||||
|
|
|
|||
|
|
@ -139,7 +139,8 @@ static u64 psched_ns_t2l(const struct psched_ratecfg *r,
|
|||
return len;
|
||||
}
|
||||
|
||||
static void tbf_offload_change(struct Qdisc *sch)
|
||||
static void tbf_offload_change(struct Qdisc *sch,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct tbf_sched_data *q = qdisc_priv(sch);
|
||||
struct net_device *dev = qdisc_dev(sch);
|
||||
|
|
@ -148,6 +149,7 @@ static void tbf_offload_change(struct Qdisc *sch)
|
|||
if (!tc_can_offload(dev) || !dev->netdev_ops->ndo_setup_tc)
|
||||
return;
|
||||
|
||||
qopt.extack = extack;
|
||||
qopt.command = TC_TBF_REPLACE;
|
||||
qopt.handle = sch->handle;
|
||||
qopt.parent = sch->parent;
|
||||
|
|
@ -166,6 +168,7 @@ static void tbf_offload_destroy(struct Qdisc *sch)
|
|||
if (!tc_can_offload(dev) || !dev->netdev_ops->ndo_setup_tc)
|
||||
return;
|
||||
|
||||
qopt.extack = NULL;
|
||||
qopt.command = TC_TBF_DESTROY;
|
||||
qopt.handle = sch->handle;
|
||||
qopt.parent = sch->parent;
|
||||
|
|
@ -176,6 +179,7 @@ static int tbf_offload_dump(struct Qdisc *sch)
|
|||
{
|
||||
struct tc_tbf_qopt_offload qopt;
|
||||
|
||||
qopt.extack = NULL;
|
||||
qopt.command = TC_TBF_STATS;
|
||||
qopt.handle = sch->handle;
|
||||
qopt.parent = sch->parent;
|
||||
|
|
@ -193,6 +197,7 @@ static void tbf_offload_graft(struct Qdisc *sch, struct Qdisc *new,
|
|||
.parent = sch->parent,
|
||||
.child_handle = new->handle,
|
||||
.command = TC_TBF_GRAFT,
|
||||
.extack = extack,
|
||||
};
|
||||
|
||||
qdisc_offload_graft_helper(qdisc_dev(sch), sch, new, old,
|
||||
|
|
@ -477,7 +482,7 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt,
|
|||
qdisc_put(old);
|
||||
err = 0;
|
||||
|
||||
tbf_offload_change(sch);
|
||||
tbf_offload_change(sch, extack);
|
||||
done:
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user