Skip to content

Commit 8b792f8

Browse files
committed
Merge branch 'mlxsw-Various-fixes'
Ido Schimmel says: ==================== mlxsw: Various fixes This patch set contains various fixes for mlxsw. Patch #1 splits the init() callback between Spectrum-2 and Spectrum-3 in order to avoid enforcing the same firmware version for both ASICs, as this can't possibly work. Without this patch the driver cannot boot with the Spectrum-3 ASIC. Patches #2-#3 fix a long standing race condition that was recently exposed while testing the driver on an emulator, which is very slow compared to the actual hardware. The problem is explained in detail in the commit messages. Patch #4 fixes a selftest. Patch #5 prevents offloaded qdiscs from presenting a non-zero backlog to the user when the netdev is down. This is done by clearing the cached backlog in the driver when the netdev goes down. Patch #6 fixes qdisc statistics (backlog and tail drops) to also take into account the multicast traffic classes. v2: * Patches #2-#3: use skb_cow_head() instead of skb_unshare() as suggested by Jakub. Remove unnecessary check regarding headroom * Patches #5-#6: new ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents eb50790 + 85005b8 commit 8b792f8

File tree

4 files changed

+76
-33
lines changed

4 files changed

+76
-33
lines changed

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

+41-13
Original file line numberDiff line numberDiff line change
@@ -860,23 +860,17 @@ static netdev_tx_t mlxsw_sp_port_xmit(struct sk_buff *skb,
860860
u64 len;
861861
int err;
862862

863+
if (skb_cow_head(skb, MLXSW_TXHDR_LEN)) {
864+
this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
865+
dev_kfree_skb_any(skb);
866+
return NETDEV_TX_OK;
867+
}
868+
863869
memset(skb->cb, 0, sizeof(struct mlxsw_skb_cb));
864870

865871
if (mlxsw_core_skb_transmit_busy(mlxsw_sp->core, &tx_info))
866872
return NETDEV_TX_BUSY;
867873

868-
if (unlikely(skb_headroom(skb) < MLXSW_TXHDR_LEN)) {
869-
struct sk_buff *skb_orig = skb;
870-
871-
skb = skb_realloc_headroom(skb, MLXSW_TXHDR_LEN);
872-
if (!skb) {
873-
this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
874-
dev_kfree_skb_any(skb_orig);
875-
return NETDEV_TX_OK;
876-
}
877-
dev_consume_skb_any(skb_orig);
878-
}
879-
880874
if (eth_skb_pad(skb)) {
881875
this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
882876
return NETDEV_TX_OK;
@@ -1215,6 +1209,9 @@ static void update_stats_cache(struct work_struct *work)
12151209
periodic_hw_stats.update_dw.work);
12161210

12171211
if (!netif_carrier_ok(mlxsw_sp_port->dev))
1212+
/* Note: mlxsw_sp_port_down_wipe_counters() clears the cache as
1213+
* necessary when port goes down.
1214+
*/
12181215
goto out;
12191216

12201217
mlxsw_sp_port_get_hw_stats(mlxsw_sp_port->dev,
@@ -4324,6 +4321,15 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port,
43244321
return 0;
43254322
}
43264323

4324+
static void
4325+
mlxsw_sp_port_down_wipe_counters(struct mlxsw_sp_port *mlxsw_sp_port)
4326+
{
4327+
int i;
4328+
4329+
for (i = 0; i < TC_MAX_QUEUE; i++)
4330+
mlxsw_sp_port->periodic_hw_stats.xstats.backlog[i] = 0;
4331+
}
4332+
43274333
static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg,
43284334
char *pude_pl, void *priv)
43294335
{
@@ -4345,6 +4351,7 @@ static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg,
43454351
} else {
43464352
netdev_info(mlxsw_sp_port->dev, "link down\n");
43474353
netif_carrier_off(mlxsw_sp_port->dev);
4354+
mlxsw_sp_port_down_wipe_counters(mlxsw_sp_port);
43484355
}
43494356
}
43504357

@@ -5132,6 +5139,27 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core,
51325139
return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
51335140
}
51345141

5142+
static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core,
5143+
const struct mlxsw_bus_info *mlxsw_bus_info,
5144+
struct netlink_ext_ack *extack)
5145+
{
5146+
struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
5147+
5148+
mlxsw_sp->kvdl_ops = &mlxsw_sp2_kvdl_ops;
5149+
mlxsw_sp->afa_ops = &mlxsw_sp2_act_afa_ops;
5150+
mlxsw_sp->afk_ops = &mlxsw_sp2_afk_ops;
5151+
mlxsw_sp->mr_tcam_ops = &mlxsw_sp2_mr_tcam_ops;
5152+
mlxsw_sp->acl_tcam_ops = &mlxsw_sp2_acl_tcam_ops;
5153+
mlxsw_sp->nve_ops_arr = mlxsw_sp2_nve_ops_arr;
5154+
mlxsw_sp->mac_mask = mlxsw_sp2_mac_mask;
5155+
mlxsw_sp->rif_ops_arr = mlxsw_sp2_rif_ops_arr;
5156+
mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals;
5157+
mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops;
5158+
mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops;
5159+
5160+
return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
5161+
}
5162+
51355163
static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
51365164
{
51375165
struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
@@ -5634,7 +5662,7 @@ static struct mlxsw_driver mlxsw_sp2_driver = {
56345662
static struct mlxsw_driver mlxsw_sp3_driver = {
56355663
.kind = mlxsw_sp3_driver_name,
56365664
.priv_size = sizeof(struct mlxsw_sp),
5637-
.init = mlxsw_sp2_init,
5665+
.init = mlxsw_sp3_init,
56385666
.fini = mlxsw_sp_fini,
56395667
.basic_trap_groups_set = mlxsw_sp_basic_trap_groups_set,
56405668
.port_split = mlxsw_sp_port_split,

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

+23-7
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,20 @@ mlxsw_sp_qdisc_get_xstats(struct mlxsw_sp_port *mlxsw_sp_port,
195195
return -EOPNOTSUPP;
196196
}
197197

198+
static u64
199+
mlxsw_sp_xstats_backlog(struct mlxsw_sp_port_xstats *xstats, int tclass_num)
200+
{
201+
return xstats->backlog[tclass_num] +
202+
xstats->backlog[tclass_num + 8];
203+
}
204+
205+
static u64
206+
mlxsw_sp_xstats_tail_drop(struct mlxsw_sp_port_xstats *xstats, int tclass_num)
207+
{
208+
return xstats->tail_drop[tclass_num] +
209+
xstats->tail_drop[tclass_num + 8];
210+
}
211+
198212
static void
199213
mlxsw_sp_qdisc_bstats_per_priority_get(struct mlxsw_sp_port_xstats *xstats,
200214
u8 prio_bitmap, u64 *tx_packets,
@@ -269,7 +283,7 @@ mlxsw_sp_setup_tc_qdisc_red_clean_stats(struct mlxsw_sp_port *mlxsw_sp_port,
269283
&stats_base->tx_bytes);
270284
red_base->prob_mark = xstats->ecn;
271285
red_base->prob_drop = xstats->wred_drop[tclass_num];
272-
red_base->pdrop = xstats->tail_drop[tclass_num];
286+
red_base->pdrop = mlxsw_sp_xstats_tail_drop(xstats, tclass_num);
273287

274288
stats_base->overlimits = red_base->prob_drop + red_base->prob_mark;
275289
stats_base->drops = red_base->prob_drop + red_base->pdrop;
@@ -370,7 +384,8 @@ mlxsw_sp_qdisc_get_red_xstats(struct mlxsw_sp_port *mlxsw_sp_port,
370384

371385
early_drops = xstats->wred_drop[tclass_num] - xstats_base->prob_drop;
372386
marks = xstats->ecn - xstats_base->prob_mark;
373-
pdrops = xstats->tail_drop[tclass_num] - xstats_base->pdrop;
387+
pdrops = mlxsw_sp_xstats_tail_drop(xstats, tclass_num) -
388+
xstats_base->pdrop;
374389

375390
res->pdrop += pdrops;
376391
res->prob_drop += early_drops;
@@ -403,9 +418,10 @@ mlxsw_sp_qdisc_get_red_stats(struct mlxsw_sp_port *mlxsw_sp_port,
403418

404419
overlimits = xstats->wred_drop[tclass_num] + xstats->ecn -
405420
stats_base->overlimits;
406-
drops = xstats->wred_drop[tclass_num] + xstats->tail_drop[tclass_num] -
421+
drops = xstats->wred_drop[tclass_num] +
422+
mlxsw_sp_xstats_tail_drop(xstats, tclass_num) -
407423
stats_base->drops;
408-
backlog = xstats->backlog[tclass_num];
424+
backlog = mlxsw_sp_xstats_backlog(xstats, tclass_num);
409425

410426
_bstats_update(stats_ptr->bstats, tx_bytes, tx_packets);
411427
stats_ptr->qstats->overlimits += overlimits;
@@ -576,9 +592,9 @@ mlxsw_sp_qdisc_get_prio_stats(struct mlxsw_sp_port *mlxsw_sp_port,
576592
tx_packets = stats->tx_packets - stats_base->tx_packets;
577593

578594
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
579-
drops += xstats->tail_drop[i];
595+
drops += mlxsw_sp_xstats_tail_drop(xstats, i);
580596
drops += xstats->wred_drop[i];
581-
backlog += xstats->backlog[i];
597+
backlog += mlxsw_sp_xstats_backlog(xstats, i);
582598
}
583599
drops = drops - stats_base->drops;
584600

@@ -614,7 +630,7 @@ mlxsw_sp_setup_tc_qdisc_prio_clean_stats(struct mlxsw_sp_port *mlxsw_sp_port,
614630

615631
stats_base->drops = 0;
616632
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
617-
stats_base->drops += xstats->tail_drop[i];
633+
stats_base->drops += mlxsw_sp_xstats_tail_drop(xstats, i);
618634
stats_base->drops += xstats->wred_drop[i];
619635
}
620636

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

+6-11
Original file line numberDiff line numberDiff line change
@@ -299,22 +299,17 @@ static netdev_tx_t mlxsw_sx_port_xmit(struct sk_buff *skb,
299299
u64 len;
300300
int err;
301301

302+
if (skb_cow_head(skb, MLXSW_TXHDR_LEN)) {
303+
this_cpu_inc(mlxsw_sx_port->pcpu_stats->tx_dropped);
304+
dev_kfree_skb_any(skb);
305+
return NETDEV_TX_OK;
306+
}
307+
302308
memset(skb->cb, 0, sizeof(struct mlxsw_skb_cb));
303309

304310
if (mlxsw_core_skb_transmit_busy(mlxsw_sx->core, &tx_info))
305311
return NETDEV_TX_BUSY;
306312

307-
if (unlikely(skb_headroom(skb) < MLXSW_TXHDR_LEN)) {
308-
struct sk_buff *skb_orig = skb;
309-
310-
skb = skb_realloc_headroom(skb, MLXSW_TXHDR_LEN);
311-
if (!skb) {
312-
this_cpu_inc(mlxsw_sx_port->pcpu_stats->tx_dropped);
313-
dev_kfree_skb_any(skb_orig);
314-
return NETDEV_TX_OK;
315-
}
316-
dev_consume_skb_any(skb_orig);
317-
}
318313
mlxsw_sx_txhdr_construct(skb, &tx_info);
319314
/* TX header is consumed by HW on the way so we shouldn't count its
320315
* bytes as being sent.

tools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh

+6-2
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ test_mc_aware()
232232
stop_traffic
233233
local ucth1=${uc_rate[1]}
234234

235-
start_traffic $h1 own bc bc
235+
start_traffic $h1 192.0.2.65 bc bc
236236

237237
local d0=$(date +%s)
238238
local t0=$(ethtool_stats_get $h3 rx_octets_prio_0)
@@ -254,7 +254,11 @@ test_mc_aware()
254254
ret = 100 * ($ucth1 - $ucth2) / $ucth1
255255
if (ret > 0) { ret } else { 0 }
256256
")
257-
check_err $(bc <<< "$deg > 25")
257+
258+
# Minimum shaper of 200Mbps on MC TCs should cause about 20% of
259+
# degradation on 1Gbps link.
260+
check_err $(bc <<< "$deg < 15") "Minimum shaper not in effect"
261+
check_err $(bc <<< "$deg > 25") "MC traffic degrades UC performance too much"
258262

259263
local interval=$((d1 - d0))
260264
local mc_ir=$(rate $u0 $u1 $interval)

0 commit comments

Comments
 (0)