net: cpsw: avoid alignment faults by taking NET_IP_ALIGN into account
authorArd Biesheuvel <ardb@kernel.org>
Tue, 18 Jan 2022 10:22:04 +0000 (11:22 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 27 Jan 2022 10:05:41 +0000 (11:05 +0100)
commit 1771afd47430f5e95c9c3a2e3a8a63e67402d3fe upstream.

Both versions of the CPSW driver declare a CPSW_HEADROOM_NA macro that
takes NET_IP_ALIGN into account, but fail to use it appropriately when
storing incoming packets in memory. This results in the IPv4 source and
destination addresses to appear misaligned in memory, which causes
aligment faults that need to be fixed up in software.

So let's switch from CPSW_HEADROOM to CPSW_HEADROOM_NA where needed.
This gets rid of any alignment faults on the RX path on a Beaglebone
White.

Fixes: 9ed4050c0d75 ("net: ethernet: ti: cpsw: add XDP support")
Cc: Grygorii Strashko <grygorii.strashko@ti.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/cpsw_new.c
drivers/net/ethernet/ti/cpsw_priv.c

index 66f7ddd9b1f9940943b64c824b54049a46d9ed49..e226ecd95a2cc183e0d0850b349025acd6bfab66 100644 (file)
@@ -349,7 +349,7 @@ static void cpsw_rx_handler(void *token, int len, int status)
        struct cpsw_common      *cpsw = ndev_to_cpsw(xmeta->ndev);
        int                     pkt_size = cpsw->rx_packet_max;
        int                     ret = 0, port, ch = xmeta->ch;
-       int                     headroom = CPSW_HEADROOM;
+       int                     headroom = CPSW_HEADROOM_NA;
        struct net_device       *ndev = xmeta->ndev;
        struct cpsw_priv        *priv;
        struct page_pool        *pool;
@@ -392,7 +392,7 @@ static void cpsw_rx_handler(void *token, int len, int status)
        }
 
        if (priv->xdp_prog) {
-               int headroom = CPSW_HEADROOM, size = len;
+               int size = len;
 
                xdp_init_buff(&xdp, PAGE_SIZE, &priv->xdp_rxq[ch]);
                if (status & CPDMA_RX_VLAN_ENCAP) {
@@ -442,7 +442,7 @@ requeue:
        xmeta->ndev = ndev;
        xmeta->ch = ch;
 
-       dma = page_pool_get_dma_addr(new_page) + CPSW_HEADROOM;
+       dma = page_pool_get_dma_addr(new_page) + CPSW_HEADROOM_NA;
        ret = cpdma_chan_submit_mapped(cpsw->rxv[ch].ch, new_page, dma,
                                       pkt_size, 0);
        if (ret < 0) {
index 7968f24d99c8550fea08dde45bb77f38b4e3ebaa..9e16afbdbdc1d52191256a0b71f17005c5ded388 100644 (file)
@@ -283,7 +283,7 @@ static void cpsw_rx_handler(void *token, int len, int status)
 {
        struct page *new_page, *page = token;
        void *pa = page_address(page);
-       int headroom = CPSW_HEADROOM;
+       int headroom = CPSW_HEADROOM_NA;
        struct cpsw_meta_xdp *xmeta;
        struct cpsw_common *cpsw;
        struct net_device *ndev;
@@ -336,7 +336,7 @@ static void cpsw_rx_handler(void *token, int len, int status)
        }
 
        if (priv->xdp_prog) {
-               int headroom = CPSW_HEADROOM, size = len;
+               int size = len;
 
                xdp_init_buff(&xdp, PAGE_SIZE, &priv->xdp_rxq[ch]);
                if (status & CPDMA_RX_VLAN_ENCAP) {
@@ -386,7 +386,7 @@ requeue:
        xmeta->ndev = ndev;
        xmeta->ch = ch;
 
-       dma = page_pool_get_dma_addr(new_page) + CPSW_HEADROOM;
+       dma = page_pool_get_dma_addr(new_page) + CPSW_HEADROOM_NA;
        ret = cpdma_chan_submit_mapped(cpsw->rxv[ch].ch, new_page, dma,
                                       pkt_size, 0);
        if (ret < 0) {
index ecc2a6b7e28f226a4f08ec7f1f83772d6058787c..6bb5ac51d23c333cb6bfff915a672cff190eed2f 100644 (file)
@@ -1120,7 +1120,7 @@ int cpsw_fill_rx_channels(struct cpsw_priv *priv)
                        xmeta->ndev = priv->ndev;
                        xmeta->ch = ch;
 
-                       dma = page_pool_get_dma_addr(page) + CPSW_HEADROOM;
+                       dma = page_pool_get_dma_addr(page) + CPSW_HEADROOM_NA;
                        ret = cpdma_chan_idle_submit_mapped(cpsw->rxv[ch].ch,
                                                            page, dma,
                                                            cpsw->rx_packet_max,