Commit 7e3efae8 authored by Aaro Koskinen's avatar Aaro Koskinen Committed by Greg Kroah-Hartman

net: stmmac: use correct DMA buffer size in the RX descriptor

commit 583e6361 upstream.

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: default avatarAaro Koskinen <aaro.koskinen@nokia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
[acj: backport to v4.9 -stable :
- adjust context
- skipped the section modifying non-existent functions in dwxgmac2_descs.c and
hwif.h ]
Signed-off-by: default avatarAviraj CJ <acj@cisco.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d93f4bce
...@@ -354,7 +354,7 @@ struct dma_features { ...@@ -354,7 +354,7 @@ struct dma_features {
struct stmmac_desc_ops { struct stmmac_desc_ops {
/* DMA RX descriptor ring initialization */ /* DMA RX descriptor ring initialization */
void (*init_rx_desc) (struct dma_desc *p, int disable_rx_ic, int mode, 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 */ /* DMA TX descriptor ring initialization */
void (*init_tx_desc) (struct dma_desc *p, int mode, int end); void (*init_tx_desc) (struct dma_desc *p, int mode, int end);
......
...@@ -33,11 +33,14 @@ ...@@ -33,11 +33,14 @@
/* Specific functions used for Ring mode */ /* Specific functions used for Ring mode */
/* Enhanced descriptors */ /* 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 - 1) if (bfsize == BUF_SIZE_16KiB)
<< ERDES1_BUFFER2_SIZE_SHIFT) p->des1 |= cpu_to_le32((BUF_SIZE_8KiB
& ERDES1_BUFFER2_SIZE_MASK); << ERDES1_BUFFER2_SIZE_SHIFT)
& ERDES1_BUFFER2_SIZE_MASK);
if (end) if (end)
p->des1 |= cpu_to_le32(ERDES1_END_RING); p->des1 |= cpu_to_le32(ERDES1_END_RING);
...@@ -63,11 +66,15 @@ static inline void enh_set_tx_desc_len_on_ring(struct dma_desc *p, int len) ...@@ -63,11 +66,15 @@ static inline void enh_set_tx_desc_len_on_ring(struct dma_desc *p, int len)
} }
/* Normal descriptors */ /* 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) if (bfsize >= BUF_SIZE_2KiB) {
<< RDES1_BUFFER2_SIZE_SHIFT) int bfsize2;
& RDES1_BUFFER2_SIZE_MASK);
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) if (end)
p->des1 |= cpu_to_le32(RDES1_END_RING); p->des1 |= cpu_to_le32(RDES1_END_RING);
......
...@@ -289,7 +289,7 @@ static int dwmac4_wrback_get_rx_timestamp_status(void *desc, u32 ats) ...@@ -289,7 +289,7 @@ static int dwmac4_wrback_get_rx_timestamp_status(void *desc, u32 ats)
} }
static void dwmac4_rd_init_rx_desc(struct dma_desc *p, int disable_rx_ic, 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)
{ {
p->des3 = cpu_to_le32(RDES3_OWN | RDES3_BUFFER1_VALID_ADDR); p->des3 = cpu_to_le32(RDES3_OWN | RDES3_BUFFER1_VALID_ADDR);
......
...@@ -269,15 +269,19 @@ static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x, ...@@ -269,15 +269,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, 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->des0 |= cpu_to_le32(RDES0_OWN);
p->des1 |= cpu_to_le32((BUF_SIZE_8KiB - 1) & 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) if (mode == STMMAC_CHAIN_MODE)
ehn_desc_rx_set_on_chain(p); ehn_desc_rx_set_on_chain(p);
else else
ehn_desc_rx_set_on_ring(p, end); ehn_desc_rx_set_on_ring(p, end, bfsize);
if (disable_rx_ic) if (disable_rx_ic)
p->des1 |= cpu_to_le32(ERDES1_DISABLE_IC); p->des1 |= cpu_to_le32(ERDES1_DISABLE_IC);
......
...@@ -137,15 +137,19 @@ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x, ...@@ -137,15 +137,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, 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->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(bfsize1 & RDES1_BUFFER1_SIZE_MASK);
if (mode == STMMAC_CHAIN_MODE) if (mode == STMMAC_CHAIN_MODE)
ndesc_rx_set_on_chain(p, end); ndesc_rx_set_on_chain(p, end);
else else
ndesc_rx_set_on_ring(p, end); ndesc_rx_set_on_ring(p, end, bfsize);
if (disable_rx_ic) if (disable_rx_ic)
p->des1 |= cpu_to_le32(RDES1_DISABLE_IC); p->des1 |= cpu_to_le32(RDES1_DISABLE_IC);
......
...@@ -956,11 +956,11 @@ static void stmmac_clear_descriptors(struct stmmac_priv *priv) ...@@ -956,11 +956,11 @@ static void stmmac_clear_descriptors(struct stmmac_priv *priv)
if (priv->extend_desc) if (priv->extend_desc)
priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic, priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic,
priv->use_riwt, priv->mode, priv->use_riwt, priv->mode,
(i == DMA_RX_SIZE - 1)); (i == DMA_RX_SIZE - 1), priv->dma_buf_sz);
else else
priv->hw->desc->init_rx_desc(&priv->dma_rx[i], priv->hw->desc->init_rx_desc(&priv->dma_rx[i],
priv->use_riwt, priv->mode, priv->use_riwt, priv->mode,
(i == DMA_RX_SIZE - 1)); (i == DMA_RX_SIZE - 1), priv->dma_buf_sz);
for (i = 0; i < DMA_TX_SIZE; i++) for (i = 0; i < DMA_TX_SIZE; i++)
if (priv->extend_desc) if (priv->extend_desc)
priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic, priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
...@@ -2479,7 +2479,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv) ...@@ -2479,7 +2479,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
wmb(); wmb();
if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00))
priv->hw->desc->init_rx_desc(p, priv->use_riwt, 0, 0); priv->hw->desc->init_rx_desc(p, priv->use_riwt, 0, 0, priv->dma_buf_sz);
else else
priv->hw->desc->set_rx_owner(p); priv->hw->desc->set_rx_owner(p);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment