Skip to content

Commit f2105b2

Browse files
committed
stmmac: troubleshoot unexpected bits in des0 & des1
Current implementation of descriptor init procedure only takes care about setting/clearing ownership flag in "des0"/"des1" fields while it is perfectly possible to get unexpected bits set because of the following factors: [1] On driver probe underlying memory allocated with dma_alloc_coherent() might not be zeroed and so it will be filled with garbage. [2] During driver operation some bits could be set by SD/MMC controller (for example error flags etc). And unexpected and/or randomly set flags in "des0"/"des1" fields may lead to unpredictable behavior of GMAC DMA block. This change addresses both items above with: [1] Use of dma_zalloc_coherent() instead of simple dma_alloc_coherent() to make sure allocated memory is zeroed. That shouldn't affect performance because this allocation only happens once on driver probe. [2] Do explicit zeroing of both "des0" and "des1" fields of all buffer descriptors during initialization of DMA transfer. And while at it fixed identation of dma_free_coherent() counterpart as well. Signed-off-by: Alexey Brodkin <[email protected]> Cc: Giuseppe Cavallaro <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: David Miller <[email protected]>
1 parent c4ff8d6 commit f2105b2

File tree

4 files changed

+28
-24
lines changed

4 files changed

+28
-24
lines changed

drivers/net/ethernet/stmicro/stmmac/descs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ struct dma_desc {
158158
u32 buffer2_size:13;
159159
u32 reserved4:3;
160160
} etx; /* -- enhanced -- */
161+
162+
u64 all_flags;
161163
} des01;
162164
unsigned int des2;
163165
unsigned int des3;

drivers/net/ethernet/stmicro/stmmac/enh_desc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x,
240240
static void enh_desc_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
241241
int mode, int end)
242242
{
243+
p->des01.all_flags = 0;
243244
p->des01.erx.own = 1;
244245
p->des01.erx.buffer1_size = BUF_SIZE_8KiB - 1;
245246

@@ -254,7 +255,7 @@ static void enh_desc_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
254255

255256
static void enh_desc_init_tx_desc(struct dma_desc *p, int mode, int end)
256257
{
257-
p->des01.etx.own = 0;
258+
p->des01.all_flags = 0;
258259
if (mode == STMMAC_CHAIN_MODE)
259260
ehn_desc_tx_set_on_chain(p, end);
260261
else

drivers/net/ethernet/stmicro/stmmac/norm_desc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x,
123123
static void ndesc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, int mode,
124124
int end)
125125
{
126+
p->des01.all_flags = 0;
126127
p->des01.rx.own = 1;
127128
p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1;
128129

@@ -137,7 +138,7 @@ static void ndesc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, int mode,
137138

138139
static void ndesc_init_tx_desc(struct dma_desc *p, int mode, int end)
139140
{
140-
p->des01.tx.own = 0;
141+
p->des01.all_flags = 0;
141142
if (mode == STMMAC_CHAIN_MODE)
142143
ndesc_tx_set_on_chain(p, end);
143144
else

drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,41 +1172,41 @@ static int alloc_dma_desc_resources(struct stmmac_priv *priv)
11721172
goto err_tx_skbuff;
11731173

11741174
if (priv->extend_desc) {
1175-
priv->dma_erx = dma_alloc_coherent(priv->device, rxsize *
1176-
sizeof(struct
1177-
dma_extended_desc),
1178-
&priv->dma_rx_phy,
1179-
GFP_KERNEL);
1175+
priv->dma_erx = dma_zalloc_coherent(priv->device, rxsize *
1176+
sizeof(struct
1177+
dma_extended_desc),
1178+
&priv->dma_rx_phy,
1179+
GFP_KERNEL);
11801180
if (!priv->dma_erx)
11811181
goto err_dma;
11821182

1183-
priv->dma_etx = dma_alloc_coherent(priv->device, txsize *
1184-
sizeof(struct
1185-
dma_extended_desc),
1186-
&priv->dma_tx_phy,
1187-
GFP_KERNEL);
1183+
priv->dma_etx = dma_zalloc_coherent(priv->device, txsize *
1184+
sizeof(struct
1185+
dma_extended_desc),
1186+
&priv->dma_tx_phy,
1187+
GFP_KERNEL);
11881188
if (!priv->dma_etx) {
11891189
dma_free_coherent(priv->device, priv->dma_rx_size *
1190-
sizeof(struct dma_extended_desc),
1191-
priv->dma_erx, priv->dma_rx_phy);
1190+
sizeof(struct dma_extended_desc),
1191+
priv->dma_erx, priv->dma_rx_phy);
11921192
goto err_dma;
11931193
}
11941194
} else {
1195-
priv->dma_rx = dma_alloc_coherent(priv->device, rxsize *
1196-
sizeof(struct dma_desc),
1197-
&priv->dma_rx_phy,
1198-
GFP_KERNEL);
1195+
priv->dma_rx = dma_zalloc_coherent(priv->device, rxsize *
1196+
sizeof(struct dma_desc),
1197+
&priv->dma_rx_phy,
1198+
GFP_KERNEL);
11991199
if (!priv->dma_rx)
12001200
goto err_dma;
12011201

1202-
priv->dma_tx = dma_alloc_coherent(priv->device, txsize *
1203-
sizeof(struct dma_desc),
1204-
&priv->dma_tx_phy,
1205-
GFP_KERNEL);
1202+
priv->dma_tx = dma_zalloc_coherent(priv->device, txsize *
1203+
sizeof(struct dma_desc),
1204+
&priv->dma_tx_phy,
1205+
GFP_KERNEL);
12061206
if (!priv->dma_tx) {
12071207
dma_free_coherent(priv->device, priv->dma_rx_size *
1208-
sizeof(struct dma_desc),
1209-
priv->dma_rx, priv->dma_rx_phy);
1208+
sizeof(struct dma_desc),
1209+
priv->dma_rx, priv->dma_rx_phy);
12101210
goto err_dma;
12111211
}
12121212
}

0 commit comments

Comments
 (0)