Skip to content

Commit

Permalink
net: stmmac: use correct DMA buffer size in the RX descriptor
Browse files Browse the repository at this point in the history
We always program the maximum DMA buffer size into the receive descriptor,
although the allocated size may be less. E.g. with the default MTU size
we allocate only 1536 bytes. If somebody sends us a bigger frame, then
memory may get corrupted.

Fix by using exact buffer sizes.

Signed-off-by: Aaro Koskinen <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
aakoskin authored and davem330 committed Mar 31, 2019
1 parent 288ac52 commit 583e636
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 19 deletions.
22 changes: 14 additions & 8 deletions drivers/net/ethernet/stmicro/stmmac/descs_com.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@
/* Specific functions used for Ring mode */

/* Enhanced descriptors */
static inline void ehn_desc_rx_set_on_ring(struct dma_desc *p, int end)
static inline void ehn_desc_rx_set_on_ring(struct dma_desc *p, int end,
int bfsize)
{
p->des1 |= cpu_to_le32((BUF_SIZE_8KiB
<< ERDES1_BUFFER2_SIZE_SHIFT)
& ERDES1_BUFFER2_SIZE_MASK);
if (bfsize == BUF_SIZE_16KiB)
p->des1 |= cpu_to_le32((BUF_SIZE_8KiB
<< ERDES1_BUFFER2_SIZE_SHIFT)
& ERDES1_BUFFER2_SIZE_MASK);

if (end)
p->des1 |= cpu_to_le32(ERDES1_END_RING);
Expand All @@ -59,11 +61,15 @@ static inline void enh_set_tx_desc_len_on_ring(struct dma_desc *p, int len)
}

/* Normal descriptors */
static inline void ndesc_rx_set_on_ring(struct dma_desc *p, int end)
static inline void ndesc_rx_set_on_ring(struct dma_desc *p, int end, int bfsize)
{
p->des1 |= cpu_to_le32(((BUF_SIZE_2KiB - 1)
<< RDES1_BUFFER2_SIZE_SHIFT)
& RDES1_BUFFER2_SIZE_MASK);
if (bfsize >= BUF_SIZE_2KiB) {
int bfsize2;

bfsize2 = min(bfsize - BUF_SIZE_2KiB + 1, BUF_SIZE_2KiB - 1);
p->des1 |= cpu_to_le32((bfsize2 << RDES1_BUFFER2_SIZE_SHIFT)
& RDES1_BUFFER2_SIZE_MASK);
}

if (end)
p->des1 |= cpu_to_le32(RDES1_END_RING);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ static int dwmac4_wrback_get_rx_timestamp_status(void *desc, void *next_desc,
}

static void dwmac4_rd_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
int mode, int end)
int mode, int end, int bfsize)
{
dwmac4_set_rx_owner(p, disable_rx_ic);
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ static int dwxgmac2_get_rx_timestamp_status(void *desc, void *next_desc,
}

static void dwxgmac2_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
int mode, int end)
int mode, int end, int bfsize)
{
dwxgmac2_set_rx_owner(p, disable_rx_ic);
}
Expand Down
10 changes: 7 additions & 3 deletions drivers/net/ethernet/stmicro/stmmac/enh_desc.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,15 +259,19 @@ static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x,
}

static void enh_desc_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
int mode, int end)
int mode, int end, int bfsize)
{
int bfsize1;

p->des0 |= cpu_to_le32(RDES0_OWN);
p->des1 |= cpu_to_le32(BUF_SIZE_8KiB & ERDES1_BUFFER1_SIZE_MASK);

bfsize1 = min(bfsize, BUF_SIZE_8KiB);
p->des1 |= cpu_to_le32(bfsize1 & ERDES1_BUFFER1_SIZE_MASK);

if (mode == STMMAC_CHAIN_MODE)
ehn_desc_rx_set_on_chain(p);
else
ehn_desc_rx_set_on_ring(p, end);
ehn_desc_rx_set_on_ring(p, end, bfsize);

if (disable_rx_ic)
p->des1 |= cpu_to_le32(ERDES1_DISABLE_IC);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/stmicro/stmmac/hwif.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ struct dma_extended_desc;
struct stmmac_desc_ops {
/* DMA RX descriptor ring initialization */
void (*init_rx_desc)(struct dma_desc *p, int disable_rx_ic, int mode,
int end);
int end, int bfsize);
/* DMA TX descriptor ring initialization */
void (*init_tx_desc)(struct dma_desc *p, int mode, int end);
/* Invoked by the xmit function to prepare the tx descriptor */
Expand Down
10 changes: 7 additions & 3 deletions drivers/net/ethernet/stmicro/stmmac/norm_desc.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,19 @@ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x,
}

static void ndesc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, int mode,
int end)
int end, int bfsize)
{
int bfsize1;

p->des0 |= cpu_to_le32(RDES0_OWN);
p->des1 |= cpu_to_le32((BUF_SIZE_2KiB - 1) & RDES1_BUFFER1_SIZE_MASK);

bfsize1 = min(bfsize, BUF_SIZE_2KiB - 1);
p->des1 |= cpu_to_le32(bfsize & RDES1_BUFFER1_SIZE_MASK);

if (mode == STMMAC_CHAIN_MODE)
ndesc_rx_set_on_chain(p, end);
else
ndesc_rx_set_on_ring(p, end);
ndesc_rx_set_on_ring(p, end, bfsize);

if (disable_rx_ic)
p->des1 |= cpu_to_le32(RDES1_DISABLE_IC);
Expand Down
6 changes: 4 additions & 2 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1136,11 +1136,13 @@ static void stmmac_clear_rx_descriptors(struct stmmac_priv *priv, u32 queue)
if (priv->extend_desc)
stmmac_init_rx_desc(priv, &rx_q->dma_erx[i].basic,
priv->use_riwt, priv->mode,
(i == DMA_RX_SIZE - 1));
(i == DMA_RX_SIZE - 1),
priv->dma_buf_sz);
else
stmmac_init_rx_desc(priv, &rx_q->dma_rx[i],
priv->use_riwt, priv->mode,
(i == DMA_RX_SIZE - 1));
(i == DMA_RX_SIZE - 1),
priv->dma_buf_sz);
}

/**
Expand Down

0 comments on commit 583e636

Please sign in to comment.