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

PD#TV-11316

[ Upstream commit 583e636141 ]

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 <aaro.koskinen@nokia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>

Change-Id: I32f3f0758ee6df0217dd9d1275c08b04163d811b
Signed-off-by: Jiamin Ma <jiamin.ma@amlogic.com>
This commit is contained in:
Aaro Koskinen
2019-03-27 22:35:35 +02:00
committed by Luke Go
parent 2c43efce4c
commit 5741242073
6 changed files with 35 additions and 17 deletions

View File

@@ -354,7 +354,7 @@ struct dma_features {
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);

View File

@@ -33,10 +33,12 @@
/* 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 |= ((BUF_SIZE_8KiB - 1) << ERDES1_BUFFER2_SIZE_SHIFT)
& ERDES1_BUFFER2_SIZE_MASK;
if (bfsize == BUF_SIZE_16KiB)
p->des1 |= ((BUF_SIZE_8KiB - 1) << ERDES1_BUFFER2_SIZE_SHIFT)
& ERDES1_BUFFER2_SIZE_MASK;
if (end)
p->des1 |= ERDES1_END_RING;
@@ -61,10 +63,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 |= ((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 |= RDES1_END_RING;

View File

@@ -285,7 +285,7 @@ exit:
}
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 = RDES3_OWN | RDES3_BUFFER1_VALID_ADDR;

View File

@@ -263,15 +263,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 |= RDES0_OWN;
p->des1 |= ((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)
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 |= ERDES1_DISABLE_IC;

View File

@@ -139,15 +139,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 |= RDES0_OWN;
p->des1 |= (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 |= RDES1_DISABLE_IC;

View File

@@ -974,11 +974,13 @@ static void stmmac_clear_descriptors(struct stmmac_priv *priv)
if (priv->extend_desc)
priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic,
priv->use_riwt, priv->mode,
(i == DMA_RX_SIZE - 1));
(i == DMA_RX_SIZE - 1),
priv->dma_buf_sz);
else
priv->hw->desc->init_rx_desc(&priv->dma_rx[i],
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++)
if (priv->extend_desc)
priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
@@ -2524,7 +2526,8 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
wmb();
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
priv->hw->desc->set_rx_owner(p);