Skip to content

Commit 72d61d3

Browse files
committed
Merge branch 'mlxsw-Support-dcbnl_setbuffer-dcbnl_getbuffer'
Ido Schimmel says: ==================== mlxsw: Support dcbnl_setbuffer, dcbnl_getbuffer Petr says: On Spectrum, port buffers, also called port headroom, is where packets are stored while they are parsed and the forwarding decision is being made. For lossless traffic flows, in case shared buffer admission is not allowed, headroom is also where to put the extra traffic received before the sent PAUSE takes effect. Linux supports two DCB interfaces related to the headroom: dcbnl_setbuffer for configuration, and dcbnl_getbuffer for inspection. This patch set implements them. With dcbnl_setbuffer in place, there will be two sources of authority over the ingress configuration: the DCB ETS hook, because ETS configuration is mirrored to ingress, and the DCB setbuffer hook. mlxsw is in a similar situation on the egress side, where there are two sources of the ETS configuration: the DCB ETS hook, and the TC qdisc hooks. This is a non-intuitive situation, because the way the ASIC ends up being configured depends not only on the actual configured bits, but also on the order in which they were configured. To prevent these issues on the ingress side, two configuration modes will exist: DCB mode and TC mode. DCB ETS will keep getting projected to ingress in the (default) DCB mode. When a qdisc is installed on a port, it will be switched to the TC mode, the ingress configuration will be done through the dcbnl_setbuffer callback. The reason is that the dcbnl_setbuffer hook is not standardized and supported by lldpad. Projecting DCB ETS configuration to ingress is a reasonable heuristic to configure ingress especially when PFC is in effect. In patch #1, the toggle between the DCB and TC modes of headroom configuration, described above, is introduced. Patch #2 implements dcbnl_getbuffer and dcbnl_setbuffer. dcbnl_getbuffer can be always used to determine the current port headroom configuration. dcbnl_setbuffer is only permitted in the TC mode. In patch #3, make the qdisc module toggle the headroom mode from DCB to TC and back, depending on whether there is an offloaded qdisc on the port. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 4d11af5 + 509f04c commit 72d61d3

File tree

4 files changed

+122
-4
lines changed

4 files changed

+122
-4
lines changed

drivers/net/ethernet/mellanox/mlxsw/spectrum.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,18 +434,29 @@ struct mlxsw_sp_hdroom_prio {
434434
u8 buf_idx;
435435
/* Value of buf_idx deduced from the DCB ETS configuration. */
436436
u8 ets_buf_idx;
437+
/* Value of buf_idx taken from the dcbnl_setbuffer configuration. */
438+
u8 set_buf_idx;
437439
bool lossy;
438440
};
439441

440442
struct mlxsw_sp_hdroom_buf {
441443
u32 thres_cells;
442444
u32 size_cells;
445+
/* Size requirement form dcbnl_setbuffer. */
446+
u32 set_size_cells;
443447
bool lossy;
444448
};
445449

450+
enum mlxsw_sp_hdroom_mode {
451+
MLXSW_SP_HDROOM_MODE_DCB,
452+
MLXSW_SP_HDROOM_MODE_TC,
453+
};
454+
446455
#define MLXSW_SP_PB_COUNT 10
447456

448457
struct mlxsw_sp_hdroom {
458+
enum mlxsw_sp_hdroom_mode mode;
459+
449460
struct {
450461
struct mlxsw_sp_hdroom_prio prio[IEEE_8021Q_MAX_PRIORITIES];
451462
} prios;

drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,16 @@ void mlxsw_sp_hdroom_prios_reset_buf_idx(struct mlxsw_sp_hdroom *hdroom)
304304
{
305305
int prio;
306306

307-
for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++)
308-
hdroom->prios.prio[prio].buf_idx = hdroom->prios.prio[prio].ets_buf_idx;
307+
for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) {
308+
switch (hdroom->mode) {
309+
case MLXSW_SP_HDROOM_MODE_DCB:
310+
hdroom->prios.prio[prio].buf_idx = hdroom->prios.prio[prio].ets_buf_idx;
311+
break;
312+
case MLXSW_SP_HDROOM_MODE_TC:
313+
hdroom->prios.prio[prio].buf_idx = hdroom->prios.prio[prio].set_buf_idx;
314+
break;
315+
}
316+
}
309317
}
310318

311319
void mlxsw_sp_hdroom_bufs_reset_lossiness(struct mlxsw_sp_hdroom *hdroom)
@@ -411,7 +419,14 @@ void mlxsw_sp_hdroom_bufs_reset_sizes(struct mlxsw_sp_port *mlxsw_sp_port,
411419
delay_cells = mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, delay_cells);
412420

413421
buf->thres_cells = thres_cells;
414-
buf->size_cells = thres_cells + delay_cells;
422+
if (hdroom->mode == MLXSW_SP_HDROOM_MODE_DCB) {
423+
buf->size_cells = thres_cells + delay_cells;
424+
} else {
425+
/* Do not allow going below the minimum size, even if
426+
* the user requested it.
427+
*/
428+
buf->size_cells = max(buf->set_size_cells, buf->thres_cells);
429+
}
415430
}
416431
}
417432

@@ -575,6 +590,7 @@ static int mlxsw_sp_port_headroom_init(struct mlxsw_sp_port *mlxsw_sp_port)
575590
int prio;
576591

577592
hdroom.mtu = mlxsw_sp_port->dev->mtu;
593+
hdroom.mode = MLXSW_SP_HDROOM_MODE_DCB;
578594
for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++)
579595
hdroom.prios.prio[prio].lossy = true;
580596

drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,62 @@ static int mlxsw_sp_dcbnl_ieee_setpfc(struct net_device *dev,
592592
return err;
593593
}
594594

595+
static int mlxsw_sp_dcbnl_getbuffer(struct net_device *dev, struct dcbnl_buffer *buf)
596+
{
597+
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
598+
struct mlxsw_sp_hdroom *hdroom = mlxsw_sp_port->hdroom;
599+
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
600+
int prio;
601+
int i;
602+
603+
buf->total_size = 0;
604+
605+
BUILD_BUG_ON(DCBX_MAX_BUFFERS > MLXSW_SP_PB_COUNT);
606+
for (i = 0; i < MLXSW_SP_PB_COUNT; i++) {
607+
u32 bytes = mlxsw_sp_cells_bytes(mlxsw_sp, hdroom->bufs.buf[i].size_cells);
608+
609+
if (i < DCBX_MAX_BUFFERS)
610+
buf->buffer_size[i] = bytes;
611+
buf->total_size += bytes;
612+
}
613+
614+
buf->total_size += mlxsw_sp_cells_bytes(mlxsw_sp, hdroom->int_buf.size_cells);
615+
616+
for (prio = 0; prio < IEEE_8021Q_MAX_PRIORITIES; prio++)
617+
buf->prio2buffer[prio] = hdroom->prios.prio[prio].buf_idx;
618+
619+
return 0;
620+
}
621+
622+
static int mlxsw_sp_dcbnl_setbuffer(struct net_device *dev, struct dcbnl_buffer *buf)
623+
{
624+
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
625+
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
626+
struct mlxsw_sp_hdroom hdroom;
627+
int prio;
628+
int i;
629+
630+
hdroom = *mlxsw_sp_port->hdroom;
631+
632+
if (hdroom.mode != MLXSW_SP_HDROOM_MODE_TC) {
633+
netdev_err(dev, "The use of dcbnl_setbuffer is only allowed if egress is configured using TC\n");
634+
return -EINVAL;
635+
}
636+
637+
for (prio = 0; prio < IEEE_8021Q_MAX_PRIORITIES; prio++)
638+
hdroom.prios.prio[prio].set_buf_idx = buf->prio2buffer[prio];
639+
640+
BUILD_BUG_ON(DCBX_MAX_BUFFERS > MLXSW_SP_PB_COUNT);
641+
for (i = 0; i < DCBX_MAX_BUFFERS; i++)
642+
hdroom.bufs.buf[i].set_size_cells = mlxsw_sp_bytes_cells(mlxsw_sp,
643+
buf->buffer_size[i]);
644+
645+
mlxsw_sp_hdroom_prios_reset_buf_idx(&hdroom);
646+
mlxsw_sp_hdroom_bufs_reset_lossiness(&hdroom);
647+
mlxsw_sp_hdroom_bufs_reset_sizes(mlxsw_sp_port, &hdroom);
648+
return mlxsw_sp_hdroom_configure(mlxsw_sp_port, &hdroom);
649+
}
650+
595651
static const struct dcbnl_rtnl_ops mlxsw_sp_dcbnl_ops = {
596652
.ieee_getets = mlxsw_sp_dcbnl_ieee_getets,
597653
.ieee_setets = mlxsw_sp_dcbnl_ieee_setets,
@@ -604,6 +660,9 @@ static const struct dcbnl_rtnl_ops mlxsw_sp_dcbnl_ops = {
604660

605661
.getdcbx = mlxsw_sp_dcbnl_getdcbx,
606662
.setdcbx = mlxsw_sp_dcbnl_setdcbx,
663+
664+
.dcbnl_getbuffer = mlxsw_sp_dcbnl_getbuffer,
665+
.dcbnl_setbuffer = mlxsw_sp_dcbnl_setbuffer,
607666
};
608667

609668
static int mlxsw_sp_port_ets_init(struct mlxsw_sp_port *mlxsw_sp_port)

drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,25 +140,40 @@ static int
140140
mlxsw_sp_qdisc_destroy(struct mlxsw_sp_port *mlxsw_sp_port,
141141
struct mlxsw_sp_qdisc *mlxsw_sp_qdisc)
142142
{
143+
struct mlxsw_sp_qdisc *root_qdisc = &mlxsw_sp_port->qdisc->root_qdisc;
144+
int err_hdroom = 0;
143145
int err = 0;
144146

145147
if (!mlxsw_sp_qdisc)
146148
return 0;
147149

150+
if (root_qdisc == mlxsw_sp_qdisc) {
151+
struct mlxsw_sp_hdroom hdroom = *mlxsw_sp_port->hdroom;
152+
153+
hdroom.mode = MLXSW_SP_HDROOM_MODE_DCB;
154+
mlxsw_sp_hdroom_prios_reset_buf_idx(&hdroom);
155+
mlxsw_sp_hdroom_bufs_reset_lossiness(&hdroom);
156+
mlxsw_sp_hdroom_bufs_reset_sizes(mlxsw_sp_port, &hdroom);
157+
err_hdroom = mlxsw_sp_hdroom_configure(mlxsw_sp_port, &hdroom);
158+
}
159+
148160
if (mlxsw_sp_qdisc->ops && mlxsw_sp_qdisc->ops->destroy)
149161
err = mlxsw_sp_qdisc->ops->destroy(mlxsw_sp_port,
150162
mlxsw_sp_qdisc);
151163

152164
mlxsw_sp_qdisc->handle = TC_H_UNSPEC;
153165
mlxsw_sp_qdisc->ops = NULL;
154-
return err;
166+
167+
return err_hdroom ?: err;
155168
}
156169

157170
static int
158171
mlxsw_sp_qdisc_replace(struct mlxsw_sp_port *mlxsw_sp_port, u32 handle,
159172
struct mlxsw_sp_qdisc *mlxsw_sp_qdisc,
160173
struct mlxsw_sp_qdisc_ops *ops, void *params)
161174
{
175+
struct mlxsw_sp_qdisc *root_qdisc = &mlxsw_sp_port->qdisc->root_qdisc;
176+
struct mlxsw_sp_hdroom orig_hdroom;
162177
int err;
163178

164179
if (mlxsw_sp_qdisc->ops && mlxsw_sp_qdisc->ops->type != ops->type)
@@ -168,6 +183,21 @@ mlxsw_sp_qdisc_replace(struct mlxsw_sp_port *mlxsw_sp_port, u32 handle,
168183
* new one.
169184
*/
170185
mlxsw_sp_qdisc_destroy(mlxsw_sp_port, mlxsw_sp_qdisc);
186+
187+
orig_hdroom = *mlxsw_sp_port->hdroom;
188+
if (root_qdisc == mlxsw_sp_qdisc) {
189+
struct mlxsw_sp_hdroom hdroom = orig_hdroom;
190+
191+
hdroom.mode = MLXSW_SP_HDROOM_MODE_TC;
192+
mlxsw_sp_hdroom_prios_reset_buf_idx(&hdroom);
193+
mlxsw_sp_hdroom_bufs_reset_lossiness(&hdroom);
194+
mlxsw_sp_hdroom_bufs_reset_sizes(mlxsw_sp_port, &hdroom);
195+
196+
err = mlxsw_sp_hdroom_configure(mlxsw_sp_port, &hdroom);
197+
if (err)
198+
goto err_hdroom_configure;
199+
}
200+
171201
err = ops->check_params(mlxsw_sp_port, mlxsw_sp_qdisc, params);
172202
if (err)
173203
goto err_bad_param;
@@ -191,6 +221,8 @@ mlxsw_sp_qdisc_replace(struct mlxsw_sp_port *mlxsw_sp_port, u32 handle,
191221

192222
err_bad_param:
193223
err_config:
224+
mlxsw_sp_hdroom_configure(mlxsw_sp_port, &orig_hdroom);
225+
err_hdroom_configure:
194226
if (mlxsw_sp_qdisc->handle == handle && ops->unoffload)
195227
ops->unoffload(mlxsw_sp_port, mlxsw_sp_qdisc, params);
196228

0 commit comments

Comments
 (0)