Skip to content
Snippets Groups Projects
Select Git revision
  • 84823ff80f7403752b59e00bb198724100dc611c
  • vme-testing default
  • ci-test
  • master
  • remoteproc
  • am625-sk-ov5640
  • pcal6534-upstreaming
  • lps22df-upstreaming
  • msc-upstreaming
  • imx8mp
  • iio/noa1305
  • vme-next
  • vme-next-4.14-rc4
  • v4.14-rc4
  • v4.14-rc3
  • v4.14-rc2
  • v4.14-rc1
  • v4.13
  • vme-next-4.13-rc7
  • v4.13-rc7
  • v4.13-rc6
  • v4.13-rc5
  • v4.13-rc4
  • v4.13-rc3
  • v4.13-rc2
  • v4.13-rc1
  • v4.12
  • v4.12-rc7
  • v4.12-rc6
  • v4.12-rc5
  • v4.12-rc4
  • v4.12-rc3
32 results

ll_temac_main.c

Blame
    • Esben Haabendal's avatar
      84823ff8
      net: ll_temac: Fix race condition causing TX hang · 84823ff8
      Esben Haabendal authored
      
      It is possible that the interrupt handler fires and frees up space in
      the TX ring in between checking for sufficient TX ring space and
      stopping the TX queue in temac_start_xmit. If this happens, the
      queue wake from the interrupt handler will occur before the queue is
      stopped, causing a lost wakeup and the adapter's transmit hanging.
      
      To avoid this, after stopping the queue, check again whether there is
      sufficient space in the TX ring. If so, wake up the queue again.
      
      This is a port of the similar fix in axienet driver,
      commit 7de44285 ("net: axienet: Fix race condition causing TX hang").
      
      Fixes: 23ecc4bd ("net: ll_temac: fix checksum offload logic")
      Signed-off-by: default avatarEsben Haabendal <esben@geanix.com>
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      84823ff8
      History
      net: ll_temac: Fix race condition causing TX hang
      Esben Haabendal authored
      
      It is possible that the interrupt handler fires and frees up space in
      the TX ring in between checking for sufficient TX ring space and
      stopping the TX queue in temac_start_xmit. If this happens, the
      queue wake from the interrupt handler will occur before the queue is
      stopped, causing a lost wakeup and the adapter's transmit hanging.
      
      To avoid this, after stopping the queue, check again whether there is
      sufficient space in the TX ring. If so, wake up the queue again.
      
      This is a port of the similar fix in axienet driver,
      commit 7de44285 ("net: axienet: Fix race condition causing TX hang").
      
      Fixes: 23ecc4bd ("net: ll_temac: fix checksum offload logic")
      Signed-off-by: default avatarEsben Haabendal <esben@geanix.com>
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    gup.c 82.84 KiB
    // SPDX-License-Identifier: GPL-2.0-only
    #include <linux/kernel.h>
    #include <linux/errno.h>
    #include <linux/err.h>
    #include <linux/spinlock.h>
    
    #include <linux/mm.h>
    #include <linux/memremap.h>
    #include <linux/pagemap.h>
    #include <linux/rmap.h>
    #include <linux/swap.h>
    #include <linux/swapops.h>
    
    #include <linux/sched/signal.h>
    #include <linux/rwsem.h>
    #include <linux/hugetlb.h>
    #include <linux/migrate.h>
    #include <linux/mm_inline.h>
    #include <linux/sched/mm.h>
    
    #include <asm/mmu_context.h>
    #include <asm/tlbflush.h>
    
    #include "internal.h"
    
    struct follow_page_context {
    	struct dev_pagemap *pgmap;
    	unsigned int page_mask;
    };
    
    static void hpage_pincount_add(struct page *page, int refs)
    {
    	VM_BUG_ON_PAGE(!hpage_pincount_available(page), page);
    	VM_BUG_ON_PAGE(page != compound_head(page), page);
    
    	atomic_add(refs, compound_pincount_ptr(page));
    }
    
    static void hpage_pincount_sub(struct page *page, int refs)
    {
    	VM_BUG_ON_PAGE(!hpage_pincount_available(page), page);
    	VM_BUG_ON_PAGE(page != compound_head(page), page);
    
    	atomic_sub(refs, compound_pincount_ptr(page));
    }
    
    /*
     * Return the compound head page with ref appropriately incremented,
     * or NULL if that failed.
     */
    static inline struct page *try_get_compound_head(struct page *page, int refs)
    {
    	struct page *head = compound_head(page);
    
    	if (WARN_ON_ONCE(page_ref_count(head) < 0))
    		return NULL;
    	if (unlikely(!page_cache_add_speculative(head, refs)))
    		return NULL;
    	return head;
    }
    
    /*
     * try_grab_compound_head() - attempt to elevate a page's refcount, by a
     * flags-dependent amount.
     *
     * "grab" names in this file mean, "look at flags to decide whether to use
     * FOLL_PIN or FOLL_GET behavior, when incrementing the page's refcount.
     *
     * Either FOLL_PIN or FOLL_GET (or neither) must be set, but not both at the
     * same time. (That's true throughout the get_user_pages*() and