lkml.org 
[lkml]   [2022]   [Jan]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 149/157] gianfar: simplify FCS handling and fix memory leak
    Date
    From: Andy Spencer <aspencer@spacex.com>

    commit d903ec77118c09f93a610b384d83a6df33a64fe6 upstream.

    Previously, buffer descriptors containing only the frame check sequence
    (FCS) were skipped and not added to the skb. However, the page reference
    count was still incremented, leading to a memory leak.

    Fixing this inside gfar_add_rx_frag() is difficult due to reserved
    memory handling and page reuse. Instead, move the FCS handling to
    gfar_process_frame() and trim off the FCS before passing the skb up the
    networking stack.

    Signed-off-by: Andy Spencer <aspencer@spacex.com>
    Signed-off-by: Jim Gruen <jgruen@spacex.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Cc: Ben Hutchings <ben@decadent.org.uk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/net/ethernet/freescale/gianfar.c | 23 +++++++----------------
    1 file changed, 7 insertions(+), 16 deletions(-)

    --- a/drivers/net/ethernet/freescale/gianfar.c
    +++ b/drivers/net/ethernet/freescale/gianfar.c
    @@ -2939,29 +2939,17 @@ static bool gfar_add_rx_frag(struct gfar
    {
    int size = lstatus & BD_LENGTH_MASK;
    struct page *page = rxb->page;
    - bool last = !!(lstatus & BD_LFLAG(RXBD_LAST));
    -
    - /* Remove the FCS from the packet length */
    - if (last)
    - size -= ETH_FCS_LEN;

    if (likely(first)) {
    skb_put(skb, size);
    } else {
    /* the last fragments' length contains the full frame length */
    - if (last)
    + if (lstatus & BD_LFLAG(RXBD_LAST))
    size -= skb->len;

    - /* Add the last fragment if it contains something other than
    - * the FCS, otherwise drop it and trim off any part of the FCS
    - * that was already received.
    - */
    - if (size > 0)
    - skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
    - rxb->page_offset + RXBUF_ALIGNMENT,
    - size, GFAR_RXB_TRUESIZE);
    - else if (size < 0)
    - pskb_trim(skb, skb->len + size);
    + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
    + rxb->page_offset + RXBUF_ALIGNMENT,
    + size, GFAR_RXB_TRUESIZE);
    }

    /* try reuse page */
    @@ -3074,6 +3062,9 @@ static void gfar_process_frame(struct ne
    if (priv->padding)
    skb_pull(skb, priv->padding);

    + /* Trim off the FCS */
    + pskb_trim(skb, skb->len - ETH_FCS_LEN);
    +
    if (ndev->features & NETIF_F_RXCSUM)
    gfar_rx_checksum(skb, fcb);


    \
     
     \ /
      Last update: 2022-01-25 04:10    [W:4.042 / U:0.228 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site