Messages in this thread Patch in this message | | | From | Horatiu Vultur <> | Subject | [PATCH net-next 6/7] net: lan966x: Add support for PCP rewrite | Date | Sun, 14 May 2023 22:10:28 +0200 |
| |
Add support for rewrite of PCP and DEI value, based on QoS and DP level.
The DCB rewrite table is queried for mappings between priority and PCP/DEI. The classified DP level is then encoded in the DEI bit, if a mapping for DEI exists.
Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com> --- .../ethernet/microchip/lan966x/lan966x_dcb.c | 61 ++++++++++++++++++- .../ethernet/microchip/lan966x/lan966x_main.h | 10 +++ .../ethernet/microchip/lan966x/lan966x_port.c | 37 +++++++++++ 3 files changed, 107 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_dcb.c b/drivers/net/ethernet/microchip/lan966x/lan966x_dcb.c index d86369dd2d9b7..56a2fad406333 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_dcb.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_dcb.c @@ -46,9 +46,11 @@ static bool lan966x_dcb_apptrust_contains(int portno, u8 selector) static void lan966x_dcb_app_update(struct net_device *dev) { + struct dcb_rewr_prio_pcp_map pcp_rewr_map = {0}; struct lan966x_port *port = netdev_priv(dev); struct lan966x_port_qos qos = {0}; struct dcb_app app_itr; + bool pcp_rewr = false; /* Get pcp ingress mapping */ for (int i = 0; i < ARRAY_SIZE(qos.pcp.map); i++) { @@ -69,10 +71,24 @@ static void lan966x_dcb_app_update(struct net_device *dev) if (qos.default_prio) qos.default_prio = fls(qos.default_prio) - 1; + /* Get pcp rewrite mapping */ + dcb_getrewr_prio_pcp_mask_map(dev, &pcp_rewr_map); + for (int i = 0; i < ARRAY_SIZE(pcp_rewr_map.map); i++) { + if (!pcp_rewr_map.map[i]) + continue; + + pcp_rewr = true; + qos.pcp_rewr.map[i] = fls(pcp_rewr_map.map[i]) - 1; + } + /* Enable use of pcp for queue classification */ - if (lan966x_dcb_apptrust_contains(port->chip_port, DCB_APP_SEL_PCP)) + if (lan966x_dcb_apptrust_contains(port->chip_port, DCB_APP_SEL_PCP)) { qos.pcp.enable = true; + if (pcp_rewr) + qos.pcp_rewr.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; @@ -253,11 +269,54 @@ static int lan966x_dcb_getapptrust(struct net_device *dev, u8 *selectors, return 0; } +static int lan966x_dcb_delrewr(struct net_device *dev, struct dcb_app *app) +{ + int err; + + err = dcb_delrewr(dev, app); + if (err < 0) + return err; + + lan966x_dcb_app_update(dev); + + return 0; +} + +static int lan966x_dcb_setrewr(struct net_device *dev, struct dcb_app *app) +{ + struct dcb_app app_itr; + u16 proto; + int err; + + err = lan966x_dcb_app_validate(dev, app); + if (err) + goto out; + + /* Delete current mapping, if it exists. */ + proto = dcb_getrewr(dev, app); + if (proto) { + app_itr = *app; + app_itr.protocol = proto; + lan966x_dcb_delrewr(dev, &app_itr); + } + + err = dcb_setrewr(dev, app); + if (err) + goto out; + + lan966x_dcb_app_update(dev); + +out: + return err; +} + static const struct dcbnl_rtnl_ops lan966x_dcbnl_ops = { .ieee_setapp = lan966x_dcb_ieee_setapp, .ieee_delapp = lan966x_dcb_ieee_delapp, .dcbnl_setapptrust = lan966x_dcb_setapptrust, .dcbnl_getapptrust = lan966x_dcb_getapptrust, + .dcbnl_setrewr = lan966x_dcb_setrewr, + .dcbnl_delrewr = lan966x_dcb_delrewr, }; void lan966x_dcb_init(struct lan966x *lan966x) diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h index 53711d5380166..16b0149ac2b5d 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h @@ -111,6 +111,10 @@ #define LAN966X_PORT_QOS_DSCP_COUNT 64 +/* Port PCP rewrite mode */ +#define LAN966X_PORT_REW_TAG_CTRL_CLASSIFIED 0 +#define LAN966X_PORT_REW_TAG_CTRL_MAPPED 2 + /* MAC table entry types. * ENTRYTYPE_NORMAL is subject to aging. * ENTRYTYPE_LOCKED is not subject to aging. @@ -409,9 +413,15 @@ struct lan966x_port_qos_dscp { bool enable; }; +struct lan966x_port_qos_pcp_rewr { + u16 map[NUM_PRIO_QUEUES]; + bool enable; +}; + struct lan966x_port_qos { struct lan966x_port_qos_pcp pcp; struct lan966x_port_qos_dscp dscp; + struct lan966x_port_qos_pcp_rewr pcp_rewr; u8 default_prio; }; diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_port.c b/drivers/net/ethernet/microchip/lan966x/lan966x_port.c index a6608876b71ef..6887746d081f6 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_port.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_port.c @@ -463,12 +463,49 @@ static int lan966x_port_qos_default_set(struct lan966x_port *port, return 0; } +static void lan966x_port_qos_pcp_rewr_set(struct lan966x_port *port, + struct lan966x_port_qos_pcp_rewr *qos) +{ + u8 mode = LAN966X_PORT_REW_TAG_CTRL_CLASSIFIED; + u8 pcp, dei; + + if (qos->enable) + mode = LAN966X_PORT_REW_TAG_CTRL_MAPPED; + + /* Map the values only if it is enabled otherwise will be the classified + * value + */ + lan_rmw(REW_TAG_CFG_TAG_PCP_CFG_SET(mode) | + REW_TAG_CFG_TAG_DEI_CFG_SET(mode), + REW_TAG_CFG_TAG_PCP_CFG | + REW_TAG_CFG_TAG_DEI_CFG, + port->lan966x, REW_TAG_CFG(port->chip_port)); + + /* Map each value to pcp and dei */ + for (int i = 0; i < ARRAY_SIZE(qos->map); i++) { + pcp = qos->map[i]; + if (pcp > LAN966X_PORT_QOS_PCP_COUNT) + dei = 1; + else + dei = 0; + + lan_rmw(REW_PCP_DEI_CFG_DEI_QOS_VAL_SET(dei) | + REW_PCP_DEI_CFG_PCP_QOS_VAL_SET(pcp), + REW_PCP_DEI_CFG_DEI_QOS_VAL | + REW_PCP_DEI_CFG_PCP_QOS_VAL, + port->lan966x, + REW_PCP_DEI_CFG(port->chip_port, + i + dei * LAN966X_PORT_QOS_PCP_COUNT)); + } +} + 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); lan966x_port_qos_default_set(port, qos); + lan966x_port_qos_pcp_rewr_set(port, &qos->pcp_rewr); } void lan966x_port_init(struct lan966x_port *port) -- 2.38.0
| |