OSDN Git Service

net: dsa: add ops for devlink-sb
authorVladimir Oltean <vladimir.oltean@nxp.com>
Fri, 15 Jan 2021 02:11:13 +0000 (04:11 +0200)
committerJakub Kicinski <kuba@kernel.org>
Sat, 16 Jan 2021 04:02:34 +0000 (20:02 -0800)
Switches that care about QoS might have hardware support for reserving
buffer pools for individual ports or traffic classes, and configuring
their sizes and thresholds. Through devlink-sb (shared buffers), this is
all configurable, as well as their occupancy being viewable.

Add the plumbing in DSA for these operations.

Individual drivers still need to call devlink_sb_register() with the
shared buffers they want to expose. A helper was not created in DSA for
this purpose (unlike, say, dsa_devlink_params_register), since in my
opinion it does not bring any benefit over plainly calling
devlink_sb_register() directly.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/net/dsa.h
net/dsa/dsa2.c

index fa537af..2f5435d 100644 (file)
@@ -699,6 +699,40 @@ struct dsa_switch_ops {
        int     (*devlink_info_get)(struct dsa_switch *ds,
                                    struct devlink_info_req *req,
                                    struct netlink_ext_ack *extack);
+       int     (*devlink_sb_pool_get)(struct dsa_switch *ds,
+                                      unsigned int sb_index, u16 pool_index,
+                                      struct devlink_sb_pool_info *pool_info);
+       int     (*devlink_sb_pool_set)(struct dsa_switch *ds, unsigned int sb_index,
+                                      u16 pool_index, u32 size,
+                                      enum devlink_sb_threshold_type threshold_type,
+                                      struct netlink_ext_ack *extack);
+       int     (*devlink_sb_port_pool_get)(struct dsa_switch *ds, int port,
+                                           unsigned int sb_index, u16 pool_index,
+                                           u32 *p_threshold);
+       int     (*devlink_sb_port_pool_set)(struct dsa_switch *ds, int port,
+                                           unsigned int sb_index, u16 pool_index,
+                                           u32 threshold,
+                                           struct netlink_ext_ack *extack);
+       int     (*devlink_sb_tc_pool_bind_get)(struct dsa_switch *ds, int port,
+                                              unsigned int sb_index, u16 tc_index,
+                                              enum devlink_sb_pool_type pool_type,
+                                              u16 *p_pool_index, u32 *p_threshold);
+       int     (*devlink_sb_tc_pool_bind_set)(struct dsa_switch *ds, int port,
+                                              unsigned int sb_index, u16 tc_index,
+                                              enum devlink_sb_pool_type pool_type,
+                                              u16 pool_index, u32 threshold,
+                                              struct netlink_ext_ack *extack);
+       int     (*devlink_sb_occ_snapshot)(struct dsa_switch *ds,
+                                          unsigned int sb_index);
+       int     (*devlink_sb_occ_max_clear)(struct dsa_switch *ds,
+                                           unsigned int sb_index);
+       int     (*devlink_sb_occ_port_pool_get)(struct dsa_switch *ds, int port,
+                                               unsigned int sb_index, u16 pool_index,
+                                               u32 *p_cur, u32 *p_max);
+       int     (*devlink_sb_occ_tc_port_bind_get)(struct dsa_switch *ds, int port,
+                                                  unsigned int sb_index, u16 tc_index,
+                                                  enum devlink_sb_pool_type pool_type,
+                                                  u32 *p_cur, u32 *p_max);
 
        /*
         * MTU change functionality. Switches can also adjust their MRU through
index f98eb52..cc13549 100644 (file)
@@ -463,8 +463,165 @@ static int dsa_devlink_info_get(struct devlink *dl,
        return -EOPNOTSUPP;
 }
 
+static int dsa_devlink_sb_pool_get(struct devlink *dl,
+                                  unsigned int sb_index, u16 pool_index,
+                                  struct devlink_sb_pool_info *pool_info)
+{
+       struct dsa_switch *ds = dsa_devlink_to_ds(dl);
+
+       if (!ds->ops->devlink_sb_pool_get)
+               return -EOPNOTSUPP;
+
+       return ds->ops->devlink_sb_pool_get(ds, sb_index, pool_index,
+                                           pool_info);
+}
+
+static int dsa_devlink_sb_pool_set(struct devlink *dl, unsigned int sb_index,
+                                  u16 pool_index, u32 size,
+                                  enum devlink_sb_threshold_type threshold_type,
+                                  struct netlink_ext_ack *extack)
+{
+       struct dsa_switch *ds = dsa_devlink_to_ds(dl);
+
+       if (!ds->ops->devlink_sb_pool_set)
+               return -EOPNOTSUPP;
+
+       return ds->ops->devlink_sb_pool_set(ds, sb_index, pool_index, size,
+                                           threshold_type, extack);
+}
+
+static int dsa_devlink_sb_port_pool_get(struct devlink_port *dlp,
+                                       unsigned int sb_index, u16 pool_index,
+                                       u32 *p_threshold)
+{
+       struct dsa_switch *ds = dsa_devlink_port_to_ds(dlp);
+       int port = dsa_devlink_port_to_port(dlp);
+
+       if (!ds->ops->devlink_sb_port_pool_get)
+               return -EOPNOTSUPP;
+
+       return ds->ops->devlink_sb_port_pool_get(ds, port, sb_index,
+                                                pool_index, p_threshold);
+}
+
+static int dsa_devlink_sb_port_pool_set(struct devlink_port *dlp,
+                                       unsigned int sb_index, u16 pool_index,
+                                       u32 threshold,
+                                       struct netlink_ext_ack *extack)
+{
+       struct dsa_switch *ds = dsa_devlink_port_to_ds(dlp);
+       int port = dsa_devlink_port_to_port(dlp);
+
+       if (!ds->ops->devlink_sb_port_pool_set)
+               return -EOPNOTSUPP;
+
+       return ds->ops->devlink_sb_port_pool_set(ds, port, sb_index,
+                                                pool_index, threshold, extack);
+}
+
+static int
+dsa_devlink_sb_tc_pool_bind_get(struct devlink_port *dlp,
+                               unsigned int sb_index, u16 tc_index,
+                               enum devlink_sb_pool_type pool_type,
+                               u16 *p_pool_index, u32 *p_threshold)
+{
+       struct dsa_switch *ds = dsa_devlink_port_to_ds(dlp);
+       int port = dsa_devlink_port_to_port(dlp);
+
+       if (!ds->ops->devlink_sb_tc_pool_bind_get)
+               return -EOPNOTSUPP;
+
+       return ds->ops->devlink_sb_tc_pool_bind_get(ds, port, sb_index,
+                                                   tc_index, pool_type,
+                                                   p_pool_index, p_threshold);
+}
+
+static int
+dsa_devlink_sb_tc_pool_bind_set(struct devlink_port *dlp,
+                               unsigned int sb_index, u16 tc_index,
+                               enum devlink_sb_pool_type pool_type,
+                               u16 pool_index, u32 threshold,
+                               struct netlink_ext_ack *extack)
+{
+       struct dsa_switch *ds = dsa_devlink_port_to_ds(dlp);
+       int port = dsa_devlink_port_to_port(dlp);
+
+       if (!ds->ops->devlink_sb_tc_pool_bind_set)
+               return -EOPNOTSUPP;
+
+       return ds->ops->devlink_sb_tc_pool_bind_set(ds, port, sb_index,
+                                                   tc_index, pool_type,
+                                                   pool_index, threshold,
+                                                   extack);
+}
+
+static int dsa_devlink_sb_occ_snapshot(struct devlink *dl,
+                                      unsigned int sb_index)
+{
+       struct dsa_switch *ds = dsa_devlink_to_ds(dl);
+
+       if (!ds->ops->devlink_sb_occ_snapshot)
+               return -EOPNOTSUPP;
+
+       return ds->ops->devlink_sb_occ_snapshot(ds, sb_index);
+}
+
+static int dsa_devlink_sb_occ_max_clear(struct devlink *dl,
+                                       unsigned int sb_index)
+{
+       struct dsa_switch *ds = dsa_devlink_to_ds(dl);
+
+       if (!ds->ops->devlink_sb_occ_max_clear)
+               return -EOPNOTSUPP;
+
+       return ds->ops->devlink_sb_occ_max_clear(ds, sb_index);
+}
+
+static int dsa_devlink_sb_occ_port_pool_get(struct devlink_port *dlp,
+                                           unsigned int sb_index,
+                                           u16 pool_index, u32 *p_cur,
+                                           u32 *p_max)
+{
+       struct dsa_switch *ds = dsa_devlink_port_to_ds(dlp);
+       int port = dsa_devlink_port_to_port(dlp);
+
+       if (!ds->ops->devlink_sb_occ_port_pool_get)
+               return -EOPNOTSUPP;
+
+       return ds->ops->devlink_sb_occ_port_pool_get(ds, port, sb_index,
+                                                    pool_index, p_cur, p_max);
+}
+
+static int
+dsa_devlink_sb_occ_tc_port_bind_get(struct devlink_port *dlp,
+                                   unsigned int sb_index, u16 tc_index,
+                                   enum devlink_sb_pool_type pool_type,
+                                   u32 *p_cur, u32 *p_max)
+{
+       struct dsa_switch *ds = dsa_devlink_port_to_ds(dlp);
+       int port = dsa_devlink_port_to_port(dlp);
+
+       if (!ds->ops->devlink_sb_occ_tc_port_bind_get)
+               return -EOPNOTSUPP;
+
+       return ds->ops->devlink_sb_occ_tc_port_bind_get(ds, port,
+                                                       sb_index, tc_index,
+                                                       pool_type, p_cur,
+                                                       p_max);
+}
+
 static const struct devlink_ops dsa_devlink_ops = {
-       .info_get = dsa_devlink_info_get,
+       .info_get                       = dsa_devlink_info_get,
+       .sb_pool_get                    = dsa_devlink_sb_pool_get,
+       .sb_pool_set                    = dsa_devlink_sb_pool_set,
+       .sb_port_pool_get               = dsa_devlink_sb_port_pool_get,
+       .sb_port_pool_set               = dsa_devlink_sb_port_pool_set,
+       .sb_tc_pool_bind_get            = dsa_devlink_sb_tc_pool_bind_get,
+       .sb_tc_pool_bind_set            = dsa_devlink_sb_tc_pool_bind_set,
+       .sb_occ_snapshot                = dsa_devlink_sb_occ_snapshot,
+       .sb_occ_max_clear               = dsa_devlink_sb_occ_max_clear,
+       .sb_occ_port_pool_get           = dsa_devlink_sb_occ_port_pool_get,
+       .sb_occ_tc_port_bind_get        = dsa_devlink_sb_occ_tc_port_bind_get,
 };
 
 static int dsa_switch_setup(struct dsa_switch *ds)