Skip to content

Commit df934ab

Browse files
dthompsoPaolo Abeni
authored andcommitted
mlxbf_gige: disable RX filters until RX path initialized
A recent change to the driver exposed a bug where the MAC RX filters (unicast MAC, broadcast MAC, and multicast MAC) are configured and enabled before the RX path is fully initialized. The result of this bug is that after the PHY is started packets that match these MAC RX filters start to flow into the RX FIFO. And then, after rx_init() is completed, these packets will go into the driver RX ring as well. If enough packets are received to fill the RX ring (default size is 128 packets) before the call to request_irq() completes, the driver RX function becomes stuck. This bug is intermittent but is most likely to be seen where the oob_net0 interface is connected to a busy network with lots of broadcast and multicast traffic. All the MAC RX filters must be disabled until the RX path is ready, i.e. all initialization is done and all the IRQs are installed. Fixes: f7442a6 ("mlxbf_gige: call request_irq() after NAPI initialized") Reviewed-by: Asmaa Mnebhi <[email protected]> Signed-off-by: David Thompson <[email protected]> Reviewed-by: Simon Horman <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
1 parent 58a6372 commit df934ab

File tree

4 files changed

+64
-6
lines changed

4 files changed

+64
-6
lines changed

drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
*/
4141
#define MLXBF_GIGE_BCAST_MAC_FILTER_IDX 0
4242
#define MLXBF_GIGE_LOCAL_MAC_FILTER_IDX 1
43+
#define MLXBF_GIGE_MAX_FILTER_IDX 3
4344

4445
/* Define for broadcast MAC literal */
4546
#define BCAST_MAC_ADDR 0xFFFFFFFFFFFF
@@ -175,6 +176,13 @@ enum mlxbf_gige_res {
175176
int mlxbf_gige_mdio_probe(struct platform_device *pdev,
176177
struct mlxbf_gige *priv);
177178
void mlxbf_gige_mdio_remove(struct mlxbf_gige *priv);
179+
180+
void mlxbf_gige_enable_multicast_rx(struct mlxbf_gige *priv);
181+
void mlxbf_gige_disable_multicast_rx(struct mlxbf_gige *priv);
182+
void mlxbf_gige_enable_mac_rx_filter(struct mlxbf_gige *priv,
183+
unsigned int index);
184+
void mlxbf_gige_disable_mac_rx_filter(struct mlxbf_gige *priv,
185+
unsigned int index);
178186
void mlxbf_gige_set_mac_rx_filter(struct mlxbf_gige *priv,
179187
unsigned int index, u64 dmac);
180188
void mlxbf_gige_get_mac_rx_filter(struct mlxbf_gige *priv,

drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ static int mlxbf_gige_open(struct net_device *netdev)
168168
if (err)
169169
goto napi_deinit;
170170

171+
mlxbf_gige_enable_mac_rx_filter(priv, MLXBF_GIGE_BCAST_MAC_FILTER_IDX);
172+
mlxbf_gige_enable_mac_rx_filter(priv, MLXBF_GIGE_LOCAL_MAC_FILTER_IDX);
173+
mlxbf_gige_enable_multicast_rx(priv);
174+
171175
/* Set bits in INT_EN that we care about */
172176
int_en = MLXBF_GIGE_INT_EN_HW_ACCESS_ERROR |
173177
MLXBF_GIGE_INT_EN_TX_CHECKSUM_INPUTS |
@@ -379,6 +383,7 @@ static int mlxbf_gige_probe(struct platform_device *pdev)
379383
void __iomem *plu_base;
380384
void __iomem *base;
381385
int addr, phy_irq;
386+
unsigned int i;
382387
int err;
383388

384389
base = devm_platform_ioremap_resource(pdev, MLXBF_GIGE_RES_MAC);
@@ -423,6 +428,11 @@ static int mlxbf_gige_probe(struct platform_device *pdev)
423428
priv->rx_q_entries = MLXBF_GIGE_DEFAULT_RXQ_SZ;
424429
priv->tx_q_entries = MLXBF_GIGE_DEFAULT_TXQ_SZ;
425430

431+
for (i = 0; i <= MLXBF_GIGE_MAX_FILTER_IDX; i++)
432+
mlxbf_gige_disable_mac_rx_filter(priv, i);
433+
mlxbf_gige_disable_multicast_rx(priv);
434+
mlxbf_gige_disable_promisc(priv);
435+
426436
/* Write initial MAC address to hardware */
427437
mlxbf_gige_initial_mac(priv);
428438

drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@
6262
#define MLXBF_GIGE_TX_STATUS_DATA_FIFO_FULL BIT(1)
6363
#define MLXBF_GIGE_RX_MAC_FILTER_DMAC_RANGE_START 0x0520
6464
#define MLXBF_GIGE_RX_MAC_FILTER_DMAC_RANGE_END 0x0528
65+
#define MLXBF_GIGE_RX_MAC_FILTER_GENERAL 0x0530
66+
#define MLXBF_GIGE_RX_MAC_FILTER_EN_MULTICAST BIT(1)
6567
#define MLXBF_GIGE_RX_MAC_FILTER_COUNT_DISC 0x0540
6668
#define MLXBF_GIGE_RX_MAC_FILTER_COUNT_DISC_EN BIT(0)
6769
#define MLXBF_GIGE_RX_MAC_FILTER_COUNT_PASS 0x0548

drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,60 @@
1111
#include "mlxbf_gige.h"
1212
#include "mlxbf_gige_regs.h"
1313

14-
void mlxbf_gige_set_mac_rx_filter(struct mlxbf_gige *priv,
15-
unsigned int index, u64 dmac)
14+
void mlxbf_gige_enable_multicast_rx(struct mlxbf_gige *priv)
1615
{
1716
void __iomem *base = priv->base;
18-
u64 control;
17+
u64 data;
1918

20-
/* Write destination MAC to specified MAC RX filter */
21-
writeq(dmac, base + MLXBF_GIGE_RX_MAC_FILTER +
22-
(index * MLXBF_GIGE_RX_MAC_FILTER_STRIDE));
19+
data = readq(base + MLXBF_GIGE_RX_MAC_FILTER_GENERAL);
20+
data |= MLXBF_GIGE_RX_MAC_FILTER_EN_MULTICAST;
21+
writeq(data, base + MLXBF_GIGE_RX_MAC_FILTER_GENERAL);
22+
}
23+
24+
void mlxbf_gige_disable_multicast_rx(struct mlxbf_gige *priv)
25+
{
26+
void __iomem *base = priv->base;
27+
u64 data;
28+
29+
data = readq(base + MLXBF_GIGE_RX_MAC_FILTER_GENERAL);
30+
data &= ~MLXBF_GIGE_RX_MAC_FILTER_EN_MULTICAST;
31+
writeq(data, base + MLXBF_GIGE_RX_MAC_FILTER_GENERAL);
32+
}
33+
34+
void mlxbf_gige_enable_mac_rx_filter(struct mlxbf_gige *priv,
35+
unsigned int index)
36+
{
37+
void __iomem *base = priv->base;
38+
u64 control;
2339

2440
/* Enable MAC receive filter mask for specified index */
2541
control = readq(base + MLXBF_GIGE_CONTROL);
2642
control |= (MLXBF_GIGE_CONTROL_EN_SPECIFIC_MAC << index);
2743
writeq(control, base + MLXBF_GIGE_CONTROL);
2844
}
2945

46+
void mlxbf_gige_disable_mac_rx_filter(struct mlxbf_gige *priv,
47+
unsigned int index)
48+
{
49+
void __iomem *base = priv->base;
50+
u64 control;
51+
52+
/* Disable MAC receive filter mask for specified index */
53+
control = readq(base + MLXBF_GIGE_CONTROL);
54+
control &= ~(MLXBF_GIGE_CONTROL_EN_SPECIFIC_MAC << index);
55+
writeq(control, base + MLXBF_GIGE_CONTROL);
56+
}
57+
58+
void mlxbf_gige_set_mac_rx_filter(struct mlxbf_gige *priv,
59+
unsigned int index, u64 dmac)
60+
{
61+
void __iomem *base = priv->base;
62+
63+
/* Write destination MAC to specified MAC RX filter */
64+
writeq(dmac, base + MLXBF_GIGE_RX_MAC_FILTER +
65+
(index * MLXBF_GIGE_RX_MAC_FILTER_STRIDE));
66+
}
67+
3068
void mlxbf_gige_get_mac_rx_filter(struct mlxbf_gige *priv,
3169
unsigned int index, u64 *dmac)
3270
{

0 commit comments

Comments
 (0)