* Re: [PATCH RESEND net] net: phy: xgmiitorgmii: Support generic PHY status read
From: Florian Fainelli @ 2019-02-15 17:38 UTC (permalink / raw)
To: Paul Kocialkowski, netdev, linux-arm-kernel, linux-kernel
Cc: Andrew Lunn, Heiner Kallweit, David S . Miller, Michal Simek,
Thomas Petazzoni
In-Reply-To: <20190215163220.20041-1-paul.kocialkowski@bootlin.com>
On 2/15/19 8:32 AM, Paul Kocialkowski wrote:
> Some PHY drivers like the generic one do not provide a read_status
> callback on their own but rely on genphy_read_status being called
> directly.
>
> With the current code, this results in a NULL function pointer call.
> Call genphy_read_status instead when there is no specific callback.
>
> Fixes: f411a6160bd4 ("net: phy: Add gmiitorgmii converter support")
> Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> ---
> Added Fixes tag and net label for resend.
You would want to use phy_read_status() which encapsulates that check as
well as checks that the phy_drv pointer is not NULL.
>
> drivers/net/phy/xilinx_gmii2rgmii.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/phy/xilinx_gmii2rgmii.c b/drivers/net/phy/xilinx_gmii2rgmii.c
> index 74a8782313cf..bd6084e315de 100644
> --- a/drivers/net/phy/xilinx_gmii2rgmii.c
> +++ b/drivers/net/phy/xilinx_gmii2rgmii.c
> @@ -44,7 +44,10 @@ static int xgmiitorgmii_read_status(struct phy_device *phydev)
> u16 val = 0;
> int err;
>
> - err = priv->phy_drv->read_status(phydev);
> + if (priv->phy_drv->read_status)
> + err = priv->phy_drv->read_status(phydev);
> + else
> + err = genphy_read_status(phydev);
> if (err < 0)
> return err;
>
>
--
Florian
^ permalink raw reply
* [PATCH bpf-next] bpf: make LWTUNNEL_BPF dependent on INET
From: Peter Oskolkov @ 2019-02-15 17:40 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, netdev
Cc: Peter Oskolkov, Peter Oskolkov
Lightweight tunnels are L3 constructs that are used with IP/IP6.
Make the dependency explicit at least for LWT-BPF, as now they
call into IP routing.
Signed-off-by: Peter Oskolkov <posk@google.com>
---
net/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/Kconfig b/net/Kconfig
index 5cb9de1aaf88..62da6148e9f8 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -403,7 +403,7 @@ config LWTUNNEL
config LWTUNNEL_BPF
bool "Execute BPF program as route nexthop action"
- depends on LWTUNNEL
+ depends on LWTUNNEL && INET
default y if LWTUNNEL=y
---help---
Allows to run BPF programs as a nexthop action following a route
--
2.21.0.rc0.258.g878e2cd30e-goog
^ permalink raw reply related
* Re: [PATCH v2 perf,bpf 08/11] perf, bpf: save btf information as headers to perf.data
From: Arnaldo Carvalho de Melo @ 2019-02-15 17:40 UTC (permalink / raw)
To: Song Liu, Jiri Olsa, Stephane Eranian
Cc: Netdev, linux-kernel, Alexei Starovoitov, daniel@iogearbox.net,
Kernel Team, peterz@infradead.org, namhyung@kernel.org
In-Reply-To: <164D19ED-EA72-4A56-8259-FCF13894B183@fb.com>
Em Fri, Feb 15, 2019 at 05:25:01PM +0000, Song Liu escreveu:
> > On Feb 15, 2019, at 6:26 AM, Arnaldo Carvalho de Melo <acme@redhat.com> wrote:
> > Em Thu, Feb 14, 2019 at 04:00:09PM -0800, Song Liu escreveu:
> >> This patch enables perf-record to save btf information as headers to
> >> perf.data A new header type HEADER_BTF is introduced for this data.
> > Wouldn't it be better for this HEADER_BTF to be introduced
> > already as an user space event, Song, see:
> > tools/perf/util/event.h
> > and:
> > tools/perf/util/event.c
> > perf_event__synthesize_cpu_map()
> BTF would be short living for short living BPF programs. I guess
> saving them as header is easier than merging them with samples.
> What's the benefit of saving them as user space events?
When we work with pipe mode, i.e.:
perf record -o - | perf report -i -
and other combinations (with 'perf script', 'perf inject', etc), we need
a way to pass the headers to the other side, and the way was via user
space events.
This is something Stephane and Jiri have been discussing recently,
probably they have more justifications, Stephane, Jiri?
- Arnaldo
^ permalink raw reply
* Re: linux-next: Tree for Feb 15 (net/core/lwt_bpf.c)
From: Peter Oskolkov @ 2019-02-15 17:42 UTC (permalink / raw)
To: Randy Dunlap
Cc: Stephen Rothwell, Linux Next Mailing List,
Linux Kernel Mailing List, netdev@vger.kernel.org
In-Reply-To: <51ee23dd-b852-db61-ef21-ff5819488386@infradead.org>
On Fri, Feb 15, 2019 at 8:48 AM Randy Dunlap <rdunlap@infradead.org> wrote:
>
> On 2/14/19 10:03 PM, Stephen Rothwell wrote:
> > Hi all,
> >
> > Changes since 20190214:
> >
>
> on x86_64:
>
> ld: net/core/lwt_bpf.o: in function `bpf_lwt_xmit_reroute':
> lwt_bpf.c:(.text+0x11e): undefined reference to `ip_route_output_flow'
> ld: net/core/lwt_bpf.o: in function `bpf_input':
> lwt_bpf.c:(.text+0x9d3): undefined reference to `ip_route_input_noref'
A fix suggested here: https://patchwork.ozlabs.org/patch/1043098/
>
>
> Full randconfig file is attached.
>
> --
> ~Randy
^ permalink raw reply
* Re: [PATCH bpf-next] bpf: make LWTUNNEL_BPF dependent on INET
From: Eric Dumazet @ 2019-02-15 17:46 UTC (permalink / raw)
To: Peter Oskolkov, Alexei Starovoitov, Daniel Borkmann, netdev
Cc: Peter Oskolkov
In-Reply-To: <20190215174003.33063-1-posk@google.com>
On 02/15/2019 09:40 AM, Peter Oskolkov wrote:
> Lightweight tunnels are L3 constructs that are used with IP/IP6.
> Make the dependency explicit at least for LWT-BPF, as now they
> call into IP routing.
>
> Signed-off-by: Peter Oskolkov <posk@google.com>
> ---
> net/Kconfig | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/Kconfig b/net/Kconfig
> index 5cb9de1aaf88..62da6148e9f8 100644
> --- a/net/Kconfig
> +++ b/net/Kconfig
> @@ -403,7 +403,7 @@ config LWTUNNEL
>
> config LWTUNNEL_BPF
> bool "Execute BPF program as route nexthop action"
> - depends on LWTUNNEL
> + depends on LWTUNNEL && INET
> default y if LWTUNNEL=y
> ---help---
> Allows to run BPF programs as a nexthop action following a route
>
It seems you forgot a 'Reported-by:' tag
Thanks.
^ permalink raw reply
* Re: [RFC v1 15/19] RDMA/irdma: Add miscellaneous utility definitions
From: Jason Gunthorpe @ 2019-02-15 17:47 UTC (permalink / raw)
To: Shiraz Saleem
Cc: dledford, davem, linux-rdma, netdev, mustafa.ismail,
jeffrey.t.kirsher
In-Reply-To: <20190215171107.6464-16-shiraz.saleem@intel.com>
On Fri, Feb 15, 2019 at 11:11:02AM -0600, Shiraz Saleem wrote:
> From: Mustafa Ismail <mustafa.ismail@intel.com>
>
> Add miscellaneous utility functions and headers.
>
> Signed-off-by: Mustafa Ismail <mustafa.ismail@intel.com>
> Signed-off-by: Shiraz Saleem <shiraz.saleem@intel.com>
> drivers/infiniband/hw/irdma/osdep.h | 153 ++
> drivers/infiniband/hw/irdma/protos.h | 118 ++
> drivers/infiniband/hw/irdma/status.h | 70 +
> drivers/infiniband/hw/irdma/utils.c | 2565 ++++++++++++++++++++++++++++++++++
> 4 files changed, 2906 insertions(+)
> create mode 100644 drivers/infiniband/hw/irdma/osdep.h
> create mode 100644 drivers/infiniband/hw/irdma/protos.h
> create mode 100644 drivers/infiniband/hw/irdma/status.h
> create mode 100644 drivers/infiniband/hw/irdma/utils.c
>
> diff --git a/drivers/infiniband/hw/irdma/osdep.h b/drivers/infiniband/hw/irdma/osdep.h
> new file mode 100644
> index 0000000..ade5536
> +++ b/drivers/infiniband/hw/irdma/osdep.h
> @@ -0,0 +1,153 @@
> +/* SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB */
> +/* Copyright (c) 2019, Intel Corporation. */
> +
> +#ifndef IRDMA_OSDEP_H
> +#define IRDMA_OSDEP_H
> +
> +#include <linux/version.h>
> +#include <linux/kernel.h>
> +#include <linux/vmalloc.h>
> +#include <linux/string.h>
> +#include <linux/bitops.h>
> +#include <linux/pci.h>
> +#include <net/tcp.h>
> +#include <crypto/hash.h>
> +/* get readq/writeq support for 32 bit kernels, use the low-first version */
> +#include <linux/io-64-nonatomic-lo-hi.h>
> +
> +#define STATS_TIMER_DELAY 60000
> +#define MAKEMASK(m, s) ((m) << (s))
> +
> +#define irdma_pr_err(fmt, args ...) \
> + pr_err("%s: "fmt, __func__, ## args)
> +
> +#define irdma_pr_info(fmt, args ...) \
> + pr_info("%s: " fmt, __func__, ## args)
> +
> +#define irdma_pr_warn(fmt, args ...) \
> + pr_warn("%s: " fmt, __func__, ## args)
> +
> +#define irdma_dev_err(dev, fmt, args ...) \
> + dev_err(to_device(dev), "%s: "fmt, __func__, ## args)
> +
> +#define irdma_dev_info(dev, fmt, args ...) \
> + dev_info(to_device(dev), "%s: "fmt, __func__, ## args)
> +
> +#define irdma_dev_warn(dev, fmt, args ...) \
> + dev_warn(to_device(dev), "%s: "fmt, __func__, ## args)
Does every driver really have to define these macros?
> +#define to_device(ptr) \
> + (&((struct pci_dev *)((ptr)->hw->dev_context))->dev)
?? Seems like this wants to be container_of??
> +/**
> + * irdma_insert_wqe_hdr - write wqe header
> + * @wqe: cqp wqe for header
> + * @header: header for the cqp wqe
> + */
> +static inline void irdma_insert_wqe_hdr(__le64 *wqe, u64 hdr)
> +{
> + wmb(); /* make sure WQE is populated before polarity is set */
> + set_64bit_val(wqe, 24, hdr);
Generally don't like seeing wmbs in drivers.. Are you sure this isn't
supposed to be smp_store_release(), or dma_wmb() perhaps?
> +/**
> + * irdma_inetaddr_event - system notifier for ipv4 addr events
> + * @notfier: not used
> + * @event: event for notifier
> + * @ptr: if address
> + */
> +int irdma_inetaddr_event(struct notifier_block *notifier,
> + unsigned long event,
> + void *ptr)
> +{
> + struct in_ifaddr *ifa = ptr;
> + struct net_device *event_netdev = ifa->ifa_dev->dev;
> + struct net_device *netdev;
> + struct net_device *upper_dev;
> + struct irdma_device *iwdev;
> + u32 local_ipaddr;
> +
> + iwdev = irdma_find_netdev(event_netdev);
This is all being changed too (and is probably wrongly locked here)
A new driver must not maintain their own list of devices.
> + if (iwdev->init_state < IP_ADDR_REGISTERED || iwdev->closing)
> + return NOTIFY_DONE;
> +
> + netdev = iwdev->netdev;
> + upper_dev = netdev_master_upper_dev_get(netdev);
> + if (netdev != event_netdev)
> + return NOTIFY_DONE;
What is all this? Does the driver support bonding?
You have to fix this to work in the new style - and you might need to
add more core code to sanely support bonding.
Look here:
https://patchwork.kernel.org/project/linux-rdma/list/?series=79299
> +/**
> + * irdma_add_devusecount - add dev refcount
> + * @iwdev: dev for refcount
> + */
> +void irdma_add_devusecount(struct irdma_device *iwdev)
> +{
> + atomic64_inc(&iwdev->use_count);
> +}
> +
> +/**
> + * irdma_rem_devusecount - decrement refcount for dev
> + * @iwdev: device
> + */
> +void irdma_rem_devusecount(struct irdma_device *iwdev)
> +{
> + if (!atomic64_dec_and_test(&iwdev->use_count))
> + return;
> + wake_up(&iwdev->close_wq);
> +}
> +
> +/**
> + * irdma_add_pdusecount - add pd refcount
> + * @iwpd: pd for refcount
> + */
> +void irdma_add_pdusecount(struct irdma_pd *iwpd)
> +{
> + atomic_inc(&iwpd->usecount);
> +}
Why do we have these wrappers? Don't like wrappers liket his.
Are you sure this should be an atomic, not a kref, refcount, etc?
Very concerning to refcounting of HW object structures like
this.. Most often when I see this in IB drivers it comes along with
concurrency bugs in the destroy path.
> +/**
> + * irdma_allocate_dma_mem - Memory alloc helper fn
> + * @hw: pointer to the HW structure
> + * @mem: ptr to mem struct to fill out
> + * @size: size of memory requested
> + * @alignment: what to align the allocation to
> + */
> +enum irdma_status_code irdma_allocate_dma_mem(struct irdma_hw *hw,
> + struct irdma_dma_mem *mem,
> + u64 size,
> + u32 alignment)
> +{
> + struct pci_dev *pcidev = (struct pci_dev *)hw->dev_context;
> +
> + if (!mem)
> + return IRDMA_ERR_PARAM;
> +
> + mem->size = ALIGN(size, alignment);
> + mem->va = dma_alloc_coherent(&pcidev->dev, mem->size,
> + (dma_addr_t *)&mem->pa, GFP_KERNEL);
> + if (!mem->va)
> + return IRDMA_ERR_NO_MEMORY;
> +
> + return 0;
> +}
More wrappers? Why?
Jason
^ permalink raw reply
* Re: [PATCH v2 perf,bpf 08/11] perf, bpf: save btf information as headers to perf.data
From: Song Liu @ 2019-02-15 17:47 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Jiri Olsa, Stephane Eranian, Netdev, linux-kernel,
Alexei Starovoitov, daniel@iogearbox.net, Kernel Team,
peterz@infradead.org, namhyung@kernel.org
In-Reply-To: <20190215174022.GF31177@kernel.org>
> On Feb 15, 2019, at 9:40 AM, Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
>
> Em Fri, Feb 15, 2019 at 05:25:01PM +0000, Song Liu escreveu:
>>> On Feb 15, 2019, at 6:26 AM, Arnaldo Carvalho de Melo <acme@redhat.com> wrote:
>>> Em Thu, Feb 14, 2019 at 04:00:09PM -0800, Song Liu escreveu:
>>>> This patch enables perf-record to save btf information as headers to
>>>> perf.data A new header type HEADER_BTF is introduced for this data.
>
>>> Wouldn't it be better for this HEADER_BTF to be introduced
>>> already as an user space event, Song, see:
>
>>> tools/perf/util/event.h
>
>>> and:
>
>>> tools/perf/util/event.c
>
>>> perf_event__synthesize_cpu_map()
>
>> BTF would be short living for short living BPF programs. I guess
>> saving them as header is easier than merging them with samples.
>
>> What's the benefit of saving them as user space events?
>
> When we work with pipe mode, i.e.:
>
> perf record -o - | perf report -i -
>
> and other combinations (with 'perf script', 'perf inject', etc), we need
> a way to pass the headers to the other side, and the way was via user
> space events.
>
> This is something Stephane and Jiri have been discussing recently,
> probably they have more justifications, Stephane, Jiri?
>
> - Arnaldo
I see. In this case, we will need some synchronization between main
thread and the polling thread, as they are both writing to the same
pipe.
Thanks,
Song
^ permalink raw reply
* [PATCH bpf-next v2] bpf: make LWTUNNEL_BPF dependent on INET
From: Peter Oskolkov @ 2019-02-15 17:51 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, netdev
Cc: Peter Oskolkov, Peter Oskolkov, Randy Dunlap
Lightweight tunnels are L3 constructs that are used with IP/IP6.
For example, lwtunnel_xmit is called from ip_output.c and
ip6_output.c only.
Make the dependency explicit at least for LWT-BPF, as now they
call into IP routing.
V2: added "Reported-by" below.
Reported-by: Randy Dunlap <rdunlap@infradead.org>
Signed-off-by: Peter Oskolkov <posk@google.com>
---
net/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/Kconfig b/net/Kconfig
index 5cb9de1aaf88..62da6148e9f8 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -403,7 +403,7 @@ config LWTUNNEL
config LWTUNNEL_BPF
bool "Execute BPF program as route nexthop action"
- depends on LWTUNNEL
+ depends on LWTUNNEL && INET
default y if LWTUNNEL=y
---help---
Allows to run BPF programs as a nexthop action following a route
--
2.21.0.rc0.258.g878e2cd30e-goog
^ permalink raw reply related
* Re: [PATCH bpf-next] bpf: make LWTUNNEL_BPF dependent on INET
From: Peter Oskolkov @ 2019-02-15 17:53 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Peter Oskolkov, Alexei Starovoitov, Daniel Borkmann, netdev
In-Reply-To: <59bb6b8c-e35c-cf76-d47d-63baa7336021@gmail.com>
On Fri, Feb 15, 2019 at 9:46 AM Eric Dumazet <eric.dumazet@gmail.com> wrote:
>
>
>
> On 02/15/2019 09:40 AM, Peter Oskolkov wrote:
> > Lightweight tunnels are L3 constructs that are used with IP/IP6.
> > Make the dependency explicit at least for LWT-BPF, as now they
> > call into IP routing.
> >
> > Signed-off-by: Peter Oskolkov <posk@google.com>
> > ---
> > net/Kconfig | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/net/Kconfig b/net/Kconfig
> > index 5cb9de1aaf88..62da6148e9f8 100644
> > --- a/net/Kconfig
> > +++ b/net/Kconfig
> > @@ -403,7 +403,7 @@ config LWTUNNEL
> >
> > config LWTUNNEL_BPF
> > bool "Execute BPF program as route nexthop action"
> > - depends on LWTUNNEL
> > + depends on LWTUNNEL && INET
> > default y if LWTUNNEL=y
> > ---help---
> > Allows to run BPF programs as a nexthop action following a route
> >
>
> It seems you forgot a 'Reported-by:' tag
Fixed: https://patchwork.ozlabs.org/patch/1043108/
>
> Thanks.
^ permalink raw reply
* Re: [PATCH net] vhost: correctly check the return value of translate_desc() in log_used()
From: David Miller @ 2019-02-15 18:03 UTC (permalink / raw)
To: jasowang; +Cc: mst, kvm, virtualization, netdev, linux-kernel, stephen
In-Reply-To: <20190215075324.18891-1-jasowang@redhat.com>
From: Jason Wang <jasowang@redhat.com>
Date: Fri, 15 Feb 2019 15:53:24 +0800
> When fail, translate_desc() returns negative value, otherwise the
> number of iovs. So we should fail when the return value is negative
> instead of a blindly check against zero.
>
> Reported-by: Stephen Hemminger <stephen@networkplumber.org>
> Fixes: cc5e71075947 ("vhost: log dirty page correctly")
> Signed-off-by: Jason Wang <jasowang@redhat.com>
Jason, please put the Fixes tag first.
Thank you.
^ permalink raw reply
* Re: [PATCH v2 perf,bpf 01/11] perf, bpf: consider events with attr.bpf_event as side-band events
From: Arnaldo Carvalho de Melo @ 2019-02-15 18:04 UTC (permalink / raw)
To: Song Liu
Cc: Netdev, linux-kernel, Alexei Starovoitov, Daniel Borkmann,
Kernel Team, Peter Zijlstra, jolsa@kernel.org,
namhyung@kernel.org
In-Reply-To: <ECDC9D1F-3AA3-451A-BAC7-E089D4CAAEEC@fb.com>
Em Fri, Feb 15, 2019 at 05:02:02PM +0000, Song Liu escreveu:
>
>
> > On Feb 15, 2019, at 6:14 AM, Arnaldo Carvalho de Melo <acme@redhat.com> wrote:
> >
> > Em Thu, Feb 14, 2019 at 03:58:40PM -0800, Song Liu escreveu:
> >> Events with bpf_event should be considered as side-band event, as they
> >> carry information about BPF programs.
> >>
> >> Fixes: 6ee52e2a3fe4 ("perf, bpf: Introduce PERF_RECORD_BPF_EVENT")
> >> Signed-off-by: Song Liu <songliubraving@fb.com>
> >> ---
> >> kernel/events/core.c | 3 ++-
> >> 1 file changed, 2 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/kernel/events/core.c b/kernel/events/core.c
> >> index 0a8dab322111..9403bdda5f8c 100644
> >> --- a/kernel/events/core.c
> >> +++ b/kernel/events/core.c
> >> @@ -4238,7 +4238,8 @@ static bool is_sb_event(struct perf_event *event)
> >> if (attr->mmap || attr->mmap_data || attr->mmap2 ||
> >> attr->comm || attr->comm_exec ||
> >> attr->task || attr->ksymbol ||
> ^ here
how come, I looked after context_switch, that came before, have to
replace my glasses... :-)
>
> >> - attr->context_switch)
> >> + attr->context_switch ||
> >> + attr->bpf_event)
> >
> > What about attr->ksymbol?
> It is already included up there. attr->bpf_event was missed initially
> because we didn't use events with bpf_event but not ksymbol. With this
> set, the polling thread only has bpf_event, so we need this fix.
Ok, I'll get this one merged asap.
- Arnaldo
^ permalink raw reply
* Re: [PATCH v2 perf,bpf 09/11] perf-top: add option --bpf-event
From: Arnaldo Carvalho de Melo @ 2019-02-15 18:05 UTC (permalink / raw)
To: Song Liu
Cc: Netdev, linux-kernel@vger.kernel.org, ast@kernel.org,
daniel@iogearbox.net, Kernel Team, peterz@infradead.org,
jolsa@kernel.org, namhyung@kernel.org, acme
In-Reply-To: <31C00A93-54B4-40D0-AC63-A19368AEC669@fb.com>
Em Fri, Feb 15, 2019 at 05:06:19PM +0000, Song Liu escreveu:
> > On Feb 15, 2019, at 6:27 AM, Arnaldo Carvalho de Melo <acme@redhat.com> wrote:
> > Em Thu, Feb 14, 2019 at 04:00:10PM -0800, Song Liu escreveu:
> >> bpf events are only tracked when opts->bpf_event is enabled. This patch
> >> adds command line flag to enable this for perf-top.
> > Shouldn't this start as enabled and we just provide a way to disable it
> > for testing purposes? Normally perf top works system wide, and then we
> > want to get info about BPF events, I think.
> We can enable it by default, and add a --no-bpf-event option to disable it
> for testing.
Excellent, thanks.
- Arnaldo
^ permalink raw reply
* Re: [PATCH v2 perf,bpf 11/11] perf, bpf: save information about short living bpf programs
From: Arnaldo Carvalho de Melo @ 2019-02-15 18:09 UTC (permalink / raw)
To: Song Liu
Cc: Netdev, linux-kernel, ast@kernel.org, daniel@iogearbox.net,
Kernel Team, peterz@infradead.org, jolsa@kernel.org,
namhyung@kernel.org
In-Reply-To: <62DB92A4-F708-4E89-B668-4EAFD0FA6731@fb.com>
Em Fri, Feb 15, 2019 at 05:13:01PM +0000, Song Liu escreveu:
> > On Feb 15, 2019, at 6:41 AM, Arnaldo Carvalho de Melo <acme@redhat.com> wrote:
> > Em Thu, Feb 14, 2019 at 04:00:45PM -0800, Song Liu escreveu:
> >> +pthread_t poll_thread;
> >> +
> >> +int bpf_event__start_polling_thread(struct bpf_event_poll_args *args)
> >> +{
> >> + struct perf_evsel *counter;
> >> +
> >> + args->evlist = perf_evlist__new();
> >> +
> >> + if (args->evlist == NULL)
> >> + return -1;
> >> +
> >> + if (perf_evlist__create_maps(args->evlist, args->target))
> > goto out_delete_evlist;
> >> +
> >> + if (perf_evlist__add_bpf_tracker(args->evlist))
> > goto out_delete_evlist;
> >> +
> >> + evlist__for_each_entry(args->evlist, counter) {
> >> + if (perf_evsel__open(counter, args->evlist->cpus,
> >> + args->evlist->threads) < 0)
> > goto out_delete_evlist;
> >> + }
> >> +
> >> + if (perf_evlist__mmap(args->evlist, UINT_MAX))
> > goto out_delete_evlist;
> >> +
> >> + evlist__for_each_entry(args->evlist, counter) {
> >> + if (perf_evsel__enable(counter))
> > goto out_delete_evlist;
> >> + }
> >> +
> >> + if (pthread_create(&poll_thread, NULL, bpf_poll_thread, args))
> > goto out_delete_evlist;
> >> +
> >> + return 0;
> > out_delete_evlist:
> > perf_evlist__delete(args->evlist);
> > args->evlist = NULL;
Have you seen the error handling suggestion above?
> >> +int perf_evlist__add_bpf_tracker(struct perf_evlist *evlist)
> >> +{
> >> + struct perf_event_attr attr = {
> >> + .type = PERF_TYPE_SOFTWARE,
> >> + .config = PERF_COUNT_SW_DUMMY,
> >> + .watermark = 1,
> >> + .bpf_event = 1,
> >> + .wakeup_watermark = 1,
> >> + .size = sizeof(attr), /* to capture ABI version */
> >> + };
> >> + struct perf_evsel *evsel = perf_evsel__new_idx(&attr,
> >> + evlist->nr_entries);
> >> +
> >> + if (evsel == NULL)
> >> + return -ENOMEM;
> >> +
> >> + perf_evlist__add(evlist, evsel);
> > You could use:
> > struct perf_evlist *evlist = perf_evlist__new_dummy();
> > if (evlist != NULL) {
> > struct perf_evsel *evsel == perf_evlist__first(evlist);
> > evsel->attr.bpf_event = evsel->attr.watermark = evsel->attr.wakeup_watermark = 1;
> > return 0;
> > }
> > return -1;
> This looks cleaner. Let me fix in next version.
> > Because in this case all you'll have in this evlist is the bpf tracker,
> > right? The add_bpf_tracker would be handy if we would want to have a
> > pre-existing evlist with some other events and wanted to add a bpf
> > tracker, no?
> I think all we need is a side-band evlist instead of the main evlist. May
> be we should call it side-band evlist, and make it more generic?
Sure, you could for instance have something like:
struct perf_event_attr attr = {
.watermark = 1,
.bpf_event = 1,
.wakeup_watermark = 1,
}
struct perf_evlist *evlist = perf_evlist__new_side_band(&attr);
And the other details will be set by it, i.e. the .config
.type = PERF_TYPE_SOFTWARE,
.config = PERF_COUNT_SW_DUMMY,
.size = sizeof(attr), /* to capture ABI version */
And the idx arg.
- Arnaldo
^ permalink raw reply
* Re: [net-next 5/5] net: sock: remove the definition of SOCK_DEBUG()
From: Cong Wang @ 2019-02-15 18:12 UTC (permalink / raw)
To: Eric Dumazet
Cc: Yafang Shao, David Miller, Daniel Borkmann, netdev, shaoyafang
In-Reply-To: <CANn89i+5hXmTYihyeCw-fwGG2BvC_a676bi9nbb7p907mmi6Fg@mail.gmail.com>
On Fri, Feb 15, 2019 at 8:26 AM Eric Dumazet <edumazet@google.com> wrote:
>
> On Fri, Feb 15, 2019 at 6:50 AM Yafang Shao <laoar.shao@gmail.com> wrote:
> >
> > As SOCK_DEBUG() isn't used any more, we can get ride of it now.
> >
>
> No, we are still using this infrastructure from time to time.
>
> I told you I agreed to remove the current (obsolete) TCP call sites,
> I never suggested to remove SOCK_DEBUG() completely.
Since when do we upstream care about any out-of-tree users?
You can always carry a patch to keep it downstream if you want,
no one can stop you doing it.
^ permalink raw reply
* Re: [PATCH v2 perf,bpf 11/11] perf, bpf: save information about short living bpf programs
From: Song Liu @ 2019-02-15 18:13 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Netdev, linux-kernel, ast@kernel.org, daniel@iogearbox.net,
Kernel Team, peterz@infradead.org, jolsa@kernel.org,
namhyung@kernel.org
In-Reply-To: <20190215180916.GJ5784@redhat.com>
> On Feb 15, 2019, at 10:09 AM, Arnaldo Carvalho de Melo <acme@redhat.com> wrote:
>
> Em Fri, Feb 15, 2019 at 05:13:01PM +0000, Song Liu escreveu:
>>> On Feb 15, 2019, at 6:41 AM, Arnaldo Carvalho de Melo <acme@redhat.com> wrote:
>>> Em Thu, Feb 14, 2019 at 04:00:45PM -0800, Song Liu escreveu:
>>>> +pthread_t poll_thread;
>>>> +
>>>> +int bpf_event__start_polling_thread(struct bpf_event_poll_args *args)
>>>> +{
>>>> + struct perf_evsel *counter;
>>>> +
>>>> + args->evlist = perf_evlist__new();
>>>> +
>>>> + if (args->evlist == NULL)
>>>> + return -1;
>>>> +
>>>> + if (perf_evlist__create_maps(args->evlist, args->target))
>>> goto out_delete_evlist;
>>>> +
>>>> + if (perf_evlist__add_bpf_tracker(args->evlist))
>>> goto out_delete_evlist;
>>>> +
>>>> + evlist__for_each_entry(args->evlist, counter) {
>>>> + if (perf_evsel__open(counter, args->evlist->cpus,
>>>> + args->evlist->threads) < 0)
>>> goto out_delete_evlist;
>>>> + }
>>>> +
>>>> + if (perf_evlist__mmap(args->evlist, UINT_MAX))
>>> goto out_delete_evlist;
>>>> +
>>>> + evlist__for_each_entry(args->evlist, counter) {
>>>> + if (perf_evsel__enable(counter))
>>> goto out_delete_evlist;
>>>> + }
>>>> +
>>>> + if (pthread_create(&poll_thread, NULL, bpf_poll_thread, args))
>>> goto out_delete_evlist;
>>>> +
>>>> + return 0;
>>> out_delete_evlist:
>>> perf_evlist__delete(args->evlist);
>>> args->evlist = NULL;
>
> Have you seen the error handling suggestion above?
Yes! I will include these changes, as always. :)
>
>>>> +int perf_evlist__add_bpf_tracker(struct perf_evlist *evlist)
>>>> +{
>>>> + struct perf_event_attr attr = {
>>>> + .type = PERF_TYPE_SOFTWARE,
>>>> + .config = PERF_COUNT_SW_DUMMY,
>>>> + .watermark = 1,
>>>> + .bpf_event = 1,
>>>> + .wakeup_watermark = 1,
>>>> + .size = sizeof(attr), /* to capture ABI version */
>>>> + };
>>>> + struct perf_evsel *evsel = perf_evsel__new_idx(&attr,
>>>> + evlist->nr_entries);
>>>> +
>>>> + if (evsel == NULL)
>>>> + return -ENOMEM;
>>>> +
>>>> + perf_evlist__add(evlist, evsel);
>
>>> You could use:
>
>>> struct perf_evlist *evlist = perf_evlist__new_dummy();
>>> if (evlist != NULL) {
>>> struct perf_evsel *evsel == perf_evlist__first(evlist);
>>> evsel->attr.bpf_event = evsel->attr.watermark = evsel->attr.wakeup_watermark = 1;
>>> return 0;
>>> }
>>> return -1;
>
>> This looks cleaner. Let me fix in next version.
>
>>> Because in this case all you'll have in this evlist is the bpf tracker,
>>> right? The add_bpf_tracker would be handy if we would want to have a
>>> pre-existing evlist with some other events and wanted to add a bpf
>>> tracker, no?
>
>> I think all we need is a side-band evlist instead of the main evlist. May
>> be we should call it side-band evlist, and make it more generic?
>
> Sure, you could for instance have something like:
>
> struct perf_event_attr attr = {
> .watermark = 1,
> .bpf_event = 1,
> .wakeup_watermark = 1,
> }
> struct perf_evlist *evlist = perf_evlist__new_side_band(&attr);
>
>
> And the other details will be set by it, i.e. the .config
>
> .type = PERF_TYPE_SOFTWARE,
> .config = PERF_COUNT_SW_DUMMY,
> .size = sizeof(attr), /* to capture ABI version */
>
> And the idx arg.
>
> - Arnaldo
This looks good. Let me revise the patch in that direction.
Thanks,
Song
^ permalink raw reply
* [PATCH net-next] selftests: forwarding: Add some missing configuration symbols
From: Florian Fainelli @ 2019-02-15 18:14 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, David S. Miller, Shuah Khan, Ido Schimmel,
Jiri Pirko, open list:KERNEL SELFTEST FRAMEWORK, open list
For the forwarding selftests to work, we need network namespaces when
using veth/vrf otherwise ping/ping6 commands like these:
ip vrf exec vveth0 /bin/ping 192.0.2.2 -c 10 -i 0.1 -w 5
will fail because network namespaces may not be enabled.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
tools/testing/selftests/net/forwarding/config | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tools/testing/selftests/net/forwarding/config b/tools/testing/selftests/net/forwarding/config
index 5cd2aed97958..da96eff72a8e 100644
--- a/tools/testing/selftests/net/forwarding/config
+++ b/tools/testing/selftests/net/forwarding/config
@@ -10,3 +10,5 @@ CONFIG_NET_CLS_FLOWER=m
CONFIG_NET_SCH_INGRESS=m
CONFIG_NET_ACT_GACT=m
CONFIG_VETH=m
+CONFIG_NAMESPACES=y
+CONFIG_NET_NS=y
--
2.17.1
^ permalink raw reply related
* [PATCH] visornic: use skb_put_zero() instead of open-coded version
From: Jann Horn @ 2019-02-15 18:16 UTC (permalink / raw)
To: David Kershner, sparmaintainer, jannh
Cc: Greg Kroah-Hartman, linux-kernel, netdev
Replace an open-coded version of skb_put_zero() with a call to the helper.
This is a cleanup and is also useful for potentially adding KASAN
integration to SKBs in the future.
Signed-off-by: Jann Horn <jannh@google.com>
---
drivers/staging/unisys/visornic/visornic_main.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c
index 5eeb4b93b45b..1c1a470d2e50 100644
--- a/drivers/staging/unisys/visornic/visornic_main.c
+++ b/drivers/staging/unisys/visornic/visornic_main.c
@@ -896,9 +896,7 @@ static netdev_tx_t visornic_xmit(struct sk_buff *skb, struct net_device *netdev)
((skb_end_pointer(skb) - skb->data) >= ETH_MIN_PACKET_SIZE)) {
/* pad the packet out to minimum size */
padlen = ETH_MIN_PACKET_SIZE - len;
- memset(&skb->data[len], 0, padlen);
- skb->tail += padlen;
- skb->len += padlen;
+ skb_put_zero(skb, padlen);
len += padlen;
firstfraglen += padlen;
}
--
2.21.0.rc0.258.g878e2cd30e-goog
^ permalink raw reply related
* Re: [PATCH mlx5-next 00/15] mlx5-next updates (ECPF & 50Gbps per lane)
From: Saeed Mahameed @ 2019-02-15 18:17 UTC (permalink / raw)
To: Leon Romanovsky; +Cc: netdev@vger.kernel.org, linux-rdma@vger.kernel.org
In-Reply-To: <20190213065546.3013-1-saeedm@mellanox.com>
On Tue, 2019-02-12 at 22:55 -0800, Saeed Mahameed wrote:
> Hi All,
>
> This series from Bodong and Aya provides two low level updates to
> mlx5
> core driver that are required for both mlx5e netdev and mlx5_ib
> drivers.
>
> From Bodong Wang:
> 1) Introduction of ECPF (Embedded CPU Physical Function), and low
> level
> bits for mlx5 SmartNic capabilities support.
> 2) Vport enumeration refactoring that affect mlx5_ib and mlx5_core
>
> From Aya Levin,
> 3) Add support for 50Gbps per lane link modes in the Port Type and
> Speed
> register (PTYS)
> 4) Refactor low level query functions for PTYS register
> 5) Add support for 50Gbps per lane link modes to mlx5_ib
>
Applied to mlx5-next,
Thanks.
^ permalink raw reply
* Re: [PATCH v2 perf,bpf 08/11] perf, bpf: save btf information as headers to perf.data
From: Arnaldo Carvalho de Melo @ 2019-02-15 18:20 UTC (permalink / raw)
To: Song Liu
Cc: Jiri Olsa, Stephane Eranian, Netdev, linux-kernel,
Alexei Starovoitov, daniel@iogearbox.net, Kernel Team,
peterz@infradead.org, namhyung@kernel.org
In-Reply-To: <847940EC-6E2A-4985-AE19-27758C301B5D@fb.com>
Em Fri, Feb 15, 2019 at 05:47:58PM +0000, Song Liu escreveu:
>
>
> > On Feb 15, 2019, at 9:40 AM, Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> >
> > Em Fri, Feb 15, 2019 at 05:25:01PM +0000, Song Liu escreveu:
> >>> On Feb 15, 2019, at 6:26 AM, Arnaldo Carvalho de Melo <acme@redhat.com> wrote:
> >>> Em Thu, Feb 14, 2019 at 04:00:09PM -0800, Song Liu escreveu:
> >>>> This patch enables perf-record to save btf information as headers to
> >>>> perf.data A new header type HEADER_BTF is introduced for this data.
> >
> >>> Wouldn't it be better for this HEADER_BTF to be introduced
> >>> already as an user space event, Song, see:
> >
> >>> tools/perf/util/event.h
> >
> >>> and:
> >
> >>> tools/perf/util/event.c
> >
> >>> perf_event__synthesize_cpu_map()
> >
> >> BTF would be short living for short living BPF programs. I guess
> >> saving them as header is easier than merging them with samples.
> >
> >> What's the benefit of saving them as user space events?
> >
> > When we work with pipe mode, i.e.:
> >
> > perf record -o - | perf report -i -
> >
> > and other combinations (with 'perf script', 'perf inject', etc), we need
> > a way to pass the headers to the other side, and the way was via user
> > space events.
> >
> > This is something Stephane and Jiri have been discussing recently,
> > probably they have more justifications, Stephane, Jiri?
> >
> > - Arnaldo
>
> I see. In this case, we will need some synchronization between main
> thread and the polling thread, as they are both writing to the same
> pipe.
So, the whole context is that we need to have 'perf record' to start a
thread per CPU and then read the already per-cpu mmap buffers in the
matching thread, with the right affinity, numa settings to have the
record phase not cause contention, etc, so it ends up dumping one stream
per CPU in a separate file in a 'perf.data' directory instead of a
perf.data file.
Jiri is working on that, so, if you dump one more stream into that
directory, it would, at post processing time, be ordered together with
the other stream, the per-cpu ones.
- Arnaldo
^ permalink raw reply
* [PATCH net-next 0/7] s390/qeth: updates 2019-02-15
From: Julian Wiedmann @ 2019-02-15 18:22 UTC (permalink / raw)
To: David Miller
Cc: netdev, linux-s390, Martin Schwidefsky, Heiko Carstens,
Stefan Raspl, Ursula Braun, Julian Wiedmann
Hi Dave,
please apply a few more qeth patches to net-next. Along with some smaller
improvements, this revamps our code for the SW statistics that are exposed
through ETHTOOL_GSTATS.
Thanks,
Julian
Julian Wiedmann (7):
s390/qeth: allow manual recovery when device is SOFTSETUP
s390/qeth: use a static Output Queue array
s390/qeth: reduce ethtool statistics
s390/qeth: move ethtool code into its own file
s390/qeth: overhaul ethtool statistics
s390/qeth: add support for ETHTOOL_GRINGPARAM
s390/qeth: split out OSN netdev ops
drivers/s390/net/Makefile | 2 +-
drivers/s390/net/qeth_core.h | 133 ++++------
drivers/s390/net/qeth_core_main.c | 545 ++++++--------------------------------
drivers/s390/net/qeth_core_mpc.h | 1 +
drivers/s390/net/qeth_core_sys.c | 41 +--
drivers/s390/net/qeth_ethtool.c | 370 ++++++++++++++++++++++++++
drivers/s390/net/qeth_l2_main.c | 85 +++---
drivers/s390/net/qeth_l3_main.c | 54 ++--
8 files changed, 582 insertions(+), 649 deletions(-)
create mode 100644 drivers/s390/net/qeth_ethtool.c
--
2.16.4
^ permalink raw reply
* [PATCH net-next 1/7] s390/qeth: allow manual recovery when device is SOFTSETUP
From: Julian Wiedmann @ 2019-02-15 18:22 UTC (permalink / raw)
To: David Miller
Cc: netdev, linux-s390, Martin Schwidefsky, Heiko Carstens,
Stefan Raspl, Ursula Braun, Julian Wiedmann
In-Reply-To: <20190215182231.90709-1-jwi@linux.ibm.com>
Once a qeth ccwgroup device is set online, it's also armed for internal
recovery. So allow for testing that code path via sysfs, regardless of
whether the interface is up or down.
Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
---
drivers/s390/net/qeth_core_sys.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c
index 30f61608fa22..485a335669ba 100644
--- a/drivers/s390/net/qeth_core_sys.c
+++ b/drivers/s390/net/qeth_core_sys.c
@@ -316,7 +316,7 @@ static ssize_t qeth_dev_recover_store(struct device *dev,
if (!card)
return -EINVAL;
- if (card->state != CARD_STATE_UP)
+ if (!qeth_card_hw_is_reachable(card))
return -EPERM;
i = simple_strtoul(buf, &tmp, 16);
--
2.16.4
^ permalink raw reply related
* [PATCH net-next 2/7] s390/qeth: use a static Output Queue array
From: Julian Wiedmann @ 2019-02-15 18:22 UTC (permalink / raw)
To: David Miller
Cc: netdev, linux-s390, Martin Schwidefsky, Heiko Carstens,
Stefan Raspl, Ursula Braun, Julian Wiedmann
In-Reply-To: <20190215182231.90709-1-jwi@linux.ibm.com>
qeth dynamically allocates an array for storing pointers to its
Output Queue structures. Switch this to a static array - we are
currently limited to 4 Output Queues, so shrinking the qeth_qdio_info
struct by just a few bytes doesn't justify the additional complexity.
Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
---
drivers/s390/net/qeth_core.h | 2 +-
drivers/s390/net/qeth_core_main.c | 21 ++++++---------------
2 files changed, 7 insertions(+), 16 deletions(-)
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 18696ffb662d..2ea5d7c0b94c 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -528,7 +528,7 @@ struct qeth_qdio_info {
/* output */
int no_out_queues;
- struct qeth_qdio_out_q **out_qs;
+ struct qeth_qdio_out_q *out_qs[QETH_MAX_QUEUES];
struct qdio_outbuf_state *out_bufstates;
/* priority queueing */
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 5ca934775c42..d01a4aded4cc 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -2433,12 +2433,6 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card)
goto out_freeinq;
/* outbound */
- card->qdio.out_qs =
- kcalloc(card->qdio.no_out_queues,
- sizeof(struct qeth_qdio_out_q *),
- GFP_KERNEL);
- if (!card->qdio.out_qs)
- goto out_freepool;
for (i = 0; i < card->qdio.no_out_queues; ++i) {
card->qdio.out_qs[i] = qeth_alloc_qdio_out_buf();
if (!card->qdio.out_qs[i])
@@ -2468,11 +2462,10 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card)
card->qdio.out_qs[i]->bufs[j] = NULL;
}
out_freeoutq:
- while (i > 0)
+ while (i > 0) {
qeth_free_output_queue(card->qdio.out_qs[--i]);
- kfree(card->qdio.out_qs);
- card->qdio.out_qs = NULL;
-out_freepool:
+ card->qdio.out_qs[i] = NULL;
+ }
qeth_free_buffer_pool(card);
out_freeinq:
qeth_free_qdio_queue(card->qdio.in_q);
@@ -2501,11 +2494,9 @@ static void qeth_free_qdio_buffers(struct qeth_card *card)
/* inbound buffer pool */
qeth_free_buffer_pool(card);
/* free outbound qdio_qs */
- if (card->qdio.out_qs) {
- for (i = 0; i < card->qdio.no_out_queues; i++)
- qeth_free_output_queue(card->qdio.out_qs[i]);
- kfree(card->qdio.out_qs);
- card->qdio.out_qs = NULL;
+ for (i = 0; i < card->qdio.no_out_queues; i++) {
+ qeth_free_output_queue(card->qdio.out_qs[i]);
+ card->qdio.out_qs[i] = NULL;
}
}
--
2.16.4
^ permalink raw reply related
* Re: [net-next 5/5] net: sock: remove the definition of SOCK_DEBUG()
From: Eric Dumazet @ 2019-02-15 18:22 UTC (permalink / raw)
To: Cong Wang; +Cc: Yafang Shao, David Miller, Daniel Borkmann, netdev, shaoyafang
In-Reply-To: <CAM_iQpUR74cYzHL85fgdK72FGvk99zR6Kh46YH-kRnYb4icUsg@mail.gmail.com>
On Fri, Feb 15, 2019 at 10:13 AM Cong Wang <xiyou.wangcong@gmail.com> wrote:
>
> On Fri, Feb 15, 2019 at 8:26 AM Eric Dumazet <edumazet@google.com> wrote:
> >
> > On Fri, Feb 15, 2019 at 6:50 AM Yafang Shao <laoar.shao@gmail.com> wrote:
> > >
> > > As SOCK_DEBUG() isn't used any more, we can get ride of it now.
> > >
> >
> > No, we are still using this infrastructure from time to time.
> >
> > I told you I agreed to remove the current (obsolete) TCP call sites,
> > I never suggested to remove SOCK_DEBUG() completely.
>
> Since when do we upstream care about any out-of-tree users?
>
> You can always carry a patch to keep it downstream if you want,
> no one can stop you doing it.
Somehow the patch series seems to present things in this way :
Eric Dumazet suggested to remove completely the SOCK_DEBUG() interface.
I did not.
I sometimes am lazy and use SOCK_DEBUG() myself, so I would like we keep it.
I know that others are doing the same thing, so I do not feel any shame.
Feel free to ignore my feedback.
^ permalink raw reply
* [PATCH net-next 3/7] s390/qeth: reduce ethtool statistics
From: Julian Wiedmann @ 2019-02-15 18:22 UTC (permalink / raw)
To: David Miller
Cc: netdev, linux-s390, Martin Schwidefsky, Heiko Carstens,
Stefan Raspl, Ursula Braun, Julian Wiedmann
In-Reply-To: <20190215182231.90709-1-jwi@linux.ibm.com>
Counting the number of function calls and the time spent in functions
is best left to proper tracing facilities.
Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
---
drivers/s390/net/qeth_core.h | 29 -------------
drivers/s390/net/qeth_core_main.c | 85 ++++-----------------------------------
drivers/s390/net/qeth_l2_main.c | 8 ----
drivers/s390/net/qeth_l3_main.c | 8 ----
4 files changed, 7 insertions(+), 123 deletions(-)
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 2ea5d7c0b94c..9928728649eb 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -126,30 +126,6 @@ struct qeth_perf_stats {
unsigned int sc_dp_p;
unsigned int sc_p_dp;
- /* qdio_cq_handler: number of times called, time spent in */
- __u64 cq_start_time;
- unsigned int cq_cnt;
- unsigned int cq_time;
- /* qdio_input_handler: number of times called, time spent in */
- __u64 inbound_start_time;
- unsigned int inbound_cnt;
- unsigned int inbound_time;
- /* qeth_send_packet: number of times called, time spent in */
- __u64 outbound_start_time;
- unsigned int outbound_cnt;
- unsigned int outbound_time;
- /* qdio_output_handler: number of times called, time spent in */
- __u64 outbound_handler_start_time;
- unsigned int outbound_handler_cnt;
- unsigned int outbound_handler_time;
- /* number of calls to and time spent in do_QDIO for inbound queue */
- __u64 inbound_do_qdio_start_time;
- unsigned int inbound_do_qdio_cnt;
- unsigned int inbound_do_qdio_time;
- /* number of calls to and time spent in do_QDIO for outbound queues */
- __u64 outbound_do_qdio_start_time;
- unsigned int outbound_do_qdio_cnt;
- unsigned int outbound_do_qdio_time;
unsigned int large_send_bytes;
unsigned int large_send_cnt;
unsigned int sg_skbs_sent;
@@ -859,11 +835,6 @@ static inline int qeth_get_elements_for_range(addr_t start, addr_t end)
return PFN_UP(end) - PFN_DOWN(start);
}
-static inline int qeth_get_micros(void)
-{
- return (int) (get_tod_clock() >> 12);
-}
-
static inline int qeth_get_ip_version(struct sk_buff *skb)
{
struct vlan_ethhdr *veth = vlan_eth_hdr(skb);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index d01a4aded4cc..e3127e232fb2 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -3244,17 +3244,8 @@ static void qeth_queue_input_buffer(struct qeth_card *card, int index)
* 'index') un-requeued -> this buffer is the first buffer that
* will be requeued the next time
*/
- if (card->options.performance_stats) {
- card->perf_stats.inbound_do_qdio_cnt++;
- card->perf_stats.inbound_do_qdio_start_time =
- qeth_get_micros();
- }
rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0,
queue->next_buf_to_init, count);
- if (card->options.performance_stats)
- card->perf_stats.inbound_do_qdio_time +=
- qeth_get_micros() -
- card->perf_stats.inbound_do_qdio_start_time;
if (rc) {
QETH_CARD_TEXT(card, 2, "qinberr");
}
@@ -3407,22 +3398,12 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
}
netif_trans_update(queue->card->dev);
- if (queue->card->options.performance_stats) {
- queue->card->perf_stats.outbound_do_qdio_cnt++;
- queue->card->perf_stats.outbound_do_qdio_start_time =
- qeth_get_micros();
- }
qdio_flags = QDIO_FLAG_SYNC_OUTPUT;
if (atomic_read(&queue->set_pci_flags_count))
qdio_flags |= QDIO_FLAG_PCI_OUT;
atomic_add(count, &queue->used_buffers);
-
rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags,
queue->queue_no, index, count);
- if (queue->card->options.performance_stats)
- queue->card->perf_stats.outbound_do_qdio_time +=
- qeth_get_micros() -
- queue->card->perf_stats.outbound_do_qdio_start_time;
if (rc) {
queue->card->stats.tx_errors += count;
/* ignore temporary SIGA errors without busy condition */
@@ -3529,7 +3510,7 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err,
int rc;
if (!qeth_is_cq(card, queue))
- goto out;
+ return;
QETH_CARD_TEXT_(card, 5, "qcqhe%d", first_element);
QETH_CARD_TEXT_(card, 5, "qcqhc%d", count);
@@ -3538,12 +3519,7 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err,
if (qdio_err) {
netif_stop_queue(card->dev);
qeth_schedule_recovery(card);
- goto out;
- }
-
- if (card->options.performance_stats) {
- card->perf_stats.cq_cnt++;
- card->perf_stats.cq_start_time = qeth_get_micros();
+ return;
}
for (i = first_element; i < first_element + count; ++i) {
@@ -3571,14 +3547,6 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err,
}
card->qdio.c_q->next_buf_to_init = (card->qdio.c_q->next_buf_to_init
+ count) % QDIO_MAX_BUFFERS_PER_Q;
-
- if (card->options.performance_stats) {
- int delta_t = qeth_get_micros();
- delta_t -= card->perf_stats.cq_start_time;
- card->perf_stats.cq_time += delta_t;
- }
-out:
- return;
}
static void qeth_qdio_input_handler(struct ccw_device *ccwdev,
@@ -3614,11 +3582,7 @@ static void qeth_qdio_output_handler(struct ccw_device *ccwdev,
qeth_schedule_recovery(card);
return;
}
- if (card->options.performance_stats) {
- card->perf_stats.outbound_handler_cnt++;
- card->perf_stats.outbound_handler_start_time =
- qeth_get_micros();
- }
+
for (i = first_element; i < (first_element + count); ++i) {
int bidx = i % QDIO_MAX_BUFFERS_PER_Q;
buffer = queue->bufs[bidx];
@@ -3664,9 +3628,6 @@ static void qeth_qdio_output_handler(struct ccw_device *ccwdev,
qeth_check_outbound_queue(queue);
netif_wake_queue(queue->card->dev);
- if (card->options.performance_stats)
- card->perf_stats.outbound_handler_time += qeth_get_micros() -
- card->perf_stats.outbound_handler_start_time;
}
/* We cannot use outbound queue 3 for unicast packets on HiperSockets */
@@ -5319,11 +5280,6 @@ int qeth_poll(struct napi_struct *napi, int budget)
int done;
int new_budget = budget;
- if (card->options.performance_stats) {
- card->perf_stats.inbound_cnt++;
- card->perf_stats.inbound_start_time = qeth_get_micros();
- }
-
while (1) {
if (!card->rx.b_count) {
card->rx.qdio_err = 0;
@@ -5381,9 +5337,6 @@ int qeth_poll(struct napi_struct *napi, int budget)
if (qdio_start_irq(card->data.ccwdev, 0))
napi_schedule(&card->napi);
out:
- if (card->options.performance_stats)
- card->perf_stats.inbound_time += qeth_get_micros() -
- card->perf_stats.inbound_start_time;
return work_done;
}
EXPORT_SYMBOL_GPL(qeth_poll);
@@ -5984,21 +5937,9 @@ static struct {
/* 20 */{"queue 1 buffer usage"},
{"queue 2 buffer usage"},
{"queue 3 buffer usage"},
- {"rx poll time"},
- {"rx poll count"},
- {"rx do_QDIO time"},
- {"rx do_QDIO count"},
- {"tx handler time"},
- {"tx handler count"},
- {"tx time"},
-/* 30 */{"tx count"},
- {"tx do_QDIO time"},
- {"tx do_QDIO count"},
{"tx csum"},
{"tx lin"},
{"tx linfail"},
- {"cq handler count"},
- {"cq handler time"},
{"rx csum"}
};
@@ -6046,22 +5987,10 @@ void qeth_core_get_ethtool_stats(struct net_device *dev,
atomic_read(&card->qdio.out_qs[2]->used_buffers) : 0;
data[22] = (card->qdio.no_out_queues > 3) ?
atomic_read(&card->qdio.out_qs[3]->used_buffers) : 0;
- data[23] = card->perf_stats.inbound_time;
- data[24] = card->perf_stats.inbound_cnt;
- data[25] = card->perf_stats.inbound_do_qdio_time;
- data[26] = card->perf_stats.inbound_do_qdio_cnt;
- data[27] = card->perf_stats.outbound_handler_time;
- data[28] = card->perf_stats.outbound_handler_cnt;
- data[29] = card->perf_stats.outbound_time;
- data[30] = card->perf_stats.outbound_cnt;
- data[31] = card->perf_stats.outbound_do_qdio_time;
- data[32] = card->perf_stats.outbound_do_qdio_cnt;
- data[33] = card->perf_stats.tx_csum;
- data[34] = card->perf_stats.tx_lin;
- data[35] = card->perf_stats.tx_linfail;
- data[36] = card->perf_stats.cq_cnt;
- data[37] = card->perf_stats.cq_time;
- data[38] = card->perf_stats.rx_csum;
+ data[23] = card->perf_stats.tx_csum;
+ data[24] = card->perf_stats.tx_lin;
+ data[25] = card->perf_stats.tx_linfail;
+ data[26] = card->perf_stats.rx_csum;
}
EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats);
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index c566139da43d..8931dd6e2caa 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -632,11 +632,6 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
}
queue = qeth_get_tx_queue(card, skb, ipv, cast_type);
-
- if (card->options.performance_stats) {
- card->perf_stats.outbound_cnt++;
- card->perf_stats.outbound_start_time = qeth_get_micros();
- }
netif_stop_queue(dev);
if (IS_OSN(card))
@@ -648,9 +643,6 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
if (!rc) {
card->stats.tx_packets++;
card->stats.tx_bytes += tx_bytes;
- if (card->options.performance_stats)
- card->perf_stats.outbound_time += qeth_get_micros() -
- card->perf_stats.outbound_start_time;
netif_wake_queue(dev);
return NETDEV_TX_OK;
} else if (rc == -EBUSY) {
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 8eb24c7f2750..012a290f1f4b 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -2092,11 +2092,6 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
goto tx_drop;
queue = qeth_get_tx_queue(card, skb, ipv, cast_type);
-
- if (card->options.performance_stats) {
- card->perf_stats.outbound_cnt++;
- card->perf_stats.outbound_start_time = qeth_get_micros();
- }
netif_stop_queue(dev);
if (ipv == 4 || IS_IQD(card))
@@ -2108,9 +2103,6 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
if (!rc) {
card->stats.tx_packets++;
card->stats.tx_bytes += tx_bytes;
- if (card->options.performance_stats)
- card->perf_stats.outbound_time += qeth_get_micros() -
- card->perf_stats.outbound_start_time;
netif_wake_queue(dev);
return NETDEV_TX_OK;
} else if (rc == -EBUSY) {
--
2.16.4
^ permalink raw reply related
* [PATCH net-next 4/7] s390/qeth: move ethtool code into its own file
From: Julian Wiedmann @ 2019-02-15 18:22 UTC (permalink / raw)
To: David Miller
Cc: netdev, linux-s390, Martin Schwidefsky, Heiko Carstens,
Stefan Raspl, Ursula Braun, Julian Wiedmann
In-Reply-To: <20190215182231.90709-1-jwi@linux.ibm.com>
Most of this is self-contained code.
Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
---
drivers/s390/net/Makefile | 2 +-
drivers/s390/net/qeth_core.h | 12 +-
drivers/s390/net/qeth_core_main.c | 317 +-----------------------------------
drivers/s390/net/qeth_ethtool.c | 333 ++++++++++++++++++++++++++++++++++++++
drivers/s390/net/qeth_l2_main.c | 23 +--
drivers/s390/net/qeth_l3_main.c | 10 --
6 files changed, 346 insertions(+), 351 deletions(-)
create mode 100644 drivers/s390/net/qeth_ethtool.c
diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile
index f2d6bbe57a6f..bc55ec316adb 100644
--- a/drivers/s390/net/Makefile
+++ b/drivers/s390/net/Makefile
@@ -9,7 +9,7 @@ obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
obj-$(CONFIG_SMSGIUCV_EVENT) += smsgiucv_app.o
obj-$(CONFIG_LCS) += lcs.o
-qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o
+qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o qeth_ethtool.o
obj-$(CONFIG_QETH) += qeth.o
qeth_l2-y += qeth_l2_main.o qeth_l2_sys.o
obj-$(CONFIG_QETH_L2) += qeth_l2.o
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 9928728649eb..5e08f112db13 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -18,7 +18,6 @@
#include <linux/in6.h>
#include <linux/bitops.h>
#include <linux/seq_file.h>
-#include <linux/ethtool.h>
#include <linux/hashtable.h>
#include <linux/ip.h>
#include <linux/refcount.h>
@@ -922,6 +921,8 @@ static inline struct qeth_qdio_out_q *qeth_get_tx_queue(struct qeth_card *card,
extern struct qeth_discipline qeth_l2_discipline;
extern struct qeth_discipline qeth_l3_discipline;
+extern const struct ethtool_ops qeth_ethtool_ops;
+extern const struct ethtool_ops qeth_osn_ethtool_ops;
extern const struct attribute_group *qeth_generic_attr_groups[];
extern const struct attribute_group *qeth_osn_attr_groups[];
extern const struct attribute_group qeth_device_attr_group;
@@ -976,20 +977,15 @@ void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *);
int qeth_query_switch_attributes(struct qeth_card *card,
struct qeth_switch_info *sw_info);
+int qeth_query_card_info(struct qeth_card *card,
+ struct carrier_info *carrier_info);
unsigned int qeth_count_elements(struct sk_buff *skb, unsigned int data_offset);
int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
struct sk_buff *skb, struct qeth_hdr *hdr,
unsigned int offset, unsigned int hd_len,
int elements_needed);
int qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-int qeth_core_get_sset_count(struct net_device *, int);
-void qeth_core_get_ethtool_stats(struct net_device *,
- struct ethtool_stats *, u64 *);
-void qeth_core_get_strings(struct net_device *, u32, u8 *);
-void qeth_core_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);
void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...);
-int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev,
- struct ethtool_link_ksettings *cmd);
int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback);
int qeth_configure_cq(struct qeth_card *, enum qeth_cq);
int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index e3127e232fb2..96e4876a4daa 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -4698,8 +4698,8 @@ static int qeth_query_card_info_cb(struct qeth_card *card,
return 0;
}
-static int qeth_query_card_info(struct qeth_card *card,
- struct carrier_info *carrier_info)
+int qeth_query_card_info(struct qeth_card *card,
+ struct carrier_info *carrier_info)
{
struct qeth_cmd_buffer *iob;
@@ -5623,7 +5623,10 @@ static struct net_device *qeth_alloc_netdev(struct qeth_card *card)
SET_NETDEV_DEV(dev, &card->gdev->dev);
netif_carrier_off(dev);
- if (!IS_OSN(card)) {
+ if (IS_OSN(card)) {
+ dev->ethtool_ops = &qeth_osn_ethtool_ops;
+ } else {
+ dev->ethtool_ops = &qeth_ethtool_ops;
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
dev->hw_features |= NETIF_F_SG;
dev->vlan_features |= NETIF_F_SG;
@@ -5911,314 +5914,6 @@ int qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
EXPORT_SYMBOL_GPL(qeth_do_ioctl);
-static struct {
- const char str[ETH_GSTRING_LEN];
-} qeth_ethtool_stats_keys[] = {
-/* 0 */{"rx skbs"},
- {"rx buffers"},
- {"tx skbs"},
- {"tx buffers"},
- {"tx skbs no packing"},
- {"tx buffers no packing"},
- {"tx skbs packing"},
- {"tx buffers packing"},
- {"tx sg skbs"},
- {"tx buffer elements"},
-/* 10 */{"rx sg skbs"},
- {"rx sg frags"},
- {"rx sg page allocs"},
- {"tx large kbytes"},
- {"tx large count"},
- {"tx pk state ch n->p"},
- {"tx pk state ch p->n"},
- {"tx pk watermark low"},
- {"tx pk watermark high"},
- {"queue 0 buffer usage"},
-/* 20 */{"queue 1 buffer usage"},
- {"queue 2 buffer usage"},
- {"queue 3 buffer usage"},
- {"tx csum"},
- {"tx lin"},
- {"tx linfail"},
- {"rx csum"}
-};
-
-int qeth_core_get_sset_count(struct net_device *dev, int stringset)
-{
- switch (stringset) {
- case ETH_SS_STATS:
- return (sizeof(qeth_ethtool_stats_keys) / ETH_GSTRING_LEN);
- default:
- return -EINVAL;
- }
-}
-EXPORT_SYMBOL_GPL(qeth_core_get_sset_count);
-
-void qeth_core_get_ethtool_stats(struct net_device *dev,
- struct ethtool_stats *stats, u64 *data)
-{
- struct qeth_card *card = dev->ml_priv;
- data[0] = card->stats.rx_packets -
- card->perf_stats.initial_rx_packets;
- data[1] = card->perf_stats.bufs_rec;
- data[2] = card->stats.tx_packets -
- card->perf_stats.initial_tx_packets;
- data[3] = card->perf_stats.bufs_sent;
- data[4] = card->stats.tx_packets - card->perf_stats.initial_tx_packets
- - card->perf_stats.skbs_sent_pack;
- data[5] = card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack;
- data[6] = card->perf_stats.skbs_sent_pack;
- data[7] = card->perf_stats.bufs_sent_pack;
- data[8] = card->perf_stats.sg_skbs_sent;
- data[9] = card->perf_stats.buf_elements_sent;
- data[10] = card->perf_stats.sg_skbs_rx;
- data[11] = card->perf_stats.sg_frags_rx;
- data[12] = card->perf_stats.sg_alloc_page_rx;
- data[13] = (card->perf_stats.large_send_bytes >> 10);
- data[14] = card->perf_stats.large_send_cnt;
- data[15] = card->perf_stats.sc_dp_p;
- data[16] = card->perf_stats.sc_p_dp;
- data[17] = QETH_LOW_WATERMARK_PACK;
- data[18] = QETH_HIGH_WATERMARK_PACK;
- data[19] = atomic_read(&card->qdio.out_qs[0]->used_buffers);
- data[20] = (card->qdio.no_out_queues > 1) ?
- atomic_read(&card->qdio.out_qs[1]->used_buffers) : 0;
- data[21] = (card->qdio.no_out_queues > 2) ?
- atomic_read(&card->qdio.out_qs[2]->used_buffers) : 0;
- data[22] = (card->qdio.no_out_queues > 3) ?
- atomic_read(&card->qdio.out_qs[3]->used_buffers) : 0;
- data[23] = card->perf_stats.tx_csum;
- data[24] = card->perf_stats.tx_lin;
- data[25] = card->perf_stats.tx_linfail;
- data[26] = card->perf_stats.rx_csum;
-}
-EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats);
-
-void qeth_core_get_strings(struct net_device *dev, u32 stringset, u8 *data)
-{
- switch (stringset) {
- case ETH_SS_STATS:
- memcpy(data, &qeth_ethtool_stats_keys,
- sizeof(qeth_ethtool_stats_keys));
- break;
- default:
- WARN_ON(1);
- break;
- }
-}
-EXPORT_SYMBOL_GPL(qeth_core_get_strings);
-
-void qeth_core_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- struct qeth_card *card = dev->ml_priv;
-
- strlcpy(info->driver, IS_LAYER2(card) ? "qeth_l2" : "qeth_l3",
- sizeof(info->driver));
- strlcpy(info->version, "1.0", sizeof(info->version));
- strlcpy(info->fw_version, card->info.mcl_level,
- sizeof(info->fw_version));
- snprintf(info->bus_info, sizeof(info->bus_info), "%s/%s/%s",
- CARD_RDEV_ID(card), CARD_WDEV_ID(card), CARD_DDEV_ID(card));
-}
-EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo);
-
-/* Helper function to fill 'advertising' and 'supported' which are the same. */
-/* Autoneg and full-duplex are supported and advertised unconditionally. */
-/* Always advertise and support all speeds up to specified, and only one */
-/* specified port type. */
-static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd,
- int maxspeed, int porttype)
-{
- ethtool_link_ksettings_zero_link_mode(cmd, supported);
- ethtool_link_ksettings_zero_link_mode(cmd, advertising);
- ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising);
-
- ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
- ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
-
- switch (porttype) {
- case PORT_TP:
- ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
- ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
- break;
- case PORT_FIBRE:
- ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
- ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
- break;
- default:
- ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
- ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
- WARN_ON_ONCE(1);
- }
-
- /* partially does fall through, to also select lower speeds */
- switch (maxspeed) {
- case SPEED_25000:
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 25000baseSR_Full);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 25000baseSR_Full);
- break;
- case SPEED_10000:
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 10000baseT_Full);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 10000baseT_Full);
- case SPEED_1000:
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 1000baseT_Full);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 1000baseT_Full);
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 1000baseT_Half);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 1000baseT_Half);
- case SPEED_100:
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 100baseT_Full);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 100baseT_Full);
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 100baseT_Half);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 100baseT_Half);
- case SPEED_10:
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 10baseT_Full);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 10baseT_Full);
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 10baseT_Half);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 10baseT_Half);
- /* end fallthrough */
- break;
- default:
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 10baseT_Full);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 10baseT_Full);
- ethtool_link_ksettings_add_link_mode(cmd, supported,
- 10baseT_Half);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- 10baseT_Half);
- WARN_ON_ONCE(1);
- }
-}
-
-int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev,
- struct ethtool_link_ksettings *cmd)
-{
- struct qeth_card *card = netdev->ml_priv;
- enum qeth_link_types link_type;
- struct carrier_info carrier_info;
- int rc;
-
- if ((card->info.type == QETH_CARD_TYPE_IQD) || (card->info.guestlan))
- link_type = QETH_LINK_TYPE_10GBIT_ETH;
- else
- link_type = card->info.link_type;
-
- cmd->base.duplex = DUPLEX_FULL;
- cmd->base.autoneg = AUTONEG_ENABLE;
- cmd->base.phy_address = 0;
- cmd->base.mdio_support = 0;
- cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID;
- cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID;
-
- switch (link_type) {
- case QETH_LINK_TYPE_FAST_ETH:
- case QETH_LINK_TYPE_LANE_ETH100:
- cmd->base.speed = SPEED_100;
- cmd->base.port = PORT_TP;
- break;
- case QETH_LINK_TYPE_GBIT_ETH:
- case QETH_LINK_TYPE_LANE_ETH1000:
- cmd->base.speed = SPEED_1000;
- cmd->base.port = PORT_FIBRE;
- break;
- case QETH_LINK_TYPE_10GBIT_ETH:
- cmd->base.speed = SPEED_10000;
- cmd->base.port = PORT_FIBRE;
- break;
- case QETH_LINK_TYPE_25GBIT_ETH:
- cmd->base.speed = SPEED_25000;
- cmd->base.port = PORT_FIBRE;
- break;
- default:
- cmd->base.speed = SPEED_10;
- cmd->base.port = PORT_TP;
- }
- qeth_set_cmd_adv_sup(cmd, cmd->base.speed, cmd->base.port);
-
- /* Check if we can obtain more accurate information. */
- /* If QUERY_CARD_INFO command is not supported or fails, */
- /* just return the heuristics that was filled above. */
- rc = qeth_query_card_info(card, &carrier_info);
- if (rc == -EOPNOTSUPP) /* for old hardware, return heuristic */
- return 0;
- if (rc) /* report error from the hardware operation */
- return rc;
- /* on success, fill in the information got from the hardware */
-
- netdev_dbg(netdev,
- "card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n",
- carrier_info.card_type,
- carrier_info.port_mode,
- carrier_info.port_speed);
-
- /* Update attributes for which we've obtained more authoritative */
- /* information, leave the rest the way they where filled above. */
- switch (carrier_info.card_type) {
- case CARD_INFO_TYPE_1G_COPPER_A:
- case CARD_INFO_TYPE_1G_COPPER_B:
- cmd->base.port = PORT_TP;
- qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port);
- break;
- case CARD_INFO_TYPE_1G_FIBRE_A:
- case CARD_INFO_TYPE_1G_FIBRE_B:
- cmd->base.port = PORT_FIBRE;
- qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port);
- break;
- case CARD_INFO_TYPE_10G_FIBRE_A:
- case CARD_INFO_TYPE_10G_FIBRE_B:
- cmd->base.port = PORT_FIBRE;
- qeth_set_cmd_adv_sup(cmd, SPEED_10000, cmd->base.port);
- break;
- }
-
- switch (carrier_info.port_mode) {
- case CARD_INFO_PORTM_FULLDUPLEX:
- cmd->base.duplex = DUPLEX_FULL;
- break;
- case CARD_INFO_PORTM_HALFDUPLEX:
- cmd->base.duplex = DUPLEX_HALF;
- break;
- }
-
- switch (carrier_info.port_speed) {
- case CARD_INFO_PORTS_10M:
- cmd->base.speed = SPEED_10;
- break;
- case CARD_INFO_PORTS_100M:
- cmd->base.speed = SPEED_100;
- break;
- case CARD_INFO_PORTS_1G:
- cmd->base.speed = SPEED_1000;
- break;
- case CARD_INFO_PORTS_10G:
- cmd->base.speed = SPEED_10000;
- break;
- case CARD_INFO_PORTS_25G:
- cmd->base.speed = SPEED_25000;
- break;
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(qeth_core_ethtool_get_link_ksettings);
-
static int qeth_start_csum_cb(struct qeth_card *card, struct qeth_reply *reply,
unsigned long data)
{
diff --git a/drivers/s390/net/qeth_ethtool.c b/drivers/s390/net/qeth_ethtool.c
new file mode 100644
index 000000000000..a275f31150b2
--- /dev/null
+++ b/drivers/s390/net/qeth_ethtool.c
@@ -0,0 +1,333 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright IBM Corp. 2018
+ */
+
+#define KMSG_COMPONENT "qeth"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#include <linux/ethtool.h>
+#include "qeth_core.h"
+
+static struct {
+ const char str[ETH_GSTRING_LEN];
+} qeth_ethtool_stats_keys[] = {
+/* 0 */{"rx skbs"},
+ {"rx buffers"},
+ {"tx skbs"},
+ {"tx buffers"},
+ {"tx skbs no packing"},
+ {"tx buffers no packing"},
+ {"tx skbs packing"},
+ {"tx buffers packing"},
+ {"tx sg skbs"},
+ {"tx buffer elements"},
+/* 10 */{"rx sg skbs"},
+ {"rx sg frags"},
+ {"rx sg page allocs"},
+ {"tx large kbytes"},
+ {"tx large count"},
+ {"tx pk state ch n->p"},
+ {"tx pk state ch p->n"},
+ {"tx pk watermark low"},
+ {"tx pk watermark high"},
+ {"queue 0 buffer usage"},
+/* 20 */{"queue 1 buffer usage"},
+ {"queue 2 buffer usage"},
+ {"queue 3 buffer usage"},
+ {"tx csum"},
+ {"tx lin"},
+ {"tx linfail"},
+ {"rx csum"}
+};
+
+static int qeth_get_sset_count(struct net_device *dev, int stringset)
+{
+ switch (stringset) {
+ case ETH_SS_STATS:
+ return (sizeof(qeth_ethtool_stats_keys) / ETH_GSTRING_LEN);
+ default:
+ return -EINVAL;
+ }
+}
+
+static void qeth_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct qeth_card *card = dev->ml_priv;
+
+ data[0] = card->stats.rx_packets -
+ card->perf_stats.initial_rx_packets;
+ data[1] = card->perf_stats.bufs_rec;
+ data[2] = card->stats.tx_packets -
+ card->perf_stats.initial_tx_packets;
+ data[3] = card->perf_stats.bufs_sent;
+ data[4] = card->stats.tx_packets - card->perf_stats.initial_tx_packets
+ - card->perf_stats.skbs_sent_pack;
+ data[5] = card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack;
+ data[6] = card->perf_stats.skbs_sent_pack;
+ data[7] = card->perf_stats.bufs_sent_pack;
+ data[8] = card->perf_stats.sg_skbs_sent;
+ data[9] = card->perf_stats.buf_elements_sent;
+ data[10] = card->perf_stats.sg_skbs_rx;
+ data[11] = card->perf_stats.sg_frags_rx;
+ data[12] = card->perf_stats.sg_alloc_page_rx;
+ data[13] = (card->perf_stats.large_send_bytes >> 10);
+ data[14] = card->perf_stats.large_send_cnt;
+ data[15] = card->perf_stats.sc_dp_p;
+ data[16] = card->perf_stats.sc_p_dp;
+ data[17] = QETH_LOW_WATERMARK_PACK;
+ data[18] = QETH_HIGH_WATERMARK_PACK;
+ data[19] = atomic_read(&card->qdio.out_qs[0]->used_buffers);
+ data[20] = (card->qdio.no_out_queues > 1) ?
+ atomic_read(&card->qdio.out_qs[1]->used_buffers) : 0;
+ data[21] = (card->qdio.no_out_queues > 2) ?
+ atomic_read(&card->qdio.out_qs[2]->used_buffers) : 0;
+ data[22] = (card->qdio.no_out_queues > 3) ?
+ atomic_read(&card->qdio.out_qs[3]->used_buffers) : 0;
+ data[23] = card->perf_stats.tx_csum;
+ data[24] = card->perf_stats.tx_lin;
+ data[25] = card->perf_stats.tx_linfail;
+ data[26] = card->perf_stats.rx_csum;
+}
+
+static void qeth_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+ switch (stringset) {
+ case ETH_SS_STATS:
+ memcpy(data, &qeth_ethtool_stats_keys,
+ sizeof(qeth_ethtool_stats_keys));
+ break;
+ default:
+ WARN_ON(1);
+ break;
+ }
+}
+
+static void qeth_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct qeth_card *card = dev->ml_priv;
+
+ strlcpy(info->driver, IS_LAYER2(card) ? "qeth_l2" : "qeth_l3",
+ sizeof(info->driver));
+ strlcpy(info->version, "1.0", sizeof(info->version));
+ strlcpy(info->fw_version, card->info.mcl_level,
+ sizeof(info->fw_version));
+ snprintf(info->bus_info, sizeof(info->bus_info), "%s/%s/%s",
+ CARD_RDEV_ID(card), CARD_WDEV_ID(card), CARD_DDEV_ID(card));
+}
+
+/* Helper function to fill 'advertising' and 'supported' which are the same. */
+/* Autoneg and full-duplex are supported and advertised unconditionally. */
+/* Always advertise and support all speeds up to specified, and only one */
+/* specified port type. */
+static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd,
+ int maxspeed, int porttype)
+{
+ ethtool_link_ksettings_zero_link_mode(cmd, supported);
+ ethtool_link_ksettings_zero_link_mode(cmd, advertising);
+ ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising);
+
+ ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
+
+ switch (porttype) {
+ case PORT_TP:
+ ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
+ break;
+ case PORT_FIBRE:
+ ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
+ break;
+ default:
+ ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
+ WARN_ON_ONCE(1);
+ }
+
+ /* partially does fall through, to also select lower speeds */
+ switch (maxspeed) {
+ case SPEED_25000:
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 25000baseSR_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 25000baseSR_Full);
+ break;
+ case SPEED_10000:
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 10000baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 10000baseT_Full);
+ /* fall through */
+ case SPEED_1000:
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 1000baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 1000baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 1000baseT_Half);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 1000baseT_Half);
+ /* fall through */
+ case SPEED_100:
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 100baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 100baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 100baseT_Half);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 100baseT_Half);
+ /* fall through */
+ case SPEED_10:
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 10baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 10baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 10baseT_Half);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 10baseT_Half);
+ break;
+ default:
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 10baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 10baseT_Full);
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
+ 10baseT_Half);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
+ 10baseT_Half);
+ WARN_ON_ONCE(1);
+ }
+}
+
+
+static int qeth_get_link_ksettings(struct net_device *netdev,
+ struct ethtool_link_ksettings *cmd)
+{
+ struct qeth_card *card = netdev->ml_priv;
+ enum qeth_link_types link_type;
+ struct carrier_info carrier_info;
+ int rc;
+
+ if (IS_IQD(card) || IS_VM_NIC(card))
+ link_type = QETH_LINK_TYPE_10GBIT_ETH;
+ else
+ link_type = card->info.link_type;
+
+ cmd->base.duplex = DUPLEX_FULL;
+ cmd->base.autoneg = AUTONEG_ENABLE;
+ cmd->base.phy_address = 0;
+ cmd->base.mdio_support = 0;
+ cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID;
+ cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID;
+
+ switch (link_type) {
+ case QETH_LINK_TYPE_FAST_ETH:
+ case QETH_LINK_TYPE_LANE_ETH100:
+ cmd->base.speed = SPEED_100;
+ cmd->base.port = PORT_TP;
+ break;
+ case QETH_LINK_TYPE_GBIT_ETH:
+ case QETH_LINK_TYPE_LANE_ETH1000:
+ cmd->base.speed = SPEED_1000;
+ cmd->base.port = PORT_FIBRE;
+ break;
+ case QETH_LINK_TYPE_10GBIT_ETH:
+ cmd->base.speed = SPEED_10000;
+ cmd->base.port = PORT_FIBRE;
+ break;
+ case QETH_LINK_TYPE_25GBIT_ETH:
+ cmd->base.speed = SPEED_25000;
+ cmd->base.port = PORT_FIBRE;
+ break;
+ default:
+ cmd->base.speed = SPEED_10;
+ cmd->base.port = PORT_TP;
+ }
+ qeth_set_cmd_adv_sup(cmd, cmd->base.speed, cmd->base.port);
+
+ /* Check if we can obtain more accurate information. */
+ /* If QUERY_CARD_INFO command is not supported or fails, */
+ /* just return the heuristics that was filled above. */
+ rc = qeth_query_card_info(card, &carrier_info);
+ if (rc == -EOPNOTSUPP) /* for old hardware, return heuristic */
+ return 0;
+ if (rc) /* report error from the hardware operation */
+ return rc;
+ /* on success, fill in the information got from the hardware */
+
+ netdev_dbg(netdev,
+ "card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n",
+ carrier_info.card_type,
+ carrier_info.port_mode,
+ carrier_info.port_speed);
+
+ /* Update attributes for which we've obtained more authoritative */
+ /* information, leave the rest the way they where filled above. */
+ switch (carrier_info.card_type) {
+ case CARD_INFO_TYPE_1G_COPPER_A:
+ case CARD_INFO_TYPE_1G_COPPER_B:
+ cmd->base.port = PORT_TP;
+ qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port);
+ break;
+ case CARD_INFO_TYPE_1G_FIBRE_A:
+ case CARD_INFO_TYPE_1G_FIBRE_B:
+ cmd->base.port = PORT_FIBRE;
+ qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port);
+ break;
+ case CARD_INFO_TYPE_10G_FIBRE_A:
+ case CARD_INFO_TYPE_10G_FIBRE_B:
+ cmd->base.port = PORT_FIBRE;
+ qeth_set_cmd_adv_sup(cmd, SPEED_10000, cmd->base.port);
+ break;
+ }
+
+ switch (carrier_info.port_mode) {
+ case CARD_INFO_PORTM_FULLDUPLEX:
+ cmd->base.duplex = DUPLEX_FULL;
+ break;
+ case CARD_INFO_PORTM_HALFDUPLEX:
+ cmd->base.duplex = DUPLEX_HALF;
+ break;
+ }
+
+ switch (carrier_info.port_speed) {
+ case CARD_INFO_PORTS_10M:
+ cmd->base.speed = SPEED_10;
+ break;
+ case CARD_INFO_PORTS_100M:
+ cmd->base.speed = SPEED_100;
+ break;
+ case CARD_INFO_PORTS_1G:
+ cmd->base.speed = SPEED_1000;
+ break;
+ case CARD_INFO_PORTS_10G:
+ cmd->base.speed = SPEED_10000;
+ break;
+ case CARD_INFO_PORTS_25G:
+ cmd->base.speed = SPEED_25000;
+ break;
+ }
+
+ return 0;
+}
+
+const struct ethtool_ops qeth_ethtool_ops = {
+ .get_link = ethtool_op_get_link,
+ .get_strings = qeth_get_strings,
+ .get_ethtool_stats = qeth_get_ethtool_stats,
+ .get_sset_count = qeth_get_sset_count,
+ .get_drvinfo = qeth_get_drvinfo,
+ .get_link_ksettings = qeth_get_link_ksettings,
+};
+
+const struct ethtool_ops qeth_osn_ethtool_ops = {
+ .get_strings = qeth_get_strings,
+ .get_ethtool_stats = qeth_get_ethtool_stats,
+ .get_sset_count = qeth_get_sset_count,
+ .get_drvinfo = qeth_get_drvinfo,
+};
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 8931dd6e2caa..dbcba77fd94c 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -696,22 +696,6 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
unregister_netdev(card->dev);
}
-static const struct ethtool_ops qeth_l2_ethtool_ops = {
- .get_link = ethtool_op_get_link,
- .get_strings = qeth_core_get_strings,
- .get_ethtool_stats = qeth_core_get_ethtool_stats,
- .get_sset_count = qeth_core_get_sset_count,
- .get_drvinfo = qeth_core_get_drvinfo,
- .get_link_ksettings = qeth_core_ethtool_get_link_ksettings,
-};
-
-static const struct ethtool_ops qeth_l2_osn_ops = {
- .get_strings = qeth_core_get_strings,
- .get_ethtool_stats = qeth_core_get_ethtool_stats,
- .get_sset_count = qeth_core_get_sset_count,
- .get_drvinfo = qeth_core_get_drvinfo,
-};
-
static const struct net_device_ops qeth_l2_netdev_ops = {
.ndo_open = qeth_open,
.ndo_stop = qeth_stop,
@@ -735,13 +719,10 @@ static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok)
card->dev->priv_flags |= IFF_UNICAST_FLT;
card->dev->netdev_ops = &qeth_l2_netdev_ops;
- if (card->info.type == QETH_CARD_TYPE_OSN) {
- card->dev->ethtool_ops = &qeth_l2_osn_ops;
+ if (IS_OSN(card))
card->dev->flags |= IFF_NOARP;
- } else {
- card->dev->ethtool_ops = &qeth_l2_ethtool_ops;
+ else
card->dev->needed_headroom = sizeof(struct qeth_hdr);
- }
if (IS_OSM(card)) {
card->dev->features |= NETIF_F_VLAN_CHALLENGED;
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 012a290f1f4b..40c7d53f5512 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -2117,15 +2117,6 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
-static const struct ethtool_ops qeth_l3_ethtool_ops = {
- .get_link = ethtool_op_get_link,
- .get_strings = qeth_core_get_strings,
- .get_ethtool_stats = qeth_core_get_ethtool_stats,
- .get_sset_count = qeth_core_get_sset_count,
- .get_drvinfo = qeth_core_get_drvinfo,
- .get_link_ksettings = qeth_core_ethtool_get_link_ksettings,
-};
-
/*
* we need NOARP for IPv4 but we want neighbor solicitation for IPv6. Setting
* NOARP on the netdevice is no option because it also turns off neighbor
@@ -2247,7 +2238,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card, bool carrier_ok)
return -ENODEV;
card->dev->needed_headroom = headroom;
- card->dev->ethtool_ops = &qeth_l3_ethtool_ops;
card->dev->features |= NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_CTAG_FILTER;
--
2.16.4
^ permalink raw reply related
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