LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* RE: powerpc/mpc85xx: Add BSC9132 QDS Support
From: Harninder Rai @ 2014-05-09  8:55 UTC (permalink / raw)
  To: Scott Wood
  Cc: linuxppc-dev@lists.ozlabs.org, prabhakar@freescale.com,
	Ruchika Gupta
In-Reply-To: <20140503003113.GB20757@home.buserror.net>



> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Saturday, May 03, 2014 6:01 AM
> To: Rai Harninder-B01044
> Cc: linuxppc-dev@lists.ozlabs.org; Gupta Ruchika-R66431
> Subject: Re: powerpc/mpc85xx: Add BSC9132 QDS Support
>=20
> On Tue, Mar 18, 2014 at 01:05:02PM +0530, harninder rai wrote:
> > +&ifc {
> > +	#address-cells =3D <2>;
> > +	#size-cells =3D <1>;
> > +	compatible =3D "fsl,ifc", "simple-bus";
> > +	/* FIXME: Test whether interrupts are split */
> > +	interrupts =3D <16 2 0 0 20 2 0 0>;
> > +};
>=20
> Have you done this test yet?
Checked with Prabhakar and he says that on 9132, the IFC interrupts are spl=
it
B4/T4 (and variants), C29x etc onwards are when the interrupts got merged i=
nto single interrupt
>=20
> -Scott

^ permalink raw reply

* Re: [PATCH v2 1/2] powerpc/pm: add api to get suspend state which is STANDBY or MEM
From: Li Yang @ 2014-05-09  9:33 UTC (permalink / raw)
  To: Scott Wood
  Cc: Zhao Chenhui, linux-pm@vger.kernel.org, Rafael J. Wysocki,
	Dongsheng Wang, 正雄 金, linuxppc-dev
In-Reply-To: <1398811632.24575.98.camel@snotra.buserror.net>

On Wed, Apr 30, 2014 at 6:47 AM, Scott Wood <scottwood@freescale.com> wrote:
> On Mon, 2014-04-28 at 13:53 +0800, Leo Li wrote:
>> On Sat, Apr 26, 2014 at 5:45 AM, Scott Wood <scottwood@freescale.com> wrote:
>> > On Thu, 2014-04-24 at 14:11 +0800, Dongsheng Wang wrote:
>> >> From: Wang Dongsheng <dongsheng.wang@freescale.com>
>> >>
>> >> Add set_pm_suspend_state & pm_suspend_state functions to set/get
>> >> suspend state. When system going to sleep or deep sleep, devices
>> >> can get the system suspend state(STANDBY/MEM) through pm_suspend_state
>> >> function and to handle different situations.
>> >>
>> >> Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>
>> >> ---
>> >> *v2*
>> >> Move pm api from fsl platform to powerpc general framework.
>> >
>> > What is powerpc-specific about this?
>>
>> Generally I agree with you.  But I had the discussion about this topic
>> a while ago with the PM maintainer.  He suggestion to go with the
>> platform way.
>>
>> https://lkml.org/lkml/2013/8/16/505
>
> If what he meant was whether you could do what this patch does, then you
> can answer him with, "No, because it got nacked as not being platform or
> arch specific."  Oh, and you're still using .valid as the hook to set
> the platform state, which is awful -- I think .begin is what you want to
> use.

I'm not saying the current patch is good for upstream.  Actually I did
say that the patch need to be updated for upstream purpose.  I only
meant that we discussed about having the mem/standby passed by generic
kernel/power interface as you suggested internally and got an negative
feedback.

>
> If we did it in powerpc code, then what would we do on ARM?  Copy the
> code?  No.

If you are saying that this shouldn't be done in arch/powerpc  Yes.
We have determined to use drivers/platform folder for the re-used code
with ARM.  Platform power management code will be moved there.

>
> Now, a more legitimate objection to putting it in generic code might be
> that "standby" and "mem" are loosely defined and the knowledge of how a
> driver should react to each is platform specific -- but your patch
> doesn't address that.  You still have the driver itself interpret what
> "standby" and "mem" mean.
>

Yup, we will address it in next batch.

- Leo

^ permalink raw reply

* Re: [PATCH] powerpc: irq work racing with timer interrupt can result in timer interrupt hang
From: Preeti U Murthy @ 2014-05-09  9:52 UTC (permalink / raw)
  To: Anton Blanchard, benh; +Cc: paulmck, paulus, linuxppc-dev
In-Reply-To: <20140509174712.55fe72d0@kryten>

Hi Anton,

On 05/09/2014 01:17 PM, Anton Blanchard wrote:
> I am seeing an issue where a CPU running perf eventually hangs.
> Traces show timer interrupts happening every 4 seconds even
> when a userspace task is running on the CPU. /proc/timer_list
> also shows pending hrtimers have not run in over an hour,
> including the scheduler.
> 
> Looking closer, decrementers_next_tb is getting set to
> 0xffffffffffffffff, and at that point we will never take
> a timer interrupt again.
> 
> In __timer_interrupt() we set decrementers_next_tb to
> 0xffffffffffffffff and rely on ->event_handler to update it:
> 
>         *next_tb = ~(u64)0;
>         if (evt->event_handler)
>                 evt->event_handler(evt);
> 
> In this case ->event_handler is hrtimer_interrupt. This will eventually
> call back through the clockevents code with the next event to be
> programmed:
> 
> static int decrementer_set_next_event(unsigned long evt,
>                                       struct clock_event_device *dev)
> {
>         /* Don't adjust the decrementer if some irq work is pending */
>         if (test_irq_work_pending())
>                 return 0;
>         __get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt;
> 
> If irq work came in between these two points, we will return
> before updating decrementers_next_tb and we never process a timer
> interrupt again.
> 
> This looks to have been introduced by 0215f7d8c53f (powerpc: Fix races
> with irq_work). Fix it by removing the early exit and relying on
> code later on in the function to force an early decrementer:
> 
>        /* We may have raced with new irq work */
>        if (test_irq_work_pending())
>                set_dec(1);
> 

There is another scenario we are missing. Its not necessary that on a
timer interrupt the event handler will call back through the
set_next_event().
If there are no pending timers then the event handler will not bother
programming the tick device and simply return.IOW, set_next_event() will
not be called. In that case we will miss taking care of pending irq work
altogether.

__timer_interrupt() -> event_handler -> next_time = KTIME_MAX ->
__timer_interrupt().

In __timer_interrupt() we do not check for pending irq anywhere after
the call to the event handler and we hence miss servicing irqs in the
above scenario.

How about you also move the check:
 if (test_irq_pending())
   set_dec(1)

in __timer_interrupt() outside the _else_ loop? This will ensure that no
matter what, before exiting timer interrupt handler we check for pending
irq work.

Regards
Preeti U Murthy

> Signed-off-by: Anton Blanchard <anton@samba.org>
> Cc: stable@vger.kernel.org # 3.14+
> ---
> 
> diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
> index 122a580..4f0b676 100644
> --- a/arch/powerpc/kernel/time.c
> +++ b/arch/powerpc/kernel/time.c
> @@ -813,9 +888,6 @@ static void __init clocksource_init(void)
>  static int decrementer_set_next_event(unsigned long evt,
>  				      struct clock_event_device *dev)
>  {
> -	/* Don't adjust the decrementer if some irq work is pending */
> -	if (test_irq_work_pending())
> -		return 0;
>  	__get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt;
>  	set_dec(evt);

How about if you move the test_irq_work_pending
Why do we have test_irq_work_pending() later in the function
decrementer_set_next_event()?
>  
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
> 

^ permalink raw reply

* Re: [PATCH] powerpc: irq work racing with timer interrupt can result in timer interrupt hang
From: Paul E. McKenney @ 2014-05-09 13:41 UTC (permalink / raw)
  To: Anton Blanchard; +Cc: paulus, linuxppc-dev
In-Reply-To: <20140509174712.55fe72d0@kryten>

On Fri, May 09, 2014 at 05:47:12PM +1000, Anton Blanchard wrote:
> I am seeing an issue where a CPU running perf eventually hangs.
> Traces show timer interrupts happening every 4 seconds even
> when a userspace task is running on the CPU.

Is this by chance every 4.2 seconds?  The reason I ask is that
Paul Clarke and I are seeing an interrupt every 4.2 seconds when
he runs NO_HZ_FULL, and are trying to get rid of it.  ;-)

						Thanx, Paul

>                                              /proc/timer_list
> also shows pending hrtimers have not run in over an hour,
> including the scheduler.
> 
> Looking closer, decrementers_next_tb is getting set to
> 0xffffffffffffffff, and at that point we will never take
> a timer interrupt again.
> 
> In __timer_interrupt() we set decrementers_next_tb to
> 0xffffffffffffffff and rely on ->event_handler to update it:
> 
>         *next_tb = ~(u64)0;
>         if (evt->event_handler)
>                 evt->event_handler(evt);
> 
> In this case ->event_handler is hrtimer_interrupt. This will eventually
> call back through the clockevents code with the next event to be
> programmed:
> 
> static int decrementer_set_next_event(unsigned long evt,
>                                       struct clock_event_device *dev)
> {
>         /* Don't adjust the decrementer if some irq work is pending */
>         if (test_irq_work_pending())
>                 return 0;
>         __get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt;
> 
> If irq work came in between these two points, we will return
> before updating decrementers_next_tb and we never process a timer
> interrupt again.
> 
> This looks to have been introduced by 0215f7d8c53f (powerpc: Fix races
> with irq_work). Fix it by removing the early exit and relying on
> code later on in the function to force an early decrementer:
> 
>        /* We may have raced with new irq work */
>        if (test_irq_work_pending())
>                set_dec(1);
> 
> Signed-off-by: Anton Blanchard <anton@samba.org>
> Cc: stable@vger.kernel.org # 3.14+
> ---
> 
> diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
> index 122a580..4f0b676 100644
> --- a/arch/powerpc/kernel/time.c
> +++ b/arch/powerpc/kernel/time.c
> @@ -813,9 +888,6 @@ static void __init clocksource_init(void)
>  static int decrementer_set_next_event(unsigned long evt,
>  				      struct clock_event_device *dev)
>  {
> -	/* Don't adjust the decrementer if some irq work is pending */
> -	if (test_irq_work_pending())
> -		return 0;
>  	__get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt;
>  	set_dec(evt);
> 
> 

^ permalink raw reply

* Re: [PATCH v2 1/2] powerpc/pm: add api to get suspend state which is STANDBY or MEM
From: Scott Wood @ 2014-05-09 17:09 UTC (permalink / raw)
  To: Li Yang
  Cc: Zhao Chenhui, linux-pm@vger.kernel.org, Rafael J. Wysocki,
	Dongsheng Wang, 正雄 金, linuxppc-dev
In-Reply-To: <CADRPPNRukfr92m4hSTar_N4iNYJ8fRPMnyOokzc9tCEDLg_BVw@mail.gmail.com>

On Fri, 2014-05-09 at 17:33 +0800, Li Yang wrote:
> On Wed, Apr 30, 2014 at 6:47 AM, Scott Wood <scottwood@freescale.com> wrote:
> > On Mon, 2014-04-28 at 13:53 +0800, Leo Li wrote:
> >> On Sat, Apr 26, 2014 at 5:45 AM, Scott Wood <scottwood@freescale.com> wrote:
> >> > On Thu, 2014-04-24 at 14:11 +0800, Dongsheng Wang wrote:
> >> >> From: Wang Dongsheng <dongsheng.wang@freescale.com>
> >> >>
> >> >> Add set_pm_suspend_state & pm_suspend_state functions to set/get
> >> >> suspend state. When system going to sleep or deep sleep, devices
> >> >> can get the system suspend state(STANDBY/MEM) through pm_suspend_state
> >> >> function and to handle different situations.
> >> >>
> >> >> Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>
> >> >> ---
> >> >> *v2*
> >> >> Move pm api from fsl platform to powerpc general framework.
> >> >
> >> > What is powerpc-specific about this?
> >>
> >> Generally I agree with you.  But I had the discussion about this topic
> >> a while ago with the PM maintainer.  He suggestion to go with the
> >> platform way.
> >>
> >> https://lkml.org/lkml/2013/8/16/505
> >
> > If what he meant was whether you could do what this patch does, then you
> > can answer him with, "No, because it got nacked as not being platform or
> > arch specific."  Oh, and you're still using .valid as the hook to set
> > the platform state, which is awful -- I think .begin is what you want to
> > use.
> 
> I'm not saying the current patch is good for upstream.  Actually I did
> say that the patch need to be updated for upstream purpose. 

I don't follow -- this thread is an upstream submission.

> > Now, a more legitimate objection to putting it in generic code might be
> > that "standby" and "mem" are loosely defined and the knowledge of how a
> > driver should react to each is platform specific -- but your patch
> > doesn't address that.  You still have the driver itself interpret what
> > "standby" and "mem" mean.
> >
> 
> Yup, we will address it in next batch.

Thanks.

-Scott

^ permalink raw reply

* Re: [PATCH 1/1] booke/watchdog: refine and clean up the codes
From: Guenter Roeck @ 2014-05-09 17:44 UTC (permalink / raw)
  To: Yuantian.Tang; +Cc: scottwood, wim, linuxppc-dev, linux-watchdog
In-Reply-To: <1399514666-2572-1-git-send-email-Yuantian.Tang@freescale.com>

On Thu, May 08, 2014 at 10:04:26AM +0800, Yuantian.Tang@freescale.com wrote:
> From: Tang Yuantian <yuantian.tang@freescale.com>
> 
> Basically, this patch does the following:
> 1. Move the codes of parsing boot parameters from setup-common.c
>    to driver. In this way, code reader can know directly that
>    there are boot parameters that can change the timeout.
> 2. Make boot parameter 'booke_wdt_period' effective.
>    currently, when driver is loaded, default timeout is always
>    being used in stead of booke_wdt_period.
> 3. Wrap up the watchdog timeout in device struct and clean up
>    unnecessary codes.
> 
> Signed-off-by: Tang Yuantian <yuantian.tang@freescale.com>
> Acked-by: Scott Wood <scottwood@freescale.com>

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

^ permalink raw reply

* Re: [PATCHv2] powerpc/85xx: Add OCA4080 board support
From: Scott Wood @ 2014-05-09 19:24 UTC (permalink / raw)
  To: Martijn de Gouw; +Cc: stef.van.os, Martijn de Gouw, linuxppc-dev
In-Reply-To: <1397584306-8706-1-git-send-email-martijn.de.gouw@prodrive-technologies.com>

On Tue, Apr 15, 2014 at 07:51:46PM +0200, Martijn de Gouw wrote:
> diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c
> index fbd871e..f3685047 100644
> --- a/arch/powerpc/platforms/85xx/corenet_generic.c
> +++ b/arch/powerpc/platforms/85xx/corenet_generic.c
> @@ -55,8 +55,6 @@ void __init corenet_gen_setup_arch(void)
>  	mpc85xx_smp_init();
>  
>  	swiotlb_detect_4g();
> -
> -	pr_info("%s board from Freescale Semiconductor\n", ppc_md.name);

Valentin's patch kept this line but removed "from Freescale
Semiconductor"; I'll leave it like that when applying.

-Scott

^ permalink raw reply

* Re: [v6,3/5] powerpc/book3e: support kgdb for kernel space
From: Scott Wood @ 2014-05-09 19:36 UTC (permalink / raw)
  To: Tiejun Chen; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <1382520685-11609-4-git-send-email-tiejun.chen@windriver.com>

On Wed, Oct 23, 2013 at 05:31:23PM +0800, Tiejun Chen wrote:
> Currently we need to skip this for supporting KGDB.
> 
> Signed-off-by: Tiejun Chen <tiejun.chen@windriver.com>
> 
> ---
> arch/powerpc/kernel/exceptions-64e.S |    4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
> index a55cf62..0b750c6 100644
> --- a/arch/powerpc/kernel/exceptions-64e.S
> +++ b/arch/powerpc/kernel/exceptions-64e.S
> @@ -597,11 +597,13 @@ kernel_dbg_exc:
>  	rfdi
>  
>  	/* Normal debug exception */
> +1:	andi.	r14,r11,MSR_PR;		/* check for userspace again */
> +#ifndef CONFIG_KGDB
>  	/* XXX We only handle coming from userspace for now since we can't
>  	 *     quite save properly an interrupted kernel state yet
>  	 */
> -1:	andi.	r14,r11,MSR_PR;		/* check for userspace again */
>  	beq	kernel_dbg_exc;		/* if from kernel mode */
> +#endif

Now that we have support for properly saving state on special level
exceptions, that should be used here.  With the above patch, what happens
if e.g. a debug exception fires during a TLB miss, and the kgdb handler
takes its own TLB miss accessing the serial port?

-Scott

^ permalink raw reply

* linux-next: add scottwood/linux.git
From: Scott Wood @ 2014-05-09 21:15 UTC (permalink / raw)
  To: Stephen Rothwell; +Cc: linux-next, linuxppc-dev
In-Reply-To: <1395709794.12479.411.camel@snotra.buserror.net>

On Mon, 2014-03-24 at 20:09 -0500, Scott Wood wrote:
> On Mon, 2014-03-24 at 10:33 +1100, Benjamin Herrenschmidt wrote:
> > On Mon, 2014-03-24 at 10:16 +1100, Benjamin Herrenschmidt wrote:
> > > On Wed, 2014-03-19 at 23:25 -0500, Scott Wood wrote:
> > > > The following changes since commit c7e64b9ce04aa2e3fad7396d92b5cb92056d16ac:
> > > > 
> > > >   powerpc/powernv Platform dump interface (2014-03-07 16:19:10 +1100)
> > > > 
> > > > are available in the git repository at:
> > > > 
> > > >   git://git.kernel.org/pub/scm/linux/kernel/git/scottwood/linux.git next
> > > > 
> > > > for you to fetch changes up to 48b16180d0d91324e5d2423c6d53d97bbe3dcc14:
> > > > 
> > > >   fsl/pci: The new pci suspend/resume implementation (2014-03-19 22:37:44 -0500)
> > > 
> > > Stephen just informed me that your tree wasn't in -next ... Kumar's
> > > still is.
> > > 
> > > Can you guys fix that up ? I somewhat rely on the FSL stuff to simmer
> > > in -next on its own.
> 
> Stephen, what's the process for adding a tree?

ping

-Scott


> 
> I suppose we should update MAINTAINERS while we're at it.
> 
> > Oh and where is my little summary to put in the merge commit ?
> > 
> > I made one up for this time around.
> 
> Oops, forgot again.  Now I've added something to the script I use to
> generate pull requests, to give me a reminder.
> 
> -Scott
> 

^ permalink raw reply

* Re: [PATCH] powerpc: irq work racing with timer interrupt can result in timer interrupt hang
From: Paul E. McKenney @ 2014-05-09 22:08 UTC (permalink / raw)
  To: Gabriel Paubert; +Cc: linuxppc-dev, paulus, Anton Blanchard
In-Reply-To: <20140509215005.GA28239@visitor2.iram.es>

On Fri, May 09, 2014 at 11:50:05PM +0200, Gabriel Paubert wrote:
> On Fri, May 09, 2014 at 06:41:13AM -0700, Paul E. McKenney wrote:
> > On Fri, May 09, 2014 at 05:47:12PM +1000, Anton Blanchard wrote:
> > > I am seeing an issue where a CPU running perf eventually hangs.
> > > Traces show timer interrupts happening every 4 seconds even
> > > when a userspace task is running on the CPU.
> > 
> > Is this by chance every 4.2 seconds?  The reason I ask is that
> > Paul Clarke and I are seeing an interrupt every 4.2 seconds when
> > he runs NO_HZ_FULL, and are trying to get rid of it.  ;-)
> 
> Hmmm, it's close to 2^32 nanoseconds, isnt't it suspiscious?

Now that you mention it...  ;-)

So you are telling me that we are not succeeding in completely turning
off the decrementer interrupt?

							Thanx, Paul

^ permalink raw reply

* Re: [PATCH] powerpc: irq work racing with timer interrupt can result in timer interrupt hang
From: Gabriel Paubert @ 2014-05-09 21:50 UTC (permalink / raw)
  To: Paul E. McKenney; +Cc: linuxppc-dev, paulus, Anton Blanchard
In-Reply-To: <20140509134113.GP8754@linux.vnet.ibm.com>

On Fri, May 09, 2014 at 06:41:13AM -0700, Paul E. McKenney wrote:
> On Fri, May 09, 2014 at 05:47:12PM +1000, Anton Blanchard wrote:
> > I am seeing an issue where a CPU running perf eventually hangs.
> > Traces show timer interrupts happening every 4 seconds even
> > when a userspace task is running on the CPU.
> 
> Is this by chance every 4.2 seconds?  The reason I ask is that
> Paul Clarke and I are seeing an interrupt every 4.2 seconds when
> he runs NO_HZ_FULL, and are trying to get rid of it.  ;-)

Hmmm, it's close to 2^32 nanoseconds, isnt't it suspiscious?

	Gabriel

^ permalink raw reply

* [PATCH] powerpc: Fix "attempt to move .org backwards" error (again)
From: Guenter Roeck @ 2014-05-10  0:07 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras, linux-kernel, Guenter Roeck

Commit 4e243b7 (powerpc: Fix "attempt to move .org backwards" error) fixes the
allyesconfig build by moving machine_check_common to a different location.
While this fixes most of the errors, both allmodconfig and allyesconfig still
fail as follows.

arch/powerpc/kernel/exceptions-64s.S:1315: Error: attempt to move .org backwards

Fix by moving machine_check_common after the offending address.

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
This fixes the build error, but unfortunately I don't have a system to test
the resulting image.

 arch/powerpc/kernel/exceptions-64s.S | 49 ++++++++++++++++++------------------
 1 file changed, 24 insertions(+), 25 deletions(-)

diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 3afd391..25398be 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1138,31 +1138,6 @@ unrecov_user_slb:
 
 #endif /* __DISABLED__ */
 
-
-	/*
-	 * Machine check is different because we use a different
-	 * save area: PACA_EXMC instead of PACA_EXGEN.
-	 */
-	.align	7
-	.globl machine_check_common
-machine_check_common:
-
-	mfspr	r10,SPRN_DAR
-	std	r10,PACA_EXGEN+EX_DAR(r13)
-	mfspr	r10,SPRN_DSISR
-	stw	r10,PACA_EXGEN+EX_DSISR(r13)
-	EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
-	FINISH_NAP
-	DISABLE_INTS
-	ld	r3,PACA_EXGEN+EX_DAR(r13)
-	lwz	r4,PACA_EXGEN+EX_DSISR(r13)
-	std	r3,_DAR(r1)
-	std	r4,_DSISR(r1)
-	bl	.save_nvgprs
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	bl	.machine_check_exception
-	b	.ret_from_except
-
 	.align	7
 	.globl alignment_common
 alignment_common:
@@ -1328,6 +1303,30 @@ fwnmi_data_area:
 initial_stab:
 	.space	4096
 
+	/*
+	 * Machine check is different because we use a different
+	 * save area: PACA_EXMC instead of PACA_EXGEN.
+	 */
+	.align	7
+	.globl machine_check_common
+machine_check_common:
+
+	mfspr	r10,SPRN_DAR
+	std	r10,PACA_EXGEN+EX_DAR(r13)
+	mfspr	r10,SPRN_DSISR
+	stw	r10,PACA_EXGEN+EX_DSISR(r13)
+	EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
+	FINISH_NAP
+	DISABLE_INTS
+	ld	r3,PACA_EXGEN+EX_DAR(r13)
+	lwz	r4,PACA_EXGEN+EX_DSISR(r13)
+	std	r3,_DAR(r1)
+	std	r4,_DSISR(r1)
+	bl	.save_nvgprs
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.machine_check_exception
+	b	.ret_from_except
+
 #ifdef CONFIG_PPC_POWERNV
 _GLOBAL(opal_mc_secondary_handler)
 	HMT_MEDIUM_PPR_DISCARD
-- 
1.9.1

^ permalink raw reply related

* [PATCH 1/1] powerpc/perf: Adjust callchain based on DWARF debug info
From: Sukadev Bhattiprolu @ 2014-05-10  2:46 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Michael Ellerman, Anton Blanchard, linux-kernel, Ulrich.Weigand,
	Maynard Johnson, linuxppc-dev

[PATCH 1/1] powerpc/perf: Adjust callchain based on DWARF debug info

When saving the callchain on Power, the kernel conservatively saves excess
entries in the callchain. A few of these entries are needed in some cases
but not others.

Eg: the value in the link register (LR) is needed only when it holds the
return address of a function. At other times it must be ignored.

If the unnecessary entries are not ignored, we end up with duplicate arcs
in the call-graphs.

Use DWARF debug information to ignore the unnecessary entries.

Callgraph before the patch:

    14.67%          2234  sprintft  libc-2.18.so       [.] __random
            |
            --- __random
               |
               |--61.12%-- __random
               |          |
               |          |--97.15%-- rand
               |          |          do_my_sprintf
               |          |          main
               |          |          generic_start_main.isra.0
               |          |          __libc_start_main
               |          |          0x0
               |          |
               |           --2.85%-- do_my_sprintf
               |                     main
               |                     generic_start_main.isra.0
               |                     __libc_start_main
               |                     0x0
               |
                --38.88%-- rand
                          |
                          |--94.01%-- rand
                          |          do_my_sprintf
                          |          main
                          |          generic_start_main.isra.0
                          |          __libc_start_main
                          |          0x0
                          |
                           --5.99%-- do_my_sprintf
                                     main
                                     generic_start_main.isra.0
                                     __libc_start_main
                                     0x0

Callgraph after the patch:

    14.67%          2234  sprintft  libc-2.18.so       [.] __random
            |
            --- __random
               |
               |--95.93%-- rand
               |          do_my_sprintf
               |          main
               |          generic_start_main.isra.0
               |          __libc_start_main
               |          0x0
               |
                --4.07%-- do_my_sprintf
                          main
                          generic_start_main.isra.0
                          __libc_start_main
                          0x0

TODO:	For split-debug info objects like glibc, we can only determine
	the call-frame-address only when both .eh_frame and .debug_info
	sections are available. We should be able to determin the CFA
	even without the .eh_frame section.

Thanks to Ulrich Weigand for help with DWARF debug information.

Fix suggested by Anton Blanchard.

Reported-by: Maynard Johnson <maynard@us.ibm.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
 tools/perf/arch/powerpc/Makefile                |   1 +
 tools/perf/arch/powerpc/util/adjust-callchain.c | 278 ++++++++++++++++++++++++
 tools/perf/config/Makefile                      |   5 +
 tools/perf/util/callchain.h                     |  12 +
 tools/perf/util/machine.c                       |  16 +-
 5 files changed, 310 insertions(+), 2 deletions(-)
 create mode 100644 tools/perf/arch/powerpc/util/adjust-callchain.c

diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile
index 744e629..512cc8d 100644
--- a/tools/perf/arch/powerpc/Makefile
+++ b/tools/perf/arch/powerpc/Makefile
@@ -3,3 +3,4 @@ PERF_HAVE_DWARF_REGS := 1
 LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
 endif
 LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
+LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/adjust-callchain.o
diff --git a/tools/perf/arch/powerpc/util/adjust-callchain.c b/tools/perf/arch/powerpc/util/adjust-callchain.c
new file mode 100644
index 0000000..31b1f95
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/adjust-callchain.c
@@ -0,0 +1,278 @@
+/*
+ * Use DWARF Debug information to skip unnecessary callchain entries.
+ *
+ * Copyright (C) 2014 Sukadev Bhattiprolu, IBM Corporation.
+ * Copyright (C) 2014 Ulrich Weigand, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <inttypes.h>
+#include <dwarf.h>
+#include <elfutils/libdwfl.h>
+
+#include "util/thread.h"
+#include "util/callchain.h"
+
+/*
+ * When saving the callchain on Power, the kernel conservatively saves
+ * excess entries in the callchain. A few of these entries are needed
+ * in some cases but not others. If the unnecessary entries are not
+ * ignored, we end up with duplicate arcs in the call-graphs. Use
+ * DWARF debug information to skip over any unnecessary callchain
+ * entries.
+ * 
+ * See function header for arch_adjust_callchain() below for more details.
+ *
+ * The libdwfl code in this file is based on code from elfutils
+ * (libdwfl/argp-std.c, libdwfl/tests/addrcfi.c, etc).
+ */
+static char *debuginfo_path;
+
+static const Dwfl_Callbacks offline_callbacks = {
+	.debuginfo_path = &debuginfo_path,
+	.find_debuginfo = dwfl_standard_find_debuginfo,
+	.section_address = dwfl_offline_section_address,
+};
+
+
+/*
+ * Use the DWARF expression for the Call-frame-address and determine
+ * if return address is in LR and if a new frame was allocated.
+ */
+static int check_return_reg(int ra_regno, Dwarf_Frame *frame)
+{
+	Dwarf_Op ops_mem[2];
+	Dwarf_Op dummy;
+	Dwarf_Op *ops = &dummy;
+  	size_t nops;
+	int result;
+
+	result = dwarf_frame_register(frame, ra_regno, ops_mem, &ops, &nops);
+	if (result < 0) {
+		pr_debug("dwarf_frame_register() %s\n", dwarf_errmsg(-1));
+		return -1;
+	}
+
+	/* 
+	 * Check if return address is on the stack.
+	 */
+	if (nops != 0 || ops != NULL)
+		return 0;
+
+	/*
+	 * Return address is in LR. Check if a frame was allocated
+	 * but not-yet used.
+	 */
+        result = dwarf_frame_cfa(frame, &ops, &nops);
+        if (result < 0) {
+                pr_debug("dwarf_frame_cfa() returns %d, %s\n", result,
+					dwarf_errmsg(-1));
+                return -1;
+        }
+
+	/*
+	 * If call frame address is in r1, no new frame was allocated.
+	 */
+        if (nops == 1 && ops[0].atom == DW_OP_bregx && ops[0].number == 1 &&
+					ops[0].number2 == 0)
+                return 1;      
+
+	/*
+	 * A new frame was allocated but has not yet been used.
+	 */
+        return 2;
+}
+
+/*
+ * Get the DWARF frame from the .eh_frame section.
+ */
+static Dwarf_Frame *get_eh_frame(Dwfl_Module *mod, Dwarf_Addr pc) 
+{
+        int             result;
+        Dwarf_Addr      bias;
+        Dwarf_CFI       *cfi;
+        Dwarf_Frame     *frame;
+
+        cfi = dwfl_module_eh_cfi(mod, &bias);   // CHECK
+        if (!cfi) {
+                pr_debug("%s(): no CFI - %s\n", __func__, dwfl_errmsg(-1));
+                return NULL;
+        }
+
+        result = dwarf_cfi_addrframe(cfi, pc, &frame);
+        if (result) {
+                pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1));
+                return NULL;
+        }
+
+        return frame;
+}
+
+/*
+ * Get the DWARF frame from the .debug_frame section.
+ */
+static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc)
+{
+        Dwarf_CFI       *cfi;
+        Dwarf_Addr      bias;
+        Dwarf_Frame     *frame;
+        int             result;
+
+        cfi = dwfl_module_dwarf_cfi(mod, &bias);
+        if (!cfi) {
+                pr_debug("%s(): no CFI - %s\n", __func__, dwfl_errmsg(-1));
+                return NULL;
+        }
+
+        result = dwarf_cfi_addrframe(cfi, pc, &frame);
+        if (result) {
+                pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1));
+                return NULL;
+        }
+
+        return frame;
+}
+
+/*
+ * Return:
+ * 	0 if return address for the program counter @pc is on stack
+ * 	1 if return address is in LR and no new stack frame was allocated
+ * 	2 if return address is in LR and a new frame was allocated (but not
+ * 	  yet used)
+ * 	-1 in case of errors
+ */
+static int check_return_addr(const char *exec_file, Dwarf_Addr pc)
+{
+	Dwfl		*dwfl;
+	Dwfl_Module	*mod;
+	Dwarf_Frame	*frame;
+	int		ra_regno;
+	Dwarf_Addr 	start = pc;
+	Dwarf_Addr 	end = pc;
+	bool 		signalp;
+
+	pr_debug("Testing: %s, @0x%llx\n", exec_file, (unsigned long long)pc);
+
+	dwfl = dwfl_begin(&offline_callbacks);
+	if (!dwfl) {
+		pr_debug("dwfl_begin() failed: %s\n", dwarf_errmsg(-1));
+		return -1;
+	}
+
+	if (dwfl_report_offline(dwfl, "",  exec_file, -1) == NULL) {
+		pr_debug("dwfl_report_offline() failed %s\n", dwarf_errmsg(-1));
+		return -1;
+	}
+
+	mod = dwfl_addrmodule(dwfl, pc);
+	if (!mod) {
+		pr_debug("dwfl_addrmodule() failed, %s\n", dwarf_errmsg(-1));
+		return -1;
+	}
+
+	/*
+	 * To work with split debug info files (eg: glibc), check both
+	 * .eh_frame and .debug_frame sections of the ELF header.
+	 */
+	frame = get_eh_frame(mod, pc);
+	if (!frame) {
+		frame = get_dwarf_frame(mod, pc);
+		if (!frame)
+			return -1;
+	}
+
+	ra_regno = dwarf_frame_info (frame, &start, &end, &signalp);
+	if (ra_regno < 0) {
+		pr_debug("Return address register unavailable: %s\n",
+				dwarf_errmsg(-1));
+		return -1;
+	}
+
+	return check_return_reg(ra_regno, frame);
+}
+
+/*
+ * The callchain saved by the kernel always includes the link register (LR).
+ * 	
+ * 	0:	PERF_CONTEXT_USER
+ * 	1:	Program counter (Next instruction pointer)
+ * 	2:	LR value
+ * 	3:	Caller's caller
+ * 	4:	...
+ *
+ * The value in LR is only needed when it holds a return address. If the
+ * return address is on the stack, we should ignore the LR value.
+ *
+ * Further, when the return address is in the LR, if a new frame was just
+ * allocated but the LR was not saved into it, then the LR contains the
+ * caller, slot 4: contains the caller's caller and the contents of slot 3:
+ * (chain->ips[3]) is undefined and must be ignored.
+ *
+ * Use DWARF debug information to determine if any entries need to be skipped.
+ *
+ * Return:
+ * 	index:	of callchain entry that needs to be ignored (if any)
+ * 	-1 	if no entry needs to be ignored or in case of errors
+ *
+ * TODO:
+ * 	Rather than returning an index into the callchain and have the
+ * 	caller skip that entry, we could modify the callchain in-place
+ * 	by putting a PERF_CONTEXT_IGNORE marker in the affected entry.
+ *
+ * 	But @chain points to read-only mmap, so the caller needs to
+ * 	duplicate the callchain to modify in-place - something like:
+ *
+ * 		new_callchain = arch_duplicate_callchain()
+ * 		arch_adjust_callchain(new_callchain)
+ * 		arch_free_callchain(new_callchain)
+ *
+ * 	Since we only expect to adjust <= 1 entry for now, just return
+ * 	the index.
+ */
+int arch_adjust_callchain(struct machine *machine, struct thread *thread,
+				struct ip_callchain *chain)
+{
+	struct addr_location al;
+	struct dso *dso = NULL;
+	int rc;
+	u64 ip;
+	u64 skip_slot = -1;
+	
+	if (chain->nr < 3)
+		return skip_slot;
+
+	ip = chain->ips[2];
+
+	thread__find_addr_location(thread, machine, PERF_RECORD_MISC_USER,
+			MAP__FUNCTION, ip, &al);
+
+	if (al.map)
+		dso = al.map->dso;
+
+	if (!dso) {
+		pr_debug("%" PRIx64 " dso is NULL\n", ip);
+		return skip_slot;
+	}
+
+	rc = check_return_addr(dso->long_name, ip);
+
+	pr_debug("DSO %s, nr %" PRIx64 ", ip 0x%" PRIx64 "rc %d\n",
+				dso->long_name, chain->nr, ip, rc);
+
+	if (rc == 0) {
+		/* 
+		 * Return address on stack. Ignore LR value in callchain
+		 */
+		skip_slot = 2;
+	} else if (rc == 2) {
+		/* 
+		 * New frame allocated but return address still in LR.
+		 * Ignore the caller's caller entry in callchain.
+		 */
+		skip_slot = 3;
+	}
+	return skip_slot;
+}
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 5a3c452..7e93877 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -29,11 +29,16 @@ ifeq ($(ARCH),x86)
   endif
   NO_PERF_REGS := 0
 endif
+
 ifeq ($(ARCH),arm)
   NO_PERF_REGS := 0
   LIBUNWIND_LIBS = -lunwind -lunwind-arm
 endif
 
+ifeq ($(ARCH),powerpc)
+  CFLAGS += -DHAVE_ADJUST_CALLCHAIN
+endif
+
 ifeq ($(LIBUNWIND_LIBS),)
   NO_LIBUNWIND := 1
 else
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 8ad97e9..81ecb90 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -157,4 +157,16 @@ int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent
 int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample);
 
 extern const char record_callchain_help[];
+
+#ifdef HAVE_ADJUST_CALLCHAIN
+extern int arch_adjust_callchain(struct machine *machine,
+			struct thread *thread, struct ip_callchain *chain);
+#else
+static inline int arch_adjust_callchain(struct machine *machine,
+			struct thread *thread, struct ip_callchain *chain)
+{
+	return -1;
+}
+#endif
+
 #endif	/* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index a53cd0b..dce3bf0 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1271,6 +1271,7 @@ static int machine__resolve_callchain_sample(struct machine *machine,
 	int chain_nr = min(max_stack, (int)chain->nr);
 	int i;
 	int err;
+	int skip_slot;
 
 	callchain_cursor_reset(&callchain_cursor);
 
@@ -1279,14 +1280,25 @@ static int machine__resolve_callchain_sample(struct machine *machine,
 		return 0;
 	}
 
+	/*
+	 * Based on DWARF debug information, some architectures skip
+	 * some of the callchain entries saved by the kernel.
+	 */
+	skip_slot = arch_adjust_callchain(machine, thread, chain);
+
 	for (i = 0; i < chain_nr; i++) {
 		u64 ip;
 		struct addr_location al;
 
-		if (callchain_param.order == ORDER_CALLEE)
+		if (callchain_param.order == ORDER_CALLEE) {
+			if (i == skip_slot)
+				continue;
 			ip = chain->ips[i];
-		else
+		} else {
+			if ((int)(chain->nr - i - 1) == skip_slot)
+				continue;
 			ip = chain->ips[chain->nr - i - 1];
+		}
 
 		if (ip >= PERF_CONTEXT_MAX) {
 			switch (ip) {
-- 
1.8.4.2

^ permalink raw reply related

* Re: [PATCH] powerpc: irq work racing with timer interrupt can result in timer interrupt hang
From: Benjamin Herrenschmidt @ 2014-05-10  4:26 UTC (permalink / raw)
  To: Preeti U Murthy; +Cc: paulmck, paulus, Anton Blanchard, linuxppc-dev
In-Reply-To: <536CA561.8010803@linux.vnet.ibm.com>

On Fri, 2014-05-09 at 15:22 +0530, Preeti U Murthy wrote:
> in __timer_interrupt() outside the _else_ loop? This will ensure that no
> matter what, before exiting timer interrupt handler we check for pending
> irq work.

We still need to make sure that set_next_event() doesn't move the
dec beyond the next tick if there is a pending timer... maybe we
can fix it like this:

static int decrementer_set_next_event(unsigned long evt,
				      struct clock_event_device *dev)
{
	__get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt;

	/* Don't adjust the decrementer if some irq work is pending */
	if (!test_irq_work_pending())
		set_dec(evt);

	return 0;
}

Along with a single occurrence of:

	if (test_irq_work_pending())
		set_dec(1);

At the end of __timer_interrupt(), outside if the current else {}
case, this should work, don't you think ?

What about this completely untested patch ?

diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 122a580..ba7e83b 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -503,12 +503,13 @@ void __timer_interrupt(void)
                now = *next_tb - now;
                if (now <= DECREMENTER_MAX)
                        set_dec((int)now);
-               /* We may have raced with new irq work */
-               if (test_irq_work_pending())
-                       set_dec(1);
                __get_cpu_var(irq_stat).timer_irqs_others++;
        }
 
+       /* We may have raced with new irq work */
+       if (test_irq_work_pending())
+               set_dec(1);
+
 #ifdef CONFIG_PPC64
        /* collect purr register values often, for accurate calculations */
        if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
@@ -813,15 +814,11 @@ static void __init clocksource_init(void)
 static int decrementer_set_next_event(unsigned long evt,
                                      struct clock_event_device *dev)
 {
-       /* Don't adjust the decrementer if some irq work is pending */
-       if (test_irq_work_pending())
-               return 0;
        __get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt;
-       set_dec(evt);
 
-       /* We may have raced with new irq work */
-       if (test_irq_work_pending())
-               set_dec(1);
+       /* Don't adjust the decrementer if some irq work is pending */
+       if (!test_irq_work_pending())
+               set_dec(evt);
 
        return 0;
 }

^ permalink raw reply related

* [PATCH] printk/of_serial: fix serial console cessation part way through boot.
From: Stephen Chivers @ 2014-05-10  5:37 UTC (permalink / raw)
  To: geert, jslaby, gregkh
  Cc: devicetree, linux-serial, linux-kernel, rob+dt, schivers,
	grant.likely, linuxppc-dev, cproctor

Commit 5f5c9ae56c38942623f69c3e6dc6ec78e4da2076
"serial_core: Unregister console in uart_remove_one_port()"
fixed a crash where a serial port was removed but
not deregistered as a console.

There is a side effect of that commit for platforms having serial consoles
and of_serial configured (CONFIG_SERIAL_OF_PLATFORM). The serial console
is disabled midway through the boot process.

This cessation of the serial console affects PowerPC computers
such as the MVME5100 and SAM440EP.

The sequence is:

	bootconsole [udbg0] enabled
	....
	serial8250/16550 driver initialises and registers its UARTS,
	one of these is the serial console.
	console [ttyS0] enabled
	....
	of_serial probes "platform" devices, registering them as it goes.
	One of these is the serial console.
	console [ttyS0] disabled.

The disabling of the serial console is due to:

	a.  unregister_console in printk not clearing the
	    CONS_ENABLED bit in the console flags,
	    even though it has announced that the console is disabled; and

	b.  of_platform_serial_probe in of_serial not setting the port type
	    before it registers with serial8250_register_8250_port.

This patch ensures that the serial console is re-enabled when of_serial
registers a serial port that corresponds to the designated console.

Signed-off-by: Stephen Chivers <schivers@csc.com>
Tested-by: Stephen Chivers <schivers@csc.com>

===
The above failure was identified in Linux-3.15-rc2.

Tested using MVME5100 and SAM440EP PowerPC computers with
kernels built from Linux-3.15-rc5 and tty-next.

The continued operation of the serial console is vital for computers
such as the MVME5100 as that Single Board Computer does not
have any grapical/display hardware.

---
 drivers/tty/serial/of_serial.c |    1 +
 kernel/printk/printk.c         |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index 9924660..27981e2 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -173,6 +173,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 	{
 		struct uart_8250_port port8250;
 		memset(&port8250, 0, sizeof(port8250));
+		port.type = port_type;
 		port8250.port = port;
 
 		if (port.fifosize)
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 7228258..221229c 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2413,6 +2413,7 @@ int unregister_console(struct console *console)
 	if (console_drivers != NULL && console->flags & CON_CONSDEV)
 		console_drivers->flags |= CON_CONSDEV;
 
+	console->flags &= ~CON_ENABLED;
 	console_unlock();
 	console_sysfs_notify();
 	return res;

^ permalink raw reply related

* device tree, fedora 20 install
From: Anatoly Pugachev @ 2014-05-10  6:28 UTC (permalink / raw)
  To: linuxppc-dev

Hello!

There's a regression somewhere in kernel, I'm unable to boot
installation kernel version 3.11.10-301.fc20.ppc64 of fedora 20 on IBM
JS22 (type 7998) blade. But my previous attempt with kernel
3.9.5-301.fc19.ppc64 was able to boot.

I have the following output with 3.11.10-301.fc20.ppc64 kernel:

  Booting `Install Fedora 20 (64-bit kernel)'

OF stdout device is: /vdevice/vty@30000000
Preparing to boot Linux version 3.11.10-301.fc20.ppc64
(mockbuild@ppc-builder7.qa.fedoraproject.org) (gcc version 4.8.2
20131017 (Red Hat 4.8.2-1) (GCC) ) #1 SMP Tue Dec 10 00:35:15 MST 2013
Detected machine type: 0000000000000101
Max number of cores passed to firmware: 512 (NR_CPUS = 1024)
Calling ibm,client-architecture-
support... done
command line: BOOT_IMAGE=/ppc/ppc64/vmlinuz ro
memory layout at init:
  memory_limit : 0000000000000000 (16 MB aligned)
  alloc_bottom : 0000000006e80000
  alloc_top    : 0000000008000000
  alloc_top_hi : 0000000008000000
  rmo_top      : 0000000008000000
  ram_top      : 0000000008000000
found display   : /pci@800000020000202/display@1, opening... done
instantiating rtas at 0x0000000006eb0000... done
Querying for OPAL presence... not there.
boot cpu hw idx 0
starting cpu hw idx 2... done
starting cpu hw idx 4... done
starting cpu hw idx 6... done
copying OF device tree...
Building dt strings...
Building dt structure...
No memory for flatten_device_tree (no room)
EXIT called ok
0 >



while with 3.9.5-301.fc19.ppc64 it pass DT stage:

Welcome to the 64-bit Fedora 19 installer!
Hit <TAB> for boot options.


Welcome to yaboot version 1.3.17 (Red Hat 1.3.17-6.fc19)
Enter "help" to get some basic usage information
boot: linux
Please wait, loading kernel...
   Elf64 kernel loaded...
Loading ramdisk...
ramdisk loaded at 03980000, size: 9872 Kbytes
OF stdout device is: /vdevice/vty@30000000
Preparing to boot Linux version 3.9.5-301.fc19.ppc64
(mockbuild@ppc-builder3.qa.fedoraproject.org) (gcc version 4.8.1
20130603 (Red Hat 4.8.1-1)
(GCC) ) #1 SMP Tue Jun 11 15:07:48 MST 2013
Detected machine type: 0000000000000101
Max number of cores passed to firmware: 512 (NR_CPUS = 1024)
Calling ibm,client-architecture-support... done
command line: ro
memory layout at init:
  memory_limit : 0000000000000000 (16 MB aligned)
  alloc_bottom : 0000000004330000
  alloc_top    : 0000000008000000
  alloc_top_hi : 0000000008000000
  rmo_top      : 0000000008000000
  ram_top      : 0000000008000000
found display   : /pci@800000020000202/display@1, opening... done
instantiating rtas at 0x0000000006db0000... done
Querying for OPAL presence... not there.
boot cpu hw idx 0
starting cpu hw idx 2... done
starting cpu hw idx 4... done
starting cpu hw idx 6... done
copying OF device tree...
Building dt strings...
Building dt structure...
Device tree strings 0x0000000004440000 -> 0x000000000444182e
Device tree struct  0x0000000004450000 -> 0x0000000004470000
Calling quiesce...
returning from prom_init
[    0.000000] Using pSeries machine description
[    0.000000] Using 1TB segments
[    0.000000] Found initrd at 0xc000000003980000:0xc000000004324000
[    0.000000] bootconsole [udbg0] enabled
[    0.000000] Partition configured for 8 cpus.
(and so on...)



Can someone help me with this issue? Thanks.

^ permalink raw reply

* Re: [PATCH] powerpc: irq work racing with timer interrupt can result in timer interrupt hang
From: Paul Mackerras @ 2014-05-10  6:33 UTC (permalink / raw)
  To: Paul E. McKenney; +Cc: linuxppc-dev, Anton Blanchard
In-Reply-To: <20140509220845.GY8754@linux.vnet.ibm.com>

On Fri, May 09, 2014 at 03:08:45PM -0700, Paul E. McKenney wrote:
> On Fri, May 09, 2014 at 11:50:05PM +0200, Gabriel Paubert wrote:
> > On Fri, May 09, 2014 at 06:41:13AM -0700, Paul E. McKenney wrote:
> > > On Fri, May 09, 2014 at 05:47:12PM +1000, Anton Blanchard wrote:
> > > > I am seeing an issue where a CPU running perf eventually hangs.
> > > > Traces show timer interrupts happening every 4 seconds even
> > > > when a userspace task is running on the CPU.
> > > 
> > > Is this by chance every 4.2 seconds?  The reason I ask is that
> > > Paul Clarke and I are seeing an interrupt every 4.2 seconds when
> > > he runs NO_HZ_FULL, and are trying to get rid of it.  ;-)
> > 
> > Hmmm, it's close to 2^32 nanoseconds, isnt't it suspiscious?
> 
> Now that you mention it...  ;-)
> 
> So you are telling me that we are not succeeding in completely turning
> off the decrementer interrupt?

There is no way to turn off the decrementer interrupt without turning
off external (device) interrupts.

On IBM Power CPUs since POWER6, the decrementer runs at 512MHz.  If
you set the decrementer to 0x7fffffff it will interrupt in 4.194
seconds, so that would be what you're seeing.  The only way to avoid
the interrupt becoming pending is to keep on setting it to a large
value before it gets to -1.

If an interrupt every 4.2 seconds is a problem in some applications,
then we need to talk to the Power architects.

Regards,
Paul.

^ permalink raw reply

* Re: [PATCH v2 1/2] powerpc/pm: add api to get suspend state which is STANDBY or MEM
From: Li Yang @ 2014-05-10 12:35 UTC (permalink / raw)
  To: Scott Wood
  Cc: Zhao Chenhui, linux-pm@vger.kernel.org, Rafael J. Wysocki,
	Dongsheng Wang, 正雄 金, linuxppc-dev
In-Reply-To: <1399655386.15726.438.camel@snotra.buserror.net>

On Sat, May 10, 2014 at 1:09 AM, Scott Wood <scottwood@freescale.com> wrote:
> On Fri, 2014-05-09 at 17:33 +0800, Li Yang wrote:
>> On Wed, Apr 30, 2014 at 6:47 AM, Scott Wood <scottwood@freescale.com> wrote:
>> > On Mon, 2014-04-28 at 13:53 +0800, Leo Li wrote:
>> >> On Sat, Apr 26, 2014 at 5:45 AM, Scott Wood <scottwood@freescale.com> wrote:
>> >> > On Thu, 2014-04-24 at 14:11 +0800, Dongsheng Wang wrote:
>> >> >> From: Wang Dongsheng <dongsheng.wang@freescale.com>
>> >> >>
>> >> >> Add set_pm_suspend_state & pm_suspend_state functions to set/get
>> >> >> suspend state. When system going to sleep or deep sleep, devices
>> >> >> can get the system suspend state(STANDBY/MEM) through pm_suspend_state
>> >> >> function and to handle different situations.
>> >> >>
>> >> >> Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>
>> >> >> ---
>> >> >> *v2*
>> >> >> Move pm api from fsl platform to powerpc general framework.
>> >> >
>> >> > What is powerpc-specific about this?
>> >>
>> >> Generally I agree with you.  But I had the discussion about this topic
>> >> a while ago with the PM maintainer.  He suggestion to go with the
>> >> platform way.
>> >>
>> >> https://lkml.org/lkml/2013/8/16/505
>> >
>> > If what he meant was whether you could do what this patch does, then you
>> > can answer him with, "No, because it got nacked as not being platform or
>> > arch specific."  Oh, and you're still using .valid as the hook to set
>> > the platform state, which is awful -- I think .begin is what you want to
>> > use.
>>
>> I'm not saying the current patch is good for upstream.  Actually I did
>> say that the patch need to be updated for upstream purpose.
>
> I don't follow -- this thread is an upstream submission.

Thought you were suggesting to change the generic PM interface for
this as discussed internally.  So I was just providing the information
about previous discussion.  Nothing more.

Regards,
Leo

^ permalink raw reply

* Re: [PATCH] powerpc: irq work racing with timer interrupt can result in timer interrupt hang
From: Preeti U Murthy @ 2014-05-10 15:36 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: paulmck, paulus, Anton Blanchard, linuxppc-dev
In-Reply-To: <1399695993.4481.47.camel@pasglop>

On 05/10/2014 09:56 AM, Benjamin Herrenschmidt wrote:
> On Fri, 2014-05-09 at 15:22 +0530, Preeti U Murthy wrote:
>> in __timer_interrupt() outside the _else_ loop? This will ensure that no
>> matter what, before exiting timer interrupt handler we check for pending
>> irq work.
> 
> We still need to make sure that set_next_event() doesn't move the
> dec beyond the next tick if there is a pending timer... maybe we

Sorry, but didn't get this. s/if there is pending timer/if there is
pending irq work ?

> can fix it like this:

We can call set_next_event() from events like hrtimer_cancel() or
hrtimer_forward() as well. In that case we don't come to
decrementer_set_next_event() from __timer_interrupt(). Then, if we race
with irq work, we *do not do* a set_dec(1) ( I am referring to the patch
below ), we might never set the decrementer to fire immediately right?

Or does this scenario never arise?

Regards
Preeti U Murthy
> 
> static int decrementer_set_next_event(unsigned long evt,
> 				      struct clock_event_device *dev)
> {
> 	__get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt;
> 
> 	/* Don't adjust the decrementer if some irq work is pending */
> 	if (!test_irq_work_pending())
> 		set_dec(evt);
> 
> 	return 0;
> }
> 
> Along with a single occurrence of:
> 
> 	if (test_irq_work_pending())
> 		set_dec(1);
> 
> At the end of __timer_interrupt(), outside if the current else {}
> case, this should work, don't you think ?
> 
> What about this completely untested patch ?
> 
> diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
> index 122a580..ba7e83b 100644
> --- a/arch/powerpc/kernel/time.c
> +++ b/arch/powerpc/kernel/time.c
> @@ -503,12 +503,13 @@ void __timer_interrupt(void)
>                 now = *next_tb - now;
>                 if (now <= DECREMENTER_MAX)
>                         set_dec((int)now);
> -               /* We may have raced with new irq work */
> -               if (test_irq_work_pending())
> -                       set_dec(1);
>                 __get_cpu_var(irq_stat).timer_irqs_others++;
>         }
> 
> +       /* We may have raced with new irq work */
> +       if (test_irq_work_pending())
> +               set_dec(1);
> +
>  #ifdef CONFIG_PPC64
>         /* collect purr register values often, for accurate calculations */
>         if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
> @@ -813,15 +814,11 @@ static void __init clocksource_init(void)
>  static int decrementer_set_next_event(unsigned long evt,
>                                       struct clock_event_device *dev)
>  {
> -       /* Don't adjust the decrementer if some irq work is pending */
> -       if (test_irq_work_pending())
> -               return 0;
>         __get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt;
> -       set_dec(evt);
> 
> -       /* We may have raced with new irq work */
> -       if (test_irq_work_pending())
> -               set_dec(1);
> +       /* Don't adjust the decrementer if some irq work is pending */
> +       if (!test_irq_work_pending())
> +               set_dec(evt);
> 
>         return 0;
>  }
> 
> 
> 
> 

^ permalink raw reply

* Re: [PATCH] powerpc: irq work racing with timer interrupt can result in timer interrupt hang
From: Paul E. McKenney @ 2014-05-10 16:33 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, Anton Blanchard
In-Reply-To: <20140510063337.GA13634@iris.ozlabs.ibm.com>

On Sat, May 10, 2014 at 04:33:37PM +1000, Paul Mackerras wrote:
> On Fri, May 09, 2014 at 03:08:45PM -0700, Paul E. McKenney wrote:
> > On Fri, May 09, 2014 at 11:50:05PM +0200, Gabriel Paubert wrote:
> > > On Fri, May 09, 2014 at 06:41:13AM -0700, Paul E. McKenney wrote:
> > > > On Fri, May 09, 2014 at 05:47:12PM +1000, Anton Blanchard wrote:
> > > > > I am seeing an issue where a CPU running perf eventually hangs.
> > > > > Traces show timer interrupts happening every 4 seconds even
> > > > > when a userspace task is running on the CPU.
> > > > 
> > > > Is this by chance every 4.2 seconds?  The reason I ask is that
> > > > Paul Clarke and I are seeing an interrupt every 4.2 seconds when
> > > > he runs NO_HZ_FULL, and are trying to get rid of it.  ;-)
> > > 
> > > Hmmm, it's close to 2^32 nanoseconds, isnt't it suspiscious?
> > 
> > Now that you mention it...  ;-)
> > 
> > So you are telling me that we are not succeeding in completely turning
> > off the decrementer interrupt?
> 
> There is no way to turn off the decrementer interrupt without turning
> off external (device) interrupts.
> 
> On IBM Power CPUs since POWER6, the decrementer runs at 512MHz.  If
> you set the decrementer to 0x7fffffff it will interrupt in 4.194
> seconds, so that would be what you're seeing.  The only way to avoid
> the interrupt becoming pending is to keep on setting it to a large
> value before it gets to -1.
> 
> If an interrupt every 4.2 seconds is a problem in some applications,
> then we need to talk to the Power architects.

Thank you for filling me in on this!  Might be worth doing just that.

							Thanx, Paul

^ permalink raw reply

* Re: [PATCH] powerpc: irq work racing with timer interrupt can result in timer interrupt hang
From: Benjamin Herrenschmidt @ 2014-05-10 22:25 UTC (permalink / raw)
  To: Preeti U Murthy; +Cc: paulmck, paulus, Anton Blanchard, linuxppc-dev
In-Reply-To: <536E477F.2070009@linux.vnet.ibm.com>

On Sat, 2014-05-10 at 21:06 +0530, Preeti U Murthy wrote:
> On 05/10/2014 09:56 AM, Benjamin Herrenschmidt wrote:
> > On Fri, 2014-05-09 at 15:22 +0530, Preeti U Murthy wrote:
> >> in __timer_interrupt() outside the _else_ loop? This will ensure that no
> >> matter what, before exiting timer interrupt handler we check for pending
> >> irq work.
> > 
> > We still need to make sure that set_next_event() doesn't move the
> > dec beyond the next tick if there is a pending timer... maybe we
> 
> Sorry, but didn't get this. s/if there is pending timer/if there is
> pending irq work ?

Yes, sorry :-) That's what I meant.

> > can fix it like this:
> 
> We can call set_next_event() from events like hrtimer_cancel() or
> hrtimer_forward() as well. In that case we don't come to
> decrementer_set_next_event() from __timer_interrupt(). Then, if we race
> with irq work, we *do not do* a set_dec(1) ( I am referring to the patch
> below ), we might never set the decrementer to fire immediately right?
> 
> Or does this scenario never arise?

So my proposed patch handles that no ?

With that patch, we do the set_dec(1) in two cases:

 - The existing arch_irq_work_raise() which is unchanged

 - At the end of __timer_interrupt() if an irq work is still pending

And the patch also makes decrementer_set_next_event() not modify the
decrementer if an irq work is pending, but *still* adjust next_tb unlike
what the code does now.

Thus the timer interrupt, when it happens, will re-adjust the dec
properly using next_tb.

Do we still miss a case ?

Cheers,
Ben.

> Regards
> Preeti U Murthy
> > 
> > static int decrementer_set_next_event(unsigned long evt,
> > 				      struct clock_event_device *dev)
> > {
> > 	__get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt;
> > 
> > 	/* Don't adjust the decrementer if some irq work is pending */
> > 	if (!test_irq_work_pending())
> > 		set_dec(evt);
> > 
> > 	return 0;
> > }
> > 
> > Along with a single occurrence of:
> > 
> > 	if (test_irq_work_pending())
> > 		set_dec(1);
> > 
> > At the end of __timer_interrupt(), outside if the current else {}
> > case, this should work, don't you think ?
> > 
> > What about this completely untested patch ?
> > 
> > diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
> > index 122a580..ba7e83b 100644
> > --- a/arch/powerpc/kernel/time.c
> > +++ b/arch/powerpc/kernel/time.c
> > @@ -503,12 +503,13 @@ void __timer_interrupt(void)
> >                 now = *next_tb - now;
> >                 if (now <= DECREMENTER_MAX)
> >                         set_dec((int)now);
> > -               /* We may have raced with new irq work */
> > -               if (test_irq_work_pending())
> > -                       set_dec(1);
> >                 __get_cpu_var(irq_stat).timer_irqs_others++;
> >         }
> > 
> > +       /* We may have raced with new irq work */
> > +       if (test_irq_work_pending())
> > +               set_dec(1);
> > +
> >  #ifdef CONFIG_PPC64
> >         /* collect purr register values often, for accurate calculations */
> >         if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
> > @@ -813,15 +814,11 @@ static void __init clocksource_init(void)
> >  static int decrementer_set_next_event(unsigned long evt,
> >                                       struct clock_event_device *dev)
> >  {
> > -       /* Don't adjust the decrementer if some irq work is pending */
> > -       if (test_irq_work_pending())
> > -               return 0;
> >         __get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt;
> > -       set_dec(evt);
> > 
> > -       /* We may have raced with new irq work */
> > -       if (test_irq_work_pending())
> > -               set_dec(1);
> > +       /* Don't adjust the decrementer if some irq work is pending */
> > +       if (!test_irq_work_pending())
> > +               set_dec(evt);
> > 
> >         return 0;
> >  }
> > 
> > 
> > 
> > 

^ permalink raw reply

* [PATCH] [resend] net: get rid of SET_ETHTOOL_OPS
From: Wilfried Klaebe @ 2014-05-11  0:12 UTC (permalink / raw)
  To: netdev
  Cc: devel, linux-s390, b.a.t.m.a.n, trivial, xen-devel, linux-rdma,
	dev, linux-usb, linux-wireless, linux-kernel, linux-acenic,
	e1000-devel, bridge, devel, nios2-dev, virtualization,
	linuxppc-dev, David S. Miller

net: get rid of SET_ETHTOOL_OPS

Dave Miller mentioned he'd like to see SET_ETHTOOL_OPS gone.
This does that.

Mostly done via coccinelle script:
@@
struct ethtool_ops *ops;
struct net_device *dev;
@@
-       SET_ETHTOOL_OPS(dev, ops);
+       dev->ethtool_ops = ops;

Compile tested only, but I'd seriously wonder if this broke anything.

Suggested-by: Dave Miller <davem@davemloft.net>
Signed-off-by: Wilfried Klaebe <w-lkml@lebenslange-mailadresse.de>

---

Applies against v3.15-rc4 and v3.15-rc5 likewise.

resend: trimmed CC list. Thanks to Dave for notifying me.

diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
index c4b3940..078cadd 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
@@ -105,5 +105,5 @@ static const struct ethtool_ops ipoib_ethtool_ops = {
 
 void ipoib_set_ethtool_ops(struct net_device *dev)
 {
-	SET_ETHTOOL_OPS(dev, &ipoib_ethtool_ops);
+	dev->ethtool_ops = &ipoib_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c
index 35df0b9..a968654 100644
--- a/drivers/net/ethernet/3com/3c509.c
+++ b/drivers/net/ethernet/3com/3c509.c
@@ -534,7 +534,7 @@ static int el3_common_init(struct net_device *dev)
 	/* The EL3-specific entries in the device structure. */
 	dev->netdev_ops = &netdev_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
-	SET_ETHTOOL_OPS(dev, &ethtool_ops);
+	dev->ethtool_ops = &ethtool_ops;
 
 	err = register_netdev(dev);
 	if (err) {
diff --git a/drivers/net/ethernet/3com/3c589_cs.c b/drivers/net/ethernet/3com/3c589_cs.c
index 063557e..f18647c 100644
--- a/drivers/net/ethernet/3com/3c589_cs.c
+++ b/drivers/net/ethernet/3com/3c589_cs.c
@@ -218,7 +218,7 @@ static int tc589_probe(struct pcmcia_device *link)
 	dev->netdev_ops = &el3_netdev_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
-	SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
+	dev->ethtool_ops = &netdev_ethtool_ops;
 
 	return tc589_config(link);
 }
diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c
index 465cc71..e13b046 100644
--- a/drivers/net/ethernet/3com/typhoon.c
+++ b/drivers/net/ethernet/3com/typhoon.c
@@ -2435,7 +2435,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netif_napi_add(dev, &tp->napi, typhoon_poll, 16);
 	dev->watchdog_timeo	= TX_TIMEOUT;
 
-	SET_ETHTOOL_OPS(dev, &typhoon_ethtool_ops);
+	dev->ethtool_ops = &typhoon_ethtool_ops;
 
 	/* We can handle scatter gather, up to 16 entries, and
 	 * we can do IP checksumming (only version 4, doh...)
diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c
index 171d73c..40dbbf7 100644
--- a/drivers/net/ethernet/adaptec/starfire.c
+++ b/drivers/net/ethernet/adaptec/starfire.c
@@ -784,7 +784,7 @@ static int starfire_init_one(struct pci_dev *pdev,
 
 	dev->netdev_ops = &netdev_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
-	SET_ETHTOOL_OPS(dev, &ethtool_ops);
+	dev->ethtool_ops = &ethtool_ops;
 
 	netif_napi_add(dev, &np->napi, netdev_poll, max_interrupt_work);
 
diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c
index 1517e9df..9a6991b 100644
--- a/drivers/net/ethernet/alteon/acenic.c
+++ b/drivers/net/ethernet/alteon/acenic.c
@@ -476,7 +476,7 @@ static int acenic_probe_one(struct pci_dev *pdev,
 	dev->watchdog_timeo = 5*HZ;
 
 	dev->netdev_ops = &ace_netdev_ops;
-	SET_ETHTOOL_OPS(dev, &ace_ethtool_ops);
+	dev->ethtool_ops = &ace_ethtool_ops;
 
 	/* we only display this string ONCE */
 	if (!boards_found)
diff --git a/drivers/net/ethernet/altera/altera_tse_ethtool.c b/drivers/net/ethernet/altera/altera_tse_ethtool.c
index 319ca74..8ac4bd2 100644
--- a/drivers/net/ethernet/altera/altera_tse_ethtool.c
+++ b/drivers/net/ethernet/altera/altera_tse_ethtool.c
@@ -231,5 +231,5 @@ static const struct ethtool_ops tse_ethtool_ops = {
 
 void altera_tse_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &tse_ethtool_ops);
+	netdev->ethtool_ops = &tse_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c
index 26efaaa..068dc7c 100644
--- a/drivers/net/ethernet/amd/amd8111e.c
+++ b/drivers/net/ethernet/amd/amd8111e.c
@@ -1900,7 +1900,7 @@ static int amd8111e_probe_one(struct pci_dev *pdev,
 
 	/* Initialize driver entry points */
 	dev->netdev_ops = &amd8111e_netdev_ops;
-	SET_ETHTOOL_OPS(dev, &ops);
+	dev->ethtool_ops = &ops;
 	dev->irq =pdev->irq;
 	dev->watchdog_timeo = AMD8111E_TX_TIMEOUT;
 	netif_napi_add(dev, &lp->napi, amd8111e_rx_poll, 32);
diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c
index a2bd91e..a78e4c1 100644
--- a/drivers/net/ethernet/amd/au1000_eth.c
+++ b/drivers/net/ethernet/amd/au1000_eth.c
@@ -1229,7 +1229,7 @@ static int au1000_probe(struct platform_device *pdev)
 	dev->base_addr = base->start;
 	dev->irq = irq;
 	dev->netdev_ops = &au1000_netdev_ops;
-	SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops);
+	dev->ethtool_ops = &au1000_ethtool_ops;
 	dev->watchdog_timeo = ETH_TX_TIMEOUT;
 
 	/*
diff --git a/drivers/net/ethernet/amd/nmclan_cs.c b/drivers/net/ethernet/amd/nmclan_cs.c
index 08569fe..abf3b15 100644
--- a/drivers/net/ethernet/amd/nmclan_cs.c
+++ b/drivers/net/ethernet/amd/nmclan_cs.c
@@ -457,7 +457,7 @@ static int nmclan_probe(struct pcmcia_device *link)
     lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
 
     dev->netdev_ops = &mace_netdev_ops;
-    SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
+    dev->ethtool_ops = &netdev_ethtool_ops;
     dev->watchdog_timeo = TX_TIMEOUT;
 
     return nmclan_config(link);
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index 17bb9ce..49faa97 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -1302,7 +1302,7 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	}
 
 	netdev->netdev_ops = &alx_netdev_ops;
-	SET_ETHTOOL_OPS(netdev, &alx_ethtool_ops);
+	netdev->ethtool_ops = &alx_ethtool_ops;
 	netdev->irq = pdev->irq;
 	netdev->watchdog_timeo = ALX_WATCHDOG_TIME;
 
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
index 859ea84..ecacaae 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
@@ -305,5 +305,5 @@ static const struct ethtool_ops atl1c_ethtool_ops = {
 
 void atl1c_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &atl1c_ethtool_ops);
+	netdev->ethtool_ops = &atl1c_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c b/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
index 82b2386..206e9b7 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
@@ -388,5 +388,5 @@ static const struct ethtool_ops atl1e_ethtool_ops = {
 
 void atl1e_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &atl1e_ethtool_ops);
+	netdev->ethtool_ops = &atl1e_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index 78befb5..2587fed 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -1396,7 +1396,7 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	atl2_setup_pcicmd(pdev);
 
 	netdev->netdev_ops = &atl2_netdev_ops;
-	SET_ETHTOOL_OPS(netdev, &atl2_ethtool_ops);
+	netdev->ethtool_ops = &atl2_ethtool_ops;
 	netdev->watchdog_timeo = 5 * HZ;
 	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
 
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index 05ba625..ca5a20a 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -2380,7 +2380,7 @@ static int b44_init_one(struct ssb_device *sdev,
 	netif_napi_add(dev, &bp->napi, b44_poll, 64);
 	dev->watchdog_timeo = B44_TX_TIMEOUT;
 	dev->irq = sdev->irq;
-	SET_ETHTOOL_OPS(dev, &b44_ethtool_ops);
+	dev->ethtool_ops = &b44_ethtool_ops;
 
 	err = ssb_bus_powerup(sdev->bus, 0);
 	if (err) {
diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
index a7d11f5..1e7bba9c 100644
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -1898,7 +1898,7 @@ static int bcm_enet_probe(struct platform_device *pdev)
 	dev->netdev_ops = &bcm_enet_ops;
 	netif_napi_add(dev, &priv->napi, bcm_enet_poll, 16);
 
-	SET_ETHTOOL_OPS(dev, &bcm_enet_ethtool_ops);
+	dev->ethtool_ops = &bcm_enet_ethtool_ops;
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	ret = register_netdev(dev);
@@ -2784,7 +2784,7 @@ static int bcm_enetsw_probe(struct platform_device *pdev)
 	/* register netdevice */
 	dev->netdev_ops = &bcm_enetsw_ops;
 	netif_napi_add(dev, &priv->napi, bcm_enet_poll, 16);
-	SET_ETHTOOL_OPS(dev, &bcm_enetsw_ethtool_ops);
+	dev->ethtool_ops = &bcm_enetsw_ethtool_ops;
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	spin_lock_init(&priv->enetsw_mdio_lock);
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index 0297a79..05c6af6 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1436,7 +1436,7 @@ static int bgmac_probe(struct bcma_device *core)
 		return -ENOMEM;
 	net_dev->netdev_ops = &bgmac_netdev_ops;
 	net_dev->irq = core->irq;
-	SET_ETHTOOL_OPS(net_dev, &bgmac_ethtool_ops);
+	net_dev->ethtool_ops = &bgmac_ethtool_ops;
 	bgmac = netdev_priv(net_dev);
 	bgmac->net_dev = net_dev;
 	bgmac->core = core;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index b6de05e..0322409 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -3506,8 +3506,6 @@ static const struct ethtool_ops bnx2x_vf_ethtool_ops = {
 
 void bnx2x_set_ethtool_ops(struct bnx2x *bp, struct net_device *netdev)
 {
-	if (IS_PF(bp))
-		SET_ETHTOOL_OPS(netdev, &bnx2x_ethtool_ops);
-	else /* vf */
-		SET_ETHTOOL_OPS(netdev, &bnx2x_vf_ethtool_ops);
+	netdev->ethtool_ops = (IS_PF(bp)) ?
+		&bnx2x_ethtool_ops : &bnx2x_vf_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 0966bd0..5ba1cfb 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -2481,7 +2481,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
 	dev_set_drvdata(&pdev->dev, dev);
 	ether_addr_copy(dev->dev_addr, macaddr);
 	dev->watchdog_timeo = 2 * HZ;
-	SET_ETHTOOL_OPS(dev, &bcmgenet_ethtool_ops);
+	dev->ethtool_ops = &bcmgenet_ethtool_ops;
 	dev->netdev_ops = &bcmgenet_netdev_ops;
 	netif_napi_add(dev, &priv->napi, bcmgenet_poll, 64);
 
diff --git a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
index f9e1508..adca62b 100644
--- a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
+++ b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
@@ -1137,5 +1137,5 @@ static const struct ethtool_ops bnad_ethtool_ops = {
 void
 bnad_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &bnad_ethtool_ops);
+	netdev->ethtool_ops = &bnad_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 521dfea..25d6b2a 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -1737,7 +1737,7 @@ static int xgmac_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, ndev);
 	ether_setup(ndev);
 	ndev->netdev_ops = &xgmac_netdev_ops;
-	SET_ETHTOOL_OPS(ndev, &xgmac_ethtool_ops);
+	ndev->ethtool_ops = &xgmac_ethtool_ops;
 	spin_lock_init(&priv->stats_lock);
 	INIT_WORK(&priv->tx_timeout_work, xgmac_tx_timeout_work);
 
diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index 0fe7ff7..c1b2c1d 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -1100,7 +1100,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 		netif_napi_add(netdev, &adapter->napi, t1_poll, 64);
 
-		SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops);
+		netdev->ethtool_ops = &t1_ethtool_ops;
 	}
 
 	if (t1_init_sw_modules(adapter, bi) < 0) {
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 07bbb71..3ed5079 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -3291,7 +3291,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 			netdev->features |= NETIF_F_HIGHDMA;
 
 		netdev->netdev_ops = &cxgb_netdev_ops;
-		SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops);
+		netdev->ethtool_ops = &cxgb_ethtool_ops;
 	}
 
 	pci_set_drvdata(pdev, adapter);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 6fe5891..7c61f89 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -6074,7 +6074,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev->priv_flags |= IFF_UNICAST_FLT;
 
 		netdev->netdev_ops = &cxgb4_netdev_ops;
-		SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops);
+		netdev->ethtool_ops = &cxgb_ethtool_ops;
 	}
 
 	pci_set_drvdata(pdev, adapter);
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index 5285928..ff1cdd1 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -2664,7 +2664,7 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
 		netdev->priv_flags |= IFF_UNICAST_FLT;
 
 		netdev->netdev_ops = &cxgb4vf_netdev_ops;
-		SET_ETHTOOL_OPS(netdev, &cxgb4vf_ethtool_ops);
+		netdev->ethtool_ops = &cxgb4vf_ethtool_ops;
 
 		/*
 		 * Initialize the hardware/software state for the port.
diff --git a/drivers/net/ethernet/cisco/enic/enic_ethtool.c b/drivers/net/ethernet/cisco/enic/enic_ethtool.c
index 47e3562..58a8c67 100644
--- a/drivers/net/ethernet/cisco/enic/enic_ethtool.c
+++ b/drivers/net/ethernet/cisco/enic/enic_ethtool.c
@@ -253,5 +253,5 @@ static const struct ethtool_ops enic_ethtool_ops = {
 
 void enic_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &enic_ethtool_ops);
+	netdev->ethtool_ops = &enic_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c
index 1642de7..8616608 100644
--- a/drivers/net/ethernet/dec/tulip/tulip_core.c
+++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
@@ -1703,7 +1703,7 @@ static int tulip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 #ifdef CONFIG_TULIP_NAPI
 	netif_napi_add(dev, &tp->napi, tulip_poll, 16);
 #endif
-	SET_ETHTOOL_OPS(dev, &ops);
+	dev->ethtool_ops = &ops;
 
 	if (register_netdev(dev))
 		goto err_out_free_ring;
diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c
index 4fb756d..2324f2d 100644
--- a/drivers/net/ethernet/dlink/dl2k.c
+++ b/drivers/net/ethernet/dlink/dl2k.c
@@ -227,7 +227,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
 	}
 	dev->netdev_ops = &netdev_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
-	SET_ETHTOOL_OPS(dev, &ethtool_ops);
+	dev->ethtool_ops = &ethtool_ops;
 #if 0
 	dev->features = NETIF_F_IP_CSUM;
 #endif
diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c
index d9e5ca0..433c1e1 100644
--- a/drivers/net/ethernet/dlink/sundance.c
+++ b/drivers/net/ethernet/dlink/sundance.c
@@ -577,7 +577,7 @@ static int sundance_probe1(struct pci_dev *pdev,
 
 	/* The chip-specific entries in the device structure. */
 	dev->netdev_ops = &netdev_ops;
-	SET_ETHTOOL_OPS(dev, &ethtool_ops);
+	dev->ethtool_ops = &ethtool_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
 	pci_set_drvdata(pdev, dev);
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index a186454..9a9e7c7 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -4301,7 +4301,7 @@ static void be_netdev_init(struct net_device *netdev)
 
 	netdev->netdev_ops = &be_netdev_ops;
 
-	SET_ETHTOOL_OPS(netdev, &be_ethtool_ops);
+	netdev->ethtool_ops = &be_ethtool_ops;
 }
 
 static void be_unmap_pci_bars(struct be_adapter *adapter)
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 68069ea..c77fa4a 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1210,7 +1210,7 @@ static int ftgmac100_probe(struct platform_device *pdev)
 
 	SET_NETDEV_DEV(netdev, &pdev->dev);
 
-	SET_ETHTOOL_OPS(netdev, &ftgmac100_ethtool_ops);
+	netdev->ethtool_ops = &ftgmac100_ethtool_ops;
 	netdev->netdev_ops = &ftgmac100_netdev_ops;
 	netdev->features = NETIF_F_IP_CSUM | NETIF_F_GRO;
 
diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c
index 8be5b40..4ff1adc 100644
--- a/drivers/net/ethernet/faraday/ftmac100.c
+++ b/drivers/net/ethernet/faraday/ftmac100.c
@@ -1085,7 +1085,7 @@ static int ftmac100_probe(struct platform_device *pdev)
 	}
 
 	SET_NETDEV_DEV(netdev, &pdev->dev);
-	SET_ETHTOOL_OPS(netdev, &ftmac100_ethtool_ops);
+	netdev->ethtool_ops = &ftmac100_ethtool_ops;
 	netdev->netdev_ops = &ftmac100_netdev_ops;
 
 	platform_set_drvdata(pdev, netdev);
diff --git a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
index 413329e..cc83350 100644
--- a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
+++ b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
@@ -417,5 +417,5 @@ static const struct ethtool_ops uec_ethtool_ops = {
 
 void uec_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &uec_ethtool_ops);
+	netdev->ethtool_ops = &uec_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
index 7becab1..cfe7a74 100644
--- a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
+++ b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
@@ -256,7 +256,7 @@ static int fmvj18x_probe(struct pcmcia_device *link)
     dev->netdev_ops = &fjn_netdev_ops;
     dev->watchdog_timeo = TX_TIMEOUT;
 
-    SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
+    dev->ethtool_ops = &netdev_ethtool_ops;
 
     return fmvj18x_config(link);
 } /* fmvj18x_attach */
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c b/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c
index 95837b9..6055e3e 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c
@@ -278,5 +278,5 @@ static const struct ethtool_ops ehea_ethtool_ops = {
 
 void ehea_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &ehea_ethtool_ops);
+	netdev->ethtool_ops = &ehea_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index ae342fd..87bd953 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -2879,7 +2879,7 @@ static int emac_probe(struct platform_device *ofdev)
 		dev->commac.ops = &emac_commac_sg_ops;
 	} else
 		ndev->netdev_ops = &emac_netdev_ops;
-	SET_ETHTOOL_OPS(ndev, &emac_ethtool_ops);
+	ndev->ethtool_ops = &emac_ethtool_ops;
 
 	netif_carrier_off(ndev);
 
diff --git a/drivers/net/ethernet/icplus/ipg.c b/drivers/net/ethernet/icplus/ipg.c
index 25045ae..5727779 100644
--- a/drivers/net/ethernet/icplus/ipg.c
+++ b/drivers/net/ethernet/icplus/ipg.c
@@ -2245,7 +2245,7 @@ static int ipg_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	 */
 	dev->netdev_ops = &ipg_netdev_ops;
 	SET_NETDEV_DEV(dev, &pdev->dev);
-	SET_ETHTOOL_OPS(dev, &ipg_ethtool_ops);
+	dev->ethtool_ops = &ipg_ethtool_ops;
 
 	rc = pci_request_regions(pdev, DRV_NAME);
 	if (rc)
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
index b56461c..9d979d7 100644
--- a/drivers/net/ethernet/intel/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -2854,7 +2854,7 @@ static int e100_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev->hw_features |= NETIF_F_RXALL;
 
 	netdev->netdev_ops = &e100_netdev_ops;
-	SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops);
+	netdev->ethtool_ops = &e100_ethtool_ops;
 	netdev->watchdog_timeo = E100_WATCHDOG_PERIOD;
 	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
 
diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
index 73a8aee..341889a 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
@@ -1905,5 +1905,5 @@ static const struct ethtool_ops e1000_ethtool_ops = {
 
 void e1000_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops);
+	netdev->ethtool_ops = &e1000_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
index cad250b..d9f8a2d 100644
--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -2315,5 +2315,5 @@ static const struct ethtool_ops e1000_ethtool_ops = {
 
 void e1000e_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops);
+	netdev->ethtool_ops = &e1000_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index 03d99cb..7673f86 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -1692,5 +1692,5 @@ static const struct ethtool_ops i40e_ethtool_ops = {
 
 void i40e_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &i40e_ethtool_ops);
+	netdev->ethtool_ops = &i40e_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
index 8b0db1c..4defd51 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
@@ -389,5 +389,5 @@ static struct ethtool_ops i40evf_ethtool_ops = {
  **/
 void i40evf_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &i40evf_ethtool_ops);
+	netdev->ethtool_ops = &i40evf_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index e5570ac..30b76e1 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -3029,5 +3029,5 @@ static const struct ethtool_ops igb_ethtool_ops = {
 
 void igb_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &igb_ethtool_ops);
+	netdev->ethtool_ops = &igb_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/intel/igbvf/ethtool.c b/drivers/net/ethernet/intel/igbvf/ethtool.c
index 90eef07..f58170b 100644
--- a/drivers/net/ethernet/intel/igbvf/ethtool.c
+++ b/drivers/net/ethernet/intel/igbvf/ethtool.c
@@ -476,5 +476,5 @@ static const struct ethtool_ops igbvf_ethtool_ops = {
 
 void igbvf_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &igbvf_ethtool_ops);
+	netdev->ethtool_ops = &igbvf_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c b/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c
index dbb7dd2..1da2d98 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c
@@ -656,5 +656,5 @@ static const struct ethtool_ops ixgb_ethtool_ops = {
 
 void ixgb_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &ixgb_ethtool_ops);
+	netdev->ethtool_ops = &ixgb_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index 6c55c14..31d7268 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -3099,5 +3099,5 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
 
 void ixgbe_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &ixgbe_ethtool_ops);
+	netdev->ethtool_ops = &ixgbe_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
index 1baecb6..a757f07 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
@@ -813,5 +813,5 @@ static const struct ethtool_ops ixgbevf_ethtool_ops = {
 
 void ixgbevf_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &ixgbevf_ethtool_ops);
+	netdev->ethtool_ops = &ixgbevf_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index b7b8d74..df1d1b9 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -2889,7 +2889,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
 	if (err)
 		goto out;
 
-	SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops);
+	dev->ethtool_ops = &mv643xx_eth_ethtool_ops;
 
 	init_pscr(mp, pd->speed, pd->duplex);
 
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 14786c8..72bc47f 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -2813,7 +2813,7 @@ static int mvneta_probe(struct platform_device *pdev)
 	dev->watchdog_timeo = 5 * HZ;
 	dev->netdev_ops = &mvneta_netdev_ops;
 
-	SET_ETHTOOL_OPS(dev, &mvneta_eth_tool_ops);
+	dev->ethtool_ops = &mvneta_eth_tool_ops;
 
 	pp = netdev_priv(dev);
 
diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index b358c2f..8f5aa7c 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -1488,7 +1488,7 @@ static int pxa168_eth_probe(struct platform_device *pdev)
 	dev->netdev_ops = &pxa168_eth_netdev_ops;
 	dev->watchdog_timeo = 2 * HZ;
 	dev->base_addr = 0;
-	SET_ETHTOOL_OPS(dev, &pxa168_ethtool_ops);
+	dev->ethtool_ops = &pxa168_ethtool_ops;
 
 	INIT_WORK(&pep->tx_timeout_task, pxa168_eth_tx_timeout_task);
 
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index b811064..6969338 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -4760,7 +4760,7 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,
 
 	SET_NETDEV_DEV(dev, &hw->pdev->dev);
 	dev->irq = hw->pdev->irq;
-	SET_ETHTOOL_OPS(dev, &sky2_ethtool_ops);
+	dev->ethtool_ops = &sky2_ethtool_ops;
 	dev->watchdog_timeo = TX_WATCHDOG;
 	dev->netdev_ops = &sky2_netdev_ops[port];
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 7e4b172..36af5e7 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2539,7 +2539,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	netif_set_real_num_tx_queues(dev, priv->tx_ring_num);
 	netif_set_real_num_rx_queues(dev, priv->rx_ring_num);
 
-	SET_ETHTOOL_OPS(dev, &mlx4_en_ethtool_ops);
+	dev->ethtool_ops = &mlx4_en_ethtool_ops;
 
 	/*
 	 * Set driver features
diff --git a/drivers/net/ethernet/micrel/ks8695net.c b/drivers/net/ethernet/micrel/ks8695net.c
index 16435b3..6c7c78ba 100644
--- a/drivers/net/ethernet/micrel/ks8695net.c
+++ b/drivers/net/ethernet/micrel/ks8695net.c
@@ -1504,15 +1504,15 @@ ks8695_probe(struct platform_device *pdev)
 	if (ksp->phyiface_regs && ksp->link_irq == -1) {
 		ks8695_init_switch(ksp);
 		ksp->dtype = KS8695_DTYPE_LAN;
-		SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops);
+		ndev->ethtool_ops = &ks8695_ethtool_ops;
 	} else if (ksp->phyiface_regs && ksp->link_irq != -1) {
 		ks8695_init_wan_phy(ksp);
 		ksp->dtype = KS8695_DTYPE_WAN;
-		SET_ETHTOOL_OPS(ndev, &ks8695_wan_ethtool_ops);
+		ndev->ethtool_ops = &ks8695_wan_ethtool_ops;
 	} else {
 		/* No initialisation since HPNA does not have a PHY */
 		ksp->dtype = KS8695_DTYPE_HPNA;
-		SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops);
+		ndev->ethtool_ops = &ks8695_ethtool_ops;
 	}
 
 	/* And bring up the net_device with the net core */
diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
index e0c92e0..13767eb 100644
--- a/drivers/net/ethernet/micrel/ks8851.c
+++ b/drivers/net/ethernet/micrel/ks8851.c
@@ -1471,7 +1471,7 @@ static int ks8851_probe(struct spi_device *spi)
 
 	skb_queue_head_init(&ks->txq);
 
-	SET_ETHTOOL_OPS(ndev, &ks8851_ethtool_ops);
+	ndev->ethtool_ops = &ks8851_ethtool_ops;
 	SET_NETDEV_DEV(ndev, &spi->dev);
 
 	spi_set_drvdata(spi, ks);
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
index 14ac0e2..4b9592c1 100644
--- a/drivers/net/ethernet/micrel/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -7106,7 +7106,7 @@ static int pcidev_init(struct pci_dev *pdev, const struct pci_device_id *id)
 		}
 
 		dev->netdev_ops = &netdev_ops;
-		SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
+		dev->ethtool_ops = &netdev_ethtool_ops;
 		if (register_netdev(dev))
 			goto pcidev_init_reg_err;
 		port_set_power_saving(port, true);
diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c
index c7b40aa..b1b5f66 100644
--- a/drivers/net/ethernet/microchip/enc28j60.c
+++ b/drivers/net/ethernet/microchip/enc28j60.c
@@ -1593,7 +1593,7 @@ static int enc28j60_probe(struct spi_device *spi)
 	dev->irq = spi->irq;
 	dev->netdev_ops = &enc28j60_netdev_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
-	SET_ETHTOOL_OPS(dev, &enc28j60_ethtool_ops);
+	dev->ethtool_ops = &enc28j60_ethtool_ops;
 
 	enc28j60_lowpower(priv, true);
 
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 130f6b2..f3d5d79 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -4112,7 +4112,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer,
 		    (unsigned long)mgp);
 
-	SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops);
+	netdev->ethtool_ops = &myri10ge_ethtool_ops;
 	INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog);
 	status = register_netdev(netdev);
 	if (status != 0) {
diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c
index 64ec2a4..291fba8 100644
--- a/drivers/net/ethernet/natsemi/natsemi.c
+++ b/drivers/net/ethernet/natsemi/natsemi.c
@@ -927,7 +927,7 @@ static int natsemi_probe1(struct pci_dev *pdev, const struct pci_device_id *ent)
 	dev->netdev_ops = &natsemi_netdev_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
-	SET_ETHTOOL_OPS(dev, &ethtool_ops);
+	dev->ethtool_ops = &ethtool_ops;
 
 	if (mtu)
 		dev->mtu = mtu;
diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c
index dbccf1d..19bb824 100644
--- a/drivers/net/ethernet/natsemi/ns83820.c
+++ b/drivers/net/ethernet/natsemi/ns83820.c
@@ -2030,7 +2030,7 @@ static int ns83820_init_one(struct pci_dev *pci_dev,
 		pci_dev->subsystem_vendor, pci_dev->subsystem_device);
 
 	ndev->netdev_ops = &netdev_ops;
-	SET_ETHTOOL_OPS(ndev, &ops);
+	ndev->ethtool_ops = &ops;
 	ndev->watchdog_timeo = 5 * HZ;
 	pci_set_drvdata(pci_dev, ndev);
 
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index a2844ff..190538d 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -7919,7 +7919,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 
 	/*  Driver entry points */
 	dev->netdev_ops = &s2io_netdev_ops;
-	SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
+	dev->ethtool_ops = &netdev_ethtool_ops;
 	dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
 		NETIF_F_TSO | NETIF_F_TSO6 |
 		NETIF_F_RXCSUM | NETIF_F_LRO;
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-ethtool.c b/drivers/net/ethernet/neterion/vxge/vxge-ethtool.c
index f8f0738..ddcc81a 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-ethtool.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-ethtool.c
@@ -1128,5 +1128,5 @@ static const struct ethtool_ops vxge_ethtool_ops = {
 
 void vxge_initialize_ethtool_ops(struct net_device *ndev)
 {
-	SET_ETHTOOL_OPS(ndev, &vxge_ethtool_ops);
+	ndev->ethtool_ops = &vxge_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index fddb464..e8235c5 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -5766,7 +5766,7 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 		dev->netdev_ops = &nv_netdev_ops_optimized;
 
 	netif_napi_add(dev, &np->napi, nv_napi_poll, RX_WORK_PER_LOOP);
-	SET_ETHTOOL_OPS(dev, &ops);
+	dev->ethtool_ops = &ops;
 	dev->watchdog_timeo = NV_WATCHDOG_TIMEO;
 
 	pci_set_drvdata(pci_dev, dev);
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c
index 826f0cc..114d2fe 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c
@@ -508,5 +508,5 @@ static const struct ethtool_ops pch_gbe_ethtool_ops = {
 
 void pch_gbe_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &pch_gbe_ethtool_ops);
+	netdev->ethtool_ops = &pch_gbe_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/packetengines/hamachi.c b/drivers/net/ethernet/packetengines/hamachi.c
index b6bdeb3..9a997e4 100644
--- a/drivers/net/ethernet/packetengines/hamachi.c
+++ b/drivers/net/ethernet/packetengines/hamachi.c
@@ -724,10 +724,8 @@ static int hamachi_init_one(struct pci_dev *pdev,
 
 	/* The Hamachi-specific entries in the device structure. */
 	dev->netdev_ops = &hamachi_netdev_ops;
-	if (chip_tbl[hmp->chip_id].flags & CanHaveMII)
-		SET_ETHTOOL_OPS(dev, &ethtool_ops);
-	else
-		SET_ETHTOOL_OPS(dev, &ethtool_ops_no_mii);
+	dev->ethtool_ops = (chip_tbl[hmp->chip_id].flags & CanHaveMII) ?
+		&ethtool_ops : &ethtool_ops_no_mii;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	if (mtu)
 		dev->mtu = mtu;
diff --git a/drivers/net/ethernet/packetengines/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c
index 9a6cb48..69a8dc0 100644
--- a/drivers/net/ethernet/packetengines/yellowfin.c
+++ b/drivers/net/ethernet/packetengines/yellowfin.c
@@ -472,7 +472,7 @@ static int yellowfin_init_one(struct pci_dev *pdev,
 
 	/* The Yellowfin-specific entries in the device structure. */
 	dev->netdev_ops = &netdev_ops;
-	SET_ETHTOOL_OPS(dev, &ethtool_ops);
+	dev->ethtool_ops = &ethtool_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
 	if (mtu)
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index f09c35d..5bf0581 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -1373,7 +1373,7 @@ netxen_setup_netdev(struct netxen_adapter *adapter,
 
 	netxen_nic_change_mtu(netdev, netdev->mtu);
 
-	SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops);
+	netdev->ethtool_ops = &netxen_nic_ethtool_ops;
 
 	netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
 	                      NETIF_F_RXCSUM;
diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
index 2eabd44..b5d6bc1 100644
--- a/drivers/net/ethernet/qlogic/qla3xxx.c
+++ b/drivers/net/ethernet/qlogic/qla3xxx.c
@@ -3838,7 +3838,7 @@ static int ql3xxx_probe(struct pci_dev *pdev,
 
 	/* Set driver entry points */
 	ndev->netdev_ops = &ql3xxx_netdev_ops;
-	SET_ETHTOOL_OPS(ndev, &ql3xxx_ethtool_ops);
+	ndev->ethtool_ops = &ql3xxx_ethtool_ops;
 	ndev->watchdog_timeo = 5 * HZ;
 
 	netif_napi_add(ndev, &qdev->napi, ql_poll, 64);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index dbf7539..4bdbdca 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -2222,10 +2222,8 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
 
 	qlcnic_change_mtu(netdev, netdev->mtu);
 
-	if (qlcnic_sriov_vf_check(adapter))
-		SET_ETHTOOL_OPS(netdev, &qlcnic_sriov_vf_ethtool_ops);
-	else
-		SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops);
+	netdev->ethtool_ops = (qlcnic_sriov_vf_check(adapter)) ?
+		&qlcnic_sriov_vf_ethtool_ops : &qlcnic_ethtool_ops;
 
 	netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
 			     NETIF_F_IPV6_CSUM | NETIF_F_GRO |
@@ -2630,7 +2628,7 @@ err_out_disable_pdev:
 err_out_maintenance_mode:
 	set_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state);
 	netdev->netdev_ops = &qlcnic_netdev_failed_ops;
-	SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_failed_ops);
+	netdev->ethtool_ops = &qlcnic_ethtool_failed_ops;
 	ahw->port_type = QLCNIC_XGBE;
 
 	if (qlcnic_83xx_check(adapter))
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index 0a1d76a..79b86e9 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -4770,7 +4770,7 @@ static int qlge_probe(struct pci_dev *pdev,
 	ndev->irq = pdev->irq;
 
 	ndev->netdev_ops = &qlge_netdev_ops;
-	SET_ETHTOOL_OPS(ndev, &qlge_ethtool_ops);
+	ndev->ethtool_ops = &qlge_ethtool_ops;
 	ndev->watchdog_timeo = 10 * HZ;
 
 	err = register_netdev(ndev);
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index aa1c079..be425ad 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -7125,7 +7125,7 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	for (i = 0; i < ETH_ALEN; i++)
 		dev->dev_addr[i] = RTL_R8(MAC0 + i);
 
-	SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops);
+	dev->ethtool_ops = &rtl8169_ethtool_ops;
 	dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
 
 	netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT);
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 6a9509c..967314c 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -2843,7 +2843,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 		ndev->netdev_ops = &sh_eth_netdev_ops_tsu;
 	else
 		ndev->netdev_ops = &sh_eth_netdev_ops;
-	SET_ETHTOOL_OPS(ndev, &sh_eth_ethtool_ops);
+	ndev->ethtool_ops = &sh_eth_ethtool_ops;
 	ndev->watchdog_timeo = TX_TIMEOUT;
 
 	/* debug message level */
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c
index 0415fa5..c0981ae 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c
@@ -520,5 +520,5 @@ static const struct ethtool_ops sxgbe_ethtool_ops = {
 
 void sxgbe_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &sxgbe_ethtool_ops);
+	netdev->ethtool_ops = &sxgbe_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 63d595f..1e27404 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -2248,7 +2248,7 @@ static int efx_register_netdev(struct efx_nic *efx)
 	} else {
 		net_dev->netdev_ops = &efx_farch_netdev_ops;
 	}
-	SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops);
+	net_dev->ethtool_ops = &efx_ethtool_ops;
 	net_dev->gso_max_segs = EFX_TSO_MAX_SEGS;
 
 	rtnl_lock();
diff --git a/drivers/net/ethernet/sis/sis190.c b/drivers/net/ethernet/sis/sis190.c
index acbbe48..a863399 100644
--- a/drivers/net/ethernet/sis/sis190.c
+++ b/drivers/net/ethernet/sis/sis190.c
@@ -1877,7 +1877,7 @@ static int sis190_init_one(struct pci_dev *pdev,
 
 	dev->netdev_ops = &sis190_netdev_ops;
 
-	SET_ETHTOOL_OPS(dev, &sis190_ethtool_ops);
+	dev->ethtool_ops = &sis190_ethtool_ops;
 	dev->watchdog_timeo = SIS190_TX_TIMEOUT;
 
 	spin_lock_init(&tp->lock);
diff --git a/drivers/net/ethernet/smsc/smc91c92_cs.c b/drivers/net/ethernet/smsc/smc91c92_cs.c
index c7a4868..6b33127 100644
--- a/drivers/net/ethernet/smsc/smc91c92_cs.c
+++ b/drivers/net/ethernet/smsc/smc91c92_cs.c
@@ -318,7 +318,7 @@ static int smc91c92_probe(struct pcmcia_device *link)
 
     /* The SMC91c92-specific entries in the device structure. */
     dev->netdev_ops = &smc_netdev_ops;
-    SET_ETHTOOL_OPS(dev, &ethtool_ops);
+    dev->ethtool_ops = &ethtool_ops;
     dev->watchdog_timeo = TX_TIMEOUT;
 
     smc->mii_if.dev = dev;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index c5f9cb8..c963394 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -784,5 +784,5 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
 
 void stmmac_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &stmmac_ethtool_ops);
+	netdev->ethtool_ops = &stmmac_ethtool_ops;
 }
diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c
index 2ead877..38da73a 100644
--- a/drivers/net/ethernet/tehuti/tehuti.c
+++ b/drivers/net/ethernet/tehuti/tehuti.c
@@ -2413,7 +2413,7 @@ static void bdx_set_ethtool_ops(struct net_device *netdev)
 		.get_ethtool_stats = bdx_get_ethtool_stats,
 	};
 
-	SET_ETHTOOL_OPS(netdev, &bdx_ethtool_ops);
+	netdev->ethtool_ops = &bdx_ethtool_ops;
 }
 
 /**
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 36aa109..6ecab3c 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -1975,7 +1975,7 @@ static int cpsw_probe_dual_emac(struct platform_device *pdev,
 	ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 
 	ndev->netdev_ops = &cpsw_netdev_ops;
-	SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops);
+	ndev->ethtool_ops = &cpsw_ethtool_ops;
 	netif_napi_add(ndev, &priv_sl2->napi, cpsw_poll, CPSW_POLL_WEIGHT);
 
 	/* register the network device */
@@ -2204,7 +2204,7 @@ static int cpsw_probe(struct platform_device *pdev)
 	ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 
 	ndev->netdev_ops = &cpsw_netdev_ops;
-	SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops);
+	ndev->ethtool_ops = &cpsw_ethtool_ops;
 	netif_napi_add(ndev, &priv->napi, cpsw_poll, CPSW_POLL_WEIGHT);
 
 	/* register the network device */
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 8f0e69c..e76eae5 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1980,7 +1980,7 @@ static int davinci_emac_probe(struct platform_device *pdev)
 	}
 
 	ndev->netdev_ops = &emac_netdev_ops;
-	SET_ETHTOOL_OPS(ndev, &ethtool_ops);
+	ndev->ethtool_ops = &ethtool_ops;
 	netif_napi_add(ndev, &priv->napi, emac_poll, EMAC_POLL_WEIGHT);
 
 	/* register the network device */
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 31e55fb..2170db5 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -715,7 +715,7 @@ static int netvsc_probe(struct hv_device *dev,
 	net->features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG | NETIF_F_RXCSUM |
 			NETIF_F_IP_CSUM | NETIF_F_TSO;
 
-	SET_ETHTOOL_OPS(net, &ethtool_ops);
+	net->ethtool_ops = &ethtool_ops;
 	SET_NETDEV_DEV(net, &dev->device);
 
 	/* Notify the netvsc driver of the new device */
diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c
index 63aa9d9..27536aa 100644
--- a/drivers/net/ntb_netdev.c
+++ b/drivers/net/ntb_netdev.c
@@ -348,7 +348,7 @@ static int ntb_netdev_probe(struct pci_dev *pdev)
 	memcpy(ndev->dev_addr, ndev->perm_addr, ndev->addr_len);
 
 	ndev->netdev_ops = &ntb_netdev_ops;
-	SET_ETHTOOL_OPS(ndev, &ntb_ethtool_ops);
+	ndev->ethtool_ops = &ntb_ethtool_ops;
 
 	dev->qp = ntb_transport_create_queue(ndev, pdev, &ntb_netdev_handlers);
 	if (!dev->qp) {
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index a849718..dac7a0d 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -494,7 +494,7 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
 	ndev->mtu = RIO_MAX_MSG_SIZE - 14;
 	ndev->features = NETIF_F_LLTX;
 	SET_NETDEV_DEV(ndev, &mport->dev);
-	SET_ETHTOOL_OPS(ndev, &rionet_ethtool_ops);
+	ndev->ethtool_ops = &rionet_ethtool_ops;
 
 	spin_lock_init(&rnet->lock);
 	spin_lock_init(&rnet->tx_lock);
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
index 630caf4..8cfc3bb 100644
--- a/drivers/net/usb/catc.c
+++ b/drivers/net/usb/catc.c
@@ -793,7 +793,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
 
 	netdev->netdev_ops = &catc_netdev_ops;
 	netdev->watchdog_timeo = TX_TIMEOUT;
-	SET_ETHTOOL_OPS(netdev, &ops);
+	netdev->ethtool_ops = &ops;
 
 	catc->usbdev = usbdev;
 	catc->netdev = netdev;
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 660bd5e..a3a0586 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -2425,7 +2425,7 @@ static void hso_net_init(struct net_device *net)
 	net->type = ARPHRD_NONE;
 	net->mtu = DEFAULT_MTU - 14;
 	net->tx_queue_len = 10;
-	SET_ETHTOOL_OPS(net, &ops);
+	net->ethtool_ops = &ops;
 
 	/* and initialize the semaphore */
 	spin_lock_init(&hso_net->net_lock);
diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c
index 421934c..f725707 100644
--- a/drivers/net/usb/ipheth.c
+++ b/drivers/net/usb/ipheth.c
@@ -524,7 +524,7 @@ static int ipheth_probe(struct usb_interface *intf,
 	usb_set_intfdata(intf, dev);
 
 	SET_NETDEV_DEV(netdev, &intf->dev);
-	SET_ETHTOOL_OPS(netdev, &ops);
+	netdev->ethtool_ops = &ops;
 
 	retval = register_netdev(netdev);
 	if (retval) {
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index a359d3b..dcb6d33 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -1171,7 +1171,7 @@ err_fw:
 	netdev->netdev_ops = &kaweth_netdev_ops;
 	netdev->watchdog_timeo = KAWETH_TX_TIMEOUT;
 	netdev->mtu = le16_to_cpu(kaweth->configuration.segment_size);
-	SET_ETHTOOL_OPS(netdev, &ops);
+	netdev->ethtool_ops = &ops;
 
 	/* kaweth is zeroed as part of alloc_netdev */
 	INIT_DELAYED_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl);
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index 03e8a15..f840802 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -1159,7 +1159,7 @@ static int pegasus_probe(struct usb_interface *intf,
 
 	net->watchdog_timeo = PEGASUS_TX_TIMEOUT;
 	net->netdev_ops = &pegasus_netdev_ops;
-	SET_ETHTOOL_OPS(net, &ops);
+	net->ethtool_ops = &ops;
 	pegasus->mii.dev = net;
 	pegasus->mii.mdio_read = mdio_read;
 	pegasus->mii.mdio_write = mdio_write;
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 3fbfb08..9f91c7a 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -3452,7 +3452,7 @@ static int rtl8152_probe(struct usb_interface *intf,
 			      NETIF_F_TSO | NETIF_F_FRAGLIST |
 			      NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
 
-	SET_ETHTOOL_OPS(netdev, &ops);
+	netdev->ethtool_ops = &ops;
 	netif_set_gso_max_size(netdev, RTL_LIMITED_TSO_SIZE);
 
 	tp->mii.dev = netdev;
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index da2c458..6e87e57 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -878,7 +878,7 @@ static int rtl8150_probe(struct usb_interface *intf,
 	dev->netdev = netdev;
 	netdev->netdev_ops = &rtl8150_netdev_ops;
 	netdev->watchdog_timeo = RTL8150_TX_TIMEOUT;
-	SET_ETHTOOL_OPS(netdev, &ops);
+	netdev->ethtool_ops = &ops;
 	dev->intr_interval = 100;	/* 100ms */
 
 	if (!alloc_all_urbs(dev)) {
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 7b68746..3f83359 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -1646,7 +1646,7 @@ static int virtnet_probe(struct virtio_device *vdev)
 	dev->netdev_ops = &virtnet_netdev;
 	dev->features = NETIF_F_HIGHDMA;
 
-	SET_ETHTOOL_OPS(dev, &virtnet_ethtool_ops);
+	dev->ethtool_ops = &virtnet_ethtool_ops;
 	SET_NETDEV_DEV(dev, &vdev->dev);
 
 	/* Do we support "hardware" checksums? */
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index 600ab56..00e1202 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -635,5 +635,5 @@ static const struct ethtool_ops vmxnet3_ethtool_ops = {
 
 void vmxnet3_set_ethtool_ops(struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &vmxnet3_ethtool_ops);
+	netdev->ethtool_ops = &vmxnet3_ethtool_ops;
 }
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 82355d5..457359c 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -2706,7 +2706,7 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
 		return -EEXIST;
 	}
 
-	SET_ETHTOOL_OPS(dev, &vxlan_ethtool_ops);
+	dev->ethtool_ops = &vxlan_ethtool_ops;
 
 	/* create an fdb entry for a valid default destination */
 	if (!vxlan_addr_any(&vxlan->default_dst.remote_ip)) {
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 67db34e..52919ad 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -882,7 +882,7 @@ void hostap_setup_dev(struct net_device *dev, local_info_t *local,
 	dev->mtu = local->mtu;
 
 
-	SET_ETHTOOL_OPS(dev, &prism2_ethtool_ops);
+	dev->ethtool_ops = &prism2_ethtool_ops;
 
 }
 
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index ef05c5c..a755733 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -386,7 +386,7 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
 		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
 		NETIF_F_TSO | NETIF_F_TSO6;
 	dev->features = dev->hw_features | NETIF_F_RXCSUM;
-	SET_ETHTOOL_OPS(dev, &xenvif_ethtool_ops);
+	dev->ethtool_ops = &xenvif_ethtool_ops;
 
 	dev->tx_queue_len = XENVIF_QUEUE_LENGTH;
 
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 158b5e6..895355d 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1332,7 +1332,7 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
          */
 	netdev->features |= netdev->hw_features;
 
-	SET_ETHTOOL_OPS(netdev, &xennet_ethtool_ops);
+	netdev->ethtool_ops = &xennet_ethtool_ops;
 	SET_NETDEV_DEV(netdev, &dev->dev);
 
 	netif_set_gso_max_size(netdev, XEN_NETIF_MAX_TX_SIZE - MAX_TCP_HEADER);
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 8dea3f1..047b4da 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -964,10 +964,9 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
 	card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
 	card->dev->mtu = card->info.initial_mtu;
 	card->dev->netdev_ops = &qeth_l2_netdev_ops;
-	if (card->info.type != QETH_CARD_TYPE_OSN)
-		SET_ETHTOOL_OPS(card->dev, &qeth_l2_ethtool_ops);
-	else
-		SET_ETHTOOL_OPS(card->dev, &qeth_l2_osn_ops);
+	card->dev->ethtool_ops =
+		(card->info.type != QETH_CARD_TYPE_OSN) ?
+		&qeth_l2_ethtool_ops : &qeth_l2_osn_ops;
 	card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 	card->info.broadcast_capable = 1;
 	qeth_l2_request_initial_mac(card);
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 3524d34..0a59d24 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -3298,7 +3298,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 	card->dev->ml_priv = card;
 	card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
 	card->dev->mtu = card->info.initial_mtu;
-	SET_ETHTOOL_OPS(card->dev, &qeth_l3_ethtool_ops);
+	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;
diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c
index d329cf3..15e0f4d 100644
--- a/drivers/staging/et131x/et131x.c
+++ b/drivers/staging/et131x/et131x.c
@@ -4604,7 +4604,7 @@ static int et131x_pci_setup(struct pci_dev *pdev,
 	netdev->netdev_ops     = &et131x_netdev_ops;
 
 	SET_NETDEV_DEV(netdev, &pdev->dev);
-	SET_ETHTOOL_OPS(netdev, &et131x_ethtool_ops);
+	netdev->ethtool_ops = &et131x_ethtool_ops;
 
 	adapter = et131x_adapter_init(netdev, pdev);
 
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
index d6421b9..a6158be 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
@@ -2249,7 +2249,7 @@ struct net_device *init_ft1000_card(struct pcmcia_device *link,
 
 	ft1000InitProc(dev);
 	ft1000_card_present = 1;
-	SET_ETHTOOL_OPS(dev, &ops);
+	dev->ethtool_ops = &ops;
 	printk(KERN_INFO "ft1000: %s: addr 0x%04lx irq %d, MAC addr %pM\n",
 			dev->name, dev->base_addr, dev->irq, dev->dev_addr);
 	return dev;
diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c
index c83e337..9d95761 100644
--- a/drivers/staging/netlogic/xlr_net.c
+++ b/drivers/staging/netlogic/xlr_net.c
@@ -1066,7 +1066,7 @@ static int xlr_net_probe(struct platform_device *pdev)
 	xlr_set_rx_mode(ndev);
 
 	priv->num_rx_desc += MAX_NUM_DESC_SPILL;
-	SET_ETHTOOL_OPS(ndev, &xlr_ethtool_ops);
+	ndev->ethtool_ops = &xlr_ethtool_ops;
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 
 	/* Common registers, do one time initialization */
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index ff7214a..da9dd6b 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -469,7 +469,7 @@ int cvm_oct_common_init(struct net_device *dev)
 
 	/* We do our own locking, Linux doesn't need to */
 	dev->features |= NETIF_F_LLTX;
-	SET_ETHTOOL_OPS(dev, &cvm_oct_ethtool_ops);
+	dev->ethtool_ops = &cvm_oct_ethtool_ops;
 
 	cvm_oct_phy_setup_device(dev);
 	cvm_oct_set_mac_filter(dev);
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index b7d4f82..ce8e281 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -793,7 +793,7 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g,
 
 	net->netdev_ops = &eth_netdev_ops;
 
-	SET_ETHTOOL_OPS(net, &ops);
+	net->ethtool_ops = &ops;
 
 	dev->gadget = g;
 	SET_NETDEV_DEV(net, &g->dev);
@@ -850,7 +850,7 @@ struct net_device *gether_setup_name_default(const char *netname)
 
 	net->netdev_ops = &eth_netdev_ops;
 
-	SET_ETHTOOL_OPS(net, &ops);
+	net->ethtool_ops = &ops;
 	SET_NETDEV_DEVTYPE(net, &gadget_type);
 
 	return net;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 7ed3a3a..06071f7 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -56,9 +56,6 @@ struct device;
 struct phy_device;
 /* 802.11 specific */
 struct wireless_dev;
-					/* source back-compat hooks */
-#define SET_ETHTOOL_OPS(netdev,ops) \
-	( (netdev)->ethtool_ops = (ops) )
 
 void netdev_set_default_ethtool_ops(struct net_device *dev,
 				    const struct ethtool_ops *ops);
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 744a59b..e7ee65d 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -884,7 +884,7 @@ static void batadv_softif_init_early(struct net_device *dev)
 	/* generate random address */
 	eth_hw_addr_random(dev);
 
-	SET_ETHTOOL_OPS(dev, &batadv_ethtool_ops);
+	dev->ethtool_ops = &batadv_ethtool_ops;
 
 	memset(priv, 0, sizeof(*priv));
 }
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 3e2da2c..9212015 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -348,7 +348,7 @@ void br_dev_setup(struct net_device *dev)
 
 	dev->netdev_ops = &br_netdev_ops;
 	dev->destructor = br_dev_free;
-	SET_ETHTOOL_OPS(dev, &br_ethtool_ops);
+	dev->ethtool_ops = &br_ethtool_ops;
 	SET_NETDEV_DEVTYPE(dev, &br_type);
 	dev->tx_queue_len = 0;
 	dev->priv_flags = IFF_EBRIDGE;
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 02c0e17..64c5af0 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -346,7 +346,7 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent,
 		return slave_dev;
 
 	slave_dev->features = master->vlan_features;
-	SET_ETHTOOL_OPS(slave_dev, &dsa_slave_ethtool_ops);
+	slave_dev->ethtool_ops = &dsa_slave_ethtool_ops;
 	eth_hw_addr_inherit(slave_dev, master);
 	slave_dev->tx_queue_len = 0;
 
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index 729c687..789af92 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -130,7 +130,7 @@ static void do_setup(struct net_device *netdev)
 	netdev->priv_flags &= ~IFF_TX_SKB_SHARING;
 	netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 	netdev->destructor = internal_dev_destructor;
-	SET_ETHTOOL_OPS(netdev, &internal_dev_ethtool_ops);
+	netdev->ethtool_ops = &internal_dev_ethtool_ops;
 	netdev->tx_queue_len = 0;
 
 	netdev->features = NETIF_F_LLTX | NETIF_F_SG | NETIF_F_FRAGLIST |

^ permalink raw reply related

* Re: [PATCH] [resend] net: get rid of SET_ETHTOOL_OPS
From: Anish Khurana @ 2014-05-11  7:43 UTC (permalink / raw)
  To: netdev@vger.kernel.org, David S. Miller, linux-rdma, linux-acenic,
	nios2-dev, linuxppc-dev, e1000-devel, devel, linux-usb,
	virtualization, linux-wireless, xen-devel, linux-s390, devel,
	b.a.t.m.a.n, bridge, dev, trivial, linux-kernel@vger.kernel.org
In-Reply-To: <20140511001231.GC7875@kaos.lebenslange-mailadresse.de>

SET_ETHTOOL_OPS is equivalent to :
#define SET_ETHTOOL_OPS(netdev,ops) \
    ( (netdev)->ethtool_ops = (ops) )

how it makes difference  removing this code and replacing with the
code mentioned ?

On Sun, May 11, 2014 at 5:42 AM, Wilfried Klaebe
<w-lkml@lebenslange-mailadresse.de> wrote:
> net: get rid of SET_ETHTOOL_OPS
>
> Dave Miller mentioned he'd like to see SET_ETHTOOL_OPS gone.
> This does that.
>
> Mostly done via coccinelle script:
> @@
> struct ethtool_ops *ops;
> struct net_device *dev;
> @@
> -       SET_ETHTOOL_OPS(dev, ops);
> +       dev->ethtool_ops = ops;
>
> Compile tested only, but I'd seriously wonder if this broke anything.
>
> Suggested-by: Dave Miller <davem@davemloft.net>
> Signed-off-by: Wilfried Klaebe <w-lkml@lebenslange-mailadresse.de>
>
> ---
>
> Applies against v3.15-rc4 and v3.15-rc5 likewise.
>
> resend: trimmed CC list. Thanks to Dave for notifying me.
>
> diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
> index c4b3940..078cadd 100644
> --- a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
> +++ b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
> @@ -105,5 +105,5 @@ static const struct ethtool_ops ipoib_ethtool_ops = {
>
>  void ipoib_set_ethtool_ops(struct net_device *dev)
>  {
> -       SET_ETHTOOL_OPS(dev, &ipoib_ethtool_ops);
> +       dev->ethtool_ops = &ipoib_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c
> index 35df0b9..a968654 100644
> --- a/drivers/net/ethernet/3com/3c509.c
> +++ b/drivers/net/ethernet/3com/3c509.c
> @@ -534,7 +534,7 @@ static int el3_common_init(struct net_device *dev)
>         /* The EL3-specific entries in the device structure. */
>         dev->netdev_ops = &netdev_ops;
>         dev->watchdog_timeo = TX_TIMEOUT;
> -       SET_ETHTOOL_OPS(dev, &ethtool_ops);
> +       dev->ethtool_ops = &ethtool_ops;
>
>         err = register_netdev(dev);
>         if (err) {
> diff --git a/drivers/net/ethernet/3com/3c589_cs.c b/drivers/net/ethernet/3com/3c589_cs.c
> index 063557e..f18647c 100644
> --- a/drivers/net/ethernet/3com/3c589_cs.c
> +++ b/drivers/net/ethernet/3com/3c589_cs.c
> @@ -218,7 +218,7 @@ static int tc589_probe(struct pcmcia_device *link)
>         dev->netdev_ops = &el3_netdev_ops;
>         dev->watchdog_timeo = TX_TIMEOUT;
>
> -       SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
> +       dev->ethtool_ops = &netdev_ethtool_ops;
>
>         return tc589_config(link);
>  }
> diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c
> index 465cc71..e13b046 100644
> --- a/drivers/net/ethernet/3com/typhoon.c
> +++ b/drivers/net/ethernet/3com/typhoon.c
> @@ -2435,7 +2435,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>         netif_napi_add(dev, &tp->napi, typhoon_poll, 16);
>         dev->watchdog_timeo     = TX_TIMEOUT;
>
> -       SET_ETHTOOL_OPS(dev, &typhoon_ethtool_ops);
> +       dev->ethtool_ops = &typhoon_ethtool_ops;
>
>         /* We can handle scatter gather, up to 16 entries, and
>          * we can do IP checksumming (only version 4, doh...)
> diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c
> index 171d73c..40dbbf7 100644
> --- a/drivers/net/ethernet/adaptec/starfire.c
> +++ b/drivers/net/ethernet/adaptec/starfire.c
> @@ -784,7 +784,7 @@ static int starfire_init_one(struct pci_dev *pdev,
>
>         dev->netdev_ops = &netdev_ops;
>         dev->watchdog_timeo = TX_TIMEOUT;
> -       SET_ETHTOOL_OPS(dev, &ethtool_ops);
> +       dev->ethtool_ops = &ethtool_ops;
>
>         netif_napi_add(dev, &np->napi, netdev_poll, max_interrupt_work);
>
> diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c
> index 1517e9df..9a6991b 100644
> --- a/drivers/net/ethernet/alteon/acenic.c
> +++ b/drivers/net/ethernet/alteon/acenic.c
> @@ -476,7 +476,7 @@ static int acenic_probe_one(struct pci_dev *pdev,
>         dev->watchdog_timeo = 5*HZ;
>
>         dev->netdev_ops = &ace_netdev_ops;
> -       SET_ETHTOOL_OPS(dev, &ace_ethtool_ops);
> +       dev->ethtool_ops = &ace_ethtool_ops;
>
>         /* we only display this string ONCE */
>         if (!boards_found)
> diff --git a/drivers/net/ethernet/altera/altera_tse_ethtool.c b/drivers/net/ethernet/altera/altera_tse_ethtool.c
> index 319ca74..8ac4bd2 100644
> --- a/drivers/net/ethernet/altera/altera_tse_ethtool.c
> +++ b/drivers/net/ethernet/altera/altera_tse_ethtool.c
> @@ -231,5 +231,5 @@ static const struct ethtool_ops tse_ethtool_ops = {
>
>  void altera_tse_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &tse_ethtool_ops);
> +       netdev->ethtool_ops = &tse_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c
> index 26efaaa..068dc7c 100644
> --- a/drivers/net/ethernet/amd/amd8111e.c
> +++ b/drivers/net/ethernet/amd/amd8111e.c
> @@ -1900,7 +1900,7 @@ static int amd8111e_probe_one(struct pci_dev *pdev,
>
>         /* Initialize driver entry points */
>         dev->netdev_ops = &amd8111e_netdev_ops;
> -       SET_ETHTOOL_OPS(dev, &ops);
> +       dev->ethtool_ops = &ops;
>         dev->irq =pdev->irq;
>         dev->watchdog_timeo = AMD8111E_TX_TIMEOUT;
>         netif_napi_add(dev, &lp->napi, amd8111e_rx_poll, 32);
> diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c
> index a2bd91e..a78e4c1 100644
> --- a/drivers/net/ethernet/amd/au1000_eth.c
> +++ b/drivers/net/ethernet/amd/au1000_eth.c
> @@ -1229,7 +1229,7 @@ static int au1000_probe(struct platform_device *pdev)
>         dev->base_addr = base->start;
>         dev->irq = irq;
>         dev->netdev_ops = &au1000_netdev_ops;
> -       SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops);
> +       dev->ethtool_ops = &au1000_ethtool_ops;
>         dev->watchdog_timeo = ETH_TX_TIMEOUT;
>
>         /*
> diff --git a/drivers/net/ethernet/amd/nmclan_cs.c b/drivers/net/ethernet/amd/nmclan_cs.c
> index 08569fe..abf3b15 100644
> --- a/drivers/net/ethernet/amd/nmclan_cs.c
> +++ b/drivers/net/ethernet/amd/nmclan_cs.c
> @@ -457,7 +457,7 @@ static int nmclan_probe(struct pcmcia_device *link)
>      lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
>
>      dev->netdev_ops = &mace_netdev_ops;
> -    SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
> +    dev->ethtool_ops = &netdev_ethtool_ops;
>      dev->watchdog_timeo = TX_TIMEOUT;
>
>      return nmclan_config(link);
> diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
> index 17bb9ce..49faa97 100644
> --- a/drivers/net/ethernet/atheros/alx/main.c
> +++ b/drivers/net/ethernet/atheros/alx/main.c
> @@ -1302,7 +1302,7 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>         }
>
>         netdev->netdev_ops = &alx_netdev_ops;
> -       SET_ETHTOOL_OPS(netdev, &alx_ethtool_ops);
> +       netdev->ethtool_ops = &alx_ethtool_ops;
>         netdev->irq = pdev->irq;
>         netdev->watchdog_timeo = ALX_WATCHDOG_TIME;
>
> diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
> index 859ea84..ecacaae 100644
> --- a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
> +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
> @@ -305,5 +305,5 @@ static const struct ethtool_ops atl1c_ethtool_ops = {
>
>  void atl1c_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &atl1c_ethtool_ops);
> +       netdev->ethtool_ops = &atl1c_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c b/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
> index 82b2386..206e9b7 100644
> --- a/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
> +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
> @@ -388,5 +388,5 @@ static const struct ethtool_ops atl1e_ethtool_ops = {
>
>  void atl1e_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &atl1e_ethtool_ops);
> +       netdev->ethtool_ops = &atl1e_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
> index 78befb5..2587fed 100644
> --- a/drivers/net/ethernet/atheros/atlx/atl2.c
> +++ b/drivers/net/ethernet/atheros/atlx/atl2.c
> @@ -1396,7 +1396,7 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>         atl2_setup_pcicmd(pdev);
>
>         netdev->netdev_ops = &atl2_netdev_ops;
> -       SET_ETHTOOL_OPS(netdev, &atl2_ethtool_ops);
> +       netdev->ethtool_ops = &atl2_ethtool_ops;
>         netdev->watchdog_timeo = 5 * HZ;
>         strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
>
> diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
> index 05ba625..ca5a20a 100644
> --- a/drivers/net/ethernet/broadcom/b44.c
> +++ b/drivers/net/ethernet/broadcom/b44.c
> @@ -2380,7 +2380,7 @@ static int b44_init_one(struct ssb_device *sdev,
>         netif_napi_add(dev, &bp->napi, b44_poll, 64);
>         dev->watchdog_timeo = B44_TX_TIMEOUT;
>         dev->irq = sdev->irq;
> -       SET_ETHTOOL_OPS(dev, &b44_ethtool_ops);
> +       dev->ethtool_ops = &b44_ethtool_ops;
>
>         err = ssb_bus_powerup(sdev->bus, 0);
>         if (err) {
> diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
> index a7d11f5..1e7bba9c 100644
> --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
> +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
> @@ -1898,7 +1898,7 @@ static int bcm_enet_probe(struct platform_device *pdev)
>         dev->netdev_ops = &bcm_enet_ops;
>         netif_napi_add(dev, &priv->napi, bcm_enet_poll, 16);
>
> -       SET_ETHTOOL_OPS(dev, &bcm_enet_ethtool_ops);
> +       dev->ethtool_ops = &bcm_enet_ethtool_ops;
>         SET_NETDEV_DEV(dev, &pdev->dev);
>
>         ret = register_netdev(dev);
> @@ -2784,7 +2784,7 @@ static int bcm_enetsw_probe(struct platform_device *pdev)
>         /* register netdevice */
>         dev->netdev_ops = &bcm_enetsw_ops;
>         netif_napi_add(dev, &priv->napi, bcm_enet_poll, 16);
> -       SET_ETHTOOL_OPS(dev, &bcm_enetsw_ethtool_ops);
> +       dev->ethtool_ops = &bcm_enetsw_ethtool_ops;
>         SET_NETDEV_DEV(dev, &pdev->dev);
>
>         spin_lock_init(&priv->enetsw_mdio_lock);
> diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
> index 0297a79..05c6af6 100644
> --- a/drivers/net/ethernet/broadcom/bgmac.c
> +++ b/drivers/net/ethernet/broadcom/bgmac.c
> @@ -1436,7 +1436,7 @@ static int bgmac_probe(struct bcma_device *core)
>                 return -ENOMEM;
>         net_dev->netdev_ops = &bgmac_netdev_ops;
>         net_dev->irq = core->irq;
> -       SET_ETHTOOL_OPS(net_dev, &bgmac_ethtool_ops);
> +       net_dev->ethtool_ops = &bgmac_ethtool_ops;
>         bgmac = netdev_priv(net_dev);
>         bgmac->net_dev = net_dev;
>         bgmac->core = core;
> diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
> index b6de05e..0322409 100644
> --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
> +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
> @@ -3506,8 +3506,6 @@ static const struct ethtool_ops bnx2x_vf_ethtool_ops = {
>
>  void bnx2x_set_ethtool_ops(struct bnx2x *bp, struct net_device *netdev)
>  {
> -       if (IS_PF(bp))
> -               SET_ETHTOOL_OPS(netdev, &bnx2x_ethtool_ops);
> -       else /* vf */
> -               SET_ETHTOOL_OPS(netdev, &bnx2x_vf_ethtool_ops);
> +       netdev->ethtool_ops = (IS_PF(bp)) ?
> +               &bnx2x_ethtool_ops : &bnx2x_vf_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> index 0966bd0..5ba1cfb 100644
> --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> @@ -2481,7 +2481,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
>         dev_set_drvdata(&pdev->dev, dev);
>         ether_addr_copy(dev->dev_addr, macaddr);
>         dev->watchdog_timeo = 2 * HZ;
> -       SET_ETHTOOL_OPS(dev, &bcmgenet_ethtool_ops);
> +       dev->ethtool_ops = &bcmgenet_ethtool_ops;
>         dev->netdev_ops = &bcmgenet_netdev_ops;
>         netif_napi_add(dev, &priv->napi, bcmgenet_poll, 64);
>
> diff --git a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
> index f9e1508..adca62b 100644
> --- a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
> +++ b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
> @@ -1137,5 +1137,5 @@ static const struct ethtool_ops bnad_ethtool_ops = {
>  void
>  bnad_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &bnad_ethtool_ops);
> +       netdev->ethtool_ops = &bnad_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
> index 521dfea..25d6b2a 100644
> --- a/drivers/net/ethernet/calxeda/xgmac.c
> +++ b/drivers/net/ethernet/calxeda/xgmac.c
> @@ -1737,7 +1737,7 @@ static int xgmac_probe(struct platform_device *pdev)
>         platform_set_drvdata(pdev, ndev);
>         ether_setup(ndev);
>         ndev->netdev_ops = &xgmac_netdev_ops;
> -       SET_ETHTOOL_OPS(ndev, &xgmac_ethtool_ops);
> +       ndev->ethtool_ops = &xgmac_ethtool_ops;
>         spin_lock_init(&priv->stats_lock);
>         INIT_WORK(&priv->tx_timeout_work, xgmac_tx_timeout_work);
>
> diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
> index 0fe7ff7..c1b2c1d 100644
> --- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
> +++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
> @@ -1100,7 +1100,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>
>                 netif_napi_add(netdev, &adapter->napi, t1_poll, 64);
>
> -               SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops);
> +               netdev->ethtool_ops = &t1_ethtool_ops;
>         }
>
>         if (t1_init_sw_modules(adapter, bi) < 0) {
> diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
> index 07bbb71..3ed5079 100644
> --- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
> +++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
> @@ -3291,7 +3291,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>                         netdev->features |= NETIF_F_HIGHDMA;
>
>                 netdev->netdev_ops = &cxgb_netdev_ops;
> -               SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops);
> +               netdev->ethtool_ops = &cxgb_ethtool_ops;
>         }
>
>         pci_set_drvdata(pdev, adapter);
> diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
> index 6fe5891..7c61f89 100644
> --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
> +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
> @@ -6074,7 +6074,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>                 netdev->priv_flags |= IFF_UNICAST_FLT;
>
>                 netdev->netdev_ops = &cxgb4_netdev_ops;
> -               SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops);
> +               netdev->ethtool_ops = &cxgb_ethtool_ops;
>         }
>
>         pci_set_drvdata(pdev, adapter);
> diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
> index 5285928..ff1cdd1 100644
> --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
> +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
> @@ -2664,7 +2664,7 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
>                 netdev->priv_flags |= IFF_UNICAST_FLT;
>
>                 netdev->netdev_ops = &cxgb4vf_netdev_ops;
> -               SET_ETHTOOL_OPS(netdev, &cxgb4vf_ethtool_ops);
> +               netdev->ethtool_ops = &cxgb4vf_ethtool_ops;
>
>                 /*
>                  * Initialize the hardware/software state for the port.
> diff --git a/drivers/net/ethernet/cisco/enic/enic_ethtool.c b/drivers/net/ethernet/cisco/enic/enic_ethtool.c
> index 47e3562..58a8c67 100644
> --- a/drivers/net/ethernet/cisco/enic/enic_ethtool.c
> +++ b/drivers/net/ethernet/cisco/enic/enic_ethtool.c
> @@ -253,5 +253,5 @@ static const struct ethtool_ops enic_ethtool_ops = {
>
>  void enic_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &enic_ethtool_ops);
> +       netdev->ethtool_ops = &enic_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c
> index 1642de7..8616608 100644
> --- a/drivers/net/ethernet/dec/tulip/tulip_core.c
> +++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
> @@ -1703,7 +1703,7 @@ static int tulip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>  #ifdef CONFIG_TULIP_NAPI
>         netif_napi_add(dev, &tp->napi, tulip_poll, 16);
>  #endif
> -       SET_ETHTOOL_OPS(dev, &ops);
> +       dev->ethtool_ops = &ops;
>
>         if (register_netdev(dev))
>                 goto err_out_free_ring;
> diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c
> index 4fb756d..2324f2d 100644
> --- a/drivers/net/ethernet/dlink/dl2k.c
> +++ b/drivers/net/ethernet/dlink/dl2k.c
> @@ -227,7 +227,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
>         }
>         dev->netdev_ops = &netdev_ops;
>         dev->watchdog_timeo = TX_TIMEOUT;
> -       SET_ETHTOOL_OPS(dev, &ethtool_ops);
> +       dev->ethtool_ops = &ethtool_ops;
>  #if 0
>         dev->features = NETIF_F_IP_CSUM;
>  #endif
> diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c
> index d9e5ca0..433c1e1 100644
> --- a/drivers/net/ethernet/dlink/sundance.c
> +++ b/drivers/net/ethernet/dlink/sundance.c
> @@ -577,7 +577,7 @@ static int sundance_probe1(struct pci_dev *pdev,
>
>         /* The chip-specific entries in the device structure. */
>         dev->netdev_ops = &netdev_ops;
> -       SET_ETHTOOL_OPS(dev, &ethtool_ops);
> +       dev->ethtool_ops = &ethtool_ops;
>         dev->watchdog_timeo = TX_TIMEOUT;
>
>         pci_set_drvdata(pdev, dev);
> diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
> index a186454..9a9e7c7 100644
> --- a/drivers/net/ethernet/emulex/benet/be_main.c
> +++ b/drivers/net/ethernet/emulex/benet/be_main.c
> @@ -4301,7 +4301,7 @@ static void be_netdev_init(struct net_device *netdev)
>
>         netdev->netdev_ops = &be_netdev_ops;
>
> -       SET_ETHTOOL_OPS(netdev, &be_ethtool_ops);
> +       netdev->ethtool_ops = &be_ethtool_ops;
>  }
>
>  static void be_unmap_pci_bars(struct be_adapter *adapter)
> diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
> index 68069ea..c77fa4a 100644
> --- a/drivers/net/ethernet/faraday/ftgmac100.c
> +++ b/drivers/net/ethernet/faraday/ftgmac100.c
> @@ -1210,7 +1210,7 @@ static int ftgmac100_probe(struct platform_device *pdev)
>
>         SET_NETDEV_DEV(netdev, &pdev->dev);
>
> -       SET_ETHTOOL_OPS(netdev, &ftgmac100_ethtool_ops);
> +       netdev->ethtool_ops = &ftgmac100_ethtool_ops;
>         netdev->netdev_ops = &ftgmac100_netdev_ops;
>         netdev->features = NETIF_F_IP_CSUM | NETIF_F_GRO;
>
> diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c
> index 8be5b40..4ff1adc 100644
> --- a/drivers/net/ethernet/faraday/ftmac100.c
> +++ b/drivers/net/ethernet/faraday/ftmac100.c
> @@ -1085,7 +1085,7 @@ static int ftmac100_probe(struct platform_device *pdev)
>         }
>
>         SET_NETDEV_DEV(netdev, &pdev->dev);
> -       SET_ETHTOOL_OPS(netdev, &ftmac100_ethtool_ops);
> +       netdev->ethtool_ops = &ftmac100_ethtool_ops;
>         netdev->netdev_ops = &ftmac100_netdev_ops;
>
>         platform_set_drvdata(pdev, netdev);
> diff --git a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
> index 413329e..cc83350 100644
> --- a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
> +++ b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
> @@ -417,5 +417,5 @@ static const struct ethtool_ops uec_ethtool_ops = {
>
>  void uec_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &uec_ethtool_ops);
> +       netdev->ethtool_ops = &uec_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
> index 7becab1..cfe7a74 100644
> --- a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
> +++ b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
> @@ -256,7 +256,7 @@ static int fmvj18x_probe(struct pcmcia_device *link)
>      dev->netdev_ops = &fjn_netdev_ops;
>      dev->watchdog_timeo = TX_TIMEOUT;
>
> -    SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
> +    dev->ethtool_ops = &netdev_ethtool_ops;
>
>      return fmvj18x_config(link);
>  } /* fmvj18x_attach */
> diff --git a/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c b/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c
> index 95837b9..6055e3e 100644
> --- a/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c
> +++ b/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c
> @@ -278,5 +278,5 @@ static const struct ethtool_ops ehea_ethtool_ops = {
>
>  void ehea_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &ehea_ethtool_ops);
> +       netdev->ethtool_ops = &ehea_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
> index ae342fd..87bd953 100644
> --- a/drivers/net/ethernet/ibm/emac/core.c
> +++ b/drivers/net/ethernet/ibm/emac/core.c
> @@ -2879,7 +2879,7 @@ static int emac_probe(struct platform_device *ofdev)
>                 dev->commac.ops = &emac_commac_sg_ops;
>         } else
>                 ndev->netdev_ops = &emac_netdev_ops;
> -       SET_ETHTOOL_OPS(ndev, &emac_ethtool_ops);
> +       ndev->ethtool_ops = &emac_ethtool_ops;
>
>         netif_carrier_off(ndev);
>
> diff --git a/drivers/net/ethernet/icplus/ipg.c b/drivers/net/ethernet/icplus/ipg.c
> index 25045ae..5727779 100644
> --- a/drivers/net/ethernet/icplus/ipg.c
> +++ b/drivers/net/ethernet/icplus/ipg.c
> @@ -2245,7 +2245,7 @@ static int ipg_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>          */
>         dev->netdev_ops = &ipg_netdev_ops;
>         SET_NETDEV_DEV(dev, &pdev->dev);
> -       SET_ETHTOOL_OPS(dev, &ipg_ethtool_ops);
> +       dev->ethtool_ops = &ipg_ethtool_ops;
>
>         rc = pci_request_regions(pdev, DRV_NAME);
>         if (rc)
> diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
> index b56461c..9d979d7 100644
> --- a/drivers/net/ethernet/intel/e100.c
> +++ b/drivers/net/ethernet/intel/e100.c
> @@ -2854,7 +2854,7 @@ static int e100_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>         netdev->hw_features |= NETIF_F_RXALL;
>
>         netdev->netdev_ops = &e100_netdev_ops;
> -       SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops);
> +       netdev->ethtool_ops = &e100_ethtool_ops;
>         netdev->watchdog_timeo = E100_WATCHDOG_PERIOD;
>         strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
>
> diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
> index 73a8aee..341889a 100644
> --- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
> +++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
> @@ -1905,5 +1905,5 @@ static const struct ethtool_ops e1000_ethtool_ops = {
>
>  void e1000_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops);
> +       netdev->ethtool_ops = &e1000_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
> index cad250b..d9f8a2d 100644
> --- a/drivers/net/ethernet/intel/e1000e/ethtool.c
> +++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
> @@ -2315,5 +2315,5 @@ static const struct ethtool_ops e1000_ethtool_ops = {
>
>  void e1000e_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops);
> +       netdev->ethtool_ops = &e1000_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
> index 03d99cb..7673f86 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
> @@ -1692,5 +1692,5 @@ static const struct ethtool_ops i40e_ethtool_ops = {
>
>  void i40e_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &i40e_ethtool_ops);
> +       netdev->ethtool_ops = &i40e_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
> index 8b0db1c..4defd51 100644
> --- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
> +++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
> @@ -389,5 +389,5 @@ static struct ethtool_ops i40evf_ethtool_ops = {
>   **/
>  void i40evf_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &i40evf_ethtool_ops);
> +       netdev->ethtool_ops = &i40evf_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
> index e5570ac..30b76e1 100644
> --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
> +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
> @@ -3029,5 +3029,5 @@ static const struct ethtool_ops igb_ethtool_ops = {
>
>  void igb_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &igb_ethtool_ops);
> +       netdev->ethtool_ops = &igb_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/intel/igbvf/ethtool.c b/drivers/net/ethernet/intel/igbvf/ethtool.c
> index 90eef07..f58170b 100644
> --- a/drivers/net/ethernet/intel/igbvf/ethtool.c
> +++ b/drivers/net/ethernet/intel/igbvf/ethtool.c
> @@ -476,5 +476,5 @@ static const struct ethtool_ops igbvf_ethtool_ops = {
>
>  void igbvf_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &igbvf_ethtool_ops);
> +       netdev->ethtool_ops = &igbvf_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c b/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c
> index dbb7dd2..1da2d98 100644
> --- a/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c
> +++ b/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c
> @@ -656,5 +656,5 @@ static const struct ethtool_ops ixgb_ethtool_ops = {
>
>  void ixgb_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &ixgb_ethtool_ops);
> +       netdev->ethtool_ops = &ixgb_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
> index 6c55c14..31d7268 100644
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
> @@ -3099,5 +3099,5 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
>
>  void ixgbe_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &ixgbe_ethtool_ops);
> +       netdev->ethtool_ops = &ixgbe_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
> index 1baecb6..a757f07 100644
> --- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c
> +++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
> @@ -813,5 +813,5 @@ static const struct ethtool_ops ixgbevf_ethtool_ops = {
>
>  void ixgbevf_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &ixgbevf_ethtool_ops);
> +       netdev->ethtool_ops = &ixgbevf_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
> index b7b8d74..df1d1b9 100644
> --- a/drivers/net/ethernet/marvell/mv643xx_eth.c
> +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
> @@ -2889,7 +2889,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
>         if (err)
>                 goto out;
>
> -       SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops);
> +       dev->ethtool_ops = &mv643xx_eth_ethtool_ops;
>
>         init_pscr(mp, pd->speed, pd->duplex);
>
> diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
> index 14786c8..72bc47f 100644
> --- a/drivers/net/ethernet/marvell/mvneta.c
> +++ b/drivers/net/ethernet/marvell/mvneta.c
> @@ -2813,7 +2813,7 @@ static int mvneta_probe(struct platform_device *pdev)
>         dev->watchdog_timeo = 5 * HZ;
>         dev->netdev_ops = &mvneta_netdev_ops;
>
> -       SET_ETHTOOL_OPS(dev, &mvneta_eth_tool_ops);
> +       dev->ethtool_ops = &mvneta_eth_tool_ops;
>
>         pp = netdev_priv(dev);
>
> diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
> index b358c2f..8f5aa7c 100644
> --- a/drivers/net/ethernet/marvell/pxa168_eth.c
> +++ b/drivers/net/ethernet/marvell/pxa168_eth.c
> @@ -1488,7 +1488,7 @@ static int pxa168_eth_probe(struct platform_device *pdev)
>         dev->netdev_ops = &pxa168_eth_netdev_ops;
>         dev->watchdog_timeo = 2 * HZ;
>         dev->base_addr = 0;
> -       SET_ETHTOOL_OPS(dev, &pxa168_ethtool_ops);
> +       dev->ethtool_ops = &pxa168_ethtool_ops;
>
>         INIT_WORK(&pep->tx_timeout_task, pxa168_eth_tx_timeout_task);
>
> diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
> index b811064..6969338 100644
> --- a/drivers/net/ethernet/marvell/sky2.c
> +++ b/drivers/net/ethernet/marvell/sky2.c
> @@ -4760,7 +4760,7 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,
>
>         SET_NETDEV_DEV(dev, &hw->pdev->dev);
>         dev->irq = hw->pdev->irq;
> -       SET_ETHTOOL_OPS(dev, &sky2_ethtool_ops);
> +       dev->ethtool_ops = &sky2_ethtool_ops;
>         dev->watchdog_timeo = TX_WATCHDOG;
>         dev->netdev_ops = &sky2_netdev_ops[port];
>
> diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
> index 7e4b172..36af5e7 100644
> --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
> +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
> @@ -2539,7 +2539,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
>         netif_set_real_num_tx_queues(dev, priv->tx_ring_num);
>         netif_set_real_num_rx_queues(dev, priv->rx_ring_num);
>
> -       SET_ETHTOOL_OPS(dev, &mlx4_en_ethtool_ops);
> +       dev->ethtool_ops = &mlx4_en_ethtool_ops;
>
>         /*
>          * Set driver features
> diff --git a/drivers/net/ethernet/micrel/ks8695net.c b/drivers/net/ethernet/micrel/ks8695net.c
> index 16435b3..6c7c78ba 100644
> --- a/drivers/net/ethernet/micrel/ks8695net.c
> +++ b/drivers/net/ethernet/micrel/ks8695net.c
> @@ -1504,15 +1504,15 @@ ks8695_probe(struct platform_device *pdev)
>         if (ksp->phyiface_regs && ksp->link_irq == -1) {
>                 ks8695_init_switch(ksp);
>                 ksp->dtype = KS8695_DTYPE_LAN;
> -               SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops);
> +               ndev->ethtool_ops = &ks8695_ethtool_ops;
>         } else if (ksp->phyiface_regs && ksp->link_irq != -1) {
>                 ks8695_init_wan_phy(ksp);
>                 ksp->dtype = KS8695_DTYPE_WAN;
> -               SET_ETHTOOL_OPS(ndev, &ks8695_wan_ethtool_ops);
> +               ndev->ethtool_ops = &ks8695_wan_ethtool_ops;
>         } else {
>                 /* No initialisation since HPNA does not have a PHY */
>                 ksp->dtype = KS8695_DTYPE_HPNA;
> -               SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops);
> +               ndev->ethtool_ops = &ks8695_ethtool_ops;
>         }
>
>         /* And bring up the net_device with the net core */
> diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
> index e0c92e0..13767eb 100644
> --- a/drivers/net/ethernet/micrel/ks8851.c
> +++ b/drivers/net/ethernet/micrel/ks8851.c
> @@ -1471,7 +1471,7 @@ static int ks8851_probe(struct spi_device *spi)
>
>         skb_queue_head_init(&ks->txq);
>
> -       SET_ETHTOOL_OPS(ndev, &ks8851_ethtool_ops);
> +       ndev->ethtool_ops = &ks8851_ethtool_ops;
>         SET_NETDEV_DEV(ndev, &spi->dev);
>
>         spi_set_drvdata(spi, ks);
> diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
> index 14ac0e2..4b9592c1 100644
> --- a/drivers/net/ethernet/micrel/ksz884x.c
> +++ b/drivers/net/ethernet/micrel/ksz884x.c
> @@ -7106,7 +7106,7 @@ static int pcidev_init(struct pci_dev *pdev, const struct pci_device_id *id)
>                 }
>
>                 dev->netdev_ops = &netdev_ops;
> -               SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
> +               dev->ethtool_ops = &netdev_ethtool_ops;
>                 if (register_netdev(dev))
>                         goto pcidev_init_reg_err;
>                 port_set_power_saving(port, true);
> diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c
> index c7b40aa..b1b5f66 100644
> --- a/drivers/net/ethernet/microchip/enc28j60.c
> +++ b/drivers/net/ethernet/microchip/enc28j60.c
> @@ -1593,7 +1593,7 @@ static int enc28j60_probe(struct spi_device *spi)
>         dev->irq = spi->irq;
>         dev->netdev_ops = &enc28j60_netdev_ops;
>         dev->watchdog_timeo = TX_TIMEOUT;
> -       SET_ETHTOOL_OPS(dev, &enc28j60_ethtool_ops);
> +       dev->ethtool_ops = &enc28j60_ethtool_ops;
>
>         enc28j60_lowpower(priv, true);
>
> diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
> index 130f6b2..f3d5d79 100644
> --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
> +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
> @@ -4112,7 +4112,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>         setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer,
>                     (unsigned long)mgp);
>
> -       SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops);
> +       netdev->ethtool_ops = &myri10ge_ethtool_ops;
>         INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog);
>         status = register_netdev(netdev);
>         if (status != 0) {
> diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c
> index 64ec2a4..291fba8 100644
> --- a/drivers/net/ethernet/natsemi/natsemi.c
> +++ b/drivers/net/ethernet/natsemi/natsemi.c
> @@ -927,7 +927,7 @@ static int natsemi_probe1(struct pci_dev *pdev, const struct pci_device_id *ent)
>         dev->netdev_ops = &natsemi_netdev_ops;
>         dev->watchdog_timeo = TX_TIMEOUT;
>
> -       SET_ETHTOOL_OPS(dev, &ethtool_ops);
> +       dev->ethtool_ops = &ethtool_ops;
>
>         if (mtu)
>                 dev->mtu = mtu;
> diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c
> index dbccf1d..19bb824 100644
> --- a/drivers/net/ethernet/natsemi/ns83820.c
> +++ b/drivers/net/ethernet/natsemi/ns83820.c
> @@ -2030,7 +2030,7 @@ static int ns83820_init_one(struct pci_dev *pci_dev,
>                 pci_dev->subsystem_vendor, pci_dev->subsystem_device);
>
>         ndev->netdev_ops = &netdev_ops;
> -       SET_ETHTOOL_OPS(ndev, &ops);
> +       ndev->ethtool_ops = &ops;
>         ndev->watchdog_timeo = 5 * HZ;
>         pci_set_drvdata(pci_dev, ndev);
>
> diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
> index a2844ff..190538d 100644
> --- a/drivers/net/ethernet/neterion/s2io.c
> +++ b/drivers/net/ethernet/neterion/s2io.c
> @@ -7919,7 +7919,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
>
>         /*  Driver entry points */
>         dev->netdev_ops = &s2io_netdev_ops;
> -       SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
> +       dev->ethtool_ops = &netdev_ethtool_ops;
>         dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
>                 NETIF_F_TSO | NETIF_F_TSO6 |
>                 NETIF_F_RXCSUM | NETIF_F_LRO;
> diff --git a/drivers/net/ethernet/neterion/vxge/vxge-ethtool.c b/drivers/net/ethernet/neterion/vxge/vxge-ethtool.c
> index f8f0738..ddcc81a 100644
> --- a/drivers/net/ethernet/neterion/vxge/vxge-ethtool.c
> +++ b/drivers/net/ethernet/neterion/vxge/vxge-ethtool.c
> @@ -1128,5 +1128,5 @@ static const struct ethtool_ops vxge_ethtool_ops = {
>
>  void vxge_initialize_ethtool_ops(struct net_device *ndev)
>  {
> -       SET_ETHTOOL_OPS(ndev, &vxge_ethtool_ops);
> +       ndev->ethtool_ops = &vxge_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
> index fddb464..e8235c5 100644
> --- a/drivers/net/ethernet/nvidia/forcedeth.c
> +++ b/drivers/net/ethernet/nvidia/forcedeth.c
> @@ -5766,7 +5766,7 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
>                 dev->netdev_ops = &nv_netdev_ops_optimized;
>
>         netif_napi_add(dev, &np->napi, nv_napi_poll, RX_WORK_PER_LOOP);
> -       SET_ETHTOOL_OPS(dev, &ops);
> +       dev->ethtool_ops = &ops;
>         dev->watchdog_timeo = NV_WATCHDOG_TIMEO;
>
>         pci_set_drvdata(pci_dev, dev);
> diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c
> index 826f0cc..114d2fe 100644
> --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c
> +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c
> @@ -508,5 +508,5 @@ static const struct ethtool_ops pch_gbe_ethtool_ops = {
>
>  void pch_gbe_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &pch_gbe_ethtool_ops);
> +       netdev->ethtool_ops = &pch_gbe_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/packetengines/hamachi.c b/drivers/net/ethernet/packetengines/hamachi.c
> index b6bdeb3..9a997e4 100644
> --- a/drivers/net/ethernet/packetengines/hamachi.c
> +++ b/drivers/net/ethernet/packetengines/hamachi.c
> @@ -724,10 +724,8 @@ static int hamachi_init_one(struct pci_dev *pdev,
>
>         /* The Hamachi-specific entries in the device structure. */
>         dev->netdev_ops = &hamachi_netdev_ops;
> -       if (chip_tbl[hmp->chip_id].flags & CanHaveMII)
> -               SET_ETHTOOL_OPS(dev, &ethtool_ops);
> -       else
> -               SET_ETHTOOL_OPS(dev, &ethtool_ops_no_mii);
> +       dev->ethtool_ops = (chip_tbl[hmp->chip_id].flags & CanHaveMII) ?
> +               &ethtool_ops : &ethtool_ops_no_mii;
>         dev->watchdog_timeo = TX_TIMEOUT;
>         if (mtu)
>                 dev->mtu = mtu;
> diff --git a/drivers/net/ethernet/packetengines/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c
> index 9a6cb48..69a8dc0 100644
> --- a/drivers/net/ethernet/packetengines/yellowfin.c
> +++ b/drivers/net/ethernet/packetengines/yellowfin.c
> @@ -472,7 +472,7 @@ static int yellowfin_init_one(struct pci_dev *pdev,
>
>         /* The Yellowfin-specific entries in the device structure. */
>         dev->netdev_ops = &netdev_ops;
> -       SET_ETHTOOL_OPS(dev, &ethtool_ops);
> +       dev->ethtool_ops = &ethtool_ops;
>         dev->watchdog_timeo = TX_TIMEOUT;
>
>         if (mtu)
> diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
> index f09c35d..5bf0581 100644
> --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
> +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
> @@ -1373,7 +1373,7 @@ netxen_setup_netdev(struct netxen_adapter *adapter,
>
>         netxen_nic_change_mtu(netdev, netdev->mtu);
>
> -       SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops);
> +       netdev->ethtool_ops = &netxen_nic_ethtool_ops;
>
>         netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
>                               NETIF_F_RXCSUM;
> diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
> index 2eabd44..b5d6bc1 100644
> --- a/drivers/net/ethernet/qlogic/qla3xxx.c
> +++ b/drivers/net/ethernet/qlogic/qla3xxx.c
> @@ -3838,7 +3838,7 @@ static int ql3xxx_probe(struct pci_dev *pdev,
>
>         /* Set driver entry points */
>         ndev->netdev_ops = &ql3xxx_netdev_ops;
> -       SET_ETHTOOL_OPS(ndev, &ql3xxx_ethtool_ops);
> +       ndev->ethtool_ops = &ql3xxx_ethtool_ops;
>         ndev->watchdog_timeo = 5 * HZ;
>
>         netif_napi_add(ndev, &qdev->napi, ql_poll, 64);
> diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
> index dbf7539..4bdbdca 100644
> --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
> +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
> @@ -2222,10 +2222,8 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
>
>         qlcnic_change_mtu(netdev, netdev->mtu);
>
> -       if (qlcnic_sriov_vf_check(adapter))
> -               SET_ETHTOOL_OPS(netdev, &qlcnic_sriov_vf_ethtool_ops);
> -       else
> -               SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops);
> +       netdev->ethtool_ops = (qlcnic_sriov_vf_check(adapter)) ?
> +               &qlcnic_sriov_vf_ethtool_ops : &qlcnic_ethtool_ops;
>
>         netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
>                              NETIF_F_IPV6_CSUM | NETIF_F_GRO |
> @@ -2630,7 +2628,7 @@ err_out_disable_pdev:
>  err_out_maintenance_mode:
>         set_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state);
>         netdev->netdev_ops = &qlcnic_netdev_failed_ops;
> -       SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_failed_ops);
> +       netdev->ethtool_ops = &qlcnic_ethtool_failed_ops;
>         ahw->port_type = QLCNIC_XGBE;
>
>         if (qlcnic_83xx_check(adapter))
> diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
> index 0a1d76a..79b86e9 100644
> --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
> +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
> @@ -4770,7 +4770,7 @@ static int qlge_probe(struct pci_dev *pdev,
>         ndev->irq = pdev->irq;
>
>         ndev->netdev_ops = &qlge_netdev_ops;
> -       SET_ETHTOOL_OPS(ndev, &qlge_ethtool_ops);
> +       ndev->ethtool_ops = &qlge_ethtool_ops;
>         ndev->watchdog_timeo = 10 * HZ;
>
>         err = register_netdev(ndev);
> diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
> index aa1c079..be425ad 100644
> --- a/drivers/net/ethernet/realtek/r8169.c
> +++ b/drivers/net/ethernet/realtek/r8169.c
> @@ -7125,7 +7125,7 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>         for (i = 0; i < ETH_ALEN; i++)
>                 dev->dev_addr[i] = RTL_R8(MAC0 + i);
>
> -       SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops);
> +       dev->ethtool_ops = &rtl8169_ethtool_ops;
>         dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
>
>         netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT);
> diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
> index 6a9509c..967314c 100644
> --- a/drivers/net/ethernet/renesas/sh_eth.c
> +++ b/drivers/net/ethernet/renesas/sh_eth.c
> @@ -2843,7 +2843,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
>                 ndev->netdev_ops = &sh_eth_netdev_ops_tsu;
>         else
>                 ndev->netdev_ops = &sh_eth_netdev_ops;
> -       SET_ETHTOOL_OPS(ndev, &sh_eth_ethtool_ops);
> +       ndev->ethtool_ops = &sh_eth_ethtool_ops;
>         ndev->watchdog_timeo = TX_TIMEOUT;
>
>         /* debug message level */
> diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c
> index 0415fa5..c0981ae 100644
> --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c
> +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c
> @@ -520,5 +520,5 @@ static const struct ethtool_ops sxgbe_ethtool_ops = {
>
>  void sxgbe_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &sxgbe_ethtool_ops);
> +       netdev->ethtool_ops = &sxgbe_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
> index 63d595f..1e27404 100644
> --- a/drivers/net/ethernet/sfc/efx.c
> +++ b/drivers/net/ethernet/sfc/efx.c
> @@ -2248,7 +2248,7 @@ static int efx_register_netdev(struct efx_nic *efx)
>         } else {
>                 net_dev->netdev_ops = &efx_farch_netdev_ops;
>         }
> -       SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops);
> +       net_dev->ethtool_ops = &efx_ethtool_ops;
>         net_dev->gso_max_segs = EFX_TSO_MAX_SEGS;
>
>         rtnl_lock();
> diff --git a/drivers/net/ethernet/sis/sis190.c b/drivers/net/ethernet/sis/sis190.c
> index acbbe48..a863399 100644
> --- a/drivers/net/ethernet/sis/sis190.c
> +++ b/drivers/net/ethernet/sis/sis190.c
> @@ -1877,7 +1877,7 @@ static int sis190_init_one(struct pci_dev *pdev,
>
>         dev->netdev_ops = &sis190_netdev_ops;
>
> -       SET_ETHTOOL_OPS(dev, &sis190_ethtool_ops);
> +       dev->ethtool_ops = &sis190_ethtool_ops;
>         dev->watchdog_timeo = SIS190_TX_TIMEOUT;
>
>         spin_lock_init(&tp->lock);
> diff --git a/drivers/net/ethernet/smsc/smc91c92_cs.c b/drivers/net/ethernet/smsc/smc91c92_cs.c
> index c7a4868..6b33127 100644
> --- a/drivers/net/ethernet/smsc/smc91c92_cs.c
> +++ b/drivers/net/ethernet/smsc/smc91c92_cs.c
> @@ -318,7 +318,7 @@ static int smc91c92_probe(struct pcmcia_device *link)
>
>      /* The SMC91c92-specific entries in the device structure. */
>      dev->netdev_ops = &smc_netdev_ops;
> -    SET_ETHTOOL_OPS(dev, &ethtool_ops);
> +    dev->ethtool_ops = &ethtool_ops;
>      dev->watchdog_timeo = TX_TIMEOUT;
>
>      smc->mii_if.dev = dev;
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> index c5f9cb8..c963394 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> @@ -784,5 +784,5 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
>
>  void stmmac_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &stmmac_ethtool_ops);
> +       netdev->ethtool_ops = &stmmac_ethtool_ops;
>  }
> diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c
> index 2ead877..38da73a 100644
> --- a/drivers/net/ethernet/tehuti/tehuti.c
> +++ b/drivers/net/ethernet/tehuti/tehuti.c
> @@ -2413,7 +2413,7 @@ static void bdx_set_ethtool_ops(struct net_device *netdev)
>                 .get_ethtool_stats = bdx_get_ethtool_stats,
>         };
>
> -       SET_ETHTOOL_OPS(netdev, &bdx_ethtool_ops);
> +       netdev->ethtool_ops = &bdx_ethtool_ops;
>  }
>
>  /**
> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
> index 36aa109..6ecab3c 100644
> --- a/drivers/net/ethernet/ti/cpsw.c
> +++ b/drivers/net/ethernet/ti/cpsw.c
> @@ -1975,7 +1975,7 @@ static int cpsw_probe_dual_emac(struct platform_device *pdev,
>         ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
>
>         ndev->netdev_ops = &cpsw_netdev_ops;
> -       SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops);
> +       ndev->ethtool_ops = &cpsw_ethtool_ops;
>         netif_napi_add(ndev, &priv_sl2->napi, cpsw_poll, CPSW_POLL_WEIGHT);
>
>         /* register the network device */
> @@ -2204,7 +2204,7 @@ static int cpsw_probe(struct platform_device *pdev)
>         ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
>
>         ndev->netdev_ops = &cpsw_netdev_ops;
> -       SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops);
> +       ndev->ethtool_ops = &cpsw_ethtool_ops;
>         netif_napi_add(ndev, &priv->napi, cpsw_poll, CPSW_POLL_WEIGHT);
>
>         /* register the network device */
> diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
> index 8f0e69c..e76eae5 100644
> --- a/drivers/net/ethernet/ti/davinci_emac.c
> +++ b/drivers/net/ethernet/ti/davinci_emac.c
> @@ -1980,7 +1980,7 @@ static int davinci_emac_probe(struct platform_device *pdev)
>         }
>
>         ndev->netdev_ops = &emac_netdev_ops;
> -       SET_ETHTOOL_OPS(ndev, &ethtool_ops);
> +       ndev->ethtool_ops = &ethtool_ops;
>         netif_napi_add(ndev, &priv->napi, emac_poll, EMAC_POLL_WEIGHT);
>
>         /* register the network device */
> diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
> index 31e55fb..2170db5 100644
> --- a/drivers/net/hyperv/netvsc_drv.c
> +++ b/drivers/net/hyperv/netvsc_drv.c
> @@ -715,7 +715,7 @@ static int netvsc_probe(struct hv_device *dev,
>         net->features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG | NETIF_F_RXCSUM |
>                         NETIF_F_IP_CSUM | NETIF_F_TSO;
>
> -       SET_ETHTOOL_OPS(net, &ethtool_ops);
> +       net->ethtool_ops = &ethtool_ops;
>         SET_NETDEV_DEV(net, &dev->device);
>
>         /* Notify the netvsc driver of the new device */
> diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c
> index 63aa9d9..27536aa 100644
> --- a/drivers/net/ntb_netdev.c
> +++ b/drivers/net/ntb_netdev.c
> @@ -348,7 +348,7 @@ static int ntb_netdev_probe(struct pci_dev *pdev)
>         memcpy(ndev->dev_addr, ndev->perm_addr, ndev->addr_len);
>
>         ndev->netdev_ops = &ntb_netdev_ops;
> -       SET_ETHTOOL_OPS(ndev, &ntb_ethtool_ops);
> +       ndev->ethtool_ops = &ntb_ethtool_ops;
>
>         dev->qp = ntb_transport_create_queue(ndev, pdev, &ntb_netdev_handlers);
>         if (!dev->qp) {
> diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
> index a849718..dac7a0d 100644
> --- a/drivers/net/rionet.c
> +++ b/drivers/net/rionet.c
> @@ -494,7 +494,7 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
>         ndev->mtu = RIO_MAX_MSG_SIZE - 14;
>         ndev->features = NETIF_F_LLTX;
>         SET_NETDEV_DEV(ndev, &mport->dev);
> -       SET_ETHTOOL_OPS(ndev, &rionet_ethtool_ops);
> +       ndev->ethtool_ops = &rionet_ethtool_ops;
>
>         spin_lock_init(&rnet->lock);
>         spin_lock_init(&rnet->tx_lock);
> diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
> index 630caf4..8cfc3bb 100644
> --- a/drivers/net/usb/catc.c
> +++ b/drivers/net/usb/catc.c
> @@ -793,7 +793,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
>
>         netdev->netdev_ops = &catc_netdev_ops;
>         netdev->watchdog_timeo = TX_TIMEOUT;
> -       SET_ETHTOOL_OPS(netdev, &ops);
> +       netdev->ethtool_ops = &ops;
>
>         catc->usbdev = usbdev;
>         catc->netdev = netdev;
> diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
> index 660bd5e..a3a0586 100644
> --- a/drivers/net/usb/hso.c
> +++ b/drivers/net/usb/hso.c
> @@ -2425,7 +2425,7 @@ static void hso_net_init(struct net_device *net)
>         net->type = ARPHRD_NONE;
>         net->mtu = DEFAULT_MTU - 14;
>         net->tx_queue_len = 10;
> -       SET_ETHTOOL_OPS(net, &ops);
> +       net->ethtool_ops = &ops;
>
>         /* and initialize the semaphore */
>         spin_lock_init(&hso_net->net_lock);
> diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c
> index 421934c..f725707 100644
> --- a/drivers/net/usb/ipheth.c
> +++ b/drivers/net/usb/ipheth.c
> @@ -524,7 +524,7 @@ static int ipheth_probe(struct usb_interface *intf,
>         usb_set_intfdata(intf, dev);
>
>         SET_NETDEV_DEV(netdev, &intf->dev);
> -       SET_ETHTOOL_OPS(netdev, &ops);
> +       netdev->ethtool_ops = &ops;
>
>         retval = register_netdev(netdev);
>         if (retval) {
> diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
> index a359d3b..dcb6d33 100644
> --- a/drivers/net/usb/kaweth.c
> +++ b/drivers/net/usb/kaweth.c
> @@ -1171,7 +1171,7 @@ err_fw:
>         netdev->netdev_ops = &kaweth_netdev_ops;
>         netdev->watchdog_timeo = KAWETH_TX_TIMEOUT;
>         netdev->mtu = le16_to_cpu(kaweth->configuration.segment_size);
> -       SET_ETHTOOL_OPS(netdev, &ops);
> +       netdev->ethtool_ops = &ops;
>
>         /* kaweth is zeroed as part of alloc_netdev */
>         INIT_DELAYED_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl);
> diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
> index 03e8a15..f840802 100644
> --- a/drivers/net/usb/pegasus.c
> +++ b/drivers/net/usb/pegasus.c
> @@ -1159,7 +1159,7 @@ static int pegasus_probe(struct usb_interface *intf,
>
>         net->watchdog_timeo = PEGASUS_TX_TIMEOUT;
>         net->netdev_ops = &pegasus_netdev_ops;
> -       SET_ETHTOOL_OPS(net, &ops);
> +       net->ethtool_ops = &ops;
>         pegasus->mii.dev = net;
>         pegasus->mii.mdio_read = mdio_read;
>         pegasus->mii.mdio_write = mdio_write;
> diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
> index 3fbfb08..9f91c7a 100644
> --- a/drivers/net/usb/r8152.c
> +++ b/drivers/net/usb/r8152.c
> @@ -3452,7 +3452,7 @@ static int rtl8152_probe(struct usb_interface *intf,
>                               NETIF_F_TSO | NETIF_F_FRAGLIST |
>                               NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
>
> -       SET_ETHTOOL_OPS(netdev, &ops);
> +       netdev->ethtool_ops = &ops;
>         netif_set_gso_max_size(netdev, RTL_LIMITED_TSO_SIZE);
>
>         tp->mii.dev = netdev;
> diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
> index da2c458..6e87e57 100644
> --- a/drivers/net/usb/rtl8150.c
> +++ b/drivers/net/usb/rtl8150.c
> @@ -878,7 +878,7 @@ static int rtl8150_probe(struct usb_interface *intf,
>         dev->netdev = netdev;
>         netdev->netdev_ops = &rtl8150_netdev_ops;
>         netdev->watchdog_timeo = RTL8150_TX_TIMEOUT;
> -       SET_ETHTOOL_OPS(netdev, &ops);
> +       netdev->ethtool_ops = &ops;
>         dev->intr_interval = 100;       /* 100ms */
>
>         if (!alloc_all_urbs(dev)) {
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index 7b68746..3f83359 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -1646,7 +1646,7 @@ static int virtnet_probe(struct virtio_device *vdev)
>         dev->netdev_ops = &virtnet_netdev;
>         dev->features = NETIF_F_HIGHDMA;
>
> -       SET_ETHTOOL_OPS(dev, &virtnet_ethtool_ops);
> +       dev->ethtool_ops = &virtnet_ethtool_ops;
>         SET_NETDEV_DEV(dev, &vdev->dev);
>
>         /* Do we support "hardware" checksums? */
> diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
> index 600ab56..00e1202 100644
> --- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
> +++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
> @@ -635,5 +635,5 @@ static const struct ethtool_ops vmxnet3_ethtool_ops = {
>
>  void vmxnet3_set_ethtool_ops(struct net_device *netdev)
>  {
> -       SET_ETHTOOL_OPS(netdev, &vmxnet3_ethtool_ops);
> +       netdev->ethtool_ops = &vmxnet3_ethtool_ops;
>  }
> diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
> index 82355d5..457359c 100644
> --- a/drivers/net/vxlan.c
> +++ b/drivers/net/vxlan.c
> @@ -2706,7 +2706,7 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
>                 return -EEXIST;
>         }
>
> -       SET_ETHTOOL_OPS(dev, &vxlan_ethtool_ops);
> +       dev->ethtool_ops = &vxlan_ethtool_ops;
>
>         /* create an fdb entry for a valid default destination */
>         if (!vxlan_addr_any(&vxlan->default_dst.remote_ip)) {
> diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
> index 67db34e..52919ad 100644
> --- a/drivers/net/wireless/hostap/hostap_main.c
> +++ b/drivers/net/wireless/hostap/hostap_main.c
> @@ -882,7 +882,7 @@ void hostap_setup_dev(struct net_device *dev, local_info_t *local,
>         dev->mtu = local->mtu;
>
>
> -       SET_ETHTOOL_OPS(dev, &prism2_ethtool_ops);
> +       dev->ethtool_ops = &prism2_ethtool_ops;
>
>  }
>
> diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
> index ef05c5c..a755733 100644
> --- a/drivers/net/xen-netback/interface.c
> +++ b/drivers/net/xen-netback/interface.c
> @@ -386,7 +386,7 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
>                 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
>                 NETIF_F_TSO | NETIF_F_TSO6;
>         dev->features = dev->hw_features | NETIF_F_RXCSUM;
> -       SET_ETHTOOL_OPS(dev, &xenvif_ethtool_ops);
> +       dev->ethtool_ops = &xenvif_ethtool_ops;
>
>         dev->tx_queue_len = XENVIF_QUEUE_LENGTH;
>
> diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
> index 158b5e6..895355d 100644
> --- a/drivers/net/xen-netfront.c
> +++ b/drivers/net/xen-netfront.c
> @@ -1332,7 +1332,7 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
>           */
>         netdev->features |= netdev->hw_features;
>
> -       SET_ETHTOOL_OPS(netdev, &xennet_ethtool_ops);
> +       netdev->ethtool_ops = &xennet_ethtool_ops;
>         SET_NETDEV_DEV(netdev, &dev->dev);
>
>         netif_set_gso_max_size(netdev, XEN_NETIF_MAX_TX_SIZE - MAX_TCP_HEADER);
> diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
> index 8dea3f1..047b4da 100644
> --- a/drivers/s390/net/qeth_l2_main.c
> +++ b/drivers/s390/net/qeth_l2_main.c
> @@ -964,10 +964,9 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
>         card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
>         card->dev->mtu = card->info.initial_mtu;
>         card->dev->netdev_ops = &qeth_l2_netdev_ops;
> -       if (card->info.type != QETH_CARD_TYPE_OSN)
> -               SET_ETHTOOL_OPS(card->dev, &qeth_l2_ethtool_ops);
> -       else
> -               SET_ETHTOOL_OPS(card->dev, &qeth_l2_osn_ops);
> +       card->dev->ethtool_ops =
> +               (card->info.type != QETH_CARD_TYPE_OSN) ?
> +               &qeth_l2_ethtool_ops : &qeth_l2_osn_ops;
>         card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
>         card->info.broadcast_capable = 1;
>         qeth_l2_request_initial_mac(card);
> diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
> index 3524d34..0a59d24 100644
> --- a/drivers/s390/net/qeth_l3_main.c
> +++ b/drivers/s390/net/qeth_l3_main.c
> @@ -3298,7 +3298,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
>         card->dev->ml_priv = card;
>         card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
>         card->dev->mtu = card->info.initial_mtu;
> -       SET_ETHTOOL_OPS(card->dev, &qeth_l3_ethtool_ops);
> +       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;
> diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c
> index d329cf3..15e0f4d 100644
> --- a/drivers/staging/et131x/et131x.c
> +++ b/drivers/staging/et131x/et131x.c
> @@ -4604,7 +4604,7 @@ static int et131x_pci_setup(struct pci_dev *pdev,
>         netdev->netdev_ops     = &et131x_netdev_ops;
>
>         SET_NETDEV_DEV(netdev, &pdev->dev);
> -       SET_ETHTOOL_OPS(netdev, &et131x_ethtool_ops);
> +       netdev->ethtool_ops = &et131x_ethtool_ops;
>
>         adapter = et131x_adapter_init(netdev, pdev);
>
> diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
> index d6421b9..a6158be 100644
> --- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
> +++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
> @@ -2249,7 +2249,7 @@ struct net_device *init_ft1000_card(struct pcmcia_device *link,
>
>         ft1000InitProc(dev);
>         ft1000_card_present = 1;
> -       SET_ETHTOOL_OPS(dev, &ops);
> +       dev->ethtool_ops = &ops;
>         printk(KERN_INFO "ft1000: %s: addr 0x%04lx irq %d, MAC addr %pM\n",
>                         dev->name, dev->base_addr, dev->irq, dev->dev_addr);
>         return dev;
> diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c
> index c83e337..9d95761 100644
> --- a/drivers/staging/netlogic/xlr_net.c
> +++ b/drivers/staging/netlogic/xlr_net.c
> @@ -1066,7 +1066,7 @@ static int xlr_net_probe(struct platform_device *pdev)
>         xlr_set_rx_mode(ndev);
>
>         priv->num_rx_desc += MAX_NUM_DESC_SPILL;
> -       SET_ETHTOOL_OPS(ndev, &xlr_ethtool_ops);
> +       ndev->ethtool_ops = &xlr_ethtool_ops;
>         SET_NETDEV_DEV(ndev, &pdev->dev);
>
>         /* Common registers, do one time initialization */
> diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
> index ff7214a..da9dd6b 100644
> --- a/drivers/staging/octeon/ethernet.c
> +++ b/drivers/staging/octeon/ethernet.c
> @@ -469,7 +469,7 @@ int cvm_oct_common_init(struct net_device *dev)
>
>         /* We do our own locking, Linux doesn't need to */
>         dev->features |= NETIF_F_LLTX;
> -       SET_ETHTOOL_OPS(dev, &cvm_oct_ethtool_ops);
> +       dev->ethtool_ops = &cvm_oct_ethtool_ops;
>
>         cvm_oct_phy_setup_device(dev);
>         cvm_oct_set_mac_filter(dev);
> diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
> index b7d4f82..ce8e281 100644
> --- a/drivers/usb/gadget/u_ether.c
> +++ b/drivers/usb/gadget/u_ether.c
> @@ -793,7 +793,7 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g,
>
>         net->netdev_ops = &eth_netdev_ops;
>
> -       SET_ETHTOOL_OPS(net, &ops);
> +       net->ethtool_ops = &ops;
>
>         dev->gadget = g;
>         SET_NETDEV_DEV(net, &g->dev);
> @@ -850,7 +850,7 @@ struct net_device *gether_setup_name_default(const char *netname)
>
>         net->netdev_ops = &eth_netdev_ops;
>
> -       SET_ETHTOOL_OPS(net, &ops);
> +       net->ethtool_ops = &ops;
>         SET_NETDEV_DEVTYPE(net, &gadget_type);
>
>         return net;
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index 7ed3a3a..06071f7 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -56,9 +56,6 @@ struct device;
>  struct phy_device;
>  /* 802.11 specific */
>  struct wireless_dev;
> -                                       /* source back-compat hooks */
> -#define SET_ETHTOOL_OPS(netdev,ops) \
> -       ( (netdev)->ethtool_ops = (ops) )
>
>  void netdev_set_default_ethtool_ops(struct net_device *dev,
>                                     const struct ethtool_ops *ops);
> diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
> index 744a59b..e7ee65d 100644
> --- a/net/batman-adv/soft-interface.c
> +++ b/net/batman-adv/soft-interface.c
> @@ -884,7 +884,7 @@ static void batadv_softif_init_early(struct net_device *dev)
>         /* generate random address */
>         eth_hw_addr_random(dev);
>
> -       SET_ETHTOOL_OPS(dev, &batadv_ethtool_ops);
> +       dev->ethtool_ops = &batadv_ethtool_ops;
>
>         memset(priv, 0, sizeof(*priv));
>  }
> diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
> index 3e2da2c..9212015 100644
> --- a/net/bridge/br_device.c
> +++ b/net/bridge/br_device.c
> @@ -348,7 +348,7 @@ void br_dev_setup(struct net_device *dev)
>
>         dev->netdev_ops = &br_netdev_ops;
>         dev->destructor = br_dev_free;
> -       SET_ETHTOOL_OPS(dev, &br_ethtool_ops);
> +       dev->ethtool_ops = &br_ethtool_ops;
>         SET_NETDEV_DEVTYPE(dev, &br_type);
>         dev->tx_queue_len = 0;
>         dev->priv_flags = IFF_EBRIDGE;
> diff --git a/net/dsa/slave.c b/net/dsa/slave.c
> index 02c0e17..64c5af0 100644
> --- a/net/dsa/slave.c
> +++ b/net/dsa/slave.c
> @@ -346,7 +346,7 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent,
>                 return slave_dev;
>
>         slave_dev->features = master->vlan_features;
> -       SET_ETHTOOL_OPS(slave_dev, &dsa_slave_ethtool_ops);
> +       slave_dev->ethtool_ops = &dsa_slave_ethtool_ops;
>         eth_hw_addr_inherit(slave_dev, master);
>         slave_dev->tx_queue_len = 0;
>
> diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
> index 729c687..789af92 100644
> --- a/net/openvswitch/vport-internal_dev.c
> +++ b/net/openvswitch/vport-internal_dev.c
> @@ -130,7 +130,7 @@ static void do_setup(struct net_device *netdev)
>         netdev->priv_flags &= ~IFF_TX_SKB_SHARING;
>         netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
>         netdev->destructor = internal_dev_destructor;
> -       SET_ETHTOOL_OPS(netdev, &internal_dev_ethtool_ops);
> +       netdev->ethtool_ops = &internal_dev_ethtool_ops;
>         netdev->tx_queue_len = 0;
>
>         netdev->features = NETIF_F_LLTX | NETIF_F_SG | NETIF_F_FRAGLIST |
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] powerpc: irq work racing with timer interrupt can result in timer interrupt hang
From: Preeti U Murthy @ 2014-05-11  8:15 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: paulmck, paulus, Anton Blanchard, linuxppc-dev
In-Reply-To: <1399760754.17624.21.camel@pasglop>

On 05/11/2014 03:55 AM, Benjamin Herrenschmidt wrote:
> On Sat, 2014-05-10 at 21:06 +0530, Preeti U Murthy wrote:
>> On 05/10/2014 09:56 AM, Benjamin Herrenschmidt wrote:
>>> On Fri, 2014-05-09 at 15:22 +0530, Preeti U Murthy wrote:
>>>> in __timer_interrupt() outside the _else_ loop? This will ensure that no
>>>> matter what, before exiting timer interrupt handler we check for pending
>>>> irq work.
>>>
>>> We still need to make sure that set_next_event() doesn't move the
>>> dec beyond the next tick if there is a pending timer... maybe we
>>
>> Sorry, but didn't get this. s/if there is pending timer/if there is
>> pending irq work ?
> 
> Yes, sorry :-) That's what I meant.
> 
>>> can fix it like this:
>>
>> We can call set_next_event() from events like hrtimer_cancel() or
>> hrtimer_forward() as well. In that case we don't come to
>> decrementer_set_next_event() from __timer_interrupt(). Then, if we race
>> with irq work, we *do not do* a set_dec(1) ( I am referring to the patch
>> below ), we might never set the decrementer to fire immediately right?
>>
>> Or does this scenario never arise?
> 
> So my proposed patch handles that no ?
> 
> With that patch, we do the set_dec(1) in two cases:
> 
>  - The existing arch_irq_work_raise() which is unchanged
> 
>  - At the end of __timer_interrupt() if an irq work is still pending
> 
> And the patch also makes decrementer_set_next_event() not modify the
> decrementer if an irq work is pending, but *still* adjust next_tb unlike
> what the code does now.
> 
> Thus the timer interrupt, when it happens, will re-adjust the dec
> properly using next_tb.
> 
> Do we still miss a case ?

I was thinking something like the below in decrementer_set_next_event().
See last line in particular :

 -       /* Don't adjust the decrementer if some irq work is pending */
 -       if (test_irq_work_pending())
 -               return 0;
         __get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt;
 -       set_dec(evt);

 -       /* We may have raced with new irq work */
 -       if (test_irq_work_pending())
 -               set_dec(1);
 +       /* Don't adjust the decrementer if some irq work is pending */
 +       if (!test_irq_work_pending())
 +               set_dec(evt);
 +       else
 +               set_dec(1);

                  ^^^^^ your patch currently does not have this explicit
set_dec(1) here. Will that create a problem? If there is any irq work
pending at this point, will someone set the decrementer to fire
immediately after this point? The current code in
decrementer_set_next_event() sets set_dec(1) explicitly in case of
pending irq work.

Regards
Preeti U Murthy
> 
> Cheers,
> Ben.
> 
>> Regards
>> Preeti U Murthy
>>>
>>> static int decrementer_set_next_event(unsigned long evt,
>>> 				      struct clock_event_device *dev)
>>> {
>>> 	__get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt;
>>>
>>> 	/* Don't adjust the decrementer if some irq work is pending */
>>> 	if (!test_irq_work_pending())
>>> 		set_dec(evt);
>>>
>>> 	return 0;
>>> }
>>>
>>> Along with a single occurrence of:
>>>
>>> 	if (test_irq_work_pending())
>>> 		set_dec(1);
>>>
>>> At the end of __timer_interrupt(), outside if the current else {}
>>> case, this should work, don't you think ?
>>>
>>> What about this completely untested patch ?
>>>
>>> diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
>>> index 122a580..ba7e83b 100644
>>> --- a/arch/powerpc/kernel/time.c
>>> +++ b/arch/powerpc/kernel/time.c
>>> @@ -503,12 +503,13 @@ void __timer_interrupt(void)
>>>                 now = *next_tb - now;
>>>                 if (now <= DECREMENTER_MAX)
>>>                         set_dec((int)now);
>>> -               /* We may have raced with new irq work */
>>> -               if (test_irq_work_pending())
>>> -                       set_dec(1);
>>>                 __get_cpu_var(irq_stat).timer_irqs_others++;
>>>         }
>>>
>>> +       /* We may have raced with new irq work */
>>> +       if (test_irq_work_pending())
>>> +               set_dec(1);
>>> +
>>>  #ifdef CONFIG_PPC64
>>>         /* collect purr register values often, for accurate calculations */
>>>         if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
>>> @@ -813,15 +814,11 @@ static void __init clocksource_init(void)
>>>  static int decrementer_set_next_event(unsigned long evt,
>>>                                       struct clock_event_device *dev)
>>>  {
>>> -       /* Don't adjust the decrementer if some irq work is pending */
>>> -       if (test_irq_work_pending())
>>> -               return 0;
>>>         __get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt;
>>> -       set_dec(evt);
>>>
>>> -       /* We may have raced with new irq work */
>>> -       if (test_irq_work_pending())
>>> -               set_dec(1);
>>> +       /* Don't adjust the decrementer if some irq work is pending */
>>> +       if (!test_irq_work_pending())
>>> +               set_dec(evt);
>>>
>>>         return 0;
>>>  }
>>>
>>>
>>>
>>>
> 
> 

^ permalink raw reply

* Re: [PATCH] powerpc: irq work racing with timer interrupt can result in timer interrupt hang
From: Benjamin Herrenschmidt @ 2014-05-11  8:37 UTC (permalink / raw)
  To: Preeti U Murthy; +Cc: paulmck, paulus, Anton Blanchard, linuxppc-dev
In-Reply-To: <536F3192.2050004@linux.vnet.ibm.com>

On Sun, 2014-05-11 at 13:45 +0530, Preeti U Murthy wrote:
>  +       /* Don't adjust the decrementer if some irq work is pending
> */
>  +       if (!test_irq_work_pending())
>  +               set_dec(evt);
>  +       else
>  +               set_dec(1);
> 
>                   ^^^^^ your patch currently does not have this
> explicit
> set_dec(1) here. Will that create a problem? 
>
> If there is any irq work pending at this point, will someone set the
> decrementer to fire immediately after this point? The current code in
> decrementer_set_next_event() sets set_dec(1) explicitly in case of
> pending irq work.

Hrm, actually this is an interesting point. The problem isn't that
*someone* will do a set_dec, nobody else should that matters.

The problem is that irq_work can be triggered typically by NMIs or
similar, which means that it might be queued between the
test_irq_work_pending() and the set_dec(), thus causing a race.

So basically Anton's original patch is fine :-) I had missed that
we did a post-set_dec() test already in decrementer_next_event()
so as far as I can tell, removing the pre-test, which is what Anton
does, is really all we need.

Cheers,
Ben.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox