Skip to content

Commit 8dcf69a

Browse files
DanielmachonPaolo Abeni
authored andcommitted
net: microchip: sparx5: add support for offloading dscp table
Add support for offloading dscp app entries. Dscp values are global for all ports on the sparx5 switch. Therefore, we replicate each dscp app entry per-port. Signed-off-by: Daniel Machon <daniel.machon@microchip.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent 23f8382 commit 8dcf69a

File tree

3 files changed

+116
-3
lines changed

3 files changed

+116
-3
lines changed

drivers/net/ethernet/microchip/sparx5/sparx5_dcb.c

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ static int sparx5_dcb_app_validate(struct net_device *dev,
4949
int err = 0;
5050

5151
switch (app->selector) {
52+
/* Dscp checks */
53+
case IEEE_8021QAZ_APP_SEL_DSCP:
54+
if (app->protocol >= SPARX5_PORT_QOS_DSCP_COUNT)
55+
err = -EINVAL;
56+
else if (app->priority >= SPX5_PRIOS)
57+
err = -ERANGE;
58+
break;
5259
/* Pcp checks */
5360
case DCB_APP_SEL_PCP:
5461
if (app->protocol >= SPARX5_PORT_QOS_PCP_DEI_COUNT)
@@ -119,17 +126,27 @@ static bool sparx5_dcb_apptrust_contains(int portno, u8 selector)
119126

120127
static int sparx5_dcb_app_update(struct net_device *dev)
121128
{
122-
struct dcb_app app_itr = { .selector = DCB_APP_SEL_PCP };
123129
struct sparx5_port *port = netdev_priv(dev);
130+
struct sparx5_port_qos_dscp_map *dscp_map;
124131
struct sparx5_port_qos_pcp_map *pcp_map;
125132
struct sparx5_port_qos qos = {0};
133+
struct dcb_app app_itr = {0};
126134
int portno = port->portno;
127135
int i;
128136

137+
dscp_map = &qos.dscp.map;
129138
pcp_map = &qos.pcp.map;
130139

140+
/* Get dscp ingress mapping */
141+
for (i = 0; i < ARRAY_SIZE(dscp_map->map); i++) {
142+
app_itr.selector = IEEE_8021QAZ_APP_SEL_DSCP;
143+
app_itr.protocol = i;
144+
dscp_map->map[i] = dcb_getapp(dev, &app_itr);
145+
}
146+
131147
/* Get pcp ingress mapping */
132148
for (i = 0; i < ARRAY_SIZE(pcp_map->map); i++) {
149+
app_itr.selector = DCB_APP_SEL_PCP;
133150
app_itr.protocol = i;
134151
pcp_map->map[i] = dcb_getapp(dev, &app_itr);
135152
}
@@ -140,9 +157,44 @@ static int sparx5_dcb_app_update(struct net_device *dev)
140157
qos.pcp.dp_enable = qos.pcp.qos_enable;
141158
}
142159

160+
/* Enable use of dscp for queue classification ? */
161+
if (sparx5_dcb_apptrust_contains(portno, IEEE_8021QAZ_APP_SEL_DSCP)) {
162+
qos.dscp.qos_enable = true;
163+
qos.dscp.dp_enable = qos.dscp.qos_enable;
164+
}
165+
143166
return sparx5_port_qos_set(port, &qos);
144167
}
145168

169+
/* Set or delete dscp app entry.
170+
*
171+
* Dscp mapping is global for all ports, so set and delete app entries are
172+
* replicated for each port.
173+
*/
174+
static int sparx5_dcb_ieee_dscp_setdel_app(struct net_device *dev,
175+
struct dcb_app *app, bool del)
176+
{
177+
struct sparx5_port *port = netdev_priv(dev);
178+
struct dcb_app apps[SPX5_PORTS];
179+
struct sparx5_port *port_itr;
180+
int err, i;
181+
182+
for (i = 0; i < SPX5_PORTS; i++) {
183+
port_itr = port->sparx5->ports[i];
184+
if (!port_itr)
185+
continue;
186+
memcpy(&apps[i], app, sizeof(struct dcb_app));
187+
if (del)
188+
err = dcb_ieee_delapp(port_itr->ndev, &apps[i]);
189+
else
190+
err = dcb_ieee_setapp(port_itr->ndev, &apps[i]);
191+
if (err)
192+
return err;
193+
}
194+
195+
return 0;
196+
}
197+
146198
static int sparx5_dcb_ieee_setapp(struct net_device *dev, struct dcb_app *app)
147199
{
148200
struct dcb_app app_itr;
@@ -161,7 +213,11 @@ static int sparx5_dcb_ieee_setapp(struct net_device *dev, struct dcb_app *app)
161213
dcb_ieee_delapp(dev, &app_itr);
162214
}
163215

164-
err = dcb_ieee_setapp(dev, app);
216+
if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
217+
err = sparx5_dcb_ieee_dscp_setdel_app(dev, app, false);
218+
else
219+
err = dcb_ieee_setapp(dev, app);
220+
165221
if (err)
166222
goto out;
167223

@@ -175,7 +231,11 @@ static int sparx5_dcb_ieee_delapp(struct net_device *dev, struct dcb_app *app)
175231
{
176232
int err;
177233

178-
err = dcb_ieee_delapp(dev, app);
234+
if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
235+
err = sparx5_dcb_ieee_dscp_setdel_app(dev, app, true);
236+
else
237+
err = dcb_ieee_delapp(dev, app);
238+
179239
if (err < 0)
180240
return err;
181241

drivers/net/ethernet/microchip/sparx5/sparx5_port.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,7 @@ void sparx5_port_enable(struct sparx5_port *port, bool enable)
11491149
int sparx5_port_qos_set(struct sparx5_port *port,
11501150
struct sparx5_port_qos *qos)
11511151
{
1152+
sparx5_port_qos_dscp_set(port, &qos->dscp);
11521153
sparx5_port_qos_pcp_set(port, &qos->pcp);
11531154

11541155
return 0;
@@ -1181,3 +1182,41 @@ int sparx5_port_qos_pcp_set(const struct sparx5_port *port,
11811182

11821183
return 0;
11831184
}
1185+
1186+
int sparx5_port_qos_dscp_set(const struct sparx5_port *port,
1187+
struct sparx5_port_qos_dscp *qos)
1188+
{
1189+
struct sparx5 *sparx5 = port->sparx5;
1190+
u8 *dscp = qos->map.map;
1191+
int i;
1192+
1193+
/* Enable/disable dscp and dp for qos classification.
1194+
* Disable rewrite of dscp values for now.
1195+
*/
1196+
spx5_rmw(ANA_CL_QOS_CFG_DSCP_QOS_ENA_SET(qos->qos_enable) |
1197+
ANA_CL_QOS_CFG_DSCP_DP_ENA_SET(qos->dp_enable) |
1198+
ANA_CL_QOS_CFG_DSCP_KEEP_ENA_SET(1),
1199+
ANA_CL_QOS_CFG_DSCP_QOS_ENA | ANA_CL_QOS_CFG_DSCP_DP_ENA |
1200+
ANA_CL_QOS_CFG_DSCP_KEEP_ENA, sparx5,
1201+
ANA_CL_QOS_CFG(port->portno));
1202+
1203+
/* Map each dscp value to priority and dp */
1204+
for (i = 0; i < ARRAY_SIZE(qos->map.map); i++) {
1205+
spx5_rmw(ANA_CL_DSCP_CFG_DSCP_QOS_VAL_SET(*(dscp + i)) |
1206+
ANA_CL_DSCP_CFG_DSCP_DP_VAL_SET(0),
1207+
ANA_CL_DSCP_CFG_DSCP_QOS_VAL |
1208+
ANA_CL_DSCP_CFG_DSCP_DP_VAL, sparx5,
1209+
ANA_CL_DSCP_CFG(i));
1210+
}
1211+
1212+
/* Set per-dscp trust */
1213+
for (i = 0; i < ARRAY_SIZE(qos->map.map); i++) {
1214+
if (qos->qos_enable) {
1215+
spx5_rmw(ANA_CL_DSCP_CFG_DSCP_TRUST_ENA_SET(1),
1216+
ANA_CL_DSCP_CFG_DSCP_TRUST_ENA, sparx5,
1217+
ANA_CL_DSCP_CFG(i));
1218+
}
1219+
}
1220+
1221+
return 0;
1222+
}

drivers/net/ethernet/microchip/sparx5/sparx5_port.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,19 +99,33 @@ struct sparx5_port_qos_pcp_map {
9999
u8 map[SPARX5_PORT_QOS_PCP_DEI_COUNT];
100100
};
101101

102+
#define SPARX5_PORT_QOS_DSCP_COUNT 64
103+
struct sparx5_port_qos_dscp_map {
104+
u8 map[SPARX5_PORT_QOS_DSCP_COUNT];
105+
};
106+
102107
struct sparx5_port_qos_pcp {
103108
struct sparx5_port_qos_pcp_map map;
104109
bool qos_enable;
105110
bool dp_enable;
106111
};
107112

113+
struct sparx5_port_qos_dscp {
114+
struct sparx5_port_qos_dscp_map map;
115+
bool qos_enable;
116+
bool dp_enable;
117+
};
118+
108119
struct sparx5_port_qos {
109120
struct sparx5_port_qos_pcp pcp;
121+
struct sparx5_port_qos_dscp dscp;
110122
};
111123

112124
int sparx5_port_qos_set(struct sparx5_port *port, struct sparx5_port_qos *qos);
113125

114126
int sparx5_port_qos_pcp_set(const struct sparx5_port *port,
115127
struct sparx5_port_qos_pcp *qos);
116128

129+
int sparx5_port_qos_dscp_set(const struct sparx5_port *port,
130+
struct sparx5_port_qos_dscp *qos);
117131
#endif /* __SPARX5_PORT_H__ */

0 commit comments

Comments
 (0)