mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-06 00:39:48 +00:00
net: lan966x: Add support for offloading dscp table
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>
This commit is contained in:
parent
10c71a97ee
commit
0c88d98108
3 changed files with 89 additions and 4 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -109,6 +109,8 @@
|
|||
#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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue