net: lan966x: Add support for offloading dscp table
authorHoratiu Vultur <horatiu.vultur@microchip.com>
Tue, 16 May 2023 20:14:05 +0000 (22:14 +0200)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 18 May 2023 13:32:10 +0000 (15:32 +0200)
Add support for offloading dscp app entries. The dscp values are global
for all lan966x ports.

Reviewed-by: Daniel Machon <daniel.machon@microchip.com>
Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/microchip/lan966x/lan966x_dcb.c
drivers/net/ethernet/microchip/lan966x/lan966x_main.h
drivers/net/ethernet/microchip/lan966x/lan966x_port.c

index d6210c7..17cec9e 100644 (file)
@@ -57,19 +57,62 @@ static void lan966x_dcb_app_update(struct net_device *dev)
                qos.pcp.map[i] = dcb_getapp(dev, &app_itr);
        }
 
+       /* Get dscp ingress mapping */
+       for (int i = 0; i < ARRAY_SIZE(qos.dscp.map); i++) {
+               app_itr.selector = IEEE_8021QAZ_APP_SEL_DSCP;
+               app_itr.protocol = i;
+               qos.dscp.map[i] = dcb_getapp(dev, &app_itr);
+       }
+
        /* Enable use of pcp for queue classification */
        if (lan966x_dcb_apptrust_contains(port->chip_port, DCB_APP_SEL_PCP))
                qos.pcp.enable = true;
 
+       /* Enable use of dscp for queue classification */
+       if (lan966x_dcb_apptrust_contains(port->chip_port, IEEE_8021QAZ_APP_SEL_DSCP))
+               qos.dscp.enable = true;
+
        lan966x_port_qos_set(port, &qos);
 }
 
+/* DSCP mapping is global for all ports, so set and delete app entries are
+ * replicated for each port.
+ */
+static int lan966x_dcb_ieee_dscp_setdel(struct net_device *dev,
+                                       struct dcb_app *app,
+                                       int (*setdel)(struct net_device *,
+                                                     struct dcb_app *))
+{
+       struct lan966x_port *port = netdev_priv(dev);
+       struct lan966x *lan966x = port->lan966x;
+       int err;
+
+       for (int i = 0; i < NUM_PHYS_PORTS; i++) {
+               port = lan966x->ports[i];
+               if (!port)
+                       continue;
+
+               err = setdel(port->dev, app);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
 static int lan966x_dcb_app_validate(struct net_device *dev,
                                    const struct dcb_app *app)
 {
        int err = 0;
 
        switch (app->selector) {
+       /* Dscp checks */
+       case IEEE_8021QAZ_APP_SEL_DSCP:
+               if (app->protocol >= LAN966X_PORT_QOS_DSCP_COUNT)
+                       err = -EINVAL;
+               else if (app->priority >= NUM_PRIO_QUEUES)
+                       err = -ERANGE;
+               break;
        /* Pcp checks */
        case DCB_APP_SEL_PCP:
                if (app->protocol >= LAN966X_PORT_QOS_PCP_DEI_COUNT)
@@ -93,8 +136,12 @@ static int lan966x_dcb_ieee_delapp(struct net_device *dev, struct dcb_app *app)
 {
        int err;
 
-       err = dcb_ieee_delapp(dev, app);
-       if (err < 0)
+       if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
+               err = lan966x_dcb_ieee_dscp_setdel(dev, app, dcb_ieee_delapp);
+       else
+               err = dcb_ieee_delapp(dev, app);
+
+       if (err)
                return err;
 
        lan966x_dcb_app_update(dev);
@@ -117,10 +164,14 @@ static int lan966x_dcb_ieee_setapp(struct net_device *dev, struct dcb_app *app)
        if (prio) {
                app_itr = *app;
                app_itr.priority = prio;
-               dcb_ieee_delapp(dev, &app_itr);
+               lan966x_dcb_ieee_delapp(dev, &app_itr);
        }
 
-       err = dcb_ieee_setapp(dev, app);
+       if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
+               err = lan966x_dcb_ieee_dscp_setdel(dev, app, dcb_ieee_setapp);
+       else
+               err = dcb_ieee_setapp(dev, app);
+
        if (err)
                return err;
 
index b9ca47a..8213440 100644 (file)
 #define LAN966X_PORT_QOS_PCP_DEI_COUNT \
        (LAN966X_PORT_QOS_PCP_COUNT + LAN966X_PORT_QOS_DEI_COUNT)
 
+#define LAN966X_PORT_QOS_DSCP_COUNT    64
+
 /* MAC table entry types.
  * ENTRYTYPE_NORMAL is subject to aging.
  * ENTRYTYPE_LOCKED is not subject to aging.
@@ -402,8 +404,14 @@ struct lan966x_port_qos_pcp {
        bool enable;
 };
 
+struct lan966x_port_qos_dscp {
+       u8 map[LAN966X_PORT_QOS_DSCP_COUNT];
+       bool enable;
+};
+
 struct lan966x_port_qos {
        struct lan966x_port_qos_pcp pcp;
+       struct lan966x_port_qos_dscp dscp;
 };
 
 struct lan966x_port {
index 0cee812..11c552e 100644 (file)
@@ -418,10 +418,36 @@ static void lan966x_port_qos_pcp_set(struct lan966x_port *port,
        }
 }
 
+static void lan966x_port_qos_dscp_set(struct lan966x_port *port,
+                                     struct lan966x_port_qos_dscp *qos)
+{
+       struct lan966x *lan966x = port->lan966x;
+
+       /* Enable/disable dscp for qos classification. */
+       lan_rmw(ANA_QOS_CFG_QOS_DSCP_ENA_SET(qos->enable),
+               ANA_QOS_CFG_QOS_DSCP_ENA,
+               lan966x, ANA_QOS_CFG(port->chip_port));
+
+       /* Map each dscp value to priority and dp */
+       for (int i = 0; i < ARRAY_SIZE(qos->map); i++)
+               lan_rmw(ANA_DSCP_CFG_DP_DSCP_VAL_SET(0) |
+                       ANA_DSCP_CFG_QOS_DSCP_VAL_SET(*(qos->map + i)),
+                       ANA_DSCP_CFG_DP_DSCP_VAL |
+                       ANA_DSCP_CFG_QOS_DSCP_VAL,
+                       lan966x, ANA_DSCP_CFG(i));
+
+       /* Set per-dscp trust */
+       for (int i = 0; i <  ARRAY_SIZE(qos->map); i++)
+               lan_rmw(ANA_DSCP_CFG_DSCP_TRUST_ENA_SET(qos->enable),
+                       ANA_DSCP_CFG_DSCP_TRUST_ENA,
+                       lan966x, ANA_DSCP_CFG(i));
+}
+
 void lan966x_port_qos_set(struct lan966x_port *port,
                          struct lan966x_port_qos *qos)
 {
        lan966x_port_qos_pcp_set(port, &qos->pcp);
+       lan966x_port_qos_dscp_set(port, &qos->dscp);
 }
 
 void lan966x_port_init(struct lan966x_port *port)