Linux virtualization list
 help / color / mirror / Atom feed
* Re: [dm-devel] [PATCH v5] fault-injection: introduce kvmalloc fallback options
From: Michael S. Tsirkin @ 2018-04-26 18:49 UTC (permalink / raw)
  To: Mikulas Patocka
  Cc: eric.dumazet, netdev, Randy Dunlap, linux-kernel, Matthew Wilcox,
	Michal Hocko, James Bottomley, linux-mm, dm-devel,
	Vlastimil Babka, David Rientjes, Andrew Morton, virtualization,
	David Miller, edumazet
In-Reply-To: <alpine.LRH.2.02.1804261202350.24656@file01.intranet.prod.int.rdu2.redhat.com>

On Thu, Apr 26, 2018 at 12:07:25PM -0400, Mikulas Patocka wrote:
> > IIUC debug kernels mainly exist so people who experience e.g. memory
> > corruption can try and debug the failure. In this case, CONFIG_DEBUG_SG
> > will *already* catch a failure early. Nothing special needs to be done.
> 
> The patch helps people debug such memory coprruptions (such as using DMA 
> API on the result of kvmalloc).

That's my point.  I don't think your patch helps debug any memory
corruptions.  With CONFIG_DEBUG_SG using DMA API already causes a
BUG_ON, that's before any memory can get corrupted.

-- 
MST

^ permalink raw reply

* Re: [dm-devel] [PATCH v5] fault-injection: introduce kvmalloc fallback options
From: Mikulas Patocka @ 2018-04-26 16:07 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: eric.dumazet, netdev, Randy Dunlap, linux-kernel, Matthew Wilcox,
	Michal Hocko, James Bottomley, linux-mm, dm-devel,
	Vlastimil Babka, David Rientjes, Andrew Morton, virtualization,
	David Miller, edumazet
In-Reply-To: <20180426184845-mutt-send-email-mst@kernel.org>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 2389 bytes --]



On Thu, 26 Apr 2018, Michael S. Tsirkin wrote:

> On Thu, Apr 26, 2018 at 11:44:21AM -0400, Mikulas Patocka wrote:
> > 
> > 
> > On Thu, 26 Apr 2018, James Bottomley wrote:
> > 
> > > On Thu, 2018-04-26 at 11:05 -0400, Mikulas Patocka wrote:
> > > > 
> > > > On Thu, 26 Apr 2018, James Bottomley wrote:
> > > [...]
> > > > > Perhaps find out beforehand instead of insisting on an approach
> > > > without
> > > > > knowing.  On openSUSE the grub config is built from the files in
> > > > > /etc/grub.d/ so any package can add a kernel option (and various
> > > > > conditions around activating it) simply by adding a new file.
> > > > 
> > > > And then, different versions of the debug kernel will clash when 
> > > > attempting to create the same file.
> > > 
> > > Don't be silly ... there are many ways of coping with that in rpm/dpkg.
> > 
> > I know you can deal with it - but how many lines of code will that 
> > consume? Multiplied by the total number of rpm-based distros.
> > 
> > Mikulas
> 
> I don't think debug kernels should inject faults by default.

But it is not injecting any faults. It is using the fault-injection 
framework because Michal said that it should use it. The original version 
of the patch didn't use the fault-injection framework at all.

The kvmalloc function can take two branches, the kmalloc branch and 
vmalloc branch. The vmalloc branch is taken rarely, so the kernel contains 
bugs regarding this path - and the patch increases the probability that 
the vmalloc patch is taken, to discover the bugs early and make them 
reproducible.

> IIUC debug kernels mainly exist so people who experience e.g. memory
> corruption can try and debug the failure. In this case, CONFIG_DEBUG_SG
> will *already* catch a failure early. Nothing special needs to be done.

The patch helps people debug such memory coprruptions (such as using DMA 
API on the result of kvmalloc).

> There is a much smaller class of people like QA who go actively looking
> for trouble. That's the kind of thing fault injection is good for, and
> IMO you do not want your QA team to test a separate kernel - otherwise
> you are never quite sure whatever was tested will work in the field.
> So a config option won't help them either.
> 
> How do you make sure QA tests a specific corner case? Add it to
> the test plan :)
> 
> I don't speak for Red Hat, etc.
> 
> -- 
> MST

Mikulas

[-- Attachment #2: Type: text/plain, Size: 183 bytes --]

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply

* Re: [dm-devel] [PATCH v5] fault-injection: introduce kvmalloc fallback options
From: Michael S. Tsirkin @ 2018-04-26 15:59 UTC (permalink / raw)
  To: Mikulas Patocka
  Cc: eric.dumazet, netdev, Randy Dunlap, linux-kernel, Matthew Wilcox,
	Michal Hocko, James Bottomley, linux-mm, dm-devel,
	Vlastimil Babka, David Rientjes, Andrew Morton, virtualization,
	David Miller, edumazet
In-Reply-To: <alpine.LRH.2.02.1804261142480.21152@file01.intranet.prod.int.rdu2.redhat.com>

On Thu, Apr 26, 2018 at 11:44:21AM -0400, Mikulas Patocka wrote:
> 
> 
> On Thu, 26 Apr 2018, James Bottomley wrote:
> 
> > On Thu, 2018-04-26 at 11:05 -0400, Mikulas Patocka wrote:
> > > 
> > > On Thu, 26 Apr 2018, James Bottomley wrote:
> > [...]
> > > > Perhaps find out beforehand instead of insisting on an approach
> > > without
> > > > knowing.  On openSUSE the grub config is built from the files in
> > > > /etc/grub.d/ so any package can add a kernel option (and various
> > > > conditions around activating it) simply by adding a new file.
> > > 
> > > And then, different versions of the debug kernel will clash when 
> > > attempting to create the same file.
> > 
> > Don't be silly ... there are many ways of coping with that in rpm/dpkg.
> 
> I know you can deal with it - but how many lines of code will that 
> consume? Multiplied by the total number of rpm-based distros.
> 
> Mikulas

I don't think debug kernels should inject faults by default.

IIUC debug kernels mainly exist so people who experience e.g. memory
corruption can try and debug the failure. In this case, CONFIG_DEBUG_SG
will *already* catch a failure early. Nothing special needs to be done.

There is a much smaller class of people like QA who go actively looking
for trouble. That's the kind of thing fault injection is good for, and
IMO you do not want your QA team to test a separate kernel - otherwise
you are never quite sure whatever was tested will work in the field.
So a config option won't help them either.

How do you make sure QA tests a specific corner case? Add it to
the test plan :)

I don't speak for Red Hat, etc.

-- 
MST

^ permalink raw reply

* Re: [dm-devel] [PATCH v5] fault-injection: introduce kvmalloc fallback options
From: Mikulas Patocka @ 2018-04-26 15:55 UTC (permalink / raw)
  To: James Bottomley
  Cc: eric.dumazet, mst, netdev, Randy Dunlap, linux-kernel,
	Matthew Wilcox, Michal Hocko, linux-mm, dm-devel, Vlastimil Babka,
	David Rientjes, Andrew Morton, virtualization, David Miller,
	edumazet
In-Reply-To: <1524756256.3226.7.camel@HansenPartnership.com>



On Thu, 26 Apr 2018, James Bottomley wrote:

> So you're shifting your argument from "I have to do it as a Kconfig
> option because the distros require it" to "distributions will build
> separate kernel packages for this, but won't do enabling in a non
> kernel package"?  To be honest, I think the argument is nuts but I
> don't really care.  From my point of view it's usually me explaining to
> people how to debug stuff and "you have to build your own kernel with
> this Kconfig option" compared to "add this to the kernel command line
> and reboot" is much more effort for the debugger.
> 
> James

If you have to explain to the user that he needs to turn it on, it is 
already wrong.

In order to find the kvmalloc abuses, it should be tested by as many users 
as possible. And it could be tested by as many users as possible, if it 
can be enabled in a VISIBLE place (i.e. menuconfig) - or (in my opinion 
even better) it should be bound to an CONFIG_ option that is already 
enabled for debugging kernel - then you won't have to explain anything to 
the user at all.

Hardly anyone - except for people who read this thread - will know about 
the new commandline parameters or debugfs files.

I'm not arguing that the commandline parameter or debugfs files are wrong. 
They are OK to overridde the default settings for advanced users. But they 
are useless for common users because common users won't know about them.

Mikulas

^ permalink raw reply

* Re: [dm-devel] [PATCH v5] fault-injection: introduce kvmalloc fallback options
From: Mikulas Patocka @ 2018-04-26 15:44 UTC (permalink / raw)
  To: James Bottomley
  Cc: eric.dumazet, mst, netdev, Randy Dunlap, linux-kernel,
	Matthew Wilcox, Michal Hocko, linux-mm, dm-devel, Vlastimil Babka,
	David Rientjes, Andrew Morton, virtualization, David Miller,
	edumazet
In-Reply-To: <1524756256.3226.7.camel@HansenPartnership.com>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 794 bytes --]



On Thu, 26 Apr 2018, James Bottomley wrote:

> On Thu, 2018-04-26 at 11:05 -0400, Mikulas Patocka wrote:
> > 
> > On Thu, 26 Apr 2018, James Bottomley wrote:
> [...]
> > > Perhaps find out beforehand instead of insisting on an approach
> > without
> > > knowing.  On openSUSE the grub config is built from the files in
> > > /etc/grub.d/ so any package can add a kernel option (and various
> > > conditions around activating it) simply by adding a new file.
> > 
> > And then, different versions of the debug kernel will clash when 
> > attempting to create the same file.
> 
> Don't be silly ... there are many ways of coping with that in rpm/dpkg.

I know you can deal with it - but how many lines of code will that 
consume? Multiplied by the total number of rpm-based distros.

Mikulas

[-- Attachment #2: Type: text/plain, Size: 183 bytes --]

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply

* Re: [dm-devel] [PATCH v5] fault-injection: introduce kvmalloc fallback options
From: Mikulas Patocka @ 2018-04-26 15:22 UTC (permalink / raw)
  To: James Bottomley
  Cc: eric.dumazet, mst, netdev, Randy Dunlap, linux-kernel,
	Matthew Wilcox, Michal Hocko, linux-mm, dm-devel, Vlastimil Babka,
	David Rientjes, Andrew Morton, virtualization, David Miller,
	edumazet
In-Reply-To: <alpine.LRH.2.02.1804261045001.9108@file01.intranet.prod.int.rdu2.redhat.com>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 2023 bytes --]



On Thu, 26 Apr 2018, Mikulas Patocka wrote:

> 
> 
> On Wed, 25 Apr 2018, James Bottomley wrote:
> 
> > > BTW. even developers who compile their own kernel should have this
> > > enabled by a CONFIG option - because if the developer sees the option
> > > when browsing through menuconfig, he may enable it. If he doesn't see
> > > the option, he won't even know that such an option exists.
> > 
> > I may be an atypical developer but I'd rather have a root canal than
> > browse through menuconfig options.  The way to get people to learn
> > about new debugging options is to blog about it (or write an lwn.net
> > article) which google will find the next time I ask it how I debug XXX.
> >  Google (probably as a service to humanity) rarely turns up Kconfig
> > options in response to a query.
> 
> From my point of view, this feature should be as little disruptive to the 
> developer as possible. It should work automatically behind the scenes 
> without the developer or the tester even knowing that it is working. From 
> this point of view, binding it to CONFIG_DEBUG_SG (or any other commonly 
> used debugging option) would be ideal, because driver developers already 
> enable CONFIG_DEBUG_SG, so they'll get this kvmalloc test for free.
> 
> From your point of view, you should introduce a sysfs file and a kernel 
> parameter that no one knows about - and then start blogging about it - to 
> let people know. Why would you bother people with this knowledge? They'll 
> forget about it anyway and won't turn it on.

BTW. try to think about - how many total lines of code should this feature 
consume in the whole Linux ecosystem?

I made a 10-line patch. I got pushback.

I remade it to a 53-line patch. And you try to suggest that 53 lines is 
not enough and we must also change kernel packaging scripts in distro 
kernels, because the kernel just cannot enable this feature on its own.

If we hack kernel packaging scripts in most distros, how many lines of 
code would that be? What's your target?

Mikulas

[-- Attachment #2: Type: text/plain, Size: 183 bytes --]

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply

* Re: [dm-devel] [PATCH v5] fault-injection: introduce kvmalloc fallback options
From: Mikulas Patocka @ 2018-04-26 15:05 UTC (permalink / raw)
  To: James Bottomley
  Cc: eric.dumazet, mst, netdev, Randy Dunlap, linux-kernel,
	Matthew Wilcox, Michal Hocko, linux-mm, dm-devel, Vlastimil Babka,
	David Rientjes, Andrew Morton, virtualization, David Miller,
	edumazet
In-Reply-To: <1524753932.3226.5.camel@HansenPartnership.com>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 2228 bytes --]



On Thu, 26 Apr 2018, James Bottomley wrote:

> On Thu, 2018-04-26 at 10:28 -0400, Mikulas Patocka wrote:
> > 
> > On Thu, 26 Apr 2018, Michal Hocko wrote:
> > 
> > > On Wed 25-04-18 18:42:57, Mikulas Patocka wrote:
> > > > 
> > > > 
> > > > On Wed, 25 Apr 2018, James Bottomley wrote:
> > > [...]
> > > > > Kconfig proliferation, conversely, is a bit of a nightmare from
> > both
> > > > > the user and the tester's point of view, so we're trying to
> > avoid it
> > > > > unless absolutely necessary.
> > > > > 
> > > > > James
> > > > 
> > > > I already offered that we don't need to introduce a new kernel
> > option and 
> > > > we can bind this feature to any other kernel option, that is
> > enabled in 
> > > > the debug kernel, for example CONFIG_DEBUG_SG. Michal said no and
> > he said 
> > > > that he wants a new kernel option instead.
> > > 
> > > Just for the record. I didn't say I _want_ a config option. Do not
> > > misinterpret my words. I've said that a config option would be
> > > acceptable if there is no way to deliver the functionality via
> > kernel
> > > package automatically. You haven't provided any argument that would
> > > explain why the kernel package cannot add a boot option. Maybe
> > there are
> > > some but I do not see them right now.
> > 
> > AFAIK Grub doesn't load per-kernel options from a per-kernel file.
> > Even if we hacked grub scripts to add this option, other
> > distributions won't.
> 
> Perhaps find out beforehand instead of insisting on an approach without
> knowing.  On openSUSE the grub config is built from the files in
> /etc/grub.d/ so any package can add a kernel option (and various
> conditions around activating it) simply by adding a new file.

And then, different versions of the debug kernel will clash when 
attempting to create the same file.

And what about other distributions? What about people who the RHEL kernel 
from source with "make"?

The problem with this approach that you are trying to bother more and more 
people with this little silly feature.

> The config files are quite sophisticated, so you can add what looks to 
> be a new kernel, but is really an existing kernel with different options 
> this way.
> 
> James

Mikulas

[-- Attachment #2: Type: text/plain, Size: 183 bytes --]

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply

* Re: [dm-devel] [PATCH v5] fault-injection: introduce kvmalloc fallback options
From: Mikulas Patocka @ 2018-04-26 14:55 UTC (permalink / raw)
  To: James Bottomley
  Cc: eric.dumazet, mst, netdev, Randy Dunlap, linux-kernel,
	Matthew Wilcox, Michal Hocko, linux-mm, dm-devel, Vlastimil Babka,
	David Rientjes, Andrew Morton, virtualization, David Miller,
	edumazet
In-Reply-To: <1524697697.4100.23.camel@HansenPartnership.com>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1436 bytes --]



On Wed, 25 Apr 2018, James Bottomley wrote:

> > BTW. even developers who compile their own kernel should have this
> > enabled by a CONFIG option - because if the developer sees the option
> > when browsing through menuconfig, he may enable it. If he doesn't see
> > the option, he won't even know that such an option exists.
> 
> I may be an atypical developer but I'd rather have a root canal than
> browse through menuconfig options.  The way to get people to learn
> about new debugging options is to blog about it (or write an lwn.net
> article) which google will find the next time I ask it how I debug XXX.
>  Google (probably as a service to humanity) rarely turns up Kconfig
> options in response to a query.

From my point of view, this feature should be as little disruptive to the 
developer as possible. It should work automatically behind the scenes 
without the developer or the tester even knowing that it is working. From 
this point of view, binding it to CONFIG_DEBUG_SG (or any other commonly 
used debugging option) would be ideal, because driver developers already 
enable CONFIG_DEBUG_SG, so they'll get this kvmalloc test for free.

From your point of view, you should introduce a sysfs file and a kernel 
parameter that no one knows about - and then start blogging about it - to 
let people know. Why would you bother people with this knowledge? They'll 
forget about it anyway and won't turn it on.

Mikulas

[-- Attachment #2: Type: text/plain, Size: 183 bytes --]

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply

* Re: [dm-devel] [PATCH v5] fault-injection: introduce kvmalloc fallback options
From: Mikulas Patocka @ 2018-04-26 14:28 UTC (permalink / raw)
  To: Michal Hocko
  Cc: eric.dumazet, mst, netdev, Randy Dunlap, linux-kernel,
	Matthew Wilcox, virtualization, James Bottomley, linux-mm,
	dm-devel, Vlastimil Babka, David Rientjes, Andrew Morton,
	David Miller, edumazet
In-Reply-To: <20180426125817.GO17484@dhcp22.suse.cz>



On Thu, 26 Apr 2018, Michal Hocko wrote:

> On Wed 25-04-18 18:42:57, Mikulas Patocka wrote:
> > 
> > 
> > On Wed, 25 Apr 2018, James Bottomley wrote:
> [...]
> > > Kconfig proliferation, conversely, is a bit of a nightmare from both
> > > the user and the tester's point of view, so we're trying to avoid it
> > > unless absolutely necessary.
> > > 
> > > James
> > 
> > I already offered that we don't need to introduce a new kernel option and 
> > we can bind this feature to any other kernel option, that is enabled in 
> > the debug kernel, for example CONFIG_DEBUG_SG. Michal said no and he said 
> > that he wants a new kernel option instead.
> 
> Just for the record. I didn't say I _want_ a config option. Do not
> misinterpret my words. I've said that a config option would be
> acceptable if there is no way to deliver the functionality via kernel
> package automatically. You haven't provided any argument that would
> explain why the kernel package cannot add a boot option. Maybe there are
> some but I do not see them right now.

AFAIK Grub doesn't load per-kernel options from a per-kernel file. Even if 
we hacked grub scripts to add this option, other distributions won't.

Mikulas

^ permalink raw reply

* Re: [Intel-gfx] [PATCH] drm/core: Remove drm_dev_unref() and it's uses
From: Daniel Vetter @ 2018-04-26 13:52 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: Heiko Stübner, Dave Airlie, Nouveau Dev, Linus Walleij,
	Stefan Agner, open list:VIRTIO CORE, NET..., Matthias Brugger,
	Laurent Pinchart, Benjamin Gaignard, Marek Vasut, Chunming Zhou,
	Maxime Ripard, linux-samsung-soc, Joonyoung Shim,
	Russell King - ARM Linux, Krzysztof Kozlowski, Jon Hunter,
	Xinliang Liu, open list:ARM/Rockchip SoC...
In-Reply-To: <20180426131404.GP4813@piout.net>

On Thu, Apr 26, 2018 at 3:14 PM, Alexandre Belloni
<alexandre.belloni@bootlin.com> wrote:
> Hi,
>
> On 26/04/2018 15:45:44+0300, Laurent Pinchart wrote:
>> Hi Daniel,
>>
>> On Thursday, 26 April 2018 15:36:15 EEST Daniel Vetter wrote:
>> > On Thu, Apr 26, 2018 at 03:58:19PM +0530, Vaishali Thakkar wrote:
>> > > It's been a while since we introduced drm_dev{get/put} functions
>> > > to replace reference/unreference in drm subsystem for the
>> > > consistency purpose. So, with this patch, let's just replace
>> > > all current use cases of drm_dev_unref() with drm_dev_put and remove
>> > > the function itself.
>> > >
>> > > Coccinelle was used for mass-patching.
>> > >
>> > > Signed-off-by: Vaishali Thakkar <vthakkar1994@gmail.com>
>> >
>> > Thanks for doing this. Unfortunately drm moves pretty fast, so already a
>> > conflict when I tried to apply this. Some drivers are also in their own
>> > trees, so this might lead to more fun :-/
>> >
>> > Can you pls split it up per-driver (just the directories under
>> > drivers/gpu/drm/ is enough)? Final patch to remove the function might then
>> > get stalled a bit ofc.
>>
>> I requested a single patch instead of splitting it per driver, you might want
>> to blame me for that.
>>
>
> Doesn't splitting the change per driver break bisectability unless there
> is a guarantee that the change in include/drm/drm_drv.h is applied after
> all the driver trees have been merged?

That's why I said the final patch will likely take a bit longer to get
merged, since we have to wait until all the trees converge again. But
since I have conflicts already looks like we can't take the shortcut
:-(
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply

* Re: [dm-devel] [PATCH v5] fault-injection: introduce kvmalloc fallback options
From: Michal Hocko @ 2018-04-26 12:58 UTC (permalink / raw)
  To: Mikulas Patocka
  Cc: eric.dumazet, mst, netdev, Randy Dunlap, linux-kernel,
	Matthew Wilcox, virtualization, James Bottomley, linux-mm,
	dm-devel, Vlastimil Babka, David Rientjes, Andrew Morton,
	David Miller, edumazet
In-Reply-To: <alpine.LRH.2.02.1804251830540.25124@file01.intranet.prod.int.rdu2.redhat.com>

On Wed 25-04-18 18:42:57, Mikulas Patocka wrote:
> 
> 
> On Wed, 25 Apr 2018, James Bottomley wrote:
[...]
> > Kconfig proliferation, conversely, is a bit of a nightmare from both
> > the user and the tester's point of view, so we're trying to avoid it
> > unless absolutely necessary.
> > 
> > James
> 
> I already offered that we don't need to introduce a new kernel option and 
> we can bind this feature to any other kernel option, that is enabled in 
> the debug kernel, for example CONFIG_DEBUG_SG. Michal said no and he said 
> that he wants a new kernel option instead.

Just for the record. I didn't say I _want_ a config option. Do not
misinterpret my words. I've said that a config option would be
acceptable if there is no way to deliver the functionality via kernel
package automatically. You haven't provided any argument that would
explain why the kernel package cannot add a boot option. Maybe there are
some but I do not see them right now.
-- 
Michal Hocko
SUSE Labs

^ permalink raw reply

* Re: [Intel-gfx] [PATCH] drm/core: Remove drm_dev_unref() and it's uses
From: Laurent Pinchart @ 2018-04-26 12:45 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: matthias.bgg, alexandre.belloni, heiko, airlied, nouveau,
	linus.walleij, stefan, virtualization, benjamin.gaignard,
	shawnguo, marex, David1.Zhou, maxime.ripard, linux-samsung-soc,
	jy0922.shim, linux, krzk, jonathanh, z.liuxinliang,
	linux-rockchip, kong.kongxinwei, tomi.valkeinen, bskeggs,
	puck.chen, ck.hu, airlied, linux-arm-msm, intel-gfx,
	nicolas.ferre, etnaviv, brodkin, zourongrong, linux-mediatek,
	dri-devel
In-Reply-To: <20180426123615.GA12521@phenom.ffwll.local>

Hi Daniel,

On Thursday, 26 April 2018 15:36:15 EEST Daniel Vetter wrote:
> On Thu, Apr 26, 2018 at 03:58:19PM +0530, Vaishali Thakkar wrote:
> > It's been a while since we introduced drm_dev{get/put} functions
> > to replace reference/unreference in drm subsystem for the
> > consistency purpose. So, with this patch, let's just replace
> > all current use cases of drm_dev_unref() with drm_dev_put and remove
> > the function itself.
> > 
> > Coccinelle was used for mass-patching.
> > 
> > Signed-off-by: Vaishali Thakkar <vthakkar1994@gmail.com>
> 
> Thanks for doing this. Unfortunately drm moves pretty fast, so already a
> conflict when I tried to apply this. Some drivers are also in their own
> trees, so this might lead to more fun :-/
> 
> Can you pls split it up per-driver (just the directories under
> drivers/gpu/drm/ is enough)? Final patch to remove the function might then
> get stalled a bit ofc.

I requested a single patch instead of splitting it per driver, you might want 
to blame me for that.

> Also can you pls update ./scripts/coccinelle/api/drm-get-put.cocci and
> remove that spatch hunk in the final patch, since we no longer need it?

How about just rerunning the coccinelle patch when it's time to apply this ? 
There's precedent for performing such automated changes, and it would ensure 
that no driver is left out.

> > ---
> > 
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c            |  4 ++--
> >  drivers/gpu/drm/arc/arcpgu_drv.c                   |  4 ++--
> >  drivers/gpu/drm/armada/armada_drv.c                |  6 +++---
> >  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c       |  4 ++--
> >  drivers/gpu/drm/drm_drv.c                          | 13 -------------
> >  drivers/gpu/drm/etnaviv/etnaviv_drv.c              |  4 ++--
> >  drivers/gpu/drm/exynos/exynos_drm_drv.c            |  4 ++--
> >  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c          |  4 ++--
> >  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c    |  4 ++--
> >  drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c    |  8 ++++----
> >  drivers/gpu/drm/i915/selftests/huge_pages.c        |  2 +-
> >  drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c   |  2 +-
> >  drivers/gpu/drm/i915/selftests/i915_gem_evict.c    |  2 +-
> >  drivers/gpu/drm/i915/selftests/i915_gem_gtt.c      |  2 +-
> >  drivers/gpu/drm/i915/selftests/i915_gem_object.c   |  2 +-
> >  drivers/gpu/drm/i915/selftests/i915_request.c      |  2 +-
> >  drivers/gpu/drm/i915/selftests/i915_vma.c          |  2 +-
> >  drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c |  2 +-
> >  drivers/gpu/drm/imx/imx-drm-core.c                 |  4 ++--
> >  drivers/gpu/drm/mediatek/mtk_drm_drv.c             |  6 +++---
> >  drivers/gpu/drm/msm/msm_drv.c                      |  8 ++++----
> >  drivers/gpu/drm/mxsfb/mxsfb_drv.c                  |  4 ++--
> >  drivers/gpu/drm/nouveau/nouveau_platform.c         |  2 +-
> >  drivers/gpu/drm/omapdrm/omap_drv.c                 |  4 ++--
> >  drivers/gpu/drm/pl111/pl111_drv.c                  |  4 ++--
> >  drivers/gpu/drm/qxl/qxl_drv.c                      |  2 +-
> >  drivers/gpu/drm/rcar-du/rcar_du_drv.c              |  2 +-
> >  drivers/gpu/drm/rockchip/rockchip_drm_drv.c        |  4 ++--
> >  drivers/gpu/drm/shmobile/shmob_drm_drv.c           |  4 ++--
> >  drivers/gpu/drm/sti/sti_drv.c                      |  8 ++++----
> >  drivers/gpu/drm/stm/drv.c                          |  4 ++--
> >  drivers/gpu/drm/sun4i/sun4i_drv.c                  |  4 ++--
> >  drivers/gpu/drm/tegra/drm.c                        |  4 ++--
> >  drivers/gpu/drm/tinydrm/core/tinydrm-core.c        |  6 +++---
> >  drivers/gpu/drm/tve200/tve200_drv.c                |  4 ++--
> >  drivers/gpu/drm/udl/udl_drv.c                      |  2 +-
> >  drivers/gpu/drm/vc4/vc4_drv.c                      |  4 ++--
> >  drivers/gpu/drm/vgem/vgem_drv.c                    |  2 +-
> >  drivers/gpu/drm/virtio/virtgpu_drm_bus.c           |  2 +-
> >  drivers/gpu/drm/zte/zx_drm_drv.c                   |  4 ++--
> >  include/drm/drm_drv.h                              |  1 -
> >  41 files changed, 73 insertions(+), 87 deletions(-)

-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* Re: [Intel-gfx] [PATCH] drm/core: Remove drm_dev_unref() and it's uses
From: Daniel Vetter @ 2018-04-26 12:36 UTC (permalink / raw)
  To: Vaishali Thakkar
  Cc: alexandre.belloni, heiko, airlied, nouveau, linus.walleij, stefan,
	virtualization, matthias.bgg, benjamin.gaignard, marex,
	David1.Zhou, maxime.ripard, linux-samsung-soc, jy0922.shim, linux,
	krzk, jonathanh, z.liuxinliang, linux-rockchip, kong.kongxinwei,
	tomi.valkeinen, bskeggs, puck.chen, ck.hu, airlied, linux-arm-msm,
	intel-gfx, nicolas.ferre, etnaviv, brodkin, zourongrong,
	linux-mediatek, dri-devel, rodrigo.vivi
In-Reply-To: <20180426102819.6985-1-vthakkar1994@gmail.com>

On Thu, Apr 26, 2018 at 03:58:19PM +0530, Vaishali Thakkar wrote:
> It's been a while since we introduced drm_dev{get/put} functions
> to replace reference/unreference in drm subsystem for the
> consistency purpose. So, with this patch, let's just replace
> all current use cases of drm_dev_unref() with drm_dev_put and remove
> the function itself.
> 
> Coccinelle was used for mass-patching.
> 
> Signed-off-by: Vaishali Thakkar <vthakkar1994@gmail.com>

Thanks for doing this. Unfortunately drm moves pretty fast, so already a
conflict when I tried to apply this. Some drivers are also in their own
trees, so this might lead to more fun :-/

Can you pls split it up per-driver (just the directories under
drivers/gpu/drm/ is enough)? Final patch to remove the function might then
get stalled a bit ofc.

Also can you pls update ./scripts/coccinelle/api/drm-get-put.cocci and
remove that spatch hunk in the final patch, since we no longer need it?

Thanks, Daniel

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c            |  4 ++--
>  drivers/gpu/drm/arc/arcpgu_drv.c                   |  4 ++--
>  drivers/gpu/drm/armada/armada_drv.c                |  6 +++---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c       |  4 ++--
>  drivers/gpu/drm/drm_drv.c                          | 13 -------------
>  drivers/gpu/drm/etnaviv/etnaviv_drv.c              |  4 ++--
>  drivers/gpu/drm/exynos/exynos_drm_drv.c            |  4 ++--
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c          |  4 ++--
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c    |  4 ++--
>  drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c    |  8 ++++----
>  drivers/gpu/drm/i915/selftests/huge_pages.c        |  2 +-
>  drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c   |  2 +-
>  drivers/gpu/drm/i915/selftests/i915_gem_evict.c    |  2 +-
>  drivers/gpu/drm/i915/selftests/i915_gem_gtt.c      |  2 +-
>  drivers/gpu/drm/i915/selftests/i915_gem_object.c   |  2 +-
>  drivers/gpu/drm/i915/selftests/i915_request.c      |  2 +-
>  drivers/gpu/drm/i915/selftests/i915_vma.c          |  2 +-
>  drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c |  2 +-
>  drivers/gpu/drm/imx/imx-drm-core.c                 |  4 ++--
>  drivers/gpu/drm/mediatek/mtk_drm_drv.c             |  6 +++---
>  drivers/gpu/drm/msm/msm_drv.c                      |  8 ++++----
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c                  |  4 ++--
>  drivers/gpu/drm/nouveau/nouveau_platform.c         |  2 +-
>  drivers/gpu/drm/omapdrm/omap_drv.c                 |  4 ++--
>  drivers/gpu/drm/pl111/pl111_drv.c                  |  4 ++--
>  drivers/gpu/drm/qxl/qxl_drv.c                      |  2 +-
>  drivers/gpu/drm/rcar-du/rcar_du_drv.c              |  2 +-
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.c        |  4 ++--
>  drivers/gpu/drm/shmobile/shmob_drm_drv.c           |  4 ++--
>  drivers/gpu/drm/sti/sti_drv.c                      |  8 ++++----
>  drivers/gpu/drm/stm/drv.c                          |  4 ++--
>  drivers/gpu/drm/sun4i/sun4i_drv.c                  |  4 ++--
>  drivers/gpu/drm/tegra/drm.c                        |  4 ++--
>  drivers/gpu/drm/tinydrm/core/tinydrm-core.c        |  6 +++---
>  drivers/gpu/drm/tve200/tve200_drv.c                |  4 ++--
>  drivers/gpu/drm/udl/udl_drv.c                      |  2 +-
>  drivers/gpu/drm/vc4/vc4_drv.c                      |  4 ++--
>  drivers/gpu/drm/vgem/vgem_drv.c                    |  2 +-
>  drivers/gpu/drm/virtio/virtgpu_drm_bus.c           |  2 +-
>  drivers/gpu/drm/zte/zx_drm_drv.c                   |  4 ++--
>  include/drm/drm_drv.h                              |  1 -
>  41 files changed, 73 insertions(+), 87 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> index 0b19482b36b8..5fb455febeba 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> @@ -647,7 +647,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
>  err_pci:
>  	pci_disable_device(pdev);
>  err_free:
> -	drm_dev_unref(dev);
> +	drm_dev_put(dev);
>  	return ret;
>  }
>  
> @@ -657,7 +657,7 @@ amdgpu_pci_remove(struct pci_dev *pdev)
>  	struct drm_device *dev = pci_get_drvdata(pdev);
>  
>  	drm_dev_unregister(dev);
> -	drm_dev_unref(dev);
> +	drm_dev_put(dev);
>  	pci_disable_device(pdev);
>  	pci_set_drvdata(pdev, NULL);
>  }
> diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c
> index f067de4e1e82..dcb06d4e9135 100644
> --- a/drivers/gpu/drm/arc/arcpgu_drv.c
> +++ b/drivers/gpu/drm/arc/arcpgu_drv.c
> @@ -216,7 +216,7 @@ static int arcpgu_probe(struct platform_device *pdev)
>  	arcpgu_unload(drm);
>  
>  err_unref:
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  
>  	return ret;
>  }
> @@ -227,7 +227,7 @@ static int arcpgu_remove(struct platform_device *pdev)
>  
>  	drm_dev_unregister(drm);
>  	arcpgu_unload(drm);
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
> index 4b11b6b52f1d..d1705d298a39 100644
> --- a/drivers/gpu/drm/armada/armada_drv.c
> +++ b/drivers/gpu/drm/armada/armada_drv.c
> @@ -109,7 +109,7 @@ static int armada_drm_bind(struct device *dev)
>  
>  	/*
>  	 * The drm_device structure must be at the start of
> -	 * armada_private for drm_dev_unref() to work correctly.
> +	 * armada_private for drm_dev_put() to work correctly.
>  	 */
>  	BUILD_BUG_ON(offsetof(struct armada_private, drm) != 0);
>  
> @@ -180,7 +180,7 @@ static int armada_drm_bind(struct device *dev)
>  	drm_mode_config_cleanup(&priv->drm);
>  	drm_mm_takedown(&priv->linear);
>  	flush_work(&priv->fb_unref_work);
> -	drm_dev_unref(&priv->drm);
> +	drm_dev_put(&priv->drm);
>  	return ret;
>  }
>  
> @@ -200,7 +200,7 @@ static void armada_drm_unbind(struct device *dev)
>  	drm_mm_takedown(&priv->linear);
>  	flush_work(&priv->fb_unref_work);
>  
> -	drm_dev_unref(&priv->drm);
> +	drm_dev_put(&priv->drm);
>  }
>  
>  static int compare_of(struct device *dev, void *data)
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> index c1ea5c36b006..1c8487803a70 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> @@ -774,7 +774,7 @@ static int atmel_hlcdc_dc_drm_probe(struct platform_device *pdev)
>  	atmel_hlcdc_dc_unload(ddev);
>  
>  err_unref:
> -	drm_dev_unref(ddev);
> +	drm_dev_put(ddev);
>  
>  	return ret;
>  }
> @@ -785,7 +785,7 @@ static int atmel_hlcdc_dc_drm_remove(struct platform_device *pdev)
>  
>  	drm_dev_unregister(ddev);
>  	atmel_hlcdc_dc_unload(ddev);
> -	drm_dev_unref(ddev);
> +	drm_dev_put(ddev);
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index a1b9338736e3..3dc507b13cf2 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -656,19 +656,6 @@ void drm_dev_put(struct drm_device *dev)
>  }
>  EXPORT_SYMBOL(drm_dev_put);
>  
> -/**
> - * drm_dev_unref - Drop reference of a DRM device
> - * @dev: device to drop reference of or NULL
> - *
> - * This is a compatibility alias for drm_dev_put() and should not be used by new
> - * code.
> - */
> -void drm_dev_unref(struct drm_device *dev)
> -{
> -	drm_dev_put(dev);
> -}
> -EXPORT_SYMBOL(drm_dev_unref);
> -
>  static int create_compat_control_link(struct drm_device *dev)
>  {
>  	struct drm_minor *minor;
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
> index ab50090d066c..716187a07227 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
> @@ -613,7 +613,7 @@ static int etnaviv_bind(struct device *dev)
>  out_bind:
>  	kfree(priv);
>  out_unref:
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  
>  	return ret;
>  }
> @@ -630,7 +630,7 @@ static void etnaviv_unbind(struct device *dev)
>  	drm->dev_private = NULL;
>  	kfree(priv);
>  
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  }
>  
>  static const struct component_master_ops etnaviv_master_ops = {
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> index a518e9c6d6cc..3629e5c93e3a 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> @@ -411,7 +411,7 @@ static int exynos_drm_bind(struct device *dev)
>  err_free_private:
>  	kfree(private);
>  err_free_drm:
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  
>  	return ret;
>  }
> @@ -435,7 +435,7 @@ static void exynos_drm_unbind(struct device *dev)
>  	drm->dev_private = NULL;
>  	dev_set_drvdata(dev, NULL);
>  
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  }
>  
>  static const struct component_master_ops exynos_drm_ops = {
> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
> index 80232321a244..664ac9dc1f65 100644
> --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
> +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
> @@ -358,7 +358,7 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev)
>  	return 0;
>  
>  unref:
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  unregister_pix_clk:
>  	clk_unregister(fsl_dev->pix_clk);
>  disable_clk:
> @@ -371,7 +371,7 @@ static int fsl_dcu_drm_remove(struct platform_device *pdev)
>  	struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);
>  
>  	drm_dev_unregister(fsl_dev->drm);
> -	drm_dev_unref(fsl_dev->drm);
> +	drm_dev_put(fsl_dev->drm);
>  	clk_disable_unprepare(fsl_dev->clk);
>  	clk_unregister(fsl_dev->pix_clk);
>  
> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
> index d4f6f1f9df5b..ec878c7e3f75 100644
> --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
> @@ -387,7 +387,7 @@ static int hibmc_pci_probe(struct pci_dev *pdev,
>  err_disable:
>  	pci_disable_device(pdev);
>  err_free:
> -	drm_dev_unref(dev);
> +	drm_dev_put(dev);
>  
>  	return ret;
>  }
> @@ -398,7 +398,7 @@ static void hibmc_pci_remove(struct pci_dev *pdev)
>  
>  	drm_dev_unregister(dev);
>  	hibmc_unload(dev);
> -	drm_dev_unref(dev);
> +	drm_dev_put(dev);
>  }
>  
>  static struct pci_device_id hibmc_pci_table[] = {
> diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> index ddb0403f1975..e6a62d5a00a3 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> @@ -193,7 +193,7 @@ static int kirin_drm_bind(struct device *dev)
>  
>  	ret = kirin_drm_kms_init(drm_dev);
>  	if (ret)
> -		goto err_drm_dev_unref;
> +		goto err_drm_dev_put;
>  
>  	ret = drm_dev_register(drm_dev, 0);
>  	if (ret)
> @@ -203,8 +203,8 @@ static int kirin_drm_bind(struct device *dev)
>  
>  err_kms_cleanup:
>  	kirin_drm_kms_cleanup(drm_dev);
> -err_drm_dev_unref:
> -	drm_dev_unref(drm_dev);
> +err_drm_dev_put:
> +	drm_dev_put(drm_dev);
>  
>  	return ret;
>  }
> @@ -215,7 +215,7 @@ static void kirin_drm_unbind(struct device *dev)
>  
>  	drm_dev_unregister(drm_dev);
>  	kirin_drm_kms_cleanup(drm_dev);
> -	drm_dev_unref(drm_dev);
> +	drm_dev_put(drm_dev);
>  }
>  
>  static const struct component_master_ops kirin_drm_ops = {
> diff --git a/drivers/gpu/drm/i915/selftests/huge_pages.c b/drivers/gpu/drm/i915/selftests/huge_pages.c
> index 05bbef363fff..22de60920b1a 100644
> --- a/drivers/gpu/drm/i915/selftests/huge_pages.c
> +++ b/drivers/gpu/drm/i915/selftests/huge_pages.c
> @@ -1720,7 +1720,7 @@ int i915_gem_huge_page_mock_selftests(void)
>  
>  	i915_modparams.enable_ppgtt = saved_ppgtt;
>  
> -	drm_dev_unref(&dev_priv->drm);
> +	drm_dev_put(&dev_priv->drm);
>  
>  	return err;
>  }
> diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c
> index 89dc25a5a53b..a7055b12e53c 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c
> +++ b/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c
> @@ -389,7 +389,7 @@ int i915_gem_dmabuf_mock_selftests(void)
>  
>  	err = i915_subtests(tests, i915);
>  
> -	drm_dev_unref(&i915->drm);
> +	drm_dev_put(&i915->drm);
>  	return err;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
> index ab9d7bee0aae..7b21e4135aa5 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
> +++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
> @@ -490,7 +490,7 @@ int i915_gem_evict_mock_selftests(void)
>  	err = i915_subtests(tests, i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  
> -	drm_dev_unref(&i915->drm);
> +	drm_dev_put(&i915->drm);
>  	return err;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
> index f7dc926f4ef1..1cf4e9af0b65 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
> +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
> @@ -1646,7 +1646,7 @@ int i915_gem_gtt_mock_selftests(void)
>  	err = i915_subtests(tests, i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  
> -	drm_dev_unref(&i915->drm);
> +	drm_dev_put(&i915->drm);
>  	return err;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/selftests/i915_gem_object.c
> index fbdb2419d418..7066f22ef8f1 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_gem_object.c
> +++ b/drivers/gpu/drm/i915/selftests/i915_gem_object.c
> @@ -586,7 +586,7 @@ int i915_gem_object_mock_selftests(void)
>  
>  	err = i915_subtests(tests, i915);
>  
> -	drm_dev_unref(&i915->drm);
> +	drm_dev_put(&i915->drm);
>  	return err;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c
> index 94bc2e1898a4..5d069de4a19a 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_request.c
> +++ b/drivers/gpu/drm/i915/selftests/i915_request.c
> @@ -262,7 +262,7 @@ int i915_request_mock_selftests(void)
>  		return -ENOMEM;
>  
>  	err = i915_subtests(tests, i915);
> -	drm_dev_unref(&i915->drm);
> +	drm_dev_put(&i915->drm);
>  
>  	return err;
>  }
> diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c
> index eb89e301b602..9fbba5defb3e 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_vma.c
> +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c
> @@ -734,7 +734,7 @@ int i915_vma_mock_selftests(void)
>  	err = i915_subtests(tests, i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  
> -	drm_dev_unref(&i915->drm);
> +	drm_dev_put(&i915->drm);
>  	return err;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c
> index 46580026c7fc..b6c9deeeda7b 100644
> --- a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c
> +++ b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c
> @@ -463,7 +463,7 @@ int intel_breadcrumbs_mock_selftests(void)
>  		return -ENOMEM;
>  
>  	err = i915_subtests(tests, i915->engine[RCS]);
> -	drm_dev_unref(&i915->drm);
> +	drm_dev_put(&i915->drm);
>  
>  	return err;
>  }
> diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
> index 1d053bbefc02..27f54cbee7fb 100644
> --- a/drivers/gpu/drm/imx/imx-drm-core.c
> +++ b/drivers/gpu/drm/imx/imx-drm-core.c
> @@ -307,7 +307,7 @@ static int imx_drm_bind(struct device *dev)
>  err_kms:
>  	drm_mode_config_cleanup(drm);
>  err_unref:
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  
>  	return ret;
>  }
> @@ -327,7 +327,7 @@ static void imx_drm_unbind(struct device *dev)
>  	component_unbind_all(drm->dev, drm);
>  	dev_set_drvdata(dev, NULL);
>  
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  }
>  
>  static const struct component_master_ops imx_drm_ops = {
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index a2ca90fc403c..5d024a154e1a 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -341,7 +341,7 @@ static int mtk_drm_bind(struct device *dev)
>  err_deinit:
>  	mtk_drm_kms_deinit(drm);
>  err_free:
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  	return ret;
>  }
>  
> @@ -350,7 +350,7 @@ static void mtk_drm_unbind(struct device *dev)
>  	struct mtk_drm_private *private = dev_get_drvdata(dev);
>  
>  	drm_dev_unregister(private->drm);
> -	drm_dev_unref(private->drm);
> +	drm_dev_put(private->drm);
>  	private->drm = NULL;
>  }
>  
> @@ -504,7 +504,7 @@ static int mtk_drm_remove(struct platform_device *pdev)
>  
>  	drm_dev_unregister(drm);
>  	mtk_drm_kms_deinit(drm);
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  
>  	component_master_del(&pdev->dev, &mtk_drm_ops);
>  	pm_runtime_disable(&pdev->dev);
> diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> index 30cd514d8f7c..558a82f828b8 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -260,7 +260,7 @@ static int msm_drm_uninit(struct device *dev)
>  	msm_mdss_destroy(ddev);
>  
>  	ddev->dev_private = NULL;
> -	drm_dev_unref(ddev);
> +	drm_dev_put(ddev);
>  
>  	kfree(priv);
>  
> @@ -368,7 +368,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
>  
>  	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
>  	if (!priv) {
> -		drm_dev_unref(ddev);
> +		drm_dev_put(ddev);
>  		return -ENOMEM;
>  	}
>  
> @@ -378,7 +378,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
>  	ret = msm_mdss_init(ddev);
>  	if (ret) {
>  		kfree(priv);
> -		drm_dev_unref(ddev);
> +		drm_dev_put(ddev);
>  		return ret;
>  	}
>  
> @@ -398,7 +398,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
>  	if (ret) {
>  		msm_mdss_destroy(ddev);
>  		kfree(priv);
> -		drm_dev_unref(ddev);
> +		drm_dev_put(ddev);
>  		return ret;
>  	}
>  
> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> index 5cae8db9dcd4..1ca9bafcd4f2 100644
> --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> @@ -403,7 +403,7 @@ static int mxsfb_probe(struct platform_device *pdev)
>  err_unload:
>  	mxsfb_unload(drm);
>  err_free:
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  
>  	return ret;
>  }
> @@ -414,7 +414,7 @@ static int mxsfb_remove(struct platform_device *pdev)
>  
>  	drm_dev_unregister(drm);
>  	mxsfb_unload(drm);
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c
> index 1ada186fab77..039e23548e08 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_platform.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_platform.c
> @@ -36,7 +36,7 @@ static int nouveau_platform_probe(struct platform_device *pdev)
>  
>  	ret = drm_dev_register(drm, 0);
>  	if (ret < 0) {
> -		drm_dev_unref(drm);
> +		drm_dev_put(drm);
>  		return ret;
>  	}
>  
> diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
> index 3632854c2b91..e12cedc15e27 100644
> --- a/drivers/gpu/drm/omapdrm/omap_drv.c
> +++ b/drivers/gpu/drm/omapdrm/omap_drv.c
> @@ -598,7 +598,7 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev)
>  	omap_drm_irq_uninstall(ddev);
>  err_free_drm_dev:
>  	omap_gem_deinit(ddev);
> -	drm_dev_unref(ddev);
> +	drm_dev_put(ddev);
>  err_destroy_wq:
>  	destroy_workqueue(priv->wq);
>  	omap_disconnect_dssdevs();
> @@ -627,7 +627,7 @@ static void omapdrm_cleanup(struct omap_drm_private *priv)
>  	omap_drm_irq_uninstall(ddev);
>  	omap_gem_deinit(ddev);
>  
> -	drm_dev_unref(ddev);
> +	drm_dev_put(ddev);
>  
>  	destroy_workqueue(priv->wq);
>  
> diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c
> index 4621259d5387..6e21308dd6c6 100644
> --- a/drivers/gpu/drm/pl111/pl111_drv.c
> +++ b/drivers/gpu/drm/pl111/pl111_drv.c
> @@ -304,7 +304,7 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
>  	return 0;
>  
>  dev_unref:
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  	return ret;
>  }
>  
> @@ -318,7 +318,7 @@ static int pl111_amba_remove(struct amba_device *amba_dev)
>  	if (priv->panel)
>  		drm_panel_bridge_remove(priv->bridge);
>  	drm_mode_config_cleanup(drm);
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
> index 2445e75cf7ea..86bd42dca09c 100644
> --- a/drivers/gpu/drm/qxl/qxl_drv.c
> +++ b/drivers/gpu/drm/qxl/qxl_drv.c
> @@ -119,7 +119,7 @@ qxl_pci_remove(struct pci_dev *pdev)
>  
>  	dev->dev_private = NULL;
>  	kfree(qdev);
> -	drm_dev_unref(dev);
> +	drm_dev_put(dev);
>  }
>  
>  static const struct file_operations qxl_fops = {
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> index 3917d839c04c..1adcf80912e1 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> @@ -378,7 +378,7 @@ static int rcar_du_remove(struct platform_device *pdev)
>  	drm_kms_helper_poll_fini(ddev);
>  	drm_mode_config_cleanup(ddev);
>  
> -	drm_dev_unref(ddev);
> +	drm_dev_put(ddev);
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> index f814d37b1db2..9c846be8fc64 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> @@ -184,7 +184,7 @@ static int rockchip_drm_bind(struct device *dev)
>  err_free:
>  	drm_dev->dev_private = NULL;
>  	dev_set_drvdata(dev, NULL);
> -	drm_dev_unref(drm_dev);
> +	drm_dev_put(drm_dev);
>  	return ret;
>  }
>  
> @@ -204,7 +204,7 @@ static void rockchip_drm_unbind(struct device *dev)
>  
>  	drm_dev->dev_private = NULL;
>  	dev_set_drvdata(dev, NULL);
> -	drm_dev_unref(drm_dev);
> +	drm_dev_put(drm_dev);
>  }
>  
>  static const struct file_operations rockchip_drm_driver_fops = {
> diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c
> index 592572554eb0..8d1ff596c774 100644
> --- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c
> +++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c
> @@ -198,7 +198,7 @@ static int shmob_drm_remove(struct platform_device *pdev)
>  	drm_kms_helper_poll_fini(ddev);
>  	drm_mode_config_cleanup(ddev);
>  	drm_irq_uninstall(ddev);
> -	drm_dev_unref(ddev);
> +	drm_dev_put(ddev);
>  
>  	return 0;
>  }
> @@ -294,7 +294,7 @@ static int shmob_drm_probe(struct platform_device *pdev)
>  	drm_kms_helper_poll_fini(ddev);
>  	drm_mode_config_cleanup(ddev);
>  err_free_drm_dev:
> -	drm_dev_unref(ddev);
> +	drm_dev_put(ddev);
>  
>  	return ret;
>  }
> diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c
> index 55b6967d27e1..e8d6199878ce 100644
> --- a/drivers/gpu/drm/sti/sti_drv.c
> +++ b/drivers/gpu/drm/sti/sti_drv.c
> @@ -242,7 +242,7 @@ static int sti_bind(struct device *dev)
>  
>  	ret = sti_init(ddev);
>  	if (ret)
> -		goto err_drm_dev_unref;
> +		goto err_drm_dev_put;
>  
>  	ret = component_bind_all(ddev->dev, ddev);
>  	if (ret)
> @@ -266,8 +266,8 @@ static int sti_bind(struct device *dev)
>  	drm_mode_config_cleanup(ddev);
>  err_cleanup:
>  	sti_cleanup(ddev);
> -err_drm_dev_unref:
> -	drm_dev_unref(ddev);
> +err_drm_dev_put:
> +	drm_dev_put(ddev);
>  	return ret;
>  }
>  
> @@ -277,7 +277,7 @@ static void sti_unbind(struct device *dev)
>  
>  	drm_dev_unregister(ddev);
>  	sti_cleanup(ddev);
> -	drm_dev_unref(ddev);
> +	drm_dev_put(ddev);
>  }
>  
>  static const struct component_master_ops sti_ops = {
> diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c
> index 9ab00a87f7cc..6ece3acabd56 100644
> --- a/drivers/gpu/drm/stm/drv.c
> +++ b/drivers/gpu/drm/stm/drv.c
> @@ -159,7 +159,7 @@ static int stm_drm_platform_probe(struct platform_device *pdev)
>  	return 0;
>  
>  err_unref:
> -	drm_dev_unref(ddev);
> +	drm_dev_put(ddev);
>  
>  	return ret;
>  }
> @@ -172,7 +172,7 @@ static int stm_drm_platform_remove(struct platform_device *pdev)
>  
>  	drm_dev_unregister(ddev);
>  	drv_unload(ddev);
> -	drm_dev_unref(ddev);
> +	drm_dev_put(ddev);
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
> index 50d19605c38f..42c881d5275d 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_drv.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
> @@ -143,7 +143,7 @@ static int sun4i_drv_bind(struct device *dev)
>  	drm_mode_config_cleanup(drm);
>  	of_reserved_mem_device_release(dev);
>  free_drm:
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  	return ret;
>  }
>  
> @@ -156,7 +156,7 @@ static void sun4i_drv_unbind(struct device *dev)
>  	sun4i_framebuffer_free(drm);
>  	drm_mode_config_cleanup(drm);
>  	of_reserved_mem_device_release(dev);
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  }
>  
>  static const struct component_master_ops sun4i_drv_master_ops = {
> diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
> index 7afe2f635f74..f5119f2bbf5f 100644
> --- a/drivers/gpu/drm/tegra/drm.c
> +++ b/drivers/gpu/drm/tegra/drm.c
> @@ -1210,7 +1210,7 @@ static int host1x_drm_probe(struct host1x_device *dev)
>  	return 0;
>  
>  unref:
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  	return err;
>  }
>  
> @@ -1219,7 +1219,7 @@ static int host1x_drm_remove(struct host1x_device *dev)
>  	struct drm_device *drm = dev_get_drvdata(&dev->dev);
>  
>  	drm_dev_unregister(drm);
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c
> index 4c6616278c48..ca2b6a8b74c2 100644
> --- a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c
> +++ b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c
> @@ -135,7 +135,7 @@ static int tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
>  	/*
>  	 * We don't embed drm_device, because that prevent us from using
>  	 * devm_kzalloc() to allocate tinydrm_device in the driver since
> -	 * drm_dev_unref() frees the structure. The devm_ functions provide
> +	 * drm_dev_put() frees the structure. The devm_ functions provide
>  	 * for easy error handling.
>  	 */
>  	drm = drm_dev_alloc(driver, parent);
> @@ -155,7 +155,7 @@ static void tinydrm_fini(struct tinydrm_device *tdev)
>  	drm_mode_config_cleanup(tdev->drm);
>  	mutex_destroy(&tdev->dirty_lock);
>  	tdev->drm->dev_private = NULL;
> -	drm_dev_unref(tdev->drm);
> +	drm_dev_put(tdev->drm);
>  }
>  
>  static void devm_tinydrm_release(void *data)
> @@ -172,7 +172,7 @@ static void devm_tinydrm_release(void *data)
>   *
>   * This function initializes @tdev, the underlying DRM device and it's
>   * mode_config. Resources will be automatically freed on driver detach (devres)
> - * using drm_mode_config_cleanup() and drm_dev_unref().
> + * using drm_mode_config_cleanup() and drm_dev_put().
>   *
>   * Returns:
>   * Zero on success, negative error code on failure.
> diff --git a/drivers/gpu/drm/tve200/tve200_drv.c b/drivers/gpu/drm/tve200/tve200_drv.c
> index ac344ddb23bc..e36a78ef68b7 100644
> --- a/drivers/gpu/drm/tve200/tve200_drv.c
> +++ b/drivers/gpu/drm/tve200/tve200_drv.c
> @@ -250,7 +250,7 @@ static int tve200_probe(struct platform_device *pdev)
>  clk_disable:
>  	clk_disable_unprepare(priv->pclk);
>  dev_unref:
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  	return ret;
>  }
>  
> @@ -265,7 +265,7 @@ static int tve200_remove(struct platform_device *pdev)
>  		drm_panel_bridge_remove(priv->bridge);
>  	drm_mode_config_cleanup(drm);
>  	clk_disable_unprepare(priv->pclk);
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
> index 3c45a3064726..d5e94eb7a4ca 100644
> --- a/drivers/gpu/drm/udl/udl_drv.c
> +++ b/drivers/gpu/drm/udl/udl_drv.c
> @@ -94,7 +94,7 @@ static int udl_usb_probe(struct usb_interface *interface,
>  	return 0;
>  
>  err_free:
> -	drm_dev_unref(dev);
> +	drm_dev_put(dev);
>  	return r;
>  }
>  
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
> index 94b99c90425a..259c85fcd32c 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.c
> +++ b/drivers/gpu/drm/vc4/vc4_drv.c
> @@ -312,7 +312,7 @@ static int vc4_drm_bind(struct device *dev)
>  	vc4_gem_destroy(drm);
>  	vc4_bo_cache_destroy(drm);
>  dev_unref:
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  	return ret;
>  }
>  
> @@ -327,7 +327,7 @@ static void vc4_drm_unbind(struct device *dev)
>  
>  	drm_mode_config_cleanup(drm);
>  
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  }
>  
>  static const struct component_master_ops vc4_drm_ops = {
> diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c
> index 2524ff116f00..305f87665499 100644
> --- a/drivers/gpu/drm/vgem/vgem_drv.c
> +++ b/drivers/gpu/drm/vgem/vgem_drv.c
> @@ -505,7 +505,7 @@ static int __init vgem_init(void)
>  static void __exit vgem_exit(void)
>  {
>  	drm_dev_unregister(&vgem_device->drm);
> -	drm_dev_unref(&vgem_device->drm);
> +	drm_dev_put(&vgem_device->drm);
>  }
>  
>  module_init(vgem_init);
> diff --git a/drivers/gpu/drm/virtio/virtgpu_drm_bus.c b/drivers/gpu/drm/virtio/virtgpu_drm_bus.c
> index 7df8d0c9026a..094b876f6da6 100644
> --- a/drivers/gpu/drm/virtio/virtgpu_drm_bus.c
> +++ b/drivers/gpu/drm/virtio/virtgpu_drm_bus.c
> @@ -85,6 +85,6 @@ int drm_virtio_init(struct drm_driver *driver, struct virtio_device *vdev)
>  	return 0;
>  
>  err_free:
> -	drm_dev_unref(dev);
> +	drm_dev_put(dev);
>  	return ret;
>  }
> diff --git a/drivers/gpu/drm/zte/zx_drm_drv.c b/drivers/gpu/drm/zte/zx_drm_drv.c
> index 6f4205e80378..02ae1caf6e8a 100644
> --- a/drivers/gpu/drm/zte/zx_drm_drv.c
> +++ b/drivers/gpu/drm/zte/zx_drm_drv.c
> @@ -122,7 +122,7 @@ static int zx_drm_bind(struct device *dev)
>  	component_unbind_all(dev, drm);
>  out_unregister:
>  	dev_set_drvdata(dev, NULL);
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  	return ret;
>  }
>  
> @@ -136,7 +136,7 @@ static void zx_drm_unbind(struct device *dev)
>  	drm_mode_config_cleanup(drm);
>  	component_unbind_all(dev, drm);
>  	dev_set_drvdata(dev, NULL);
> -	drm_dev_unref(drm);
> +	drm_dev_put(drm);
>  }
>  
>  static const struct component_master_ops zx_drm_master_ops = {
> diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
> index d23dcdd1bd95..c16dd4424b8a 100644
> --- a/include/drm/drm_drv.h
> +++ b/include/drm/drm_drv.h
> @@ -622,7 +622,6 @@ void drm_dev_unregister(struct drm_device *dev);
>  
>  void drm_dev_get(struct drm_device *dev);
>  void drm_dev_put(struct drm_device *dev);
> -void drm_dev_unref(struct drm_device *dev);
>  void drm_put_dev(struct drm_device *dev);
>  void drm_dev_unplug(struct drm_device *dev);
>  
> -- 
> 2.14.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply

* Re: [PATCH] drm/core: Remove drm_dev_unref() and it's uses
From: Thierry Reding @ 2018-04-26 12:06 UTC (permalink / raw)
  To: Vaishali Thakkar
  Cc: linux-renesas-soc, alexandre.belloni, heiko, airlied, gustavo,
	linus.walleij, joonas.lahtinen, stefan, hjc, eric,
	benjamin.gaignard, nouveau, marex, David1.Zhou, linux-samsung-soc,
	jy0922.shim, linux-rockchip, tomi.valkeinen, linux, krzk,
	jonathanh, z.liuxinliang, maxime.ripard, kong.kongxinwei, kgene,
	bskeggs, linux-arm-msm, ck.hu, airlied, virtualization, robdclark,
	linux-tegra, puck.chen, intel-gfx, maarten.lankhorst
In-Reply-To: <20180426102819.6985-1-vthakkar1994@gmail.com>


[-- Attachment #1.1: Type: text/plain, Size: 531 bytes --]

On Thu, Apr 26, 2018 at 03:58:19PM +0530, Vaishali Thakkar wrote:
> It's been a while since we introduced drm_dev{get/put} functions
> to replace reference/unreference in drm subsystem for the
> consistency purpose. So, with this patch, let's just replace
> all current use cases of drm_dev_unref() with drm_dev_put and remove
> the function itself.
> 
> Coccinelle was used for mass-patching.
> 
> Signed-off-by: Vaishali Thakkar <vthakkar1994@gmail.com>

Yes, please.

Acked-by: Thierry Reding <treding@nvidia.com>

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 183 bytes --]

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply

* Re: [PATCH] drm/core: Remove drm_dev_unref() and it's uses
From: Laurent Pinchart @ 2018-04-26 10:43 UTC (permalink / raw)
  To: Vaishali Thakkar
  Cc: linux-renesas-soc, alexandre.belloni, heiko, airlied, gustavo,
	linus.walleij, joonas.lahtinen, stefan, hjc, eric, thierry.reding,
	nouveau, freedreno, marex, David1.Zhou, linux-samsung-soc,
	jy0922.shim, linux-rockchip, tomi.valkeinen, linux, krzk,
	jonathanh, z.liuxinliang, maxime.ripard, kong.kongxinwei, kgene,
	bskeggs, linux-arm-msm, ck.hu, airlied, virtualization, robdclark,
	linux-tegra, puck.chen, intel-gfx
In-Reply-To: <20180426102819.6985-1-vthakkar1994@gmail.com>

Hi Vaishali,

Thank you for the patch.

On Thursday, 26 April 2018 13:28:19 EEST Vaishali Thakkar wrote:
> It's been a while since we introduced drm_dev{get/put} functions
> to replace reference/unreference in drm subsystem for the
> consistency purpose. So, with this patch, let's just replace
> all current use cases of drm_dev_unref() with drm_dev_put and remove
> the function itself.
> 
> Coccinelle was used for mass-patching.
> 
> Signed-off-by: Vaishali Thakkar <vthakkar1994@gmail.com>

I love seeing deprecated functions go.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c            |  4 ++--
>  drivers/gpu/drm/arc/arcpgu_drv.c                   |  4 ++--
>  drivers/gpu/drm/armada/armada_drv.c                |  6 +++---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c       |  4 ++--
>  drivers/gpu/drm/drm_drv.c                          | 13 -------------
>  drivers/gpu/drm/etnaviv/etnaviv_drv.c              |  4 ++--
>  drivers/gpu/drm/exynos/exynos_drm_drv.c            |  4 ++--
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c          |  4 ++--
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c    |  4 ++--
>  drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c    |  8 ++++----
>  drivers/gpu/drm/i915/selftests/huge_pages.c        |  2 +-
>  drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c   |  2 +-
>  drivers/gpu/drm/i915/selftests/i915_gem_evict.c    |  2 +-
>  drivers/gpu/drm/i915/selftests/i915_gem_gtt.c      |  2 +-
>  drivers/gpu/drm/i915/selftests/i915_gem_object.c   |  2 +-
>  drivers/gpu/drm/i915/selftests/i915_request.c      |  2 +-
>  drivers/gpu/drm/i915/selftests/i915_vma.c          |  2 +-
>  drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c |  2 +-
>  drivers/gpu/drm/imx/imx-drm-core.c                 |  4 ++--
>  drivers/gpu/drm/mediatek/mtk_drm_drv.c             |  6 +++---
>  drivers/gpu/drm/msm/msm_drv.c                      |  8 ++++----
>  drivers/gpu/drm/mxsfb/mxsfb_drv.c                  |  4 ++--
>  drivers/gpu/drm/nouveau/nouveau_platform.c         |  2 +-
>  drivers/gpu/drm/omapdrm/omap_drv.c                 |  4 ++--
>  drivers/gpu/drm/pl111/pl111_drv.c                  |  4 ++--
>  drivers/gpu/drm/qxl/qxl_drv.c                      |  2 +-
>  drivers/gpu/drm/rcar-du/rcar_du_drv.c              |  2 +-
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.c        |  4 ++--
>  drivers/gpu/drm/shmobile/shmob_drm_drv.c           |  4 ++--
>  drivers/gpu/drm/sti/sti_drv.c                      |  8 ++++----
>  drivers/gpu/drm/stm/drv.c                          |  4 ++--
>  drivers/gpu/drm/sun4i/sun4i_drv.c                  |  4 ++--
>  drivers/gpu/drm/tegra/drm.c                        |  4 ++--
>  drivers/gpu/drm/tinydrm/core/tinydrm-core.c        |  6 +++---
>  drivers/gpu/drm/tve200/tve200_drv.c                |  4 ++--
>  drivers/gpu/drm/udl/udl_drv.c                      |  2 +-
>  drivers/gpu/drm/vc4/vc4_drv.c                      |  4 ++--
>  drivers/gpu/drm/vgem/vgem_drv.c                    |  2 +-
>  drivers/gpu/drm/virtio/virtgpu_drm_bus.c           |  2 +-
>  drivers/gpu/drm/zte/zx_drm_drv.c                   |  4 ++--
>  include/drm/drm_drv.h                              |  1 -
>  41 files changed, 73 insertions(+), 87 deletions(-)

-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* Re: [PATCH] fault-injection: reorder config entries
From: Randy Dunlap @ 2018-04-26  3:21 UTC (permalink / raw)
  To: Mikulas Patocka, Michal Hocko
  Cc: dm-devel, eric.dumazet, mst, netdev, linux-kernel, Matthew Wilcox,
	virtualization, linux-mm, edumazet, Andrew Morton, David Miller,
	Vlastimil Babka
In-Reply-To: <alpine.LRH.2.02.1804251601160.30569@file01.intranet.prod.int.rdu2.redhat.com>

On 04/25/2018 01:02 PM, Mikulas Patocka wrote:
> This patch reorders Kconfig entries, so that menuconfig displays proper 
> indentation.
> 
> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

Acked-by: Randy Dunlap <rdunlap@infradead.org>
Tested-by: Randy Dunlap <rdunlap@infradead.org>

Thanks.

> ---
>  lib/Kconfig.debug |   36 ++++++++++++++++++------------------
>  1 file changed, 18 insertions(+), 18 deletions(-)
> 
> Index: linux-2.6/lib/Kconfig.debug
> ===================================================================
> --- linux-2.6.orig/lib/Kconfig.debug	2018-04-16 21:08:36.000000000 +0200
> +++ linux-2.6/lib/Kconfig.debug	2018-04-25 15:56:16.000000000 +0200
> @@ -1503,6 +1503,10 @@ config NETDEV_NOTIFIER_ERROR_INJECT
>  
>  	  If unsure, say N.
>  
> +config FUNCTION_ERROR_INJECTION
> +	def_bool y
> +	depends on HAVE_FUNCTION_ERROR_INJECTION && KPROBES
> +
>  config FAULT_INJECTION
>  	bool "Fault-injection framework"
>  	depends on DEBUG_KERNEL
> @@ -1510,10 +1514,6 @@ config FAULT_INJECTION
>  	  Provide fault-injection framework.
>  	  For more details, see Documentation/fault-injection/.
>  
> -config FUNCTION_ERROR_INJECTION
> -	def_bool y
> -	depends on HAVE_FUNCTION_ERROR_INJECTION && KPROBES
> -
>  config FAILSLAB
>  	bool "Fault-injection capability for kmalloc"
>  	depends on FAULT_INJECTION
> @@ -1544,16 +1544,6 @@ config FAIL_IO_TIMEOUT
>  	  Only works with drivers that use the generic timeout handling,
>  	  for others it wont do anything.
>  
> -config FAIL_MMC_REQUEST
> -	bool "Fault-injection capability for MMC IO"
> -	depends on FAULT_INJECTION_DEBUG_FS && MMC
> -	help
> -	  Provide fault-injection capability for MMC IO.
> -	  This will make the mmc core return data errors. This is
> -	  useful to test the error handling in the mmc block device
> -	  and to test how the mmc host driver handles retries from
> -	  the block device.
> -
>  config FAIL_FUTEX
>  	bool "Fault-injection capability for futexes"
>  	select DEBUG_FS
> @@ -1561,6 +1551,12 @@ config FAIL_FUTEX
>  	help
>  	  Provide fault-injection capability for futexes.
>  
> +config FAULT_INJECTION_DEBUG_FS
> +	bool "Debugfs entries for fault-injection capabilities"
> +	depends on FAULT_INJECTION && SYSFS && DEBUG_FS
> +	help
> +	  Enable configuration of fault-injection capabilities via debugfs.
> +
>  config FAIL_FUNCTION
>  	bool "Fault-injection capability for functions"
>  	depends on FAULT_INJECTION_DEBUG_FS && FUNCTION_ERROR_INJECTION
> @@ -1571,11 +1567,15 @@ config FAIL_FUNCTION
>  	  an error value and have to handle it. This is useful to test the
>  	  error handling in various subsystems.
>  
> -config FAULT_INJECTION_DEBUG_FS
> -	bool "Debugfs entries for fault-injection capabilities"
> -	depends on FAULT_INJECTION && SYSFS && DEBUG_FS
> +config FAIL_MMC_REQUEST
> +	bool "Fault-injection capability for MMC IO"
> +	depends on FAULT_INJECTION_DEBUG_FS && MMC
>  	help
> -	  Enable configuration of fault-injection capabilities via debugfs.
> +	  Provide fault-injection capability for MMC IO.
> +	  This will make the mmc core return data errors. This is
> +	  useful to test the error handling in the mmc block device
> +	  and to test how the mmc host driver handles retries from
> +	  the block device.
>  
>  config FAULT_INJECTION_STACKTRACE_FILTER
>  	bool "stacktrace filter for fault-injection capabilities"
> 


-- 
~Randy

^ permalink raw reply

* Re: [PATCH v7 net-next 4/4] netvsc: refactor notifier/event handling code to use the failover framework
From: Michael S. Tsirkin @ 2018-04-26  2:43 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Alexander Duyck, virtio-dev, Jiri Pirko, Jakub Kicinski, Netdev,
	virtualization, Siwei Liu, Sridhar Samudrala, David Miller
In-Reply-To: <20180425171831.785f412b@xeon-e3>

On Wed, Apr 25, 2018 at 05:18:31PM -0700, Stephen Hemminger wrote:
> On Wed, 25 Apr 2018 15:57:57 -0700
> Siwei Liu <loseweigh@gmail.com> wrote:
> 
> > >
> > > I think ideally the infrastructure should suppport flexible matching of
> > > NICs - netvsc is already reported to be moving to some kind of serial
> > > address.
> > >  
> > As Stephen said, Hyper-V supports the serial UUID thing from day-one.
> > It's just the Linux netvsc guest driver itself does not leverage that
> > ID from the very beginging.
> > 
> > Regards,
> > -Siwei
> 
> I am working on that.  The problem is that it requires some messy work
> to go from VF netdevice back to PCI device and from there to the PCI hyperv
> host infrastructure to find the serial number.
> 
> I was hoping that the serial number would also match the concept of PCI Express
> device serial number. But that is a completely different ID :-( 
> The PCI-E serial number is a hardware serial number more like MAC address.
> The Hyper-V serial number is more like PCI slot value.

Asuming you mean the Device Serial Number Capability,
I did consider this, and
we could use that, changing the UUID to one matching the
PV device, but I'm not sure no drivers will get confused
suddenly seeing the UUID of another company there.

If we are going the UUID route, a better idea might be to
specify the UUID of the PCI port into which the PT device is
being hotplugged.  This is PCI-Express specific, but presumably
legacy PCI/PCI-X devices aren't common enough to bother about
this for now.


-- 
MST

^ permalink raw reply

* Re: [PATCH net-next v8 4/4] netvsc: refactor notifier/event handling code to use the failover framework
From: Michael S. Tsirkin @ 2018-04-26  2:30 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: alexander.h.duyck, virtio-dev, jiri, kubakici, Sridhar Samudrala,
	virtualization, loseweigh, netdev, aaron.f.brown, davem
In-Reply-To: <20180425170837.6520a577@xeon-e3>

On Wed, Apr 25, 2018 at 05:08:37PM -0700, Stephen Hemminger wrote:
> On Wed, 25 Apr 2018 16:59:28 -0700
> Sridhar Samudrala <sridhar.samudrala@intel.com> wrote:
> 
> > Use the registration/notification framework supported by the generic
> > failover infrastructure.
> > 
> > Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
> 
> NAK unless you prove this works on legacy distributions and with DPDK 18.05
> without modification.

It looks like it should work. What kind of proof are you looking for?

-- 
MST

^ permalink raw reply

* Re: [PATCH v7 net-next 4/4] netvsc: refactor notifier/event handling code to use the failover framework
From: Michael S. Tsirkin @ 2018-04-26  2:28 UTC (permalink / raw)
  To: Siwei Liu
  Cc: Alexander Duyck, virtio-dev, Jiri Pirko, Jakub Kicinski,
	Sridhar Samudrala, virtualization, Netdev, David Miller
In-Reply-To: <CADGSJ20vck5V8JCoF0Tq9PWfBu7QYPDvg0yAZ_8Xkig7TKU7Lw@mail.gmail.com>

On Wed, Apr 25, 2018 at 03:57:57PM -0700, Siwei Liu wrote:
> On Wed, Apr 25, 2018 at 3:22 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> > On Wed, Apr 25, 2018 at 02:38:57PM -0700, Siwei Liu wrote:
> >> On Mon, Apr 23, 2018 at 1:06 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> >> > On Mon, Apr 23, 2018 at 12:44:39PM -0700, Siwei Liu wrote:
> >> >> On Mon, Apr 23, 2018 at 10:56 AM, Michael S. Tsirkin <mst@redhat.com> wrote:
> >> >> > On Mon, Apr 23, 2018 at 10:44:40AM -0700, Stephen Hemminger wrote:
> >> >> >> On Mon, 23 Apr 2018 20:24:56 +0300
> >> >> >> "Michael S. Tsirkin" <mst@redhat.com> wrote:
> >> >> >>
> >> >> >> > On Mon, Apr 23, 2018 at 10:04:06AM -0700, Stephen Hemminger wrote:
> >> >> >> > > > >
> >> >> >> > > > >I will NAK patches to change to common code for netvsc especially the
> >> >> >> > > > >three device model.  MS worked hard with distro vendors to support transparent
> >> >> >> > > > >mode, ans we really can't have a new model; or do backport.
> >> >> >> > > > >
> >> >> >> > > > >Plus, DPDK is now dependent on existing model.
> >> >> >> > > >
> >> >> >> > > > Sorry, but nobody here cares about dpdk or other similar oddities.
> >> >> >> > >
> >> >> >> > > The network device model is a userspace API, and DPDK is a userspace application.
> >> >> >> >
> >> >> >> > It is userspace but are you sure dpdk is actually poking at netdevs?
> >> >> >> > AFAIK it's normally banging device registers directly.
> >> >> >> >
> >> >> >> > > You can't go breaking userspace even if you don't like the application.
> >> >> >> >
> >> >> >> > Could you please explain how is the proposed patchset breaking
> >> >> >> > userspace? Ignoring DPDK for now, I don't think it changes the userspace
> >> >> >> > API at all.
> >> >> >> >
> >> >> >>
> >> >> >> The DPDK has a device driver vdev_netvsc which scans the Linux network devices
> >> >> >> to look for Linux netvsc device and the paired VF device and setup the
> >> >> >> DPDK environment.  This setup creates a DPDK failsafe (bondingish) instance
> >> >> >> and sets up TAP support over the Linux netvsc device as well as the Mellanox
> >> >> >> VF device.
> >> >> >>
> >> >> >> So it depends on existing 2 device model. You can't go to a 3 device model
> >> >> >> or start hiding devices from userspace.
> >> >> >
> >> >> > Okay so how does the existing patch break that? IIUC does not go to
> >> >> > a 3 device model since netvsc calls failover_register directly.
> >> >> >
> >> >> >> Also, I am working on associating netvsc and VF device based on serial number
> >> >> >> rather than MAC address. The serial number is how Windows works now, and it makes
> >> >> >> sense for Linux and Windows to use the same mechanism if possible.
> >> >> >
> >> >> > Maybe we should support same for virtio ...
> >> >> > Which serial do you mean? From vpd?
> >> >> >
> >> >> > I guess you will want to keep supporting MAC for old hypervisors?
> >> >> >
> >> >> > It all seems like a reasonable thing to support in the generic core.
> >> >>
> >> >> That's the reason why I chose explicit identifier rather than rely on
> >> >> MAC address to bind/pair a device. MAC address can change. Even if it
> >> >> can't, malicious guest user can fake MAC address to skip binding.
> >> >>
> >> >> -Siwei
> >> >
> >> > Address should be sampled at device creation to prevent this
> >> > kind of hack. Not that it buys the malicious user much:
> >> > if you can poke at MAC addresses you probably already can
> >> > break networking.
> >>
> >> I don't understand why poking at MAC address may potentially break
> >> networking.
> >
> > Set a MAC address to match another device on the same LAN,
> > packets will stop reaching that MAC.
> 
> What I meant was guest users may create a virtual link, say veth that
> has exactly the same MAC address as that for the VF, which can easily
> get around of the binding procedure.

This patchset limits binding to PCI devices so it won't be affected
by any hacks around virtual devices.

> There's no explicit flag to
> identify a VF or pass-through device AFAIK. And sometimes this happens
> maybe due to user misconfiguring the link. This process should be
> hardened to avoid from any potential configuration errors.

They are still PCI devices though.

> >
> >> Unlike VF, passthrough PCI endpoint device has its freedom
> >> to change the MAC address. Even on a VF setup it's not neccessarily
> >> always safe to assume the VF's MAC address cannot or shouldn't be
> >> changed. That depends on the specific need whether the host admin
> >> wants to restrict guest from changing the MAC address, although in
> >> most cases it's true.
> >>
> >> I understand we can use the perm_addr to distinguish. But as said,
> >> this will pose limitation of flexible configuration where one can
> >> assign VFs with identical MAC address at all while each VF belongs to
> >> different PF and/or different subnet for e.g. load balancing.
> >> And
> >> furthermore, the QEMU device model never uses MAC address to be
> >> interpreted as an identifier, which requires to be unique per VM
> >> instance. Why we're introducing this inconsistency?
> >>
> >> -Siwei
> >
> > Because it addresses most of the issues and is simple.  That's already
> > much better than what we have now which is nothing unless guest
> > configures things manually.
> 
> Did you see my QEMU patch for using BDF as the grouping identifier?

Yes. And I don't think it can work because bus numbers are
guest specified.

> And there can be others like what you suggested, but the point is that
> it's requried to support explicit grouping mechanism from day one,
> before the backup property cast into stones.

Let's start with addressing simple configs with just two NICs.

Down the road I can see possible extensions that can work: for example,
require that devices are on the same pci bridge. Or we could even make
the virtio device actually include a pci bridge (as part of same
or a child function), the PT would have to be
behind it.

As long as we are not breaking anything, adding more flags to fix
non-working configurations is always fair game.

> This is orthogonal to
> device model being proposed, be it 1-netdev or not. Delaying it would
> just mean support and compatibility burden, appearing more like a
> design flaw rather than a feature to add later on.

Well it's mostly myself who gets to support it, and I see the device
model as much more fundamental as userspace will come to depend
on it. So I'm not too worried, let's take this one step at a time.

> >
> > I think ideally the infrastructure should suppport flexible matching of
> > NICs - netvsc is already reported to be moving to some kind of serial
> > address.
> >
> As Stephen said, Hyper-V supports the serial UUID thing from day-one.
> It's just the Linux netvsc guest driver itself does not leverage that
> ID from the very beginging.
> 
> Regards,
> -Siwei

We could add something like this, too. For example,
we could add a virtual VPD capability with a UUID.

Do you know how exactly does hyperv pass the UUID for NICs?

> >
> >> >
> >> >
> >> >
> >> >
> >> >>
> >> >> >
> >> >> > --
> >> >> > MST

^ permalink raw reply

* Re: [PATCH v7 net-next 4/4] netvsc: refactor notifier/event handling code to use the failover framework
From: Stephen Hemminger @ 2018-04-26  0:18 UTC (permalink / raw)
  To: Siwei Liu
  Cc: Alexander Duyck, virtio-dev, Jiri Pirko, Michael S. Tsirkin,
	Jakub Kicinski, Sridhar Samudrala, virtualization, Netdev,
	David Miller
In-Reply-To: <CADGSJ20vck5V8JCoF0Tq9PWfBu7QYPDvg0yAZ_8Xkig7TKU7Lw@mail.gmail.com>

On Wed, 25 Apr 2018 15:57:57 -0700
Siwei Liu <loseweigh@gmail.com> wrote:

> >
> > I think ideally the infrastructure should suppport flexible matching of
> > NICs - netvsc is already reported to be moving to some kind of serial
> > address.
> >  
> As Stephen said, Hyper-V supports the serial UUID thing from day-one.
> It's just the Linux netvsc guest driver itself does not leverage that
> ID from the very beginging.
> 
> Regards,
> -Siwei

I am working on that.  The problem is that it requires some messy work
to go from VF netdevice back to PCI device and from there to the PCI hyperv
host infrastructure to find the serial number.

I was hoping that the serial number would also match the concept of PCI Express
device serial number. But that is a completely different ID :-( 
The PCI-E serial number is a hardware serial number more like MAC address.
The Hyper-V serial number is more like PCI slot value.

^ permalink raw reply

* Re: [PATCH net-next v8 4/4] netvsc: refactor notifier/event handling code to use the failover framework
From: Stephen Hemminger @ 2018-04-26  0:08 UTC (permalink / raw)
  To: Sridhar Samudrala
  Cc: alexander.h.duyck, virtio-dev, jiri, mst, kubakici, netdev,
	virtualization, loseweigh, aaron.f.brown, davem
In-Reply-To: <1524700768-38627-5-git-send-email-sridhar.samudrala@intel.com>

On Wed, 25 Apr 2018 16:59:28 -0700
Sridhar Samudrala <sridhar.samudrala@intel.com> wrote:

> Use the registration/notification framework supported by the generic
> failover infrastructure.
> 
> Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>

NAK unless you prove this works on legacy distributions and with DPDK 18.05
without modification.

^ permalink raw reply

* [PATCH net-next v8 4/4] netvsc: refactor notifier/event handling code to use the failover framework
From: Sridhar Samudrala @ 2018-04-25 23:59 UTC (permalink / raw)
  To: mst, stephen, davem, netdev, virtualization, virtio-dev,
	jesse.brandeburg, alexander.h.duyck, kubakici, sridhar.samudrala,
	jasowang, loseweigh, jiri, aaron.f.brown
In-Reply-To: <1524700768-38627-1-git-send-email-sridhar.samudrala@intel.com>

Use the registration/notification framework supported by the generic
failover infrastructure.

Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
 drivers/net/hyperv/Kconfig      |   1 +
 drivers/net/hyperv/hyperv_net.h |   2 +
 drivers/net/hyperv/netvsc_drv.c | 134 +++++++---------------------------------
 3 files changed, 26 insertions(+), 111 deletions(-)

diff --git a/drivers/net/hyperv/Kconfig b/drivers/net/hyperv/Kconfig
index 0765d5f61714..20e70d4855a9 100644
--- a/drivers/net/hyperv/Kconfig
+++ b/drivers/net/hyperv/Kconfig
@@ -1,6 +1,7 @@
 config HYPERV_NET
 	tristate "Microsoft Hyper-V virtual network driver"
 	depends on HYPERV
+	depends on MAY_USE_NET_FAILOVER
 	select UCS2_STRING
 	help
 	  Select this option to enable the Hyper-V virtual network driver.
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 6ebe39a3dde6..2ec18344c0e8 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -932,6 +932,8 @@ struct net_device_context {
 	u32 vf_alloc;
 	/* Serial number of the VF to team with */
 	u32 vf_serial;
+
+	struct net_failover *failover;
 };
 
 /* Per channel data */
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index ecc84954c511..fa446234bc11 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -43,6 +43,7 @@
 #include <net/pkt_sched.h>
 #include <net/checksum.h>
 #include <net/ip6_checksum.h>
+#include <net/net_failover.h>
 
 #include "hyperv_net.h"
 
@@ -1763,46 +1764,6 @@ static void netvsc_link_change(struct work_struct *w)
 	rtnl_unlock();
 }
 
-static struct net_device *get_netvsc_bymac(const u8 *mac)
-{
-	struct net_device *dev;
-
-	ASSERT_RTNL();
-
-	for_each_netdev(&init_net, dev) {
-		if (dev->netdev_ops != &device_ops)
-			continue;	/* not a netvsc device */
-
-		if (ether_addr_equal(mac, dev->perm_addr))
-			return dev;
-	}
-
-	return NULL;
-}
-
-static struct net_device *get_netvsc_byref(struct net_device *vf_netdev)
-{
-	struct net_device *dev;
-
-	ASSERT_RTNL();
-
-	for_each_netdev(&init_net, dev) {
-		struct net_device_context *net_device_ctx;
-
-		if (dev->netdev_ops != &device_ops)
-			continue;	/* not a netvsc device */
-
-		net_device_ctx = netdev_priv(dev);
-		if (!rtnl_dereference(net_device_ctx->nvdev))
-			continue;	/* device is removed */
-
-		if (rtnl_dereference(net_device_ctx->vf_netdev) == vf_netdev)
-			return dev;	/* a match */
-	}
-
-	return NULL;
-}
-
 /* Called when VF is injecting data into network stack.
  * Change the associated network device from VF to netvsc.
  * note: already called with rcu_read_lock
@@ -1914,24 +1875,15 @@ static void netvsc_vf_setup(struct work_struct *w)
 	rtnl_unlock();
 }
 
-static int netvsc_register_vf(struct net_device *vf_netdev)
+static int netvsc_register_vf(struct net_device *vf_netdev,
+			      struct net_device *ndev)
 {
-	struct net_device *ndev;
 	struct net_device_context *net_device_ctx;
 	struct netvsc_device *netvsc_dev;
 
 	if (vf_netdev->addr_len != ETH_ALEN)
 		return NOTIFY_DONE;
 
-	/*
-	 * We will use the MAC address to locate the synthetic interface to
-	 * associate with the VF interface. If we don't find a matching
-	 * synthetic interface, move on.
-	 */
-	ndev = get_netvsc_bymac(vf_netdev->perm_addr);
-	if (!ndev)
-		return NOTIFY_DONE;
-
 	net_device_ctx = netdev_priv(ndev);
 	netvsc_dev = rtnl_dereference(net_device_ctx->nvdev);
 	if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev))
@@ -1948,17 +1900,13 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
 }
 
 /* VF up/down change detected, schedule to change data path */
-static int netvsc_vf_changed(struct net_device *vf_netdev)
+static int netvsc_vf_changed(struct net_device *vf_netdev,
+			     struct net_device *ndev)
 {
 	struct net_device_context *net_device_ctx;
 	struct netvsc_device *netvsc_dev;
-	struct net_device *ndev;
 	bool vf_is_up = netif_running(vf_netdev);
 
-	ndev = get_netvsc_byref(vf_netdev);
-	if (!ndev)
-		return NOTIFY_DONE;
-
 	net_device_ctx = netdev_priv(ndev);
 	netvsc_dev = rtnl_dereference(net_device_ctx->nvdev);
 	if (!netvsc_dev)
@@ -1971,15 +1919,11 @@ static int netvsc_vf_changed(struct net_device *vf_netdev)
 	return NOTIFY_OK;
 }
 
-static int netvsc_unregister_vf(struct net_device *vf_netdev)
+static int netvsc_unregister_vf(struct net_device *vf_netdev,
+				struct net_device *ndev)
 {
-	struct net_device *ndev;
 	struct net_device_context *net_device_ctx;
 
-	ndev = get_netvsc_byref(vf_netdev);
-	if (!ndev)
-		return NOTIFY_DONE;
-
 	net_device_ctx = netdev_priv(ndev);
 	cancel_delayed_work_sync(&net_device_ctx->vf_takeover);
 
@@ -1993,6 +1937,12 @@ static int netvsc_unregister_vf(struct net_device *vf_netdev)
 	return NOTIFY_OK;
 }
 
+static struct net_failover_ops netvsc_failover_ops = {
+	.slave_register		= netvsc_register_vf,
+	.slave_unregister	= netvsc_unregister_vf,
+	.slave_link_change	= netvsc_vf_changed,
+};
+
 static int netvsc_probe(struct hv_device *dev,
 			const struct hv_vmbus_device_id *dev_id)
 {
@@ -2082,8 +2032,15 @@ static int netvsc_probe(struct hv_device *dev,
 		goto register_failed;
 	}
 
+	ret = net_failover_register(net, &netvsc_failover_ops,
+				    &net_device_ctx->failover);
+	if (ret != 0)
+		goto err_failover;
+
 	return ret;
 
+err_failover:
+	unregister_netdev(net);
 register_failed:
 	rndis_filter_device_remove(dev, nvdev);
 rndis_failed:
@@ -2124,13 +2081,15 @@ static int netvsc_remove(struct hv_device *dev)
 	rtnl_lock();
 	vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev);
 	if (vf_netdev)
-		netvsc_unregister_vf(vf_netdev);
+		net_failover_slave_unregister(vf_netdev);
 
 	if (nvdev)
 		rndis_filter_device_remove(dev, nvdev);
 
 	unregister_netdevice(net);
 
+	net_failover_unregister(ndev_ctx->failover);
+
 	rtnl_unlock();
 	rcu_read_unlock();
 
@@ -2157,54 +2116,8 @@ static struct  hv_driver netvsc_drv = {
 	.remove = netvsc_remove,
 };
 
-/*
- * On Hyper-V, every VF interface is matched with a corresponding
- * synthetic interface. The synthetic interface is presented first
- * to the guest. When the corresponding VF instance is registered,
- * we will take care of switching the data path.
- */
-static int netvsc_netdev_event(struct notifier_block *this,
-			       unsigned long event, void *ptr)
-{
-	struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
-
-	/* Skip our own events */
-	if (event_dev->netdev_ops == &device_ops)
-		return NOTIFY_DONE;
-
-	/* Avoid non-Ethernet type devices */
-	if (event_dev->type != ARPHRD_ETHER)
-		return NOTIFY_DONE;
-
-	/* Avoid Vlan dev with same MAC registering as VF */
-	if (is_vlan_dev(event_dev))
-		return NOTIFY_DONE;
-
-	/* Avoid Bonding master dev with same MAC registering as VF */
-	if ((event_dev->priv_flags & IFF_BONDING) &&
-	    (event_dev->flags & IFF_MASTER))
-		return NOTIFY_DONE;
-
-	switch (event) {
-	case NETDEV_REGISTER:
-		return netvsc_register_vf(event_dev);
-	case NETDEV_UNREGISTER:
-		return netvsc_unregister_vf(event_dev);
-	case NETDEV_UP:
-	case NETDEV_DOWN:
-		return netvsc_vf_changed(event_dev);
-	default:
-		return NOTIFY_DONE;
-	}
-}
-
-static struct notifier_block netvsc_netdev_notifier = {
-	.notifier_call = netvsc_netdev_event,
-};
-
 static void __exit netvsc_drv_exit(void)
 {
-	unregister_netdevice_notifier(&netvsc_netdev_notifier);
 	vmbus_driver_unregister(&netvsc_drv);
 }
 
@@ -2224,7 +2137,6 @@ static int __init netvsc_drv_init(void)
 	if (ret)
 		return ret;
 
-	register_netdevice_notifier(&netvsc_netdev_notifier);
 	return 0;
 }
 
-- 
2.14.3

^ permalink raw reply related

* [PATCH net-next v8 3/4] virtio_net: Extend virtio to use VF datapath when available
From: Sridhar Samudrala @ 2018-04-25 23:59 UTC (permalink / raw)
  To: mst, stephen, davem, netdev, virtualization, virtio-dev,
	jesse.brandeburg, alexander.h.duyck, kubakici, sridhar.samudrala,
	jasowang, loseweigh, jiri, aaron.f.brown
In-Reply-To: <1524700768-38627-1-git-send-email-sridhar.samudrala@intel.com>

This patch enables virtio_net to switch over to a VF datapath when a VF
netdev is present with the same MAC address. It allows live migration
of a VM with a direct attached VF without the need to setup a bond/team
between a VF and virtio net device in the guest.

The hypervisor needs to enable only one datapath at any time so that
packets don't get looped back to the VM over the other datapath. When a VF
is plugged, the virtio datapath link state can be marked as down. The
hypervisor needs to unplug the VF device from the guest on the source host
and reset the MAC filter of the VF to initiate failover of datapath to
virtio before starting the migration. After the migration is completed,
the destination hypervisor sets the MAC filter on the VF and plugs it back
to the guest to switch over to VF datapath.

It uses the generic failover framework that provides 2 functions to create
and destroy a master failover netdev. When STANDBY feature is enabled, an
additional netdev(failover netdev) is created that acts as a master device
and tracks the state of the 2 lower netdevs. The original virtio_net netdev
is marked as 'standby' netdev and a passthru device with the same MAC is
registered as 'primary' netdev.

This patch is based on the discussion initiated by Jesse on this thread.
https://marc.info/?l=linux-virtualization&m=151189725224231&w=2

Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
 drivers/net/Kconfig      |  1 +
 drivers/net/virtio_net.c | 35 ++++++++++++++++++++++++++++++++++-
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 891846655000..5233e94ea37e 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -331,6 +331,7 @@ config VETH
 config VIRTIO_NET
 	tristate "Virtio network driver"
 	depends on VIRTIO
+	depends on MAY_USE_NET_FAILOVER
 	---help---
 	  This is the virtual network driver for virtio.  It can be used with
 	  QEMU based VMMs (like KVM or Xen).  Say Y or M.
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 51a085b1a242..c326ee5344c0 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -30,8 +30,11 @@
 #include <linux/cpu.h>
 #include <linux/average.h>
 #include <linux/filter.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
 #include <net/route.h>
 #include <net/xdp.h>
+#include <net/net_failover.h>
 
 static int napi_weight = NAPI_POLL_WEIGHT;
 module_param(napi_weight, int, 0444);
@@ -210,6 +213,9 @@ struct virtnet_info {
 	u32 speed;
 
 	unsigned long guest_offloads;
+
+	/* failover when STANDBY feature enabled */
+	struct net_failover *failover;
 };
 
 struct padded_vnet_hdr {
@@ -2306,6 +2312,22 @@ static int virtnet_xdp(struct net_device *dev, struct netdev_bpf *xdp)
 	}
 }
 
+static int virtnet_get_phys_port_name(struct net_device *dev, char *buf,
+				      size_t len)
+{
+	struct virtnet_info *vi = netdev_priv(dev);
+	int ret;
+
+	if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_STANDBY))
+		return -EOPNOTSUPP;
+
+	ret = snprintf(buf, len, "_sby");
+	if (ret >= len)
+		return -EOPNOTSUPP;
+
+	return 0;
+}
+
 static const struct net_device_ops virtnet_netdev = {
 	.ndo_open            = virtnet_open,
 	.ndo_stop   	     = virtnet_close,
@@ -2323,6 +2345,7 @@ static const struct net_device_ops virtnet_netdev = {
 	.ndo_xdp_xmit		= virtnet_xdp_xmit,
 	.ndo_xdp_flush		= virtnet_xdp_flush,
 	.ndo_features_check	= passthru_features_check,
+	.ndo_get_phys_port_name	= virtnet_get_phys_port_name,
 };
 
 static void virtnet_config_changed_work(struct work_struct *work)
@@ -2876,10 +2899,16 @@ static int virtnet_probe(struct virtio_device *vdev)
 
 	virtnet_init_settings(dev);
 
+	if (virtio_has_feature(vdev, VIRTIO_NET_F_STANDBY)) {
+		err = net_failover_create(vi->dev, &vi->failover);
+		if (err)
+			goto free_vqs;
+	}
+
 	err = register_netdev(dev);
 	if (err) {
 		pr_debug("virtio_net: registering device failed\n");
-		goto free_vqs;
+		goto free_failover;
 	}
 
 	virtio_device_ready(vdev);
@@ -2916,6 +2945,8 @@ static int virtnet_probe(struct virtio_device *vdev)
 	vi->vdev->config->reset(vdev);
 
 	unregister_netdev(dev);
+free_failover:
+	net_failover_destroy(vi->failover);
 free_vqs:
 	cancel_delayed_work_sync(&vi->refill);
 	free_receive_page_frags(vi);
@@ -2950,6 +2981,8 @@ static void virtnet_remove(struct virtio_device *vdev)
 
 	unregister_netdev(vi->dev);
 
+	net_failover_destroy(vi->failover);
+
 	remove_vq_common(vi);
 
 	free_netdev(vi->dev);
-- 
2.14.3

^ permalink raw reply related

* [PATCH net-next v8 2/4] net: Introduce generic failover module
From: Sridhar Samudrala @ 2018-04-25 23:59 UTC (permalink / raw)
  To: mst, stephen, davem, netdev, virtualization, virtio-dev,
	jesse.brandeburg, alexander.h.duyck, kubakici, sridhar.samudrala,
	jasowang, loseweigh, jiri, aaron.f.brown
In-Reply-To: <1524700768-38627-1-git-send-email-sridhar.samudrala@intel.com>

This provides a generic interface for paravirtual drivers to listen
for netdev register/unregister/link change events from pci ethernet
devices with the same MAC and takeover their datapath. The notifier and
event handling code is based on the existing netvsc implementation.

It exposes 2 sets of interfaces to the paravirtual drivers.
1. For paravirtual drivers like virtio_net that use 3 netdev model, the
   the failover module provides interfaces to create/destroy additional
   master netdev and all the slave events are managed internally.
        net_failover_create()
        net_failover_destroy()
   A failover netdev is created that acts a master device and controls 2
   slave devices. The original virtio_net netdev is registered as 'standby'
   netdev and a passthru/vf device with the same MAC gets registered as
   'primary' netdev. Both 'standby' and 'primary' netdevs are associated
   with the same 'pci' device.  The user accesses the network interface via
   'failover' netdev. The 'failover' netdev chooses 'primary' netdev as
   default for transmits when it is available with link up and running.
2. For existing netvsc driver that uses 2 netdev model, no master netdev
   is created. The paravirtual driver registers each instance of netvsc
   as a 'failover' netdev  along with a set of ops to manage the slave
   events. There is no 'standby' netdev in this model. A passthru/vf device
   with the same MAC gets registered as 'primary' netdev.
        net_failover_register()
        net_failover_unregister()

Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
 include/linux/netdevice.h  |  16 +
 include/net/net_failover.h |  94 +++++
 net/Kconfig                |  18 +
 net/core/Makefile          |   1 +
 net/core/net_failover.c    | 892 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 1021 insertions(+)
 create mode 100644 include/net/net_failover.h
 create mode 100644 net/core/net_failover.c

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 14e0777ffcfb..b04dbf7dcf1b 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1401,6 +1401,8 @@ struct net_device_ops {
  *	entity (i.e. the master device for bridged veth)
  * @IFF_MACSEC: device is a MACsec device
  * @IFF_NO_RX_HANDLER: device doesn't support the rx_handler hook
+ * @IFF_FAILOVER: device is a failover master device
+ * @IFF_FAILOVER_SLAVE: device is lower dev of a failover master device
  */
 enum netdev_priv_flags {
 	IFF_802_1Q_VLAN			= 1<<0,
@@ -1430,6 +1432,8 @@ enum netdev_priv_flags {
 	IFF_PHONY_HEADROOM		= 1<<24,
 	IFF_MACSEC			= 1<<25,
 	IFF_NO_RX_HANDLER		= 1<<26,
+	IFF_FAILOVER			= 1<<27,
+	IFF_FAILOVER_SLAVE		= 1<<28,
 };
 
 #define IFF_802_1Q_VLAN			IFF_802_1Q_VLAN
@@ -1458,6 +1462,8 @@ enum netdev_priv_flags {
 #define IFF_RXFH_CONFIGURED		IFF_RXFH_CONFIGURED
 #define IFF_MACSEC			IFF_MACSEC
 #define IFF_NO_RX_HANDLER		IFF_NO_RX_HANDLER
+#define IFF_FAILOVER			IFF_FAILOVER
+#define IFF_FAILOVER_SLAVE		IFF_FAILOVER_SLAVE
 
 /**
  *	struct net_device - The DEVICE structure.
@@ -4308,6 +4314,16 @@ static inline bool netif_is_rxfh_configured(const struct net_device *dev)
 	return dev->priv_flags & IFF_RXFH_CONFIGURED;
 }
 
+static inline bool netif_is_failover(const struct net_device *dev)
+{
+	return dev->priv_flags & IFF_FAILOVER;
+}
+
+static inline bool netif_is_failover_slave(const struct net_device *dev)
+{
+	return dev->priv_flags & IFF_FAILOVER_SLAVE;
+}
+
 /* This device needs to keep skb dst for qdisc enqueue or ndo_start_xmit() */
 static inline void netif_keep_dst(struct net_device *dev)
 {
diff --git a/include/net/net_failover.h b/include/net/net_failover.h
new file mode 100644
index 000000000000..8d431685634a
--- /dev/null
+++ b/include/net/net_failover.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2018, Intel Corporation. */
+
+#ifndef _NET_FAILOVER_H
+#define _NET_FAILOVER_H
+
+#include <linux/netdevice.h>
+
+struct net_failover_ops {
+	int (*slave_register)(struct net_device *slave_dev,
+			      struct net_device *failover_dev);
+	int (*slave_unregister)(struct net_device *slave_dev,
+				struct net_device *failover_dev);
+	int (*slave_link_change)(struct net_device *slave_dev,
+				 struct net_device *failover_dev);
+};
+
+struct net_failover {
+	struct list_head list;
+	struct net_device __rcu *failover_dev;
+	struct net_failover_ops __rcu *ops;
+};
+
+/* failover state */
+struct net_failover_info {
+	/* primary netdev with same MAC */
+	struct net_device __rcu *primary_dev;
+
+	/* standby netdev */
+	struct net_device __rcu *standby_dev;
+
+	/* primary netdev stats */
+	struct rtnl_link_stats64 primary_stats;
+
+	/* standby netdev stats */
+	struct rtnl_link_stats64 standby_stats;
+
+	/* aggregated stats */
+	struct rtnl_link_stats64 failover_stats;
+
+	/* spinlock while updating stats */
+	spinlock_t stats_lock;
+};
+
+#if IS_ENABLED(CONFIG_NET_FAILOVER)
+
+/* Paravirtual drivers supporting 3-netdev model can use these 2 interfaces to
+ * create and destroy a failover device.
+ */
+int net_failover_create(struct net_device *standby_dev,
+			struct net_failover **pfailover);
+void net_failover_destroy(struct net_failover *failover);
+
+/* Paravirtual drivers supporting 2-netdev model can use these 2 interfaces to
+ * register and unregister a failover device.
+ */
+int net_failover_register(struct net_device *standby_dev,
+			  struct net_failover_ops *ops,
+			  struct net_failover **pfailover);
+void net_failover_unregister(struct net_failover *failover);
+
+int net_failover_slave_unregister(struct net_device *slave_dev);
+
+#else
+
+static inline int net_failover_create(struct net_device *standby_dev,
+				      struct net_failover **pfailover)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline void net_failover_destroy(struct net_failover *failover)
+{
+}
+
+static inline int net_failover_register(struct net_device *standby_dev,
+					struct net_failover_ops *ops,
+					struct net_failover **pfailover)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline void net_failover_unregister(struct net_failover *failover)
+{
+}
+
+static inline int net_failover_slave_unregister(struct net_device *slave_dev)
+{
+	return 0;
+}
+
+#endif
+
+#endif /* _NET_FAILOVER_H */
diff --git a/net/Kconfig b/net/Kconfig
index 6fa1a4493b8c..e8fe3163c5d3 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -426,6 +426,24 @@ config MAY_USE_DEVLINK
 config PAGE_POOL
        bool
 
+config NET_FAILOVER
+	tristate "Failover interface"
+	help
+	  This provides a generic interface for paravirtual drivers to listen
+	  for netdev register/unregister/link change events from pci ethernet
+	  devices with the same MAC and takeover their datapath. This also
+	  enables live migration of a VM with direct attached VF by failing
+	  over to the paravirtual datapath when the VF is unplugged.
+
+config MAY_USE_NET_FAILOVER
+	tristate
+	default m if NET_FAILOVER=m
+	default y if NET_FAILOVER=y || NET_FAILOVER=n
+	help
+	  Drivers using the failover infrastructure should have a dependency
+	  on MAY_USE_NET_FAILOVER to ensure they do not cause link errors when
+	  failover is a loadable module and the driver using it is built-in.
+
 endif   # if NET
 
 # Used by archs to tell that they support BPF JIT compiler plus which flavour.
diff --git a/net/core/Makefile b/net/core/Makefile
index 7080417f8bc8..283ed9b0e581 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -31,3 +31,4 @@ obj-$(CONFIG_DST_CACHE) += dst_cache.o
 obj-$(CONFIG_HWBM) += hwbm.o
 obj-$(CONFIG_NET_DEVLINK) += devlink.o
 obj-$(CONFIG_GRO_CELLS) += gro_cells.o
+obj-$(CONFIG_NET_FAILOVER) += net_failover.o
diff --git a/net/core/net_failover.c b/net/core/net_failover.c
new file mode 100644
index 000000000000..ac164be17563
--- /dev/null
+++ b/net/core/net_failover.c
@@ -0,0 +1,892 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018, Intel Corporation. */
+
+/* A common module to handle registrations and notifications for paravirtual
+ * drivers to enable accelerated datapath and support VF live migration.
+ *
+ * The notifier and event handling code is based on netvsc driver and failover
+ * netdev management routines are based on bond/team driver.
+ *
+ */
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/netpoll.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_vlan.h>
+#include <linux/pci.h>
+#include <net/sch_generic.h>
+#include <uapi/linux/if_arp.h>
+#include <net/net_failover.h>
+
+static LIST_HEAD(net_failover_list);
+static DEFINE_SPINLOCK(net_failover_lock);
+
+static int net_failover_open(struct net_device *dev)
+{
+	struct net_failover_info *nfo_info = netdev_priv(dev);
+	struct net_device *primary_dev, *standby_dev;
+	int err;
+
+	netif_carrier_off(dev);
+	netif_tx_wake_all_queues(dev);
+
+	primary_dev = rtnl_dereference(nfo_info->primary_dev);
+	if (primary_dev) {
+		err = dev_open(primary_dev);
+		if (err)
+			goto err_primary_open;
+	}
+
+	standby_dev = rtnl_dereference(nfo_info->standby_dev);
+	if (standby_dev) {
+		err = dev_open(standby_dev);
+		if (err)
+			goto err_standby_open;
+	}
+
+	return 0;
+
+err_standby_open:
+	dev_close(primary_dev);
+err_primary_open:
+	netif_tx_disable(dev);
+	return err;
+}
+
+static int net_failover_close(struct net_device *dev)
+{
+	struct net_failover_info *nfo_info = netdev_priv(dev);
+	struct net_device *slave_dev;
+
+	netif_tx_disable(dev);
+
+	slave_dev = rtnl_dereference(nfo_info->primary_dev);
+	if (slave_dev)
+		dev_close(slave_dev);
+
+	slave_dev = rtnl_dereference(nfo_info->standby_dev);
+	if (slave_dev)
+		dev_close(slave_dev);
+
+	return 0;
+}
+
+static netdev_tx_t net_failover_drop_xmit(struct sk_buff *skb,
+					  struct net_device *dev)
+{
+	atomic_long_inc(&dev->tx_dropped);
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
+}
+
+static bool net_failover_xmit_ready(struct net_device *dev)
+{
+	return netif_running(dev) && netif_carrier_ok(dev);
+}
+
+static netdev_tx_t net_failover_start_xmit(struct sk_buff *skb,
+					   struct net_device *dev)
+{
+	struct net_failover_info *nfo_info = netdev_priv(dev);
+	struct net_device *xmit_dev;
+
+	/* Try xmit via primary netdev followed by standby netdev */
+	xmit_dev = rcu_dereference_bh(nfo_info->primary_dev);
+	if (!xmit_dev || !net_failover_xmit_ready(xmit_dev)) {
+		xmit_dev = rcu_dereference_bh(nfo_info->standby_dev);
+		if (!xmit_dev || !net_failover_xmit_ready(xmit_dev))
+			return net_failover_drop_xmit(skb, dev);
+	}
+
+	skb->dev = xmit_dev;
+	skb->queue_mapping = qdisc_skb_cb(skb)->slave_dev_queue_mapping;
+
+	return dev_queue_xmit(skb);
+}
+
+static u16 net_failover_select_queue(struct net_device *dev,
+				     struct sk_buff *skb, void *accel_priv,
+				     select_queue_fallback_t fallback)
+{
+	struct net_failover_info *nfo_info = netdev_priv(dev);
+	struct net_device *primary_dev;
+	u16 txq;
+
+	rcu_read_lock();
+	primary_dev = rcu_dereference(nfo_info->primary_dev);
+	if (primary_dev) {
+		const struct net_device_ops *ops = primary_dev->netdev_ops;
+
+		if (ops->ndo_select_queue)
+			txq = ops->ndo_select_queue(primary_dev, skb,
+						    accel_priv, fallback);
+		else
+			txq = fallback(primary_dev, skb);
+
+		qdisc_skb_cb(skb)->slave_dev_queue_mapping = skb->queue_mapping;
+
+		return txq;
+	}
+
+	txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0;
+
+	/* Save the original txq to restore before passing to the driver */
+	qdisc_skb_cb(skb)->slave_dev_queue_mapping = skb->queue_mapping;
+
+	if (unlikely(txq >= dev->real_num_tx_queues)) {
+		do {
+			txq -= dev->real_num_tx_queues;
+		} while (txq >= dev->real_num_tx_queues);
+	}
+
+	return txq;
+}
+
+/* fold stats, assuming all rtnl_link_stats64 fields are u64, but
+ * that some drivers can provide 32bit values only.
+ */
+static void net_failover_fold_stats(struct rtnl_link_stats64 *_res,
+				    const struct rtnl_link_stats64 *_new,
+				    const struct rtnl_link_stats64 *_old)
+{
+	const u64 *new = (const u64 *)_new;
+	const u64 *old = (const u64 *)_old;
+	u64 *res = (u64 *)_res;
+	int i;
+
+	for (i = 0; i < sizeof(*_res) / sizeof(u64); i++) {
+		u64 nv = new[i];
+		u64 ov = old[i];
+		s64 delta = nv - ov;
+
+		/* detects if this particular field is 32bit only */
+		if (((nv | ov) >> 32) == 0)
+			delta = (s64)(s32)((u32)nv - (u32)ov);
+
+		/* filter anomalies, some drivers reset their stats
+		 * at down/up events.
+		 */
+		if (delta > 0)
+			res[i] += delta;
+	}
+}
+
+static void net_failover_get_stats(struct net_device *dev,
+				   struct rtnl_link_stats64 *stats)
+{
+	struct net_failover_info *nfo_info = netdev_priv(dev);
+	const struct rtnl_link_stats64 *new;
+	struct rtnl_link_stats64 temp;
+	struct net_device *slave_dev;
+
+	spin_lock(&nfo_info->stats_lock);
+	memcpy(stats, &nfo_info->failover_stats, sizeof(*stats));
+
+	rcu_read_lock();
+
+	slave_dev = rcu_dereference(nfo_info->primary_dev);
+	if (slave_dev) {
+		new = dev_get_stats(slave_dev, &temp);
+		net_failover_fold_stats(stats, new, &nfo_info->primary_stats);
+		memcpy(&nfo_info->primary_stats, new, sizeof(*new));
+	}
+
+	slave_dev = rcu_dereference(nfo_info->standby_dev);
+	if (slave_dev) {
+		new = dev_get_stats(slave_dev, &temp);
+		net_failover_fold_stats(stats, new, &nfo_info->standby_stats);
+		memcpy(&nfo_info->standby_stats, new, sizeof(*new));
+	}
+
+	rcu_read_unlock();
+
+	memcpy(&nfo_info->failover_stats, stats, sizeof(*stats));
+	spin_unlock(&nfo_info->stats_lock);
+}
+
+static int net_failover_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct net_failover_info *nfo_info = netdev_priv(dev);
+	struct net_device *primary_dev, *standby_dev;
+	int ret = 0;
+
+	primary_dev = rcu_dereference(nfo_info->primary_dev);
+	if (primary_dev) {
+		ret = dev_set_mtu(primary_dev, new_mtu);
+		if (ret)
+			return ret;
+	}
+
+	standby_dev = rcu_dereference(nfo_info->standby_dev);
+	if (standby_dev) {
+		ret = dev_set_mtu(standby_dev, new_mtu);
+		if (ret) {
+			dev_set_mtu(primary_dev, dev->mtu);
+			return ret;
+		}
+	}
+
+	dev->mtu = new_mtu;
+
+	return 0;
+}
+
+static void net_failover_set_rx_mode(struct net_device *dev)
+{
+	struct net_failover_info *nfo_info = netdev_priv(dev);
+	struct net_device *slave_dev;
+
+	rcu_read_lock();
+
+	slave_dev = rcu_dereference(nfo_info->primary_dev);
+	if (slave_dev) {
+		dev_uc_sync_multiple(slave_dev, dev);
+		dev_mc_sync_multiple(slave_dev, dev);
+	}
+
+	slave_dev = rcu_dereference(nfo_info->standby_dev);
+	if (slave_dev) {
+		dev_uc_sync_multiple(slave_dev, dev);
+		dev_mc_sync_multiple(slave_dev, dev);
+	}
+
+	rcu_read_unlock();
+}
+
+static int net_failover_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
+					u16 vid)
+{
+	struct net_failover_info *nfo_info = netdev_priv(dev);
+	struct net_device *primary_dev, *standby_dev;
+	int ret = 0;
+
+	primary_dev = rcu_dereference(nfo_info->primary_dev);
+	if (primary_dev) {
+		ret = vlan_vid_add(primary_dev, proto, vid);
+		if (ret)
+			return ret;
+	}
+
+	standby_dev = rcu_dereference(nfo_info->standby_dev);
+	if (standby_dev) {
+		ret = vlan_vid_add(standby_dev, proto, vid);
+		if (ret)
+			vlan_vid_del(primary_dev, proto, vid);
+	}
+
+	return ret;
+}
+
+static int net_failover_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
+					 u16 vid)
+{
+	struct net_failover_info *nfo_info = netdev_priv(dev);
+	struct net_device *slave_dev;
+
+	slave_dev = rcu_dereference(nfo_info->primary_dev);
+	if (slave_dev)
+		vlan_vid_del(slave_dev, proto, vid);
+
+	slave_dev = rcu_dereference(nfo_info->standby_dev);
+	if (slave_dev)
+		vlan_vid_del(slave_dev, proto, vid);
+
+	return 0;
+}
+
+static const struct net_device_ops failover_dev_ops = {
+	.ndo_open		= net_failover_open,
+	.ndo_stop		= net_failover_close,
+	.ndo_start_xmit		= net_failover_start_xmit,
+	.ndo_select_queue	= net_failover_select_queue,
+	.ndo_get_stats64	= net_failover_get_stats,
+	.ndo_change_mtu		= net_failover_change_mtu,
+	.ndo_set_rx_mode	= net_failover_set_rx_mode,
+	.ndo_vlan_rx_add_vid	= net_failover_vlan_rx_add_vid,
+	.ndo_vlan_rx_kill_vid	= net_failover_vlan_rx_kill_vid,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_features_check	= passthru_features_check,
+};
+
+#define FAILOVER_NAME "failover"
+#define FAILOVER_VERSION "0.1"
+
+static void nfo_ethtool_get_drvinfo(struct net_device *dev,
+				    struct ethtool_drvinfo *drvinfo)
+{
+	strlcpy(drvinfo->driver, FAILOVER_NAME, sizeof(drvinfo->driver));
+	strlcpy(drvinfo->version, FAILOVER_VERSION, sizeof(drvinfo->version));
+}
+
+static int nfo_ethtool_get_link_ksettings(struct net_device *dev,
+					  struct ethtool_link_ksettings *cmd)
+{
+	struct net_failover_info *nfo_info = netdev_priv(dev);
+	struct net_device *slave_dev;
+
+	slave_dev = rtnl_dereference(nfo_info->primary_dev);
+	if (!slave_dev || !net_failover_xmit_ready(slave_dev)) {
+		slave_dev = rtnl_dereference(nfo_info->standby_dev);
+		if (!slave_dev || !net_failover_xmit_ready(slave_dev)) {
+			cmd->base.duplex = DUPLEX_UNKNOWN;
+			cmd->base.port = PORT_OTHER;
+			cmd->base.speed = SPEED_UNKNOWN;
+
+			return 0;
+		}
+	}
+
+	return __ethtool_get_link_ksettings(slave_dev, cmd);
+}
+
+static const struct ethtool_ops failover_ethtool_ops = {
+	.get_drvinfo            = nfo_ethtool_get_drvinfo,
+	.get_link               = ethtool_op_get_link,
+	.get_link_ksettings     = nfo_ethtool_get_link_ksettings,
+};
+
+static struct net_device *net_failover_get_bymac(u8 *mac,
+						 struct net_failover_ops **ops)
+{
+	struct net_device *failover_dev;
+	struct net_failover *failover;
+
+	spin_lock(&net_failover_lock);
+	list_for_each_entry(failover, &net_failover_list, list) {
+		failover_dev = rtnl_dereference(failover->failover_dev);
+		if (ether_addr_equal(failover_dev->perm_addr, mac)) {
+			*ops = rtnl_dereference(failover->ops);
+			spin_unlock(&net_failover_lock);
+			return failover_dev;
+		}
+	}
+	spin_unlock(&net_failover_lock);
+	return NULL;
+}
+
+/* Called when slave dev is injecting data into network stack.
+ * Change the associated network device from lower dev to virtio.
+ * note: already called with rcu_read_lock
+ */
+static rx_handler_result_t net_failover_handle_frame(struct sk_buff **pskb)
+{
+	struct sk_buff *skb = *pskb;
+	struct net_device *ndev = rcu_dereference(skb->dev->rx_handler_data);
+
+	skb->dev = ndev;
+
+	return RX_HANDLER_ANOTHER;
+}
+
+#define FAILOVER_VLAN_FEATURES	(NETIF_F_HW_CSUM | NETIF_F_SG | \
+				 NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \
+				 NETIF_F_HIGHDMA | NETIF_F_LRO)
+
+#define FAILOVER_ENC_FEATURES	(NETIF_F_HW_CSUM | NETIF_F_SG | \
+				 NETIF_F_RXCSUM | NETIF_F_ALL_TSO)
+
+static void net_failover_compute_features(struct net_device *dev)
+{
+	u32 vlan_features = FAILOVER_VLAN_FEATURES & NETIF_F_ALL_FOR_ALL;
+	netdev_features_t enc_features  = FAILOVER_ENC_FEATURES;
+	unsigned short max_hard_header_len = ETH_HLEN;
+	unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
+					IFF_XMIT_DST_RELEASE_PERM;
+	struct net_failover_info *nfo_info = netdev_priv(dev);
+	struct net_device *primary_dev, *standby_dev;
+
+	primary_dev = rcu_dereference(nfo_info->primary_dev);
+	if (primary_dev) {
+		vlan_features =
+			netdev_increment_features(vlan_features,
+						  primary_dev->vlan_features,
+						  FAILOVER_VLAN_FEATURES);
+		enc_features =
+			netdev_increment_features(enc_features,
+						  primary_dev->hw_enc_features,
+						  FAILOVER_ENC_FEATURES);
+
+		dst_release_flag &= primary_dev->priv_flags;
+		if (primary_dev->hard_header_len > max_hard_header_len)
+			max_hard_header_len = primary_dev->hard_header_len;
+	}
+
+	standby_dev = rcu_dereference(nfo_info->standby_dev);
+	if (standby_dev) {
+		vlan_features =
+			netdev_increment_features(vlan_features,
+						  standby_dev->vlan_features,
+						  FAILOVER_VLAN_FEATURES);
+		enc_features =
+			netdev_increment_features(enc_features,
+						  standby_dev->hw_enc_features,
+						  FAILOVER_ENC_FEATURES);
+
+		dst_release_flag &= standby_dev->priv_flags;
+		if (standby_dev->hard_header_len > max_hard_header_len)
+			max_hard_header_len = standby_dev->hard_header_len;
+	}
+
+	dev->vlan_features = vlan_features;
+	dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL;
+	dev->hard_header_len = max_hard_header_len;
+
+	dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+	if (dst_release_flag == (IFF_XMIT_DST_RELEASE |
+				 IFF_XMIT_DST_RELEASE_PERM))
+		dev->priv_flags |= IFF_XMIT_DST_RELEASE;
+
+	netdev_change_features(dev);
+}
+
+static int net_failover_slave_register(struct net_device *slave_dev)
+{
+	struct net_failover_info *nfo_info;
+	struct net_failover_ops *nfo_ops;
+	struct net_device *failover_dev;
+	bool slave_is_standby;
+	u32 orig_mtu;
+	int err;
+
+	ASSERT_RTNL();
+
+	failover_dev = net_failover_get_bymac(slave_dev->perm_addr, &nfo_ops);
+	if (!failover_dev)
+		goto done;
+
+	if (failover_dev->type != slave_dev->type)
+		goto done;
+
+	if (nfo_ops && nfo_ops->slave_register)
+		return nfo_ops->slave_register(slave_dev, failover_dev);
+
+	nfo_info = netdev_priv(failover_dev);
+	slave_is_standby = (slave_dev->dev.parent == failover_dev->dev.parent);
+	if (slave_is_standby ? rtnl_dereference(nfo_info->standby_dev) :
+			rtnl_dereference(nfo_info->primary_dev)) {
+		netdev_err(failover_dev, "%s attempting to register as slave dev when %s already present\n",
+			   slave_dev->name,
+			   slave_is_standby ? "standby" : "primary");
+		goto done;
+	}
+
+	/* We want to allow only a direct attached VF device as a primary
+	 * netdev. As there is no easy way to check for a VF device, restrict
+	 * this to a pci device.
+	 */
+	if (!slave_is_standby && (!slave_dev->dev.parent ||
+				  !dev_is_pci(slave_dev->dev.parent)))
+		goto done;
+
+	if (failover_dev->features & NETIF_F_VLAN_CHALLENGED &&
+	    vlan_uses_dev(failover_dev)) {
+		netdev_err(failover_dev, "Device %s is VLAN challenged and failover device has VLAN set up\n",
+			   failover_dev->name);
+		goto done;
+	}
+
+	/* Align MTU of slave with failover dev */
+	orig_mtu = slave_dev->mtu;
+	err = dev_set_mtu(slave_dev, failover_dev->mtu);
+	if (err) {
+		netdev_err(failover_dev, "unable to change mtu of %s to %u register failed\n",
+			   slave_dev->name, failover_dev->mtu);
+		goto done;
+	}
+
+	dev_hold(slave_dev);
+
+	if (netif_running(failover_dev)) {
+		err = dev_open(slave_dev);
+		if (err && (err != -EBUSY)) {
+			netdev_err(failover_dev, "Opening slave %s failed err:%d\n",
+				   slave_dev->name, err);
+			goto err_dev_open;
+		}
+	}
+
+	netif_addr_lock_bh(failover_dev);
+	dev_uc_sync_multiple(slave_dev, failover_dev);
+	dev_uc_sync_multiple(slave_dev, failover_dev);
+	netif_addr_unlock_bh(failover_dev);
+
+	err = vlan_vids_add_by_dev(slave_dev, failover_dev);
+	if (err) {
+		netdev_err(failover_dev, "Failed to add vlan ids to device %s err:%d\n",
+			   slave_dev->name, err);
+		goto err_vlan_add;
+	}
+
+	err = netdev_rx_handler_register(slave_dev, net_failover_handle_frame,
+					 failover_dev);
+	if (err) {
+		netdev_err(slave_dev, "can not register failover rx handler (err = %d)\n",
+			   err);
+		goto err_handler_register;
+	}
+
+	err = netdev_upper_dev_link(slave_dev, failover_dev, NULL);
+	if (err) {
+		netdev_err(slave_dev, "can not set failover device %s (err = %d)\n",
+			   failover_dev->name, err);
+		goto err_upper_link;
+	}
+
+	slave_dev->priv_flags |= IFF_FAILOVER_SLAVE;
+
+	if (slave_is_standby) {
+		rcu_assign_pointer(nfo_info->standby_dev, slave_dev);
+		dev_get_stats(nfo_info->standby_dev, &nfo_info->standby_stats);
+	} else {
+		rcu_assign_pointer(nfo_info->primary_dev, slave_dev);
+		dev_get_stats(nfo_info->primary_dev, &nfo_info->primary_stats);
+		failover_dev->min_mtu = slave_dev->min_mtu;
+		failover_dev->max_mtu = slave_dev->max_mtu;
+	}
+
+	net_failover_compute_features(failover_dev);
+
+	call_netdevice_notifiers(NETDEV_JOIN, slave_dev);
+
+	netdev_info(failover_dev, "failover %s slave:%s registered\n",
+		    slave_is_standby ? "standby" : "primary", slave_dev->name);
+
+	goto done;
+
+err_upper_link:
+	netdev_rx_handler_unregister(slave_dev);
+err_handler_register:
+	vlan_vids_del_by_dev(slave_dev, failover_dev);
+err_vlan_add:
+	dev_uc_unsync(slave_dev, failover_dev);
+	dev_mc_unsync(slave_dev, failover_dev);
+	dev_close(slave_dev);
+err_dev_open:
+	dev_put(slave_dev);
+	dev_set_mtu(slave_dev, orig_mtu);
+done:
+	return NOTIFY_DONE;
+}
+
+int net_failover_slave_unregister(struct net_device *slave_dev)
+{
+	struct net_device *standby_dev, *primary_dev;
+	struct net_failover_info *nfo_info;
+	struct net_failover_ops *nfo_ops;
+	struct net_device *failover_dev;
+	bool slave_is_standby;
+
+	if (!netif_is_failover_slave(slave_dev))
+		goto done;
+
+	ASSERT_RTNL();
+
+	failover_dev = net_failover_get_bymac(slave_dev->perm_addr, &nfo_ops);
+	if (!failover_dev)
+		goto done;
+
+	if (nfo_ops && nfo_ops->slave_unregister)
+		return nfo_ops->slave_unregister(slave_dev, failover_dev);
+
+	nfo_info = netdev_priv(failover_dev);
+	primary_dev = rtnl_dereference(nfo_info->primary_dev);
+	standby_dev = rtnl_dereference(nfo_info->standby_dev);
+
+	if (slave_dev != primary_dev && slave_dev != standby_dev)
+		goto done;
+
+	slave_is_standby = (slave_dev->dev.parent == failover_dev->dev.parent);
+
+	netdev_rx_handler_unregister(slave_dev);
+	netdev_upper_dev_unlink(slave_dev, failover_dev);
+	vlan_vids_del_by_dev(slave_dev, failover_dev);
+	dev_uc_unsync(slave_dev, failover_dev);
+	dev_mc_unsync(slave_dev, failover_dev);
+	dev_close(slave_dev);
+	slave_dev->priv_flags &= ~IFF_FAILOVER_SLAVE;
+
+	nfo_info = netdev_priv(failover_dev);
+	net_failover_get_stats(failover_dev, &nfo_info->failover_stats);
+
+	if (slave_is_standby) {
+		RCU_INIT_POINTER(nfo_info->standby_dev, NULL);
+	} else {
+		RCU_INIT_POINTER(nfo_info->primary_dev, NULL);
+		if (standby_dev) {
+			failover_dev->min_mtu = standby_dev->min_mtu;
+			failover_dev->max_mtu = standby_dev->max_mtu;
+		}
+	}
+
+	dev_put(slave_dev);
+
+	net_failover_compute_features(failover_dev);
+
+	netdev_info(failover_dev, "failover %s slave:%s unregistered\n",
+		    slave_is_standby ? "standby" : "primary", slave_dev->name);
+
+done:
+	return NOTIFY_DONE;
+}
+EXPORT_SYMBOL_GPL(net_failover_slave_unregister);
+
+static int net_failover_slave_link_change(struct net_device *slave_dev)
+{
+	struct net_device *failover_dev, *primary_dev, *standby_dev;
+	struct net_failover_info *nfo_info;
+	struct net_failover_ops *nfo_ops;
+
+	if (!netif_is_failover_slave(slave_dev))
+		goto done;
+
+	ASSERT_RTNL();
+
+	failover_dev = net_failover_get_bymac(slave_dev->perm_addr, &nfo_ops);
+	if (!failover_dev)
+		goto done;
+
+	if (nfo_ops && nfo_ops->slave_link_change)
+		return nfo_ops->slave_link_change(slave_dev, failover_dev);
+
+	if (!netif_running(failover_dev))
+		return 0;
+
+	nfo_info = netdev_priv(failover_dev);
+
+	primary_dev = rtnl_dereference(nfo_info->primary_dev);
+	standby_dev = rtnl_dereference(nfo_info->standby_dev);
+
+	if (slave_dev != primary_dev && slave_dev != standby_dev)
+		goto done;
+
+	if ((primary_dev && net_failover_xmit_ready(primary_dev)) ||
+	    (standby_dev && net_failover_xmit_ready(standby_dev))) {
+		netif_carrier_on(failover_dev);
+		netif_tx_wake_all_queues(failover_dev);
+	} else {
+		net_failover_get_stats(failover_dev, &nfo_info->failover_stats);
+		netif_carrier_off(failover_dev);
+		netif_tx_stop_all_queues(failover_dev);
+	}
+
+done:
+	return NOTIFY_DONE;
+}
+
+static int
+net_failover_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+	struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
+
+	/* Skip parent events */
+	if (netif_is_failover(event_dev))
+		return NOTIFY_DONE;
+
+	switch (event) {
+	case NETDEV_REGISTER:
+		return net_failover_slave_register(event_dev);
+	case NETDEV_UNREGISTER:
+		return net_failover_slave_unregister(event_dev);
+	case NETDEV_UP:
+	case NETDEV_DOWN:
+	case NETDEV_CHANGE:
+		return net_failover_slave_link_change(event_dev);
+	default:
+		return NOTIFY_DONE;
+	}
+}
+
+static struct notifier_block net_failover_notifier = {
+	.notifier_call = net_failover_event,
+};
+
+static void nfo_register_existing_slave(struct net_device *failover_dev)
+{
+	struct net *net = dev_net(failover_dev);
+	struct net_device *dev;
+
+	rtnl_lock();
+	for_each_netdev(net, dev) {
+		if (netif_is_failover(dev))
+			continue;
+		if (ether_addr_equal(failover_dev->perm_addr, dev->perm_addr))
+			net_failover_slave_register(dev);
+	}
+	rtnl_unlock();
+}
+
+int net_failover_register(struct net_device *dev, struct net_failover_ops *ops,
+			  struct net_failover **pfailover)
+{
+	struct net_failover *failover;
+
+	failover = kzalloc(sizeof(*failover), GFP_KERNEL);
+	if (!failover)
+		return -ENOMEM;
+
+	rcu_assign_pointer(failover->ops, ops);
+	dev_hold(dev);
+	dev->priv_flags |= IFF_FAILOVER;
+	rcu_assign_pointer(failover->failover_dev, dev);
+
+	spin_lock(&net_failover_lock);
+	list_add_tail(&failover->list, &net_failover_list);
+	spin_unlock(&net_failover_lock);
+
+	netdev_info(dev, "failover master:%s registered\n", dev->name);
+
+	nfo_register_existing_slave(dev);
+
+	*pfailover = failover;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(net_failover_register);
+
+void net_failover_unregister(struct net_failover *failover)
+{
+	struct net_device *failover_dev;
+
+	failover_dev = rcu_dereference(failover->failover_dev);
+
+	netdev_info(failover_dev, "failover master:%s unregistered\n",
+		    failover_dev->name);
+
+	failover_dev->priv_flags &= ~IFF_FAILOVER;
+	dev_put(failover_dev);
+
+	spin_lock(&net_failover_lock);
+	list_del(&failover->list);
+	spin_unlock(&net_failover_lock);
+
+	kfree(failover);
+}
+EXPORT_SYMBOL_GPL(net_failover_unregister);
+
+int net_failover_create(struct net_device *standby_dev,
+			struct net_failover **pfailover)
+{
+	struct device *dev = standby_dev->dev.parent;
+	struct net_device *failover_dev;
+	int err;
+
+	/* Alloc at least 2 queues, for now we are going with 16 assuming
+	 * that VF devices being enslaved won't have too many queues.
+	 */
+	failover_dev = alloc_etherdev_mq(sizeof(struct net_failover_info), 16);
+	if (!failover_dev) {
+		dev_err(dev, "Unable to allocate failover_netdev!\n");
+		return -ENOMEM;
+	}
+
+	dev_net_set(failover_dev, dev_net(standby_dev));
+	SET_NETDEV_DEV(failover_dev, dev);
+
+	failover_dev->netdev_ops = &failover_dev_ops;
+	failover_dev->ethtool_ops = &failover_ethtool_ops;
+
+	/* Initialize the device options */
+	failover_dev->priv_flags |= IFF_UNICAST_FLT | IFF_NO_QUEUE;
+	failover_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE |
+				       IFF_TX_SKB_SHARING);
+
+	/* don't acquire failover netdev's netif_tx_lock when transmitting */
+	failover_dev->features |= NETIF_F_LLTX;
+
+	/* Don't allow failover devices to change network namespaces. */
+	failover_dev->features |= NETIF_F_NETNS_LOCAL;
+
+	failover_dev->hw_features = FAILOVER_VLAN_FEATURES |
+				    NETIF_F_HW_VLAN_CTAG_TX |
+				    NETIF_F_HW_VLAN_CTAG_RX |
+				    NETIF_F_HW_VLAN_CTAG_FILTER;
+
+	failover_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
+	failover_dev->features |= failover_dev->hw_features;
+
+	memcpy(failover_dev->dev_addr, standby_dev->dev_addr,
+	       failover_dev->addr_len);
+
+	failover_dev->min_mtu = standby_dev->min_mtu;
+	failover_dev->max_mtu = standby_dev->max_mtu;
+
+	err = register_netdev(failover_dev);
+	if (err < 0) {
+		dev_err(dev, "Unable to register failover_dev!\n");
+		goto err_register_netdev;
+	}
+
+	netif_carrier_off(failover_dev);
+
+	err = net_failover_register(failover_dev, NULL, pfailover);
+	if (err < 0)
+		goto err_failover_register;
+
+	return 0;
+
+err_failover_register:
+	unregister_netdev(failover_dev);
+err_register_netdev:
+	free_netdev(failover_dev);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(net_failover_create);
+
+void net_failover_destroy(struct net_failover *failover)
+{
+	struct net_failover_info *nfo_info;
+	struct net_device *failover_dev;
+	struct net_device *slave_dev;
+
+	if (!failover)
+		return;
+
+	failover_dev = rcu_dereference(failover->failover_dev);
+	nfo_info = netdev_priv(failover_dev);
+
+	netif_device_detach(failover_dev);
+
+	rtnl_lock();
+
+	slave_dev = rtnl_dereference(nfo_info->primary_dev);
+	if (slave_dev)
+		net_failover_slave_unregister(slave_dev);
+
+	slave_dev = rtnl_dereference(nfo_info->standby_dev);
+	if (slave_dev)
+		net_failover_slave_unregister(slave_dev);
+
+	net_failover_unregister(failover);
+
+	unregister_netdevice(failover_dev);
+
+	rtnl_unlock();
+
+	free_netdev(failover_dev);
+}
+EXPORT_SYMBOL_GPL(net_failover_destroy);
+
+static __init int
+net_failover_init(void)
+{
+	register_netdevice_notifier(&net_failover_notifier);
+
+	return 0;
+}
+module_init(net_failover_init);
+
+static __exit
+void net_failover_exit(void)
+{
+	unregister_netdevice_notifier(&net_failover_notifier);
+}
+module_exit(net_failover_exit);
+
+MODULE_DESCRIPTION("Failover infrastructure/interface for Paravirtual drivers");
+MODULE_LICENSE("GPL v2");
-- 
2.14.3

^ permalink raw reply related

* [PATCH net-next v8 1/4] virtio_net: Introduce VIRTIO_NET_F_STANDBY feature bit
From: Sridhar Samudrala @ 2018-04-25 23:59 UTC (permalink / raw)
  To: mst, stephen, davem, netdev, virtualization, virtio-dev,
	jesse.brandeburg, alexander.h.duyck, kubakici, sridhar.samudrala,
	jasowang, loseweigh, jiri, aaron.f.brown
In-Reply-To: <1524700768-38627-1-git-send-email-sridhar.samudrala@intel.com>

This feature bit can be used by hypervisor to indicate virtio_net device to
act as a standby for another device with the same MAC address.

VIRTIO_NET_F_STANDBY is defined as bit 62 as it is a device feature bit.

Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
 drivers/net/virtio_net.c        | 2 +-
 include/uapi/linux/virtio_net.h | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 3b5991734118..51a085b1a242 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2999,7 +2999,7 @@ static struct virtio_device_id id_table[] = {
 	VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, \
 	VIRTIO_NET_F_CTRL_MAC_ADDR, \
 	VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \
-	VIRTIO_NET_F_SPEED_DUPLEX
+	VIRTIO_NET_F_SPEED_DUPLEX, VIRTIO_NET_F_STANDBY
 
 static unsigned int features[] = {
 	VIRTNET_FEATURES,
diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h
index 5de6ed37695b..a3715a3224c1 100644
--- a/include/uapi/linux/virtio_net.h
+++ b/include/uapi/linux/virtio_net.h
@@ -57,6 +57,9 @@
 					 * Steering */
 #define VIRTIO_NET_F_CTRL_MAC_ADDR 23	/* Set MAC address */
 
+#define VIRTIO_NET_F_STANDBY	  62	/* Act as standby for another device
+					 * with the same MAC.
+					 */
 #define VIRTIO_NET_F_SPEED_DUPLEX 63	/* Device set linkspeed and duplex */
 
 #ifndef VIRTIO_NET_NO_LEGACY
-- 
2.14.3

^ permalink raw reply related


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