* Re: [PATCH iproute2 v2] bridge: make mcast_flood description consistent
From: Stephen Hemminger @ 2019-02-21 22:48 UTC (permalink / raw)
To: Vivien Didelot; +Cc: netdev, Russell King
In-Reply-To: <20190220163357.25968-1-vivien.didelot@gmail.com>
On Wed, 20 Feb 2019 11:33:57 -0500
Vivien Didelot <vivien.didelot@gmail.com> wrote:
> This patch simply changes the description of the mcast_flood flag
> with "flood" instead of "be flooded with" to avoid confusion, and be
> consistent with the description of the flooding flag, which "Controls
> whether a given port will *flood* unicast traffic for which there is
> no FDB entry."
>
> At the same time, fix the documentation for the "flood" flag which
> is incorrectly described as "flooding on" or "flooding off".
>
> Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
Applied
^ permalink raw reply
* Re: [PATCH] samples/bpf: Fix dummy program unloading for xdp_redirect samples
From: Martin Lau @ 2019-02-21 22:47 UTC (permalink / raw)
To: Maciej Fijalkowski
Cc: Toke Høiland-Jørgensen, netdev@vger.kernel.org
In-Reply-To: <20190221173054.00006df2@gmail.com>
On Thu, Feb 21, 2019 at 05:30:54PM +0100, Maciej Fijalkowski wrote:
> On Thu, 21 Feb 2019 17:05:39 +0100
> Toke Høiland-Jørgensen <toke@redhat.com> wrote:
>
> > The xdp_redirect and xdp_redirect_map sample programs both load a dummy
> > program onto the egress interfaces. However, the unload code checks these
> > programs against the wrong fd number, and thus refuses to unload them. Fix
s/fd/id/
> > the comparison to avoid this.
The change LGTM.
Acked-by: Martin KaFai Lau <kafai@fb.com>
^ permalink raw reply
* Re: [iproute PATCH] ip-address: Use correct max attribute value in print_vf_stats64()
From: Stephen Hemminger @ 2019-02-21 22:40 UTC (permalink / raw)
To: Phil Sutter; +Cc: netdev
In-Reply-To: <20190221183751.10604-1-phil@nwl.cc>
On Thu, 21 Feb 2019 19:37:51 +0100
Phil Sutter <phil@nwl.cc> wrote:
> IFLA_VF_MAX is larger than the highest valid index in vf array.
>
> Fixes: a1b99717c7cd7 ("Add displaying VF traffic statistics")
> Signed-off-by: Phil Sutter <phil@nwl.cc>
Good catch. It worked because VF_MAX is 12 and VF_STATS_MAX is 8.
Applied.
^ permalink raw reply
* Re: mlx5 stable backport help
From: Saeed Mahameed @ 2019-02-21 22:35 UTC (permalink / raw)
To: gerlitz.or@gmail.com
Cc: davem@davemloft.net, netdev@vger.kernel.org, Or Gerlitz
In-Reply-To: <CAJ3xEMibTfuFkdoV5wjq4s3aV4WCBmaKGQij-tH=5S4t7ZoSrQ@mail.gmail.com>
On Thu, 2019-02-21 at 12:21 +0200, Or Gerlitz wrote:
> On Wed, Feb 20, 2019 at 10:03 PM Saeed Mahameed <saeedm@mellanox.com>
> wrote:
> > On Tue, 2019-02-19 at 22:36 -0800, David Miller wrote:
> > > I need help backporting two changes for -stable. Namely:
> > Hi Dave Thanks for trying,
>
> here too
>
> > > 6707f74be8621ae067d2cf1c4485900e2742c20f ("net/mlx5e: Update hw
> > > flows
> > > when encap source mac changed")
> >
> > The fixes tag of the above commit is wrong and it should have been
> >
> > commit e32ee6c78efa6a32bff782bbe7a9970b018996ca
> > Author: Eli Britstein <elibr@mellanox.com>
> > Date: Mon Dec 3 17:09:54 2018 +0200
> >
> > net/mlx5e: Support tunnel encap over tagged Ethernet
> >
> > Before this patch we didn't have the support for "tunnel encap over
> > tagged Ethernet" which introduced the whole route_dev logic to
> > generate
> > the encap headers, so the patch should only exist in -rc, let's
> > just skip it.
>
> Hi Saeed,
>
> The issue exists prior to the commit you mentioned, we are doing this
> code since day one of
> tc tunnel offloads support which lacked the neigh update flow
>
> linux-stable.git]# git grep -pe "eth->h_source"
> drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
> drivers/net/ethernet/mellanox/mlx5/core/en_tc.c=static void
> gen_vxlan_header_ipv4(struct net_device *out_dev,
> drivers/net/ethernet/mellanox/mlx5/core/en_tc.c:
> ether_addr_copy(eth->h_source, out_dev->dev_addr);
> drivers/net/ethernet/mellanox/mlx5/core/en_tc.c=static void
> gen_vxlan_header_ipv6(struct net_device *out_dev,
> drivers/net/ethernet/mellanox/mlx5/core/en_tc.c:
> ether_addr_copy(eth->h_source, out_dev->dev_addr);
>
> later when 232c001398ae ("net/mlx5e: Add support to neighbour update
> flow") was done, we went short
> and did not address the case of source address change. Until the
> commit you mentioned, we didn't have the
> out_dev vs route_dev notion, but the problem exists and it's possible
> to backport the patch by
>
So we all agree that the offending patch is "net/mlx5e: Support tunnel
encap over tagged Ethernet" even if the issue existed before,
in order to fix the issue you will have to port not only this patch but
the whole series which claimed to fix the issue, so the fixes tag was
wrong.. this patch on its own is no good.
> [1] using e->out_dev instead of e->route_dev
> [2] use the hunks from mlx5e_tc_tun_create_header_ipv4/6() in
> mlx5e_create_encap_header_ipv4/6()
>
> Or.
^ permalink raw reply
* Re: [PATCH v3 net-next 1/4] net: dsa: microchip: prepare PHY for proper advertisement
From: Florian Fainelli @ 2019-02-21 22:33 UTC (permalink / raw)
To: Tristram.Ha, Sergio Paracuellos, Andrew Lunn, Pavel Machek
Cc: UNGLinuxDriver, netdev
In-Reply-To: <1550786597-591-2-git-send-email-Tristram.Ha@microchip.com>
On 2/21/19 2:03 PM, Tristram.Ha@microchip.com wrote:
> From: Tristram Ha <Tristram.Ha@microchip.com>
>
> Prepare PHY for proper advertisement as sometimes the PHY in the switch
> has its own problems even though it may share the PHY id from regular PHY
> but the fixes in the PHY driver do not apply.
>
> Signed-off-by: Tristram Ha <Tristram.Ha@microchip.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
--
Florian
^ permalink raw reply
* Re: [PATCH] x86, retpolines: raise limit for generating indirect calls from switch-case
From: Linus Torvalds @ 2019-02-21 22:27 UTC (permalink / raw)
To: Daniel Borkmann
Cc: Thomas Gleixner, Linux List Kernel Mailing, Netdev,
David S . Miller, Björn Töpel, Magnus Karlsson,
Jesper Dangaard Brouer, Alexei Starovoitov, Peter Zijlstra,
David Woodhouse, Andy Lutomirski, Borislav Petkov
In-Reply-To: <20190221221941.29358-1-daniel@iogearbox.net>
On Thu, Feb 21, 2019 at 2:20 PM Daniel Borkmann <daniel@iogearbox.net> wrote:
>
> In case of gcc, this setting is controlled by case-values-threshold
> which has an architecture global default that selects 4 or 5 (
Ack. For retpoline, that's much too low.
Patch looks sane, although it would be good to verify just which
versions of gcc this works for. All versions with retpoline?
Linus
^ permalink raw reply
* Re: [PATCH bpf-next v1] bpf, lpm: fix lookup bug in map_delete_elem
From: Martin Lau @ 2019-02-21 22:23 UTC (permalink / raw)
To: Alban Crequy
Cc: ast@kernel.org, daniel@iogearbox.net, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, alban@kinvolk.io, iago@kinvolk.io,
Craig Gallek
In-Reply-To: <20190221163926.15221-1-alban@kinvolk.io>
On Thu, Feb 21, 2019 at 05:39:26PM +0100, Alban Crequy wrote:
> From: Alban Crequy <alban@kinvolk.io>
>
> trie_delete_elem() was deleting an entry even though it was not matching
> if the prefixlen was correct. This patch adds a check on matchlen.
>
> Reproducer:
>
> $ sudo bpftool map create /sys/fs/bpf/mylpm type lpm_trie key 8 value 1 entries 128 name mylpm flags 1
> $ sudo bpftool map update pinned /sys/fs/bpf/mylpm key hex 10 00 00 00 aa bb cc dd value hex 01
> $ sudo bpftool map dump pinned /sys/fs/bpf/mylpm
> key: 10 00 00 00 aa bb cc dd value: 01
> Found 1 element
> $ sudo bpftool map delete pinned /sys/fs/bpf/mylpm key hex 10 00 00 00 ff ff ff ff
> $ echo $?
> 0
> $ sudo bpftool map dump pinned /sys/fs/bpf/mylpm
> Found 0 elements
The change makes sense to me. Can you add this reproducer to
tools/testing/selftests/bpf/test_lpm_map.c?
Bug fix should be for the "bpf" tree instead of "bpf-next"
Fixes tag is also required, like
Fixes: e454cf595853 ("bpf: Implement map_delete_elem for BPF_MAP_TYPE_LPM_TRIE")
Cc: Craig Gallek <kraig@google.com>
>
> Signed-off-by: Alban Crequy <alban@kinvolk.io>
> ---
> kernel/bpf/lpm_trie.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c
> index abf1002080df..93a5cbbde421 100644
> --- a/kernel/bpf/lpm_trie.c
> +++ b/kernel/bpf/lpm_trie.c
> @@ -471,6 +471,7 @@ static int trie_delete_elem(struct bpf_map *map, void *_key)
> }
>
> if (!node || node->prefixlen != key->prefixlen ||
> + node->prefixlen != matchlen ||
> (node->flags & LPM_TREE_NODE_FLAG_IM)) {
> ret = -ENOENT;
> goto out;
> --
> 2.20.1
>
^ permalink raw reply
* Re: [RESEND PATCH 3/7] mm/gup: Change GUP fast to use flags rather than a write 'bool'
From: Ira Weiny @ 2019-02-21 22:24 UTC (permalink / raw)
To: Souptick Joarder
Cc: John Hubbard, Andrew Morton, Michal Hocko, Kirill A. Shutemov,
Peter Zijlstra, Jason Gunthorpe, Benjamin Herrenschmidt,
Paul Mackerras, David S. Miller, Martin Schwidefsky,
Heiko Carstens, Rich Felker, Yoshinori Sato, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Ralf Baechle, Paul Burton,
James Hogan, linux-kernel, Linux-MM, linux-mips, linuxppc-dev,
linux-s390, linux-sh, sparclinux, kvm-ppc, kvm, linux-fpga,
dri-devel, linux-rdma, linux-media, linux-scsi,
open list:ANDROID DRIVERS, virtualization, netdev, linux-fbdev,
xen-devel, devel, ceph-devel, rds-devel
In-Reply-To: <CAFqt6zYvkhKw3GExRQB2e_c16KQqrKT=GoiqErA06txUQa2bMQ@mail.gmail.com>
On Thu, Feb 21, 2019 at 08:48:41AM +0530, Souptick Joarder wrote:
> Hi Ira,
>
> On Wed, Feb 20, 2019 at 11:01 AM <ira.weiny@intel.com> wrote:
> >
> > From: Ira Weiny <ira.weiny@intel.com>
> >
> > To facilitate additional options to get_user_pages_fast() change the
> > singular write parameter to be gup_flags.
> >
> > This patch does not change any functionality. New functionality will
> > follow in subsequent patches.
> >
> > Some of the get_user_pages_fast() call sites were unchanged because they
> > already passed FOLL_WRITE or 0 for the write parameter.
> >
> > Signed-off-by: Ira Weiny <ira.weiny@intel.com>
> > ---
[snip]
> > diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
> > index bd2dcfbf00cd..8fcb0a921e46 100644
> > --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
> > +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
> > @@ -582,7 +582,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
> > /* If writing != 0, then the HPTE must allow writing, if we get here */
> > write_ok = writing;
> > hva = gfn_to_hva_memslot(memslot, gfn);
> > - npages = get_user_pages_fast(hva, 1, writing, pages);
> > + npages = get_user_pages_fast(hva, 1, writing ? FOLL_WRITE : 0, pages);
>
> Just requesting for opinion,
> * writing ? FOLL_WRITE : 0 * is used in many places. How about placing it in a
> macro/ inline ?
I don't really think this would gain much. And I don't think it would be more
clear. In fact I can't even think of a macro name which would make sense. I'm
inclined to leave this as written.
Ira
>
> > if (npages < 1) {
> > /* Check if it's an I/O mapping */
> > down_read(¤t->mm->mmap_sem);
> > @@ -1175,7 +1175,7 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
> > if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
> > goto err;
> > hva = gfn_to_hva_memslot(memslot, gfn);
> > - npages = get_user_pages_fast(hva, 1, 1, pages);
> > + npages = get_user_pages_fast(hva, 1, FOLL_WRITE, pages);
> > if (npages < 1)
> > goto err;
> > page = pages[0];
> > diff --git a/arch/powerpc/kvm/e500_mmu.c b/arch/powerpc/kvm/e500_mmu.c
> > index 24296f4cadc6..e0af53fd78c5 100644
> > --- a/arch/powerpc/kvm/e500_mmu.c
> > +++ b/arch/powerpc/kvm/e500_mmu.c
> > @@ -783,7 +783,7 @@ int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
> > if (!pages)
> > return -ENOMEM;
> >
> > - ret = get_user_pages_fast(cfg->array, num_pages, 1, pages);
> > + ret = get_user_pages_fast(cfg->array, num_pages, FOLL_WRITE, pages);
> > if (ret < 0)
> > goto free_pages;
> >
> > diff --git a/arch/powerpc/mm/mmu_context_iommu.c b/arch/powerpc/mm/mmu_context_iommu.c
> > index a712a650a8b6..acb0990c8364 100644
> > --- a/arch/powerpc/mm/mmu_context_iommu.c
> > +++ b/arch/powerpc/mm/mmu_context_iommu.c
> > @@ -190,7 +190,7 @@ static long mm_iommu_do_alloc(struct mm_struct *mm, unsigned long ua,
> > for (i = 0; i < entries; ++i) {
> > cur_ua = ua + (i << PAGE_SHIFT);
> > if (1 != get_user_pages_fast(cur_ua,
> > - 1/* pages */, 1/* iswrite */, &page)) {
> > + 1/* pages */, FOLL_WRITE, &page)) {
> > ret = -EFAULT;
> > for (j = 0; j < i; ++j)
> > put_page(pfn_to_page(mem->hpas[j] >>
> > @@ -209,7 +209,7 @@ static long mm_iommu_do_alloc(struct mm_struct *mm, unsigned long ua,
> > if (mm_iommu_move_page_from_cma(page))
> > goto populate;
> > if (1 != get_user_pages_fast(cur_ua,
> > - 1/* pages */, 1/* iswrite */,
> > + 1/* pages */, FOLL_WRITE,
> > &page)) {
> > ret = -EFAULT;
> > for (j = 0; j < i; ++j)
> > diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
> > index fcb55b02990e..69d9366b966c 100644
> > --- a/arch/s390/kvm/interrupt.c
> > +++ b/arch/s390/kvm/interrupt.c
> > @@ -2278,7 +2278,7 @@ static int kvm_s390_adapter_map(struct kvm *kvm, unsigned int id, __u64 addr)
> > ret = -EFAULT;
> > goto out;
> > }
> > - ret = get_user_pages_fast(map->addr, 1, 1, &map->page);
> > + ret = get_user_pages_fast(map->addr, 1, FOLL_WRITE, &map->page);
> > if (ret < 0)
> > goto out;
> > BUG_ON(ret != 1);
> > diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c
> > index 2809d11c7a28..0a6faf3d9960 100644
> > --- a/arch/s390/mm/gup.c
> > +++ b/arch/s390/mm/gup.c
> > @@ -265,7 +265,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> > * get_user_pages_fast() - pin user pages in memory
> > * @start: starting user address
> > * @nr_pages: number of pages from start to pin
> > - * @write: whether pages will be written to
> > + * @gup_flags: flags modifying pin behaviour
> > * @pages: array that receives pointers to the pages pinned.
> > * Should be at least nr_pages long.
> > *
> > @@ -277,22 +277,22 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> > * requested. If nr_pages is 0 or negative, returns 0. If no pages
> > * were pinned, returns -errno.
> > */
> > -int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> > - struct page **pages)
> > +int get_user_pages_fast(unsigned long start, int nr_pages,
> > + unsigned int gup_flags, struct page **pages)
> > {
> > int nr, ret;
> >
> > might_sleep();
> > start &= PAGE_MASK;
> > - nr = __get_user_pages_fast(start, nr_pages, write, pages);
> > + nr = __get_user_pages_fast(start, nr_pages, gup_flags & FOLL_WRITE,
> > + pages);
> > if (nr == nr_pages)
> > return nr;
> >
> > /* Try to get the remaining pages with get_user_pages */
> > start += nr << PAGE_SHIFT;
> > pages += nr;
> > - ret = get_user_pages_unlocked(start, nr_pages - nr, pages,
> > - write ? FOLL_WRITE : 0);
> > + ret = get_user_pages_unlocked(start, nr_pages - nr, pages, gup_flags);
> > /* Have to be a bit careful with return values */
> > if (nr > 0)
> > ret = (ret < 0) ? nr : ret + nr;
> > diff --git a/arch/sh/mm/gup.c b/arch/sh/mm/gup.c
> > index 3e27f6d1f1ec..277c882f7489 100644
> > --- a/arch/sh/mm/gup.c
> > +++ b/arch/sh/mm/gup.c
> > @@ -204,7 +204,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> > * get_user_pages_fast() - pin user pages in memory
> > * @start: starting user address
> > * @nr_pages: number of pages from start to pin
> > - * @write: whether pages will be written to
> > + * @gup_flags: flags modifying pin behaviour
> > * @pages: array that receives pointers to the pages pinned.
> > * Should be at least nr_pages long.
> > *
> > @@ -216,8 +216,8 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> > * requested. If nr_pages is 0 or negative, returns 0. If no pages
> > * were pinned, returns -errno.
> > */
> > -int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> > - struct page **pages)
> > +int get_user_pages_fast(unsigned long start, int nr_pages,
> > + unsigned int gup_flags, struct page **pages)
> > {
> > struct mm_struct *mm = current->mm;
> > unsigned long addr, len, end;
> > @@ -241,7 +241,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> > next = pgd_addr_end(addr, end);
> > if (pgd_none(pgd))
> > goto slow;
> > - if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
> > + if (!gup_pud_range(pgd, addr, next, gup_flags & FOLL_WRITE,
> > + pages, &nr))
> > goto slow;
> > } while (pgdp++, addr = next, addr != end);
> > local_irq_enable();
> > @@ -261,7 +262,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> >
> > ret = get_user_pages_unlocked(start,
> > (end - start) >> PAGE_SHIFT, pages,
> > - write ? FOLL_WRITE : 0);
> > + gup_flags);
> >
> > /* Have to be a bit careful with return values */
> > if (nr > 0) {
> > diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c
> > index aee6dba83d0e..1e770a517d4a 100644
> > --- a/arch/sparc/mm/gup.c
> > +++ b/arch/sparc/mm/gup.c
> > @@ -245,8 +245,8 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> > return nr;
> > }
> >
> > -int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> > - struct page **pages)
> > +int get_user_pages_fast(unsigned long start, int nr_pages,
> > + unsigned int gup_flags, struct page **pages)
> > {
> > struct mm_struct *mm = current->mm;
> > unsigned long addr, len, end;
> > @@ -303,7 +303,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> > next = pgd_addr_end(addr, end);
> > if (pgd_none(pgd))
> > goto slow;
> > - if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
> > + if (!gup_pud_range(pgd, addr, next, gup_flags & FOLL_WRITE,
> > + pages, &nr))
> > goto slow;
> > } while (pgdp++, addr = next, addr != end);
> >
> > @@ -324,7 +325,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> >
> > ret = get_user_pages_unlocked(start,
> > (end - start) >> PAGE_SHIFT, pages,
> > - write ? FOLL_WRITE : 0);
> > + gup_flags);
> >
> > /* Have to be a bit careful with return values */
> > if (nr > 0) {
> > diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
> > index 6bdca39829bc..08715034e315 100644
> > --- a/arch/x86/kvm/paging_tmpl.h
> > +++ b/arch/x86/kvm/paging_tmpl.h
> > @@ -140,7 +140,7 @@ static int FNAME(cmpxchg_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
> > pt_element_t *table;
> > struct page *page;
> >
> > - npages = get_user_pages_fast((unsigned long)ptep_user, 1, 1, &page);
> > + npages = get_user_pages_fast((unsigned long)ptep_user, 1, FOLL_WRITE, &page);
> > /* Check if the user is doing something meaningless. */
> > if (unlikely(npages != 1))
> > return -EFAULT;
> > diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
> > index f13a3a24d360..173596a020cb 100644
> > --- a/arch/x86/kvm/svm.c
> > +++ b/arch/x86/kvm/svm.c
> > @@ -1803,7 +1803,7 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr,
> > return NULL;
> >
> > /* Pin the user virtual address. */
> > - npinned = get_user_pages_fast(uaddr, npages, write ? FOLL_WRITE : 0, pages);
> > + npinned = get_user_pages_fast(uaddr, npages, FOLL_WRITE, pages);
> > if (npinned != npages) {
> > pr_err("SEV: Failure locking %lu pages.\n", npages);
> > goto err;
> > diff --git a/drivers/fpga/dfl-afu-dma-region.c b/drivers/fpga/dfl-afu-dma-region.c
> > index e18a786fc943..c438722bf4e1 100644
> > --- a/drivers/fpga/dfl-afu-dma-region.c
> > +++ b/drivers/fpga/dfl-afu-dma-region.c
> > @@ -102,7 +102,7 @@ static int afu_dma_pin_pages(struct dfl_feature_platform_data *pdata,
> > goto unlock_vm;
> > }
> >
> > - pinned = get_user_pages_fast(region->user_addr, npages, 1,
> > + pinned = get_user_pages_fast(region->user_addr, npages, FOLL_WRITE,
> > region->pages);
> > if (pinned < 0) {
> > ret = pinned;
> > diff --git a/drivers/gpu/drm/via/via_dmablit.c b/drivers/gpu/drm/via/via_dmablit.c
> > index 345bda4494e1..0c8b09602910 100644
> > --- a/drivers/gpu/drm/via/via_dmablit.c
> > +++ b/drivers/gpu/drm/via/via_dmablit.c
> > @@ -239,7 +239,8 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
> > if (NULL == vsg->pages)
> > return -ENOMEM;
> > ret = get_user_pages_fast((unsigned long)xfer->mem_addr,
> > - vsg->num_pages, vsg->direction == DMA_FROM_DEVICE,
> > + vsg->num_pages,
> > + vsg->direction == DMA_FROM_DEVICE ? FOLL_WRITE : 0,
> > vsg->pages);
> > if (ret != vsg->num_pages) {
> > if (ret < 0)
> > diff --git a/drivers/infiniband/hw/hfi1/user_pages.c b/drivers/infiniband/hw/hfi1/user_pages.c
> > index 24b592c6522e..78ccacaf97d0 100644
> > --- a/drivers/infiniband/hw/hfi1/user_pages.c
> > +++ b/drivers/infiniband/hw/hfi1/user_pages.c
> > @@ -105,7 +105,8 @@ int hfi1_acquire_user_pages(struct mm_struct *mm, unsigned long vaddr, size_t np
> > {
> > int ret;
> >
> > - ret = get_user_pages_fast(vaddr, npages, writable, pages);
> > + ret = get_user_pages_fast(vaddr, npages, writable ? FOLL_WRITE : 0,
> > + pages);
> > if (ret < 0)
> > return ret;
> >
> > diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c
> > index 25265fd0fd6e..89cff9d1012b 100644
> > --- a/drivers/misc/genwqe/card_utils.c
> > +++ b/drivers/misc/genwqe/card_utils.c
> > @@ -603,7 +603,7 @@ int genwqe_user_vmap(struct genwqe_dev *cd, struct dma_mapping *m, void *uaddr,
> > /* pin user pages in memory */
> > rc = get_user_pages_fast(data & PAGE_MASK, /* page aligned addr */
> > m->nr_pages,
> > - m->write, /* readable/writable */
> > + m->write ? FOLL_WRITE : 0, /* readable/writable */
> > m->page_list); /* ptrs to pages */
> > if (rc < 0)
> > goto fail_get_user_pages;
> > diff --git a/drivers/misc/vmw_vmci/vmci_host.c b/drivers/misc/vmw_vmci/vmci_host.c
> > index 997f92543dd4..422d08da3244 100644
> > --- a/drivers/misc/vmw_vmci/vmci_host.c
> > +++ b/drivers/misc/vmw_vmci/vmci_host.c
> > @@ -242,7 +242,7 @@ static int vmci_host_setup_notify(struct vmci_ctx *context,
> > /*
> > * Lock physical page backing a given user VA.
> > */
> > - retval = get_user_pages_fast(uva, 1, 1, &context->notify_page);
> > + retval = get_user_pages_fast(uva, 1, FOLL_WRITE, &context->notify_page);
> > if (retval != 1) {
> > context->notify_page = NULL;
> > return VMCI_ERROR_GENERIC;
> > diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c
> > index 264f4ed8eef2..c5396ee32e51 100644
> > --- a/drivers/misc/vmw_vmci/vmci_queue_pair.c
> > +++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c
> > @@ -666,7 +666,8 @@ static int qp_host_get_user_memory(u64 produce_uva,
> > int err = VMCI_SUCCESS;
> >
> > retval = get_user_pages_fast((uintptr_t) produce_uva,
> > - produce_q->kernel_if->num_pages, 1,
> > + produce_q->kernel_if->num_pages,
> > + FOLL_WRITE,
> > produce_q->kernel_if->u.h.header_page);
> > if (retval < (int)produce_q->kernel_if->num_pages) {
> > pr_debug("get_user_pages_fast(produce) failed (retval=%d)",
> > @@ -678,7 +679,8 @@ static int qp_host_get_user_memory(u64 produce_uva,
> > }
> >
> > retval = get_user_pages_fast((uintptr_t) consume_uva,
> > - consume_q->kernel_if->num_pages, 1,
> > + consume_q->kernel_if->num_pages,
> > + FOLL_WRITE,
> > consume_q->kernel_if->u.h.header_page);
> > if (retval < (int)consume_q->kernel_if->num_pages) {
> > pr_debug("get_user_pages_fast(consume) failed (retval=%d)",
> > diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c
> > index 321bc673c417..cef0133aa47a 100644
> > --- a/drivers/platform/goldfish/goldfish_pipe.c
> > +++ b/drivers/platform/goldfish/goldfish_pipe.c
> > @@ -274,7 +274,8 @@ static int pin_user_pages(unsigned long first_page,
> > *iter_last_page_size = last_page_size;
> > }
> >
> > - ret = get_user_pages_fast(first_page, requested_pages, !is_write,
> > + ret = get_user_pages_fast(first_page, requested_pages,
> > + !is_write ? FOLL_WRITE : 0,
> > pages);
> > if (ret <= 0)
> > return -EFAULT;
> > diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c
> > index cbe467ff1aba..f681b3e9e970 100644
> > --- a/drivers/rapidio/devices/rio_mport_cdev.c
> > +++ b/drivers/rapidio/devices/rio_mport_cdev.c
> > @@ -868,7 +868,9 @@ rio_dma_transfer(struct file *filp, u32 transfer_mode,
> >
> > pinned = get_user_pages_fast(
> > (unsigned long)xfer->loc_addr & PAGE_MASK,
> > - nr_pages, dir == DMA_FROM_DEVICE, page_list);
> > + nr_pages,
> > + dir == DMA_FROM_DEVICE ? FOLL_WRITE : 0,
> > + page_list);
> >
> > if (pinned != nr_pages) {
> > if (pinned < 0) {
> > diff --git a/drivers/sbus/char/oradax.c b/drivers/sbus/char/oradax.c
> > index 6516bc3cb58b..790aa148670d 100644
> > --- a/drivers/sbus/char/oradax.c
> > +++ b/drivers/sbus/char/oradax.c
> > @@ -437,7 +437,7 @@ static int dax_lock_page(void *va, struct page **p)
> >
> > dax_dbg("uva %p", va);
> >
> > - ret = get_user_pages_fast((unsigned long)va, 1, 1, p);
> > + ret = get_user_pages_fast((unsigned long)va, 1, FOLL_WRITE, p);
> > if (ret == 1) {
> > dax_dbg("locked page %p, for VA %p", *p, va);
> > return 0;
> > diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
> > index 7ff22d3f03e3..871b25914c07 100644
> > --- a/drivers/scsi/st.c
> > +++ b/drivers/scsi/st.c
> > @@ -4918,7 +4918,8 @@ static int sgl_map_user_pages(struct st_buffer *STbp,
> >
> > /* Try to fault in all of the necessary pages */
> > /* rw==READ means read from drive, write into memory area */
> > - res = get_user_pages_fast(uaddr, nr_pages, rw == READ, pages);
> > + res = get_user_pages_fast(uaddr, nr_pages, rw == READ ? FOLL_WRITE : 0,
> > + pages);
> >
> > /* Errors and no page mapped should return here */
> > if (res < nr_pages)
> > diff --git a/drivers/staging/gasket/gasket_page_table.c b/drivers/staging/gasket/gasket_page_table.c
> > index 26755d9ca41d..f67fdf1d3817 100644
> > --- a/drivers/staging/gasket/gasket_page_table.c
> > +++ b/drivers/staging/gasket/gasket_page_table.c
> > @@ -486,8 +486,8 @@ static int gasket_perform_mapping(struct gasket_page_table *pg_tbl,
> > ptes[i].dma_addr = pg_tbl->coherent_pages[0].paddr +
> > off + i * PAGE_SIZE;
> > } else {
> > - ret = get_user_pages_fast(page_addr - offset, 1, 1,
> > - &page);
> > + ret = get_user_pages_fast(page_addr - offset, 1,
> > + FOLL_WRITE, &page);
> >
> > if (ret <= 0) {
> > dev_err(pg_tbl->device,
> > diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> > index 0b9ab1d0dd45..49fd7312e2aa 100644
> > --- a/drivers/tee/tee_shm.c
> > +++ b/drivers/tee/tee_shm.c
> > @@ -273,7 +273,7 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> > goto err;
> > }
> >
> > - rc = get_user_pages_fast(start, num_pages, 1, shm->pages);
> > + rc = get_user_pages_fast(start, num_pages, FOLL_WRITE, shm->pages);
> > if (rc > 0)
> > shm->num_pages = rc;
> > if (rc != num_pages) {
> > diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c
> > index c424913324e3..a4b10bb4086b 100644
> > --- a/drivers/vfio/vfio_iommu_spapr_tce.c
> > +++ b/drivers/vfio/vfio_iommu_spapr_tce.c
> > @@ -532,7 +532,8 @@ static int tce_iommu_use_page(unsigned long tce, unsigned long *hpa)
> > enum dma_data_direction direction = iommu_tce_direction(tce);
> >
> > if (get_user_pages_fast(tce & PAGE_MASK, 1,
> > - direction != DMA_TO_DEVICE, &page) != 1)
> > + direction != DMA_TO_DEVICE ? FOLL_WRITE : 0,
> > + &page) != 1)
> > return -EFAULT;
> >
> > *hpa = __pa((unsigned long) page_address(page));
> > diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> > index 24a129fcdd61..72685b1659ff 100644
> > --- a/drivers/vhost/vhost.c
> > +++ b/drivers/vhost/vhost.c
> > @@ -1700,7 +1700,7 @@ static int set_bit_to_user(int nr, void __user *addr)
> > int bit = nr + (log % PAGE_SIZE) * 8;
> > int r;
> >
> > - r = get_user_pages_fast(log, 1, 1, &page);
> > + r = get_user_pages_fast(log, 1, FOLL_WRITE, &page);
> > if (r < 0)
> > return r;
> > BUG_ON(r != 1);
> > diff --git a/drivers/video/fbdev/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c
> > index 8a53d1de611d..41390c8e0f67 100644
> > --- a/drivers/video/fbdev/pvr2fb.c
> > +++ b/drivers/video/fbdev/pvr2fb.c
> > @@ -686,7 +686,7 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
> > if (!pages)
> > return -ENOMEM;
> >
> > - ret = get_user_pages_fast((unsigned long)buf, nr_pages, true, pages);
> > + ret = get_user_pages_fast((unsigned long)buf, nr_pages, FOLL_WRITE, pages);
> > if (ret < nr_pages) {
> > nr_pages = ret;
> > ret = -EINVAL;
> > diff --git a/drivers/virt/fsl_hypervisor.c b/drivers/virt/fsl_hypervisor.c
> > index 8ba726e600e9..6446bcab4185 100644
> > --- a/drivers/virt/fsl_hypervisor.c
> > +++ b/drivers/virt/fsl_hypervisor.c
> > @@ -244,7 +244,7 @@ static long ioctl_memcpy(struct fsl_hv_ioctl_memcpy __user *p)
> >
> > /* Get the physical addresses of the source buffer */
> > num_pinned = get_user_pages_fast(param.local_vaddr - lb_offset,
> > - num_pages, param.source != -1, pages);
> > + num_pages, param.source != -1 ? FOLL_WRITE : 0, pages);
> >
> > if (num_pinned != num_pages) {
> > /* get_user_pages() failed */
> > diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
> > index 5efc5eee9544..7b47f1e6aab4 100644
> > --- a/drivers/xen/gntdev.c
> > +++ b/drivers/xen/gntdev.c
> > @@ -852,7 +852,7 @@ static int gntdev_get_page(struct gntdev_copy_batch *batch, void __user *virt,
> > unsigned long xen_pfn;
> > int ret;
> >
> > - ret = get_user_pages_fast(addr, 1, writeable, &page);
> > + ret = get_user_pages_fast(addr, 1, writeable ? FOLL_WRITE : 0, &page);
> > if (ret < 0)
> > return ret;
> >
> > diff --git a/fs/orangefs/orangefs-bufmap.c b/fs/orangefs/orangefs-bufmap.c
> > index 443bcd8c3c19..5a7c4fda682f 100644
> > --- a/fs/orangefs/orangefs-bufmap.c
> > +++ b/fs/orangefs/orangefs-bufmap.c
> > @@ -269,7 +269,7 @@ orangefs_bufmap_map(struct orangefs_bufmap *bufmap,
> >
> > /* map the pages */
> > ret = get_user_pages_fast((unsigned long)user_desc->ptr,
> > - bufmap->page_count, 1, bufmap->page_array);
> > + bufmap->page_count, FOLL_WRITE, bufmap->page_array);
> >
> > if (ret < 0)
> > return ret;
> > diff --git a/include/linux/mm.h b/include/linux/mm.h
> > index 05a105d9d4c3..8e1f3cd7482a 100644
> > --- a/include/linux/mm.h
> > +++ b/include/linux/mm.h
> > @@ -1537,8 +1537,8 @@ long get_user_pages_locked(unsigned long start, unsigned long nr_pages,
> > long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
> > struct page **pages, unsigned int gup_flags);
> >
> > -int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> > - struct page **pages);
> > +int get_user_pages_fast(unsigned long start, int nr_pages,
> > + unsigned int gup_flags, struct page **pages);
> >
> > /* Container for pinned pfns / pages */
> > struct frame_vector {
> > diff --git a/kernel/futex.c b/kernel/futex.c
> > index fdd312da0992..e10209946f8b 100644
> > --- a/kernel/futex.c
> > +++ b/kernel/futex.c
> > @@ -546,7 +546,7 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, enum futex_a
> > if (unlikely(should_fail_futex(fshared)))
> > return -EFAULT;
> >
> > - err = get_user_pages_fast(address, 1, 1, &page);
> > + err = get_user_pages_fast(address, 1, FOLL_WRITE, &page);
> > /*
> > * If write access is not required (eg. FUTEX_WAIT), try
> > * and get read-only access.
> > diff --git a/lib/iov_iter.c b/lib/iov_iter.c
> > index be4bd627caf0..6dbae0692719 100644
> > --- a/lib/iov_iter.c
> > +++ b/lib/iov_iter.c
> > @@ -1280,7 +1280,9 @@ ssize_t iov_iter_get_pages(struct iov_iter *i,
> > len = maxpages * PAGE_SIZE;
> > addr &= ~(PAGE_SIZE - 1);
> > n = DIV_ROUND_UP(len, PAGE_SIZE);
> > - res = get_user_pages_fast(addr, n, iov_iter_rw(i) != WRITE, pages);
> > + res = get_user_pages_fast(addr, n,
> > + iov_iter_rw(i) != WRITE ? FOLL_WRITE : 0,
> > + pages);
> > if (unlikely(res < 0))
> > return res;
> > return (res == n ? len : res * PAGE_SIZE) - *start;
> > @@ -1361,7 +1363,8 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i,
> > p = get_pages_array(n);
> > if (!p)
> > return -ENOMEM;
> > - res = get_user_pages_fast(addr, n, iov_iter_rw(i) != WRITE, p);
> > + res = get_user_pages_fast(addr, n,
> > + iov_iter_rw(i) != WRITE ? FOLL_WRITE : 0, p);
> > if (unlikely(res < 0)) {
> > kvfree(p);
> > return res;
> > diff --git a/mm/gup.c b/mm/gup.c
> > index 681388236106..6f32d36b3c5b 100644
> > --- a/mm/gup.c
> > +++ b/mm/gup.c
> > @@ -1863,7 +1863,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> > * get_user_pages_fast() - pin user pages in memory
> > * @start: starting user address
> > * @nr_pages: number of pages from start to pin
> > - * @write: whether pages will be written to
> > + * @gup_flags: flags modifying pin behaviour
> > * @pages: array that receives pointers to the pages pinned.
> > * Should be at least nr_pages long.
> > *
> > @@ -1875,8 +1875,8 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> > * requested. If nr_pages is 0 or negative, returns 0. If no pages
> > * were pinned, returns -errno.
> > */
> > -int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> > - struct page **pages)
> > +int get_user_pages_fast(unsigned long start, int nr_pages,
> > + unsigned int gup_flags, struct page **pages)
> > {
> > unsigned long addr, len, end;
> > int nr = 0, ret = 0;
> > @@ -1894,7 +1894,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> >
> > if (gup_fast_permitted(start, nr_pages)) {
> > local_irq_disable();
> > - gup_pgd_range(addr, end, write ? FOLL_WRITE : 0, pages, &nr);
> > + gup_pgd_range(addr, end, gup_flags, pages, &nr);
> > local_irq_enable();
> > ret = nr;
> > }
> > @@ -1905,7 +1905,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
> > pages += nr;
> >
> > ret = get_user_pages_unlocked(start, nr_pages - nr, pages,
> > - write ? FOLL_WRITE : 0);
> > + gup_flags);
> >
> > /* Have to be a bit careful with return values */
> > if (nr > 0) {
> > diff --git a/mm/util.c b/mm/util.c
> > index 1ea055138043..01ffe145c62b 100644
> > --- a/mm/util.c
> > +++ b/mm/util.c
> > @@ -306,7 +306,7 @@ EXPORT_SYMBOL_GPL(__get_user_pages_fast);
> > * get_user_pages_fast() - pin user pages in memory
> > * @start: starting user address
> > * @nr_pages: number of pages from start to pin
> > - * @write: whether pages will be written to
> > + * @gup_flags: flags modifying pin behaviour
> > * @pages: array that receives pointers to the pages pinned.
> > * Should be at least nr_pages long.
> > *
> > @@ -327,10 +327,10 @@ EXPORT_SYMBOL_GPL(__get_user_pages_fast);
> > * get_user_pages_fast simply falls back to get_user_pages.
> > */
> > int __weak get_user_pages_fast(unsigned long start,
> > - int nr_pages, int write, struct page **pages)
> > + int nr_pages, unsigned int gup_flags,
> > + struct page **pages)
> > {
> > - return get_user_pages_unlocked(start, nr_pages, pages,
> > - write ? FOLL_WRITE : 0);
> > + return get_user_pages_unlocked(start, nr_pages, pages, gup_flags);
> > }
> > EXPORT_SYMBOL_GPL(get_user_pages_fast);
> >
> > diff --git a/net/ceph/pagevec.c b/net/ceph/pagevec.c
> > index d3736f5bffec..74cafc0142ea 100644
> > --- a/net/ceph/pagevec.c
> > +++ b/net/ceph/pagevec.c
> > @@ -27,7 +27,7 @@ struct page **ceph_get_direct_page_vector(const void __user *data,
> > while (got < num_pages) {
> > rc = get_user_pages_fast(
> > (unsigned long)data + ((unsigned long)got * PAGE_SIZE),
> > - num_pages - got, write_page, pages + got);
> > + num_pages - got, write_page ? FOLL_WRITE : 0, pages + got);
> > if (rc < 0)
> > break;
> > BUG_ON(rc == 0);
> > diff --git a/net/rds/info.c b/net/rds/info.c
> > index e367a97a18c8..03f6fd56d237 100644
> > --- a/net/rds/info.c
> > +++ b/net/rds/info.c
> > @@ -193,7 +193,7 @@ int rds_info_getsockopt(struct socket *sock, int optname, char __user *optval,
> > ret = -ENOMEM;
> > goto out;
> > }
> > - ret = get_user_pages_fast(start, nr_pages, 1, pages);
> > + ret = get_user_pages_fast(start, nr_pages, FOLL_WRITE, pages);
> > if (ret != nr_pages) {
> > if (ret > 0)
> > nr_pages = ret;
> > diff --git a/net/rds/rdma.c b/net/rds/rdma.c
> > index 182ab8430594..b340ed4fc43a 100644
> > --- a/net/rds/rdma.c
> > +++ b/net/rds/rdma.c
> > @@ -158,7 +158,8 @@ static int rds_pin_pages(unsigned long user_addr, unsigned int nr_pages,
> > {
> > int ret;
> >
> > - ret = get_user_pages_fast(user_addr, nr_pages, write, pages);
> > + ret = get_user_pages_fast(user_addr, nr_pages, write ? FOLL_WRITE : 0,
> > + pages);
> >
> > if (ret >= 0 && ret < nr_pages) {
> > while (ret--)
> > --
> > 2.20.1
> >
>
^ permalink raw reply
* [PATCH] x86, retpolines: raise limit for generating indirect calls from switch-case
From: Daniel Borkmann @ 2019-02-21 22:19 UTC (permalink / raw)
To: tglx
Cc: linux-kernel, netdev, Daniel Borkmann, David S . Miller,
Björn Töpel, Magnus Karlsson, Jesper Dangaard Brouer,
Alexei Starovoitov, Peter Zijlstra, David Woodhouse,
Andy Lutomirski, Borislav Petkov, Linus Torvalds
From networking side, there are numerous attempts to get rid of
indirect calls in fast-path wherever feasible in order to avoid
the cost of retpolines, for example, just to name a few:
* 283c16a2dfd3 ("indirect call wrappers: helpers to speed-up indirect calls of builtin")
* aaa5d90b395a ("net: use indirect call wrappers at GRO network layer")
* 028e0a476684 ("net: use indirect call wrappers at GRO transport layer")
* 356da6d0cde3 ("dma-mapping: bypass indirect calls for dma-direct")
* 09772d92cd5a ("bpf: avoid retpoline for lookup/update/delete calls on maps")
* 10870dd89e95 ("netfilter: nf_tables: add direct calls for all builtin expressions")
[...]
Recent work on XDP from Björn and Magnus additionally found that
manually transforming the XDP return code switch statement with
more than 5 cases into if-else combination would result in a
considerable speedup in XDP layer due to avoidance of indirect
calls in CONFIG_RETPOLINE enabled builds. On i40e driver with
XDP prog attached, a 20-26% speedup has been observed [0]. Aside
from XDP, there are many other places later in the networking
stack's critical path with similar switch-case processing. Rather
than fixing every XDP-enabled driver and locations in stack by
hand, it would be good to instead raise the limit where gcc would
emit expensive indirect calls from the switch under retpolines
and stick with the default as-is in case of !retpoline configured
kernels. This would also have the advantage that for archs where
this is not necessary, we let compiler select the underlying
target optimization for these constructs and avoid potential
slow-downs by if-else hand-rewrite.
In case of gcc, this setting is controlled by case-values-threshold
which has an architecture global default that selects 4 or 5 (latter
if target does not have a case insn that compares the bounds) where
some arch back ends like arm64 or s390 override it with their own
target hooks, for example, in gcc commit db7a90aa0de5 ("S/390:
Disable prediction of indirect branches") the threshold pretty
much disables jump tables by limit of 20 under retpoline builds.
Comparing gcc's and clang's default code generation on x86-64 under
O2 level with retpoline build results in the following outcome
for 5 switch cases:
* gcc with -mindirect-branch=thunk-inline -mindirect-branch-register:
# gdb -batch -ex 'disassemble dispatch' ./c-switch
Dump of assembler code for function dispatch:
0x0000000000400be0 <+0>: cmp $0x4,%edi
0x0000000000400be3 <+3>: ja 0x400c35 <dispatch+85>
0x0000000000400be5 <+5>: lea 0x915f8(%rip),%rdx # 0x4921e4
0x0000000000400bec <+12>: mov %edi,%edi
0x0000000000400bee <+14>: movslq (%rdx,%rdi,4),%rax
0x0000000000400bf2 <+18>: add %rdx,%rax
0x0000000000400bf5 <+21>: callq 0x400c01 <dispatch+33>
0x0000000000400bfa <+26>: pause
0x0000000000400bfc <+28>: lfence
0x0000000000400bff <+31>: jmp 0x400bfa <dispatch+26>
0x0000000000400c01 <+33>: mov %rax,(%rsp)
0x0000000000400c05 <+37>: retq
0x0000000000400c06 <+38>: nopw %cs:0x0(%rax,%rax,1)
0x0000000000400c10 <+48>: jmpq 0x400c90 <fn_3>
0x0000000000400c15 <+53>: nopl (%rax)
0x0000000000400c18 <+56>: jmpq 0x400c70 <fn_2>
0x0000000000400c1d <+61>: nopl (%rax)
0x0000000000400c20 <+64>: jmpq 0x400c50 <fn_1>
0x0000000000400c25 <+69>: nopl (%rax)
0x0000000000400c28 <+72>: jmpq 0x400c40 <fn_0>
0x0000000000400c2d <+77>: nopl (%rax)
0x0000000000400c30 <+80>: jmpq 0x400cb0 <fn_4>
0x0000000000400c35 <+85>: push %rax
0x0000000000400c36 <+86>: callq 0x40dd80 <abort>
End of assembler dump.
* clang with -mretpoline emitting search tree:
# gdb -batch -ex 'disassemble dispatch' ./c-switch
Dump of assembler code for function dispatch:
0x0000000000400b30 <+0>: cmp $0x1,%edi
0x0000000000400b33 <+3>: jle 0x400b44 <dispatch+20>
0x0000000000400b35 <+5>: cmp $0x2,%edi
0x0000000000400b38 <+8>: je 0x400b4d <dispatch+29>
0x0000000000400b3a <+10>: cmp $0x3,%edi
0x0000000000400b3d <+13>: jne 0x400b52 <dispatch+34>
0x0000000000400b3f <+15>: jmpq 0x400c50 <fn_3>
0x0000000000400b44 <+20>: test %edi,%edi
0x0000000000400b46 <+22>: jne 0x400b5c <dispatch+44>
0x0000000000400b48 <+24>: jmpq 0x400c20 <fn_0>
0x0000000000400b4d <+29>: jmpq 0x400c40 <fn_2>
0x0000000000400b52 <+34>: cmp $0x4,%edi
0x0000000000400b55 <+37>: jne 0x400b66 <dispatch+54>
0x0000000000400b57 <+39>: jmpq 0x400c60 <fn_4>
0x0000000000400b5c <+44>: cmp $0x1,%edi
0x0000000000400b5f <+47>: jne 0x400b66 <dispatch+54>
0x0000000000400b61 <+49>: jmpq 0x400c30 <fn_1>
0x0000000000400b66 <+54>: push %rax
0x0000000000400b67 <+55>: callq 0x40dd20 <abort>
End of assembler dump.
For sake of comparison, clang without -mretpoline:
# gdb -batch -ex 'disassemble dispatch' ./c-switch
Dump of assembler code for function dispatch:
0x0000000000400b30 <+0>: cmp $0x4,%edi
0x0000000000400b33 <+3>: ja 0x400b57 <dispatch+39>
0x0000000000400b35 <+5>: mov %edi,%eax
0x0000000000400b37 <+7>: jmpq *0x492148(,%rax,8)
0x0000000000400b3e <+14>: jmpq 0x400bf0 <fn_0>
0x0000000000400b43 <+19>: jmpq 0x400c30 <fn_4>
0x0000000000400b48 <+24>: jmpq 0x400c10 <fn_2>
0x0000000000400b4d <+29>: jmpq 0x400c20 <fn_3>
0x0000000000400b52 <+34>: jmpq 0x400c00 <fn_1>
0x0000000000400b57 <+39>: push %rax
0x0000000000400b58 <+40>: callq 0x40dcf0 <abort>
End of assembler dump.
Raising the cases to a high number (e.g. 100) will still result
in similar code generation pattern with clang and gcc as above,
in other words clang generally turns off jump table emission by
having an extra expansion pass under retpoline build to turn
indirectbr instructions from their IR into switch instructions
as a built-in -mno-jump-table lowering of a switch (in this
case, even if IR input already contained an indirect branch).
For gcc, adding --param=case-values-threshold=20 as in similar
fashion as s390 in order to raise the limit for x86 retpoline
enabled builds results in a small vmlinux size increase of only
0.13% (before=18,027,528 after=18,051,192). For clang this
option is ignored due to i) not being needed as mentioned and
ii) not having above cmdline parameter. Non-retpoline-enabled
builds with gcc continue to use the default case-values-threshold
setting, so nothing changes here.
[0] https://lore.kernel.org/netdev/20190129095754.9390-1-bjorn.topel@gmail.com/
and "The Path to DPDK Speeds for AF_XDP", LPC 2018, networking track:
- http://vger.kernel.org/lpc_net2018_talks/lpc18_pres_af_xdp_perf-v3.pdf
- http://vger.kernel.org/lpc_net2018_talks/lpc18_paper_af_xdp_perf-v2.pdf
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Cc: David S. Miller <davem@davemloft.net>
Cc: Björn Töpel <bjorn.topel@intel.com>
Cc: Magnus Karlsson <magnus.karlsson@intel.com>
Cc: Jesper Dangaard Brouer <brouer@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
---
arch/x86/Makefile | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 9c5a67d1b9c1..f55420a67164 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -217,6 +217,11 @@ KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
# Avoid indirect branches in kernel to deal with Spectre
ifdef CONFIG_RETPOLINE
KBUILD_CFLAGS += $(RETPOLINE_CFLAGS)
+ # Additionally, avoid generating expensive indirect jumps which
+ # are subject to retpolines for small number of switch cases.
+ # clang turns off jump table generation by default when under
+ # retpoline builds, however, gcc does not for x86.
+ KBUILD_CFLAGS += $(call cc-option,--param=case-values-threshold=20)
endif
archscripts: scripts_basic
--
2.17.1
^ permalink raw reply related
* Re: [PATCH v3 net-next 3/4] net: dsa: microchip: get port link status
From: Andrew Lunn @ 2019-02-21 22:20 UTC (permalink / raw)
To: Tristram.Ha
Cc: Sergio Paracuellos, Florian Fainelli, Pavel Machek,
UNGLinuxDriver, netdev
In-Reply-To: <1550786597-591-4-git-send-email-Tristram.Ha@microchip.com>
On Thu, Feb 21, 2019 at 02:03:16PM -0800, Tristram.Ha@microchip.com wrote:
> From: Tristram Ha <Tristram.Ha@microchip.com>
>
> Get port link status to know whether to read MIB counters when the link
> is going down. Add port_cleanup function to read MIB counters the last
> time as when the port is disabled the PHY is also powered down.
>
> Signed-off-by: Tristram Ha <Tristram.Ha@microchip.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply
* Re: [PATCH v3 net-next 2/4] net: dsa: microchip: add MIB counter reading support
From: Andrew Lunn @ 2019-02-21 22:19 UTC (permalink / raw)
To: Tristram.Ha
Cc: Sergio Paracuellos, Florian Fainelli, Pavel Machek,
UNGLinuxDriver, netdev
In-Reply-To: <1550786597-591-3-git-send-email-Tristram.Ha@microchip.com>
On Thu, Feb 21, 2019 at 02:03:15PM -0800, Tristram.Ha@microchip.com wrote:
> From: Tristram Ha <Tristram.Ha@microchip.com>
>
> Add background MIB counter reading support.
>
> Port MIB counters should only be read when there is link. Otherwise it is
> a waste of time as hardware never increases those counters. There are
> exceptions as some switches keep track of dropped counts no matter what.
>
> Signed-off-by: Tristram Ha <Tristram.Ha@microchip.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply
* Re: [PATCH v3 net-next 1/4] net: dsa: microchip: prepare PHY for proper advertisement
From: Andrew Lunn @ 2019-02-21 22:15 UTC (permalink / raw)
To: Tristram.Ha
Cc: Sergio Paracuellos, Florian Fainelli, Pavel Machek,
UNGLinuxDriver, netdev
In-Reply-To: <1550786597-591-2-git-send-email-Tristram.Ha@microchip.com>
On Thu, Feb 21, 2019 at 02:03:14PM -0800, Tristram.Ha@microchip.com wrote:
> From: Tristram Ha <Tristram.Ha@microchip.com>
>
> Prepare PHY for proper advertisement as sometimes the PHY in the switch
> has its own problems even though it may share the PHY id from regular PHY
> but the fixes in the PHY driver do not apply.
>
> Signed-off-by: Tristram Ha <Tristram.Ha@microchip.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply
* [PATCH net] net: socket: set sock->sk to NULL after calling proto_ops::release()
From: Eric Biggers @ 2019-02-21 22:13 UTC (permalink / raw)
To: netdev, David S . Miller
Cc: linux-kernel, Mao Wenan, Cong Wang, Lorenzo Colitti, Tetsuo Handa,
Al Viro, Eric Biggers
From: Eric Biggers <ebiggers@google.com>
Commit 9060cb719e61 ("net: crypto set sk to NULL when af_alg_release.")
fixed a use-after-free in sockfs_setattr() when an AF_ALG socket is
closed concurrently with fchownat(). However, it ignored that many
other proto_ops::release() methods don't set sock->sk to NULL and
therefore allow the same use-after-free:
- base_sock_release
- bnep_sock_release
- cmtp_sock_release
- data_sock_release
- dn_release
- hci_sock_release
- hidp_sock_release
- iucv_sock_release
- l2cap_sock_release
- llcp_sock_release
- llc_ui_release
- rawsock_release
- rfcomm_sock_release
- sco_sock_release
- svc_release
- vcc_release
- x25_release
Rather than fixing all these and relying on every socket type to get
this right forever, just make __sock_release() set sock->sk to NULL
itself after calling proto_ops::release().
Reproducer that produces the KASAN splat when any of these socket types
are configured into the kernel:
#include <pthread.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
pthread_t t;
volatile int fd;
void *close_thread(void *arg)
{
for (;;) {
usleep(rand() % 100);
close(fd);
}
}
int main()
{
pthread_create(&t, NULL, close_thread, NULL);
for (;;) {
fd = socket(rand() % 50, rand() % 11, 0);
fchownat(fd, "", 1000, 1000, 0x1000);
close(fd);
}
}
Fixes: 86741ec25462 ("net: core: Add a UID field to struct sock.")
Cc: <stable@vger.kernel.org> # v4.10+
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
NOTE: I am not an expert in the networking code, so please carefully
check that I haven't missed some reason why this simple fix won't do.
net/socket.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/socket.c b/net/socket.c
index d80d87a395ea..320f51b22b19 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -577,6 +577,7 @@ static void __sock_release(struct socket *sock, struct inode *inode)
if (inode)
inode_lock(inode);
sock->ops->release(sock);
+ sock->sk = NULL;
if (inode)
inode_unlock(inode);
sock->ops = NULL;
--
2.21.0.rc0.258.g878e2cd30e-goog
^ permalink raw reply related
* Re: [PATCH bpf-next v2] bpf, seccomp: fix false positive preemption splat for cbpf->ebpf progs
From: Kees Cook @ 2019-02-21 22:14 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Jann Horn, Daniel Borkmann, Andy Lutomirski, Alexei Starovoitov,
Network Development
In-Reply-To: <20190221203613.q6k757fi3wxtoj5y@ast-mbp.dhcp.thefacebook.com>
On Thu, Feb 21, 2019 at 12:36 PM Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
> I also would like to touch on your comment:
> "A lot of changes will be needed for seccomp ebpf"
> There were two attempts to add it in the past and the patches were
> small and straightforward.
Yeah, agreed: doing it is technically easy. My concerns have mainly
revolved around avoiding increased complexity and attack surface.
There have been, for example, a lot of verifier bugs that were not
reachable through seccomp's BPF usage, given it enforcing only using a
subset of cBPF. i.e. seccomp filters couldn't be used as Spectre
gadgets, etc.
> If I recall correctly both times you nacked them because performance gains
> and ease of use arguments were not convincing enough, right?
Right. There wasn't, in my opinion enough of a performance benefit vs
just having efficient BPF to start with.
> Are you still not convinced ?
For now, yeah. I'm sure there will be some future time when a use-case
appears where gaining some special eBPF hook/feature will outweigh the
increased attack surface. I haven't seen it yet, but I'm not crazy
enough to think it'll never happen. (In fact, recently I even had
Tycho see if he could implement the recent seccomp user notification
stuff via eBPF.)
--
Kees Cook
^ permalink raw reply
* Re: [PATCH] mdio_bus: Fix use-after-free on device_register fails
From: Andrew Lunn @ 2019-02-21 22:13 UTC (permalink / raw)
To: Yue Haibing; +Cc: f.fainelli, hkallweit1, davem, linux-kernel, netdev
In-Reply-To: <20190221144201.11488-1-yuehaibing@huawei.com>
On Thu, Feb 21, 2019 at 10:42:01PM +0800, Yue Haibing wrote:
> From: YueHaibing <yuehaibing@huawei.com>
>
> KASAN has found use-after-free in fixed_mdio_bus_init,
> commit 0c692d07842a ("drivers/net/phy/mdio_bus.c: call
> put_device on device_register() failure") call put_device()
> while device_register() fails,give up the last reference
> to the device and allow mdiobus_release to be executed
> ,kfreeing the bus. However in most drives, mdiobus_free
> be called to free the bus while mdiobus_register fails.
> use-after-free occurs when access bus again, this patch
> revert it to let mdiobus_free free the bus.
>
> KASAN report details as below:
>
> BUG: KASAN: use-after-free in mdiobus_free+0x85/0x90 drivers/net/phy/mdio_bus.c:482
> Read of size 4 at addr ffff8881dc824d78 by task syz-executor.0/3524
>
> CPU: 1 PID: 3524 Comm: syz-executor.0 Not tainted 5.0.0-rc7+ #45
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014
> Call Trace:
> __dump_stack lib/dump_stack.c:77 [inline]
> dump_stack+0xfa/0x1ce lib/dump_stack.c:113
> print_address_description+0x65/0x270 mm/kasan/report.c:187
> kasan_report+0x149/0x18d mm/kasan/report.c:317
> mdiobus_free+0x85/0x90 drivers/net/phy/mdio_bus.c:482
> fixed_mdio_bus_init+0x283/0x1000 [fixed_phy]
> ? 0xffffffffc0e40000
> ? 0xffffffffc0e40000
> ? 0xffffffffc0e40000
> do_one_initcall+0xfa/0x5ca init/main.c:887
> do_init_module+0x204/0x5f6 kernel/module.c:3460
> load_module+0x66b2/0x8570 kernel/module.c:3808
> __do_sys_finit_module+0x238/0x2a0 kernel/module.c:3902
> do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290
> entry_SYSCALL_64_after_hwframe+0x49/0xbe
> RIP: 0033:0x462e99
> Code: f7 d8 64 89 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 bc ff ff ff f7 d8 64 89 01 48
> RSP: 002b:00007f6215c19c58 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
> RAX: ffffffffffffffda RBX: 000000000073bf00 RCX: 0000000000462e99
> RDX: 0000000000000000 RSI: 0000000020000080 RDI: 0000000000000003
> RBP: 00007f6215c19c70 R08: 0000000000000000 R09: 0000000000000000
> R10: 0000000000000000 R11: 0000000000000246 R12: 00007f6215c1a6bc
> R13: 00000000004bcefb R14: 00000000006f7030 R15: 0000000000000004
>
> Allocated by task 3524:
> set_track mm/kasan/common.c:85 [inline]
> __kasan_kmalloc.constprop.3+0xa0/0xd0 mm/kasan/common.c:496
> kmalloc include/linux/slab.h:545 [inline]
> kzalloc include/linux/slab.h:740 [inline]
> mdiobus_alloc_size+0x54/0x1b0 drivers/net/phy/mdio_bus.c:143
> fixed_mdio_bus_init+0x163/0x1000 [fixed_phy]
> do_one_initcall+0xfa/0x5ca init/main.c:887
> do_init_module+0x204/0x5f6 kernel/module.c:3460
> load_module+0x66b2/0x8570 kernel/module.c:3808
> __do_sys_finit_module+0x238/0x2a0 kernel/module.c:3902
> do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290
> entry_SYSCALL_64_after_hwframe+0x49/0xbe
>
> Freed by task 3524:
> set_track mm/kasan/common.c:85 [inline]
> __kasan_slab_free+0x130/0x180 mm/kasan/common.c:458
> slab_free_hook mm/slub.c:1409 [inline]
> slab_free_freelist_hook mm/slub.c:1436 [inline]
> slab_free mm/slub.c:2986 [inline]
> kfree+0xe1/0x270 mm/slub.c:3938
> device_release+0x78/0x200 drivers/base/core.c:919
> kobject_cleanup lib/kobject.c:662 [inline]
> kobject_release lib/kobject.c:691 [inline]
> kref_put include/linux/kref.h:67 [inline]
> kobject_put+0x146/0x240 lib/kobject.c:708
> put_device+0x1c/0x30 drivers/base/core.c:2060
> __mdiobus_register+0x483/0x560 drivers/net/phy/mdio_bus.c:382
> fixed_mdio_bus_init+0x26b/0x1000 [fixed_phy]
> do_one_initcall+0xfa/0x5ca init/main.c:887
> do_init_module+0x204/0x5f6 kernel/module.c:3460
> load_module+0x66b2/0x8570 kernel/module.c:3808
> __do_sys_finit_module+0x238/0x2a0 kernel/module.c:3902
> do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290
> entry_SYSCALL_64_after_hwframe+0x49/0xbe
>
> The buggy address belongs to the object at ffff8881dc824c80
> which belongs to the cache kmalloc-2k of size 2048
> The buggy address is located 248 bytes inside of
> 2048-byte region [ffff8881dc824c80, ffff8881dc825480)
> The buggy address belongs to the page:
> page:ffffea0007720800 count:1 mapcount:0 mapping:ffff8881f6c02800 index:0x0 compound_mapcount: 0
> flags: 0x2fffc0000010200(slab|head)
> raw: 02fffc0000010200 0000000000000000 0000000500000001 ffff8881f6c02800
> raw: 0000000000000000 00000000800f000f 00000001ffffffff 0000000000000000
> page dumped because: kasan: bad access detected
>
> Memory state around the buggy address:
> ffff8881dc824c00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
> ffff8881dc824c80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> >ffff8881dc824d00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> ^
> ffff8881dc824d80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> ffff8881dc824e00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>
> Fixes: 0c692d07842a ("drivers/net/phy/mdio_bus.c: call put_device on device_register() failure")
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply
* Re: [PATCH iproute2-next v1 01/19] rdma: update uapi headers
From: Leon Romanovsky @ 2019-02-21 22:11 UTC (permalink / raw)
To: Steve Wise
Cc: 'David Ahern', 'netdev',
'RDMA mailing list', 'Stephen Hemminger'
In-Reply-To: <01cb01d4ca20$6434e7a0$2c9eb6e0$@opengridcomputing.com>
[-- Attachment #1: Type: text/plain, Size: 942 bytes --]
On Thu, Feb 21, 2019 at 02:02:36PM -0600, Steve Wise wrote:
>
>
> > -----Original Message-----
> > From: linux-rdma-owner@vger.kernel.org <linux-rdma-
> > owner@vger.kernel.org> On Behalf Of Leon Romanovsky
> > Sent: Wednesday, February 20, 2019 1:21 AM
> > To: David Ahern <dsahern@gmail.com>
> > Cc: Leon Romanovsky <leonro@mellanox.com>; netdev
> > <netdev@vger.kernel.org>; RDMA mailing list <linux-
> > rdma@vger.kernel.org>; Stephen Hemminger
> > <stephen@networkplumber.org>
> > Subject: [PATCH iproute2-next v1 01/19] rdma: update uapi headers
> >
> > From: Leon Romanovsky <leonro@mellanox.com>
> >
> > Update rdma_netlink,h file upto kernel commit
>
> Nit: should be "rdma_netlink.h file up to"
>
> > f2a0e45f36b0 RDMA/nldev: Don't expose number of not-visible entries
> >
> > Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
>
> Reviewed-by: Steve Wise <swise@opengridcomputing.com>
Steve, thanks a lot for your review.
>
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH v1 iproute2-next 2/4] Sync up rdma_netlink.h
From: Leon Romanovsky @ 2019-02-21 22:10 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: Steve Wise, dsahern, netdev, linux-rdma
In-Reply-To: <20190221105631.7dfa5217@shemminger-XPS-13-9360>
[-- Attachment #1: Type: text/plain, Size: 1751 bytes --]
On Thu, Feb 21, 2019 at 10:56:31AM -0800, Stephen Hemminger wrote:
> On Thu, 21 Feb 2019 08:19:07 -0800
> Steve Wise <swise@opengridcomputing.com> wrote:
>
> > Pull in the latest rdma_netlink.h to get the RDMA_NLDEV_CMD_NEWLINK /
> > RDMA_NLDEV_CMD_DELLINK API.
> >
> > Signed-off-by: Steve Wise <swise@opengridcomputing.com>
> > ---
> > rdma/include/uapi/rdma/rdma_netlink.h | 74 +++++++++++++++++++++++++++--------
> > 1 file changed, 58 insertions(+), 16 deletions(-)
> >
> > diff --git a/rdma/include/uapi/rdma/rdma_netlink.h b/rdma/include/uapi/rdma/rdma_netlink.h
> > index 04c80cebef49..23a90ad52485 100644
> > --- a/rdma/include/uapi/rdma/rdma_netlink.h
> > +++ b/rdma/include/uapi/rdma/rdma_netlink.h
> > @@ -5,8 +5,7 @@
> > #include <linux/types.h>
> >
> > enum {
> > - RDMA_NL_RDMA_CM = 1,
> > - RDMA_NL_IWCM,
> > + RDMA_NL_IWCM = 2,
> > RDMA_NL_RSVD,
> > RDMA_NL_LS, /* RDMA Local Services */
> > RDMA_NL_NLDEV, /* RDMA device interface */
>
> You can't just drop elements from user ABI headers.
> That is a break of kernel ABI guarantee.
In RDMA subsystem, we have less pedantic rules and are removing
unused and mistakenly added code. This removal scheme was suggested
by Linus - remove and see who is complaining.
The big advantage of RDMA is that we know exactly what is in use
by our consumers.
In this case, we knew for sure that no one is using RDMA_NL_RDMA_CM,
and it never was backed by working user space. More on that,
the talks of RDMA_NL_RDMA_CM removal started a long time ago,
but took time till the patch was actually sent.
So yes, if people use this enum value as subsidiary to 1, they will break.
>
> Instead, mark unused elements:
> enum {
> RDMA_NL_RDMA_CM = 1, /* deprecated */
> RDMA_NL_IWCM,
> ...
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH net] net: avoid false positives in untrusted gso validation
From: David Miller @ 2019-02-21 22:08 UTC (permalink / raw)
To: willemdebruijn.kernel; +Cc: netdev, willemb
In-Reply-To: <20190219043712.97121-1-willemdebruijn.kernel@gmail.com>
From: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Date: Mon, 18 Feb 2019 23:37:12 -0500
> From: Willem de Bruijn <willemb@google.com>
>
> GSO packets with vnet_hdr must conform to a small set of gso_types.
> The below commit uses flow dissection to drop packets that do not.
>
> But it has false positives when the skb is not fully initialized.
> Dissection needs skb->protocol and skb->network_header.
>
> Infer skb->protocol from gso_type as the two must agree.
> SKB_GSO_UDP can use both ipv4 and ipv6, so try both.
>
> Exclude callers for which network header offset is not known.
>
> Fixes: d5be7f632bad ("net: validate untrusted gso packets without csum offload")
> Signed-off-by: Willem de Bruijn <willemb@google.com>
Applied and queued up for -stable, thanks.
^ permalink raw reply
* [PATCH v3 net-next 2/4] net: dsa: microchip: add MIB counter reading support
From: Tristram.Ha @ 2019-02-21 22:03 UTC (permalink / raw)
To: Sergio Paracuellos, Andrew Lunn, Florian Fainelli, Pavel Machek
Cc: Tristram Ha, UNGLinuxDriver, netdev
In-Reply-To: <1550786597-591-1-git-send-email-Tristram.Ha@microchip.com>
From: Tristram Ha <Tristram.Ha@microchip.com>
Add background MIB counter reading support.
Port MIB counters should only be read when there is link. Otherwise it is
a waste of time as hardware never increases those counters. There are
exceptions as some switches keep track of dropped counts no matter what.
Signed-off-by: Tristram Ha <Tristram.Ha@microchip.com>
---
drivers/net/dsa/microchip/ksz9477.c | 118 ++++++++++++++++++++------------
drivers/net/dsa/microchip/ksz_common.c | 121 +++++++++++++++++++++++++++++++++
drivers/net/dsa/microchip/ksz_common.h | 24 ++++++-
drivers/net/dsa/microchip/ksz_priv.h | 9 ++-
4 files changed, 224 insertions(+), 48 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index 4573b6e..e2d74c7 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -18,8 +18,8 @@
#include <net/switchdev.h>
#include "ksz_priv.h"
-#include "ksz_common.h"
#include "ksz9477_reg.h"
+#include "ksz_common.h"
static const struct {
int index;
@@ -259,6 +259,71 @@ static int ksz9477_reset_switch(struct ksz_device *dev)
return 0;
}
+static void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr,
+ u64 *cnt)
+{
+ struct ksz_port *p = &dev->ports[port];
+ u32 data;
+ int ret;
+
+ /* retain the flush/freeze bit */
+ data = p->freeze ? MIB_COUNTER_FLUSH_FREEZE : 0;
+ data |= MIB_COUNTER_READ;
+ data |= (addr << MIB_COUNTER_INDEX_S);
+ ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, data);
+
+ ret = ksz_pread_poll_timeout(ksz_pread32, dev, port,
+ REG_PORT_MIB_CTRL_STAT__4, data,
+ !(data & MIB_COUNTER_READ), 10, 1000);
+
+ /* failed to read MIB. get out of loop */
+ if (ret < 0) {
+ dev_dbg(dev->dev, "Failed to get MIB\n");
+ return;
+ }
+
+ /* count resets upon read */
+ ksz_pread32(dev, port, REG_PORT_MIB_DATA, &data);
+ *cnt += data;
+}
+
+static void ksz9477_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
+ u64 *dropped, u64 *cnt)
+{
+ addr = ksz9477_mib_names[addr].index;
+ ksz9477_r_mib_cnt(dev, port, addr, cnt);
+}
+
+static void ksz9477_freeze_mib(struct ksz_device *dev, int port, bool freeze)
+{
+ u32 val = freeze ? MIB_COUNTER_FLUSH_FREEZE : 0;
+ struct ksz_port *p = &dev->ports[port];
+
+ /* enable/disable the port for flush/freeze function */
+ mutex_lock(&p->mib.cnt_mutex);
+ ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, val);
+
+ /* used by MIB counter reading code to know freeze is enabled */
+ p->freeze = freeze;
+ mutex_unlock(&p->mib.cnt_mutex);
+}
+
+static void ksz9477_port_init_cnt(struct ksz_device *dev, int port)
+{
+ struct ksz_port_mib *mib = &dev->ports[port].mib;
+
+ /* flush all enabled port MIB counters */
+ mutex_lock(&mib->cnt_mutex);
+ ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4,
+ MIB_COUNTER_FLUSH_FREEZE);
+ ksz_write8(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FLUSH);
+ ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, 0);
+ mutex_unlock(&mib->cnt_mutex);
+
+ mib->cnt_ptr = 0;
+ memset(mib->counters, 0, dev->mib_cnt * sizeof(u64));
+}
+
static enum dsa_tag_protocol ksz9477_get_tag_protocol(struct dsa_switch *ds,
int port)
{
@@ -342,47 +407,6 @@ static void ksz9477_get_strings(struct dsa_switch *ds, int port,
}
}
-static void ksz_get_ethtool_stats(struct dsa_switch *ds, int port,
- uint64_t *buf)
-{
- struct ksz_device *dev = ds->priv;
- int i;
- u32 data;
- int timeout;
-
- mutex_lock(&dev->stats_mutex);
-
- for (i = 0; i < TOTAL_SWITCH_COUNTER_NUM; i++) {
- data = MIB_COUNTER_READ;
- data |= ((ksz9477_mib_names[i].index & 0xFF) <<
- MIB_COUNTER_INDEX_S);
- ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, data);
-
- timeout = 1000;
- do {
- ksz_pread32(dev, port, REG_PORT_MIB_CTRL_STAT__4,
- &data);
- usleep_range(1, 10);
- if (!(data & MIB_COUNTER_READ))
- break;
- } while (timeout-- > 0);
-
- /* failed to read MIB. get out of loop */
- if (!timeout) {
- dev_dbg(dev->dev, "Failed to get MIB\n");
- break;
- }
-
- /* count resets upon read */
- ksz_pread32(dev, port, REG_PORT_MIB_DATA, &data);
-
- dev->mib_value[i] += (uint64_t)data;
- buf[i] = dev->mib_value[i];
- }
-
- mutex_unlock(&dev->stats_mutex);
-}
-
static void ksz9477_cfg_port_member(struct ksz_device *dev, int port,
u8 member)
{
@@ -1151,9 +1175,14 @@ static int ksz9477_setup(struct dsa_switch *ds)
/* queue based egress rate limit */
ksz_cfg(dev, REG_SW_MAC_CTRL_5, SW_OUT_RATE_LIMIT_QUEUE_BASED, true);
+ /* enable global MIB counter freeze function */
+ ksz_cfg(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FREEZE, true);
+
/* start switch */
ksz_cfg(dev, REG_SW_OPERATION, SW_START, true);
+ ksz_init_mib_timer(dev);
+
return 0;
}
@@ -1287,6 +1316,7 @@ static int ksz9477_switch_init(struct ksz_device *dev)
if (!dev->ports)
return -ENOMEM;
for (i = 0; i < dev->mib_port_cnt; i++) {
+ mutex_init(&dev->ports[i].mib.cnt_mutex);
dev->ports[i].mib.counters =
devm_kzalloc(dev->dev,
sizeof(u64) *
@@ -1311,6 +1341,10 @@ static void ksz9477_switch_exit(struct ksz_device *dev)
.flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
.phy_setup = ksz9477_phy_setup,
.port_setup = ksz9477_port_setup,
+ .r_mib_cnt = ksz9477_r_mib_cnt,
+ .r_mib_pkt = ksz9477_r_mib_pkt,
+ .freeze_mib = ksz9477_freeze_mib,
+ .port_init_cnt = ksz9477_port_init_cnt,
.shutdown = ksz9477_reset_switch,
.detect = ksz9477_switch_detect,
.init = ksz9477_switch_init,
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 6f72842..ff32ace 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -40,6 +40,101 @@ void ksz_update_port_member(struct ksz_device *dev, int port)
}
EXPORT_SYMBOL_GPL(ksz_update_port_member);
+static void port_r_cnt(struct ksz_device *dev, int port)
+{
+ struct ksz_port_mib *mib = &dev->ports[port].mib;
+ u64 *dropped;
+
+ /* Some ports may not have MIB counters before SWITCH_COUNTER_NUM. */
+ while (mib->cnt_ptr < dev->reg_mib_cnt) {
+ dev->dev_ops->r_mib_cnt(dev, port, mib->cnt_ptr,
+ &mib->counters[mib->cnt_ptr]);
+ ++mib->cnt_ptr;
+ }
+
+ /* last one in storage */
+ dropped = &mib->counters[dev->mib_cnt];
+
+ /* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */
+ while (mib->cnt_ptr < dev->mib_cnt) {
+ dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr,
+ dropped, &mib->counters[mib->cnt_ptr]);
+ ++mib->cnt_ptr;
+ }
+ mib->cnt_ptr = 0;
+}
+
+static void ksz_mib_read_work(struct work_struct *work)
+{
+ struct ksz_device *dev = container_of(work, struct ksz_device,
+ mib_read);
+ struct ksz_port_mib *mib;
+ struct ksz_port *p;
+ int i;
+
+ for (i = 0; i < dev->mib_port_cnt; i++) {
+ p = &dev->ports[i];
+
+ /* Only read MIB counters when the port is told to do. */
+ if (!p->read)
+ continue;
+ mib = &p->mib;
+ mutex_lock(&mib->cnt_mutex);
+ port_r_cnt(dev, i);
+ mutex_unlock(&mib->cnt_mutex);
+ }
+}
+
+static void mib_monitor(struct timer_list *t)
+{
+ struct ksz_device *dev = from_timer(dev, t, mib_read_timer);
+ const struct dsa_port *dp;
+ struct net_device *netdev;
+ struct ksz_port_mib *mib;
+ struct ksz_port *p;
+ int i;
+
+ mod_timer(&dev->mib_read_timer, jiffies + dev->mib_read_interval);
+
+ /* Check which port needs to read MIB counters. */
+ for (i = 0; i < dev->mib_port_cnt; i++) {
+ p = &dev->ports[i];
+ if (!p->on)
+ continue;
+ dp = dsa_to_port(dev->ds, i);
+ netdev = dp->slave;
+
+ mib = &p->mib;
+ mutex_lock(&mib->cnt_mutex);
+
+ /* Read only dropped counters when link is not up. */
+ if (netdev && !netif_carrier_ok(netdev))
+ mib->cnt_ptr = dev->reg_mib_cnt;
+ mutex_unlock(&mib->cnt_mutex);
+ p->read = true;
+ }
+ schedule_work(&dev->mib_read);
+}
+
+void ksz_init_mib_timer(struct ksz_device *dev)
+{
+ int i;
+
+ /* Read MIB counters every 30 seconds to avoid overflow. */
+ dev->mib_read_interval = msecs_to_jiffies(30000);
+
+ INIT_WORK(&dev->mib_read, ksz_mib_read_work);
+ timer_setup(&dev->mib_read_timer, mib_monitor, 0);
+
+ for (i = 0; i < dev->mib_port_cnt; i++)
+ dev->dev_ops->port_init_cnt(dev, i);
+
+ /* Start the timer 2 seconds later. */
+ dev->mib_read_timer.expires = jiffies + msecs_to_jiffies(2000);
+ add_timer(&dev->mib_read_timer);
+}
+EXPORT_SYMBOL_GPL(ksz_init_mib_timer);
+
int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg)
{
struct ksz_device *dev = ds->priv;
@@ -72,6 +167,26 @@ int ksz_sset_count(struct dsa_switch *ds, int port, int sset)
}
EXPORT_SYMBOL_GPL(ksz_sset_count);
+void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *buf)
+{
+ const struct dsa_port *dp = dsa_to_port(ds, port);
+ struct ksz_device *dev = ds->priv;
+ struct net_device *netdev;
+ struct ksz_port_mib *mib;
+
+ mib = &dev->ports[port].mib;
+ mutex_lock(&mib->cnt_mutex);
+
+ /* Only read dropped counters if no link. */
+ netdev = dp->slave;
+ if (netdev && !netif_carrier_ok(netdev))
+ mib->cnt_ptr = dev->reg_mib_cnt;
+ port_r_cnt(dev, port);
+ memcpy(buf, mib->counters, dev->mib_cnt * sizeof(u64));
+ mutex_unlock(&mib->cnt_mutex);
+}
+EXPORT_SYMBOL_GPL(ksz_get_ethtool_stats);
+
int ksz_port_bridge_join(struct dsa_switch *ds, int port,
struct net_device *br)
{
@@ -339,6 +454,12 @@ int ksz_switch_register(struct ksz_device *dev,
void ksz_switch_remove(struct ksz_device *dev)
{
+ /* timer started */
+ if (dev->mib_read_timer.expires) {
+ del_timer_sync(&dev->mib_read_timer);
+ flush_work(&dev->mib_read);
+ }
+
dev->dev_ops->exit(dev);
dsa_unregister_switch(dev->ds);
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 2dd832d..0b0ed3d 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -1,19 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0
* Microchip switch driver common header
*
- * Copyright (C) 2017-2018 Microchip Technology Inc.
+ * Copyright (C) 2017-2019 Microchip Technology Inc.
*/
#ifndef __KSZ_COMMON_H
#define __KSZ_COMMON_H
void ksz_update_port_member(struct ksz_device *dev, int port);
+void ksz_init_mib_timer(struct ksz_device *dev);
/* Common DSA access functions */
int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg);
int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val);
int ksz_sset_count(struct dsa_switch *ds, int port, int sset);
+void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *buf);
int ksz_port_bridge_join(struct dsa_switch *ds, int port,
struct net_device *br);
void ksz_port_bridge_leave(struct dsa_switch *ds, int port,
@@ -211,4 +213,24 @@ static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
ksz_write8(dev, addr, data);
}
+/* Modify from readx_poll_timeout in iopoll.h. */
+#define ksz_pread_poll_timeout(op, dev, p, addr, val, cond, sleep_us, \
+ timeout_us) \
+({ \
+ ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); \
+ might_sleep_if(sleep_us); \
+ for (;;) { \
+ op(dev, p, addr, &(val)); \
+ if (cond) \
+ break; \
+ if (timeout_us && ktime_compare(ktime_get(), timeout) > 0) { \
+ op(dev, p, addr, &(val)); \
+ break; \
+ } \
+ if (sleep_us) \
+ usleep_range((sleep_us >> 2) + 1, sleep_us); \
+ } \
+ (cond) ? 0 : -ETIMEDOUT; \
+})
+
#endif
diff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h
index 0fdc58b..1d2d98f 100644
--- a/drivers/net/dsa/microchip/ksz_priv.h
+++ b/drivers/net/dsa/microchip/ksz_priv.h
@@ -14,8 +14,6 @@
#include <linux/etherdevice.h>
#include <net/dsa.h>
-#include "ksz9477_reg.h"
-
struct ksz_io_ops;
struct vlan_table {
@@ -23,6 +21,7 @@ struct vlan_table {
};
struct ksz_port_mib {
+ struct mutex cnt_mutex; /* structure access */
u8 cnt_ptr;
u64 *counters;
};
@@ -38,7 +37,8 @@ struct ksz_port {
u32 fiber:1; /* port is fiber */
u32 sgmii:1; /* port is SGMII */
u32 force:1;
- u32 link_just_down:1; /* link just goes down */
+ u32 read:1; /* read MIB counters in background */
+ u32 freeze:1; /* MIB counter freeze is enabled */
struct ksz_port_mib mib;
};
@@ -79,8 +79,6 @@ struct ksz_device {
struct vlan_table *vlan_cache;
- u64 mib_value[TOTAL_SWITCH_COUNTER_NUM];
-
u8 *txbuf;
struct ksz_port *ports;
@@ -153,6 +151,7 @@ struct ksz_dev_ops {
u64 *cnt);
void (*r_mib_pkt)(struct ksz_device *dev, int port, u16 addr,
u64 *dropped, u64 *cnt);
+ void (*freeze_mib)(struct ksz_device *dev, int port, bool freeze);
void (*port_init_cnt)(struct ksz_device *dev, int port);
int (*shutdown)(struct ksz_device *dev);
int (*detect)(struct ksz_device *dev);
--
1.9.1
^ permalink raw reply related
* [PATCH v3 net-next 4/4] net: dsa: microchip: remove unnecessary include headers
From: Tristram.Ha @ 2019-02-21 22:03 UTC (permalink / raw)
To: Sergio Paracuellos, Andrew Lunn, Florian Fainelli, Pavel Machek
Cc: Tristram Ha, UNGLinuxDriver, netdev
In-Reply-To: <1550786597-591-1-git-send-email-Tristram.Ha@microchip.com>
From: Tristram Ha <Tristram.Ha@microchip.com>
Remove unnecessary header include.
Signed-off-by: Tristram Ha <Tristram.Ha@microchip.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/microchip/ksz9477.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index 6ad28e2..a9465c1 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -5,14 +5,10 @@
* Copyright (C) 2017-2019 Microchip Technology Inc.
*/
-#include <linux/delay.h>
-#include <linux/export.h>
-#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_data/microchip-ksz.h>
#include <linux/phy.h>
-#include <linux/etherdevice.h>
#include <linux/if_bridge.h>
#include <net/dsa.h>
#include <net/switchdev.h>
--
1.9.1
^ permalink raw reply related
* [PATCH v3 net-next 3/4] net: dsa: microchip: get port link status
From: Tristram.Ha @ 2019-02-21 22:03 UTC (permalink / raw)
To: Sergio Paracuellos, Andrew Lunn, Florian Fainelli, Pavel Machek
Cc: Tristram Ha, UNGLinuxDriver, netdev
In-Reply-To: <1550786597-591-1-git-send-email-Tristram.Ha@microchip.com>
From: Tristram Ha <Tristram.Ha@microchip.com>
Get port link status to know whether to read MIB counters when the link
is going down. Add port_cleanup function to read MIB counters the last
time as when the port is disabled the PHY is also powered down.
Signed-off-by: Tristram Ha <Tristram.Ha@microchip.com>
---
drivers/net/dsa/microchip/ksz9477.c | 2 ++
drivers/net/dsa/microchip/ksz_common.c | 39 ++++++++++++++++++++++++++++++++--
drivers/net/dsa/microchip/ksz_common.h | 3 +++
drivers/net/dsa/microchip/ksz_priv.h | 1 +
4 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index e2d74c7..6ad28e2 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -1191,6 +1191,7 @@ static int ksz9477_setup(struct dsa_switch *ds)
.setup = ksz9477_setup,
.phy_read = ksz9477_phy_read16,
.phy_write = ksz9477_phy_write16,
+ .adjust_link = ksz_adjust_link,
.port_enable = ksz_enable_port,
.port_disable = ksz_disable_port,
.get_strings = ksz9477_get_strings,
@@ -1340,6 +1341,7 @@ static void ksz9477_switch_exit(struct ksz_device *dev)
.cfg_port_member = ksz9477_cfg_port_member,
.flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
.phy_setup = ksz9477_phy_setup,
+ .port_cleanup = ksz_port_cleanup,
.port_setup = ksz9477_port_setup,
.r_mib_cnt = ksz9477_r_mib_cnt,
.r_mib_pkt = ksz9477_r_mib_pkt,
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index ff32ace..dd66056 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -20,6 +20,22 @@
#include "ksz_priv.h"
+void ksz_port_cleanup(struct ksz_device *dev, int port)
+{
+ /* Read all MIB counters when the link is going down. */
+ if (dev->live_ports & (1 << port)) {
+ struct ksz_port *p = &dev->ports[port];
+
+ p->read = true;
+ schedule_work(&dev->mib_read);
+ }
+
+ /* Common code for port cleanup. */
+ dev->on_ports &= ~(1 << port);
+ dev->live_ports &= ~(1 << port);
+}
+EXPORT_SYMBOL_GPL(ksz_port_cleanup);
+
void ksz_update_port_member(struct ksz_device *dev, int port)
{
struct ksz_port *p;
@@ -156,6 +172,26 @@ int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val)
}
EXPORT_SYMBOL_GPL(ksz_phy_write16);
+void ksz_adjust_link(struct dsa_switch *ds, int port,
+ struct phy_device *phydev)
+{
+ struct ksz_device *dev = ds->priv;
+ struct ksz_port *p = &dev->ports[port];
+
+ if (!phydev->link) {
+ /* Read all MIB counters when the link is going down. */
+ if (dev->live_ports & (1 << port)) {
+ p->read = true;
+ schedule_work(&dev->mib_read);
+ }
+ dev->live_ports &= ~(1 << port);
+ } else {
+ /* Remember which port is connected and active. */
+ dev->live_ports |= (1 << port) & dev->on_ports;
+ }
+}
+EXPORT_SYMBOL_GPL(ksz_adjust_link);
+
int ksz_sset_count(struct dsa_switch *ds, int port, int sset)
{
struct ksz_device *dev = ds->priv;
@@ -367,8 +403,7 @@ void ksz_disable_port(struct dsa_switch *ds, int port, struct phy_device *phy)
{
struct ksz_device *dev = ds->priv;
- dev->on_ports &= ~(1 << port);
- dev->live_ports &= ~(1 << port);
+ dev->dev_ops->port_cleanup(dev, port);
/* port_stp_state_set() will be called after to disable the port so
* there is no need to do anything.
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 0b0ed3d..ebe6f8e 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -7,6 +7,7 @@
#ifndef __KSZ_COMMON_H
#define __KSZ_COMMON_H
+void ksz_port_cleanup(struct ksz_device *dev, int port);
void ksz_update_port_member(struct ksz_device *dev, int port);
void ksz_init_mib_timer(struct ksz_device *dev);
@@ -14,6 +15,8 @@
int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg);
int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val);
+void ksz_adjust_link(struct dsa_switch *ds, int port,
+ struct phy_device *phydev);
int ksz_sset_count(struct dsa_switch *ds, int port, int sset);
void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *buf);
int ksz_port_bridge_join(struct dsa_switch *ds, int port,
diff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h
index 1d2d98f..a1d84c1 100644
--- a/drivers/net/dsa/microchip/ksz_priv.h
+++ b/drivers/net/dsa/microchip/ksz_priv.h
@@ -137,6 +137,7 @@ struct ksz_dev_ops {
void (*flush_dyn_mac_table)(struct ksz_device *dev, int port);
void (*phy_setup)(struct ksz_device *dev, int port,
struct phy_device *phy);
+ void (*port_cleanup)(struct ksz_device *dev, int port);
void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port);
void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
void (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
--
1.9.1
^ permalink raw reply related
* [PATCH v3 net-next 0/4] net: dsa: microchip: add MIB counters support
From: Tristram.Ha @ 2019-02-21 22:03 UTC (permalink / raw)
To: Sergio Paracuellos, Andrew Lunn, Florian Fainelli, Pavel Machek
Cc: Tristram Ha, UNGLinuxDriver, netdev
From: Tristram Ha <Tristram.Ha@microchip.com>
This series of patches is to modify the KSZ9477 DSA driver to read MIB
counters periodically to avoid overflow.
The MIB counters should be read only when there is link. Otherwise it is
a waste of time as hardware never increases the counters.
Functions are added to check the port link status so that MIB counters
read call is used efficiently.
v3
- Use netif_carrier_ok instead of checking the phy device pointer
v2
- Create macro similar to readx_poll_timeout to use with switch
- Create ksz_port_cleanup function so that variables like on_ports and
live_ports can be updated inside it
v1
- Use readx_poll_timeout
- Do not clear MIB counters when port is enabled
- Do not advertise 1000 half-duplex mode when port is enabled
- Do not use freeze function as MIB counters may miss counts
Tristram Ha (4):
net: dsa: microchip: prepare PHY for proper advertisement
net: dsa: microchip: add MIB counter reading support
net: dsa: microchip: get port link status
net: dsa: microchip: remove unnecessary include headers
drivers/net/dsa/microchip/ksz9477.c | 137 +++++++++++++++++----------
drivers/net/dsa/microchip/ksz_common.c | 163 ++++++++++++++++++++++++++++++++-
drivers/net/dsa/microchip/ksz_common.h | 27 +++++-
drivers/net/dsa/microchip/ksz_priv.h | 14 +--
4 files changed, 284 insertions(+), 57 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH v3 net-next 1/4] net: dsa: microchip: prepare PHY for proper advertisement
From: Tristram.Ha @ 2019-02-21 22:03 UTC (permalink / raw)
To: Sergio Paracuellos, Andrew Lunn, Florian Fainelli, Pavel Machek
Cc: Tristram Ha, UNGLinuxDriver, netdev
In-Reply-To: <1550786597-591-1-git-send-email-Tristram.Ha@microchip.com>
From: Tristram Ha <Tristram.Ha@microchip.com>
Prepare PHY for proper advertisement as sometimes the PHY in the switch
has its own problems even though it may share the PHY id from regular PHY
but the fixes in the PHY driver do not apply.
Signed-off-by: Tristram Ha <Tristram.Ha@microchip.com>
---
drivers/net/dsa/microchip/ksz9477.c | 13 ++++++++++++-
drivers/net/dsa/microchip/ksz_common.c | 3 ++-
drivers/net/dsa/microchip/ksz_priv.h | 4 +++-
3 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index 674d77e..4573b6e 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -2,7 +2,7 @@
/*
* Microchip KSZ9477 switch driver main logic
*
- * Copyright (C) 2017-2018 Microchip Technology Inc.
+ * Copyright (C) 2017-2019 Microchip Technology Inc.
*/
#include <linux/delay.h>
@@ -966,6 +966,16 @@ static void ksz9477_port_mirror_del(struct dsa_switch *ds, int port,
PORT_MIRROR_SNIFFER, false);
}
+static void ksz9477_phy_setup(struct ksz_device *dev, int port,
+ struct phy_device *phy)
+{
+ if (port < dev->phy_port_cnt) {
+ /* The MAC actually cannot run in 1000 half-duplex mode. */
+ phy_remove_link_mode(phy,
+ ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
+ }
+}
+
static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
{
u8 data8;
@@ -1299,6 +1309,7 @@ static void ksz9477_switch_exit(struct ksz_device *dev)
.get_port_addr = ksz9477_get_port_addr,
.cfg_port_member = ksz9477_cfg_port_member,
.flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
+ .phy_setup = ksz9477_phy_setup,
.port_setup = ksz9477_port_setup,
.shutdown = ksz9477_reset_switch,
.detect = ksz9477_switch_detect,
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 8a5111f..6f72842 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -2,7 +2,7 @@
/*
* Microchip switch driver main logic
*
- * Copyright (C) 2017-2018 Microchip Technology Inc.
+ * Copyright (C) 2017-2019 Microchip Technology Inc.
*/
#include <linux/delay.h>
@@ -238,6 +238,7 @@ int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy)
/* setup slave port */
dev->dev_ops->port_setup(dev, port, false);
+ dev->dev_ops->phy_setup(dev, port, phy);
/* port_stp_state_set() will be called after to enable the port so
* there is no need to do anything.
diff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h
index 60b4901..0fdc58b 100644
--- a/drivers/net/dsa/microchip/ksz_priv.h
+++ b/drivers/net/dsa/microchip/ksz_priv.h
@@ -2,7 +2,7 @@
*
* Microchip KSZ series switch common definitions
*
- * Copyright (C) 2017-2018 Microchip Technology Inc.
+ * Copyright (C) 2017-2019 Microchip Technology Inc.
*/
#ifndef __KSZ_PRIV_H
@@ -137,6 +137,8 @@ struct ksz_dev_ops {
u32 (*get_port_addr)(int port, int offset);
void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member);
void (*flush_dyn_mac_table)(struct ksz_device *dev, int port);
+ void (*phy_setup)(struct ksz_device *dev, int port,
+ struct phy_device *phy);
void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port);
void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
void (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
--
1.9.1
^ permalink raw reply related
* Re: [tipc-discussion][net 0/2] improvement for wait and wakeup
From: David Miller @ 2019-02-21 21:58 UTC (permalink / raw)
To: tung.q.nguyen; +Cc: netdev, tipc-discussion
In-Reply-To: <20190219042048.23243-1-tung.q.nguyen@dektech.com.au>
From: Tung Nguyen <tung.q.nguyen@dektech.com.au>
Date: Tue, 19 Feb 2019 11:20:46 +0700
> Some improvements for tipc_wait_for_xzy().
Series applied.
^ permalink raw reply
* Re: [PATCH][net-next] bridge: remove redundant check on err in br_multicast_ipv4_rcv
From: David Miller @ 2019-02-21 21:57 UTC (permalink / raw)
To: lirongqing; +Cc: netdev
In-Reply-To: <1550542629-17121-1-git-send-email-lirongqing@baidu.com>
From: Li RongQing <lirongqing@baidu.com>
Date: Tue, 19 Feb 2019 10:17:09 +0800
> br_ip4_multicast_mrd_rcv only return 0 and -ENOMSG,
> no other negative value
>
> Signed-off-by: Li RongQing <lirongqing@baidu.com>
Applied.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox