Commit 363f98b9 authored by Horatiu Vultur's avatar Horatiu Vultur Committed by Paolo Abeni

net: lan966x: Add support for PCP rewrite

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.
Reviewed-by: default avatarDaniel Machon <daniel.machon@microchip.com>
Signed-off-by: default avatarHoratiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent f8ba50ea
......@@ -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;
......@@ -252,11 +268,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)
......
......@@ -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;
};
......
......@@ -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)
......
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