]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: stmmac: use correct DMA buffer size in the RX descriptor
authorAaro Koskinen <aaro.koskinen@nokia.com>
Wed, 27 Mar 2019 20:35:35 +0000 (22:35 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 21 Dec 2019 09:42:34 +0000 (10:42 +0100)
commit 583e6361414903c5206258a30e5bd88cb03c0254 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: Aaro Koskinen <aaro.koskinen@nokia.com>
Signed-off-by: David 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: Aviraj CJ <acj@cisco.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/descs_com.h
drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
drivers/net/ethernet/stmicro/stmmac/enh_desc.c
drivers/net/ethernet/stmicro/stmmac/norm_desc.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

index 6d2de4e01f6d00404bde51f3816ba2271adff865..e11920d1277483cbd7ca2f39715ab642efd04ba6 100644 (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);
 
index 1d181e205d6ecbb49c5d173fcb6f3ea5bfe6fe40..f9cbba2d2cc0f2653fbf46b84b6ff2624452beb0 100644 (file)
 /* 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 - 1)
-                       << 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);
@@ -63,11 +66,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);
index 3f5056858535a98215583da1cd59b24dd9255db6..a90b02926e4df498699deb28572afe55d39a6b77 100644 (file)
@@ -289,7 +289,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 = cpu_to_le32(RDES3_OWN | RDES3_BUFFER1_VALID_ADDR);
 
index 77dc5842bd0b366a0de1e6d5664ed026a55fa6c5..47f4fe50c8486f344c635a84718fe71e4a8ce720 100644 (file)
@@ -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,
-                                 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 - 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 |= cpu_to_le32(ERDES1_DISABLE_IC);
index 01f8f2e94c0fb974b7f0230c74fca83e929a2312..5a06a5a1f6ea77e0f957c91d1182ff6787c2d6e8 100644 (file)
@@ -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,
-                              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(bfsize1 & 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);
index 2c04a0739fd646340063e2820dfbde33da8fac86..f1844367ca5b9ce58d4897f824de7631efbf9e86 100644 (file)
@@ -956,11 +956,11 @@ 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,
@@ -2479,7 +2479,7 @@ 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);