diff mbox

[RFC] Fix another namespace issue with devices assigned to classes

Message ID 1275998127.1899.38.camel@yio.site
State Not Applicable, archived
Delegated to: David Miller
Headers show

Commit Message

Kay Sievers June 8, 2010, 11:55 a.m. UTC
On Tue, 2010-06-08 at 11:45 +0200, Johannes Berg wrote:
> On Tue, 2010-06-08 at 11:30 +0200, Kay Sievers wrote:
> > On Tue, Jun 8, 2010 at 11:27, Johannes Berg <johannes@sipsolutions.net> wrote:
> > > On Mon, 2010-06-07 at 14:54 +0200, Kay Sievers wrote:
> > >
> > >> > I see you remove the driver. Does this mean that in sysfs these devices
> > >> > wouldn't have a driver symlink? ISTR that we needed that for userspace,
> > >> > but I'm not entirely sure, and I don't have all the relevant userspace
> > >> > in my test setup.
> > >>
> > >> Yeah, if you need the driver, you need to use bus device, as you do
> > >> now. The driver needs to be registered with the core, and the probe
> > >> function needs to tell to bind to the devices while registered. You
> > >> can not manually assign this.
> > >
> > > So I spoke to Jouni and he says that he doesn't remember needing the
> > > driver, so I guess we don't care. Can I get you to submit that patch
> > > properly? Send it to linux-wireless@vger.kernel.org please.
> > 
> > Sure, you mean the patch that changes the hwsim code, or the one I
> > talked about to properly create a virtual bus parent?
> 
> The hwsim one you pasted earlier.

Ok, this needs testing.

Please let me know, if that works for you so far.

Thanks,
Kay


From: Kay Sievers <kay.sievers@vrfy.org>
Subject: mac80211_hwsim - convert class devices to bus devices

Class devices must never have child devices of a different class,
so use bus devices.

Embed the 'struct device' into mac80211_hwsim_data, to do proper
ressource lifetime management at device release time.

Registers a driver, to binds devices to the bus.

Use a virtual root as the parent in /sys/devices/.

Puts the monitor device under the virtual parent.

This creates the following devices (udevadm monitor):
  /module/mac80211_hwsim (module)
  /bus/mac80211_hwsim (bus)
  /bus/mac80211_hwsim/drivers/mac80211_hwsim (drivers)
  /devices/mac80211_hwsim/hwsim0 (mac80211_hwsim)
  /devices/mac80211_hwsim/hwsim0/ieee80211/phy17 (ieee80211)
  /devices/mac80211_hwsim/hwsim0/ieee80211/phy17/rfkill19 (rfkill)
  /devices/mac80211_hwsim/hwsim0/net/wlan9 (net)
  /devices/mac80211_hwsim/hwsim0/net/wlan9/queues/rx-0 (queues)
  /devices/mac80211_hwsim/hwsim0/net/wlan9/queues/rx-1 (queues)
  /devices/mac80211_hwsim/hwsim0/net/wlan9/queues/rx-2 (queues)
  /devices/mac80211_hwsim/hwsim0/net/wlan9/queues/rx-3 (queues)
  /devices/mac80211_hwsim/hwsim1 (mac80211_hwsim)
  /devices/mac80211_hwsim/hwsim1/ieee80211/phy18 (ieee80211)
  /devices/mac80211_hwsim/hwsim1/ieee80211/phy18/rfkill20 (rfkill)
  /devices/mac80211_hwsim/hwsim1/net/wlan10 (net)
  /devices/mac80211_hwsim/hwsim1/net/wlan10/queues/rx-0 (queues)
  /devices/mac80211_hwsim/hwsim1/net/wlan10/queues/rx-1 (queues)
  /devices/mac80211_hwsim/hwsim1/net/wlan10/queues/rx-2 (queues)
  /devices/mac80211_hwsim/hwsim1/net/wlan10/queues/rx-3 (queues)
  /devices/mac80211_hwsim/net/hwsim0 (net)
  /devices/mac80211_hwsim/net/hwsim0/queues/rx-0 (queues)

Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
---



--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Johannes Berg June 8, 2010, 12:03 p.m. UTC | #1
On Tue, 2010-06-08 at 13:55 +0200, Kay Sievers wrote:

> Ok, this needs testing.
> 
> Please let me know, if that works for you so far.

Will do. Just a question: none of this seems to pin the module? So can I
be sure if I rmmod the module that the release function will still be
around etc.?

johannes

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kay Sievers June 8, 2010, 1:54 p.m. UTC | #2
On Tue, Jun 8, 2010 at 14:03, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Tue, 2010-06-08 at 13:55 +0200, Kay Sievers wrote:
>
>> Ok, this needs testing.
>>
>> Please let me know, if that works for you so far.
>
> Will do. Just a question: none of this seems to pin the module? So can I
> be sure if I rmmod the module that the release function will still be
> around etc.?

Oh, sorry, that's something very specific to network devices, that the
module can be unloaded while the devices it has created are still in
use. I am not sure right now what's needed to make this work in a
single module.

Kay
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Johannes Berg June 8, 2010, 2:06 p.m. UTC | #3
On Tue, 2010-06-08 at 15:54 +0200, Kay Sievers wrote:
> On Tue, Jun 8, 2010 at 14:03, Johannes Berg <johannes@sipsolutions.net> wrote:
> > On Tue, 2010-06-08 at 13:55 +0200, Kay Sievers wrote:
> >
> >> Ok, this needs testing.
> >>
> >> Please let me know, if that works for you so far.
> >
> > Will do. Just a question: none of this seems to pin the module? So can I
> > be sure if I rmmod the module that the release function will still be
> > around etc.?
> 
> Oh, sorry, that's something very specific to network devices, that the
> module can be unloaded while the devices it has created are still in
> use. I am not sure right now what's needed to make this work in a
> single module.

Well they will be unregistered and everything, but once all the netdevs
are gone etc. the devices you create in the patch might stick around
because somebody has them open in sysfs, and I see nothing that would
pin the module in that case?

johannes

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kay Sievers June 8, 2010, 2:21 p.m. UTC | #4
On Tue, Jun 8, 2010 at 16:06, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Tue, 2010-06-08 at 15:54 +0200, Kay Sievers wrote:
>> On Tue, Jun 8, 2010 at 14:03, Johannes Berg <johannes@sipsolutions.net> wrote:
>> > On Tue, 2010-06-08 at 13:55 +0200, Kay Sievers wrote:
>> >
>> >> Ok, this needs testing.
>> >>
>> >> Please let me know, if that works for you so far.
>> >
>> > Will do. Just a question: none of this seems to pin the module? So can I
>> > be sure if I rmmod the module that the release function will still be
>> > around etc.?
>>
>> Oh, sorry, that's something very specific to network devices, that the
>> module can be unloaded while the devices it has created are still in
>> use. I am not sure right now what's needed to make this work in a
>> single module.
>
> Well they will be unregistered and everything, but once all the netdevs
> are gone etc. the devices you create in the patch might stick around
> because somebody has them open in sysfs, and I see nothing that would
> pin the module in that case?

That's what I mean, I have no idea how to solve that with network
devices. I don't think any other subsytem allows to unload the module,
when devices, the module has created, are in use.

With this patch, it is likely to fail, even without sysfs, just when
the netif is still in up, and the module is unloaded.

The current code uses the in-core class_create() logic, which was only
meant for devices with a device node, and which is cleaned up by the
core itself. That's why this issue never appeared before.

But as said, I have no idea how to solve that with a single module. It
might not work at all without moving stuff into the core. That people
use device_create() with no major/minor might indicate that something
else is needed here. :)

Kay
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Johannes Berg June 8, 2010, 2:26 p.m. UTC | #5
On Tue, 2010-06-08 at 16:21 +0200, Kay Sievers wrote:

> > Well they will be unregistered and everything, but once all the netdevs
> > are gone etc. the devices you create in the patch might stick around
> > because somebody has them open in sysfs, and I see nothing that would
> > pin the module in that case?
> 
> That's what I mean, I have no idea how to solve that with network
> devices. I don't think any other subsytem allows to unload the module,
> when devices, the module has created, are in use.

You're right ... the would only be unregistered from your release, which
would happen after the module is long gone ...

> The current code uses the in-core class_create() logic, which was only
> meant for devices with a device node, and which is cleaned up by the
> core itself. That's why this issue never appeared before.
> 
> But as said, I have no idea how to solve that with a single module. It
> might not work at all without moving stuff into the core. That people
> use device_create() with no major/minor might indicate that something
> else is needed here. :)

So ... can we apply Eric's patch for now then?

johannes

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kay Sievers June 8, 2010, 2:47 p.m. UTC | #6
On Tue, Jun 8, 2010 at 16:26, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Tue, 2010-06-08 at 16:21 +0200, Kay Sievers wrote:
>
>> > Well they will be unregistered and everything, but once all the netdevs
>> > are gone etc. the devices you create in the patch might stick around
>> > because somebody has them open in sysfs, and I see nothing that would
>> > pin the module in that case?
>>
>> That's what I mean, I have no idea how to solve that with network
>> devices. I don't think any other subsytem allows to unload the module,
>> when devices, the module has created, are in use.
>
> You're right ... the would only be unregistered from your release, which
> would happen after the module is long gone ...
>
>> The current code uses the in-core class_create() logic, which was only
>> meant for devices with a device node, and which is cleaned up by the
>> core itself. That's why this issue never appeared before.
>>
>> But as said, I have no idea how to solve that with a single module. It
>> might not work at all without moving stuff into the core. That people
>> use device_create() with no major/minor might indicate that something
>> else is needed here. :)
>
> So ... can we apply Eric's patch for now then?

It might break other stuff we don't know about yet. Just like we did
not know about what things hwsim is doing here. :)

Eric's patch change the sysfs layout and insert directories into the
device path, and stuff which hardcodes things, or accesses devices
with ../<name> will break.

I don't mind trying it, but I wouldn't be surprised if that needs to
be reverted when issues caused by this appear.


The hwsim issues are caused by the current hwsim code, by doing things
it should not do. Class devices of different classes must never be
stacked (the core should not allow that in the first place). Class
devices must never have a driver assigned behind its back. Also
device_create() should not be used for devices without a major/minor
(but that seems to be done in several other places too).

To fix the hwsim driver core interaction, core changes will probably
be needed to allow network modules to be removed while their devices
are active. That's something which seems not to work for bus devices
currently.

Kay
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Johannes Berg June 8, 2010, 3:06 p.m. UTC | #7
On Tue, 2010-06-08 at 16:47 +0200, Kay Sievers wrote:

> > So ... can we apply Eric's patch for now then?
> 
> It might break other stuff we don't know about yet. Just like we did
> not know about what things hwsim is doing here. :)

True.

> The hwsim issues are caused by the current hwsim code, by doing things
> it should not do. Class devices of different classes must never be
> stacked (the core should not allow that in the first place). Class
> devices must never have a driver assigned behind its back. Also
> device_create() should not be used for devices without a major/minor
> (but that seems to be done in several other places too).

Back when hwsim was written that would have been useful feedback to
whoever did ... now, not so much.

> To fix the hwsim driver core interaction, core changes will probably
> be needed to allow network modules to be removed while their devices
> are active. That's something which seems not to work for bus devices
> currently.

Well it just needs to pin the module refcount from the bus and/or device
struct. That seems not too hard?

johannes

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kay Sievers June 8, 2010, 4:26 p.m. UTC | #8
On Tue, Jun 8, 2010 at 17:06, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Tue, 2010-06-08 at 16:47 +0200, Kay Sievers wrote:
>
>> > So ... can we apply Eric's patch for now then?
>>
>> It might break other stuff we don't know about yet. Just like we did
>> not know about what things hwsim is doing here. :)
>
> True.
>
>> The hwsim issues are caused by the current hwsim code, by doing things
>> it should not do. Class devices of different classes must never be
>> stacked (the core should not allow that in the first place). Class
>> devices must never have a driver assigned behind its back. Also
>> device_create() should not be used for devices without a major/minor
>> (but that seems to be done in several other places too).
>
> Back when hwsim was written that would have been useful feedback to
> whoever did ... now, not so much.

Well, it still needs to be fixed. It will break again, when stuff
changes like now.

>> To fix the hwsim driver core interaction, core changes will probably
>> be needed to allow network modules to be removed while their devices
>> are active. That's something which seems not to work for bus devices
>> currently.
>
> Well it just needs to pin the module refcount from the bus and/or device
> struct. That seems not too hard?

How? If we ever get a reference of the module, it will not be able to
be unloaded while stuff is active, right?

Kay
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Johannes Berg June 8, 2010, 4:33 p.m. UTC | #9
On Tue, 2010-06-08 at 18:26 +0200, Kay Sievers wrote:

> >> To fix the hwsim driver core interaction, core changes will probably
> >> be needed to allow network modules to be removed while their devices
> >> are active. That's something which seems not to work for bus devices
> >> currently.
> >
> > Well it just needs to pin the module refcount from the bus and/or device
> > struct. That seems not too hard?
> 
> How? If we ever get a reference of the module, it will not be able to
> be unloaded while stuff is active, right?

Hmm, true, but how does this work with class devices it has now? It
seems to work fine now. It's because we have a generic release function
there I guess?

johannes

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kay Sievers June 8, 2010, 4:39 p.m. UTC | #10
On Tue, Jun 8, 2010 at 18:33, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Tue, 2010-06-08 at 18:26 +0200, Kay Sievers wrote:
>
>> >> To fix the hwsim driver core interaction, core changes will probably
>> >> be needed to allow network modules to be removed while their devices
>> >> are active. That's something which seems not to work for bus devices
>> >> currently.
>> >
>> > Well it just needs to pin the module refcount from the bus and/or device
>> > struct. That seems not too hard?
>>
>> How? If we ever get a reference of the module, it will not be able to
>> be unloaded while stuff is active, right?
>
> Hmm, true, but how does this work with class devices it has now? It
> seems to work fine now. It's because we have a generic release function
> there I guess?

Because the code to cleanup is always built into the core, yes. Even
the empty release function thing we can not do. :)

That all works if you have two modules, like almost all buses have.
That's what I meant, that we need to add stuff to the core to be able
to cleanup bus devices internally too, if we use everything in a
single module, which is also supposed to cleanup on unload, like the
network devices like to do.

Kay
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Johannes Berg June 11, 2010, 9:55 a.m. UTC | #11
On Tue, 2010-06-08 at 18:39 +0200, Kay Sievers wrote:

> That all works if you have two modules, like almost all buses have.
> That's what I meant, that we need to add stuff to the core to be able
> to cleanup bus devices internally too, if we use everything in a
> single module, which is also supposed to cleanup on unload, like the
> network devices like to do.

Or some "wait for bus to be cleaned up" we can call in the module exit
maybe?

johannes

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kay Sievers June 14, 2010, 9:13 a.m. UTC | #12
On Fri, Jun 11, 2010 at 11:55, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Tue, 2010-06-08 at 18:39 +0200, Kay Sievers wrote:
>
>> That all works if you have two modules, like almost all buses have.
>> That's what I meant, that we need to add stuff to the core to be able
>> to cleanup bus devices internally too, if we use everything in a
>> single module, which is also supposed to cleanup on unload, like the
>> network devices like to do.
>
> Or some "wait for bus to be cleaned up" we can call in the module exit
> maybe?

That would block the rmmod process until the resources are cleaned up,
wouldn't it?

The network devices can do this because the cleanup code is always
compiled-in, for a module cleaning up itself, this is kind of
complicated, isn't it?

Kay
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Johannes Berg June 14, 2010, 9:20 a.m. UTC | #13
On Mon, 2010-06-14 at 11:13 +0200, Kay Sievers wrote:

> That would block the rmmod process until the resources are cleaned up,
> wouldn't it?

Yes, would that be so bad?

> The network devices can do this because the cleanup code is always
> compiled-in, for a module cleaning up itself, this is kind of
> complicated, isn't it?

It just needs a wait_for_bus_exit() function that the module calls in
_exit?

johannes

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kay Sievers June 14, 2010, 9:39 a.m. UTC | #14
On Mon, Jun 14, 2010 at 11:20, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Mon, 2010-06-14 at 11:13 +0200, Kay Sievers wrote:
>
>> That would block the rmmod process until the resources are cleaned up,
>> wouldn't it?
>
> Yes, would that be so bad?

Sounds fine, if we can expect that nothing else can hold a reference
and may block rmmod for a very long time with this logic. Sysfs access
should be fine these days, Tejun changed this a while ago.

> It just needs a wait_for_bus_exit() function that the module calls in
> _exit?

Sounds worth trying, to see if that works as expected.

Kay
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 6f8cb3e..2543e74 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -194,7 +194,16 @@  static inline void hwsim_clear_sta_magic(struct ieee80211_sta *sta)
 	sp->magic = 0;
 }
 
-static struct class *hwsim_class;
+static struct bus_type hwsim_bus = {
+	.name = "mac80211_hwsim",
+};
+
+static struct device_driver hwsim_driver = {
+	.name = "mac80211_hwsim",
+	.bus = &hwsim_bus,
+};
+
+static struct device *hwsim_virtual_parent;
 
 static struct net_device *hwsim_mon; /* global monitor netdev */
 
@@ -280,7 +289,7 @@  static struct list_head hwsim_radios;
 struct mac80211_hwsim_data {
 	struct list_head list;
 	struct ieee80211_hw *hw;
-	struct device *dev;
+	struct device dev;
 	struct ieee80211_supported_band bands[2];
 	struct ieee80211_channel channels_2ghz[ARRAY_SIZE(hwsim_channels_2ghz)];
 	struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)];
@@ -1063,22 +1072,13 @@  static void mac80211_hwsim_free(void)
 		list_move(i, &tmplist);
 	spin_unlock_bh(&hwsim_radio_lock);
 
-	list_for_each_entry_safe(data, tmpdata, &tmplist, list) {
-		debugfs_remove(data->debugfs_group);
-		debugfs_remove(data->debugfs_ps);
-		debugfs_remove(data->debugfs);
-		ieee80211_unregister_hw(data->hw);
-		device_unregister(data->dev);
-		ieee80211_free_hw(data->hw);
-	}
-	class_destroy(hwsim_class);
+	list_for_each_entry_safe(data, tmpdata, &tmplist, list)
+		device_unregister(&data->dev);
+	device_unregister(hwsim_virtual_parent);
+	driver_unregister(&hwsim_driver);
+	bus_unregister(&hwsim_bus);
 }
 
-
-static struct device_driver mac80211_hwsim_driver = {
-	.name = "mac80211_hwsim"
-};
-
 static const struct net_device_ops hwsim_netdev_ops = {
 	.ndo_start_xmit 	= hwsim_mon_xmit,
 	.ndo_change_mtu		= eth_change_mtu,
@@ -1095,6 +1095,7 @@  static void hwsim_mon_setup(struct net_device *dev)
 	dev->type = ARPHRD_IEEE80211_RADIOTAP;
 	memset(dev->dev_addr, 0, ETH_ALEN);
 	dev->dev_addr[0] = 0x12;
+	dev->dev.parent = hwsim_virtual_parent;
 }
 
 
@@ -1231,6 +1232,17 @@  DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_group,
 			hwsim_fops_group_read, hwsim_fops_group_write,
 			"%llx\n");
 
+static void hwsim_dev_release(struct device* hwsim_dev) {
+	struct mac80211_hwsim_data *data =
+	  container_of(hwsim_dev, struct mac80211_hwsim_data, dev);
+
+	debugfs_remove(data->debugfs_group);
+	debugfs_remove(data->debugfs_ps);
+	debugfs_remove(data->debugfs);
+	ieee80211_unregister_hw(data->hw);
+	ieee80211_free_hw(data->hw);
+}
+
 static int __init init_mac80211_hwsim(void)
 {
 	int i, err = 0;
@@ -1251,9 +1263,22 @@  static int __init init_mac80211_hwsim(void)
 	spin_lock_init(&hwsim_radio_lock);
 	INIT_LIST_HEAD(&hwsim_radios);
 
-	hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim");
-	if (IS_ERR(hwsim_class))
-		return PTR_ERR(hwsim_class);
+	err = bus_register(&hwsim_bus);
+	if (err)
+		return err;
+
+	err = driver_register(&hwsim_driver);
+	if (err) {
+		bus_unregister(&hwsim_bus);
+		return err;
+	}
+
+	hwsim_virtual_parent = root_device_register("mac80211_hwsim");
+	if (IS_ERR(hwsim_virtual_parent)) {
+		driver_unregister(&hwsim_driver);
+		bus_unregister(&hwsim_bus);
+		return PTR_ERR(hwsim_virtual_parent);
+	}
 
 	memset(addr, 0, ETH_ALEN);
 	addr[0] = 0x02;
@@ -1271,18 +1296,19 @@  static int __init init_mac80211_hwsim(void)
 		data = hw->priv;
 		data->hw = hw;
 
-		data->dev = device_create(hwsim_class, NULL, 0, hw,
-					  "hwsim%d", i);
-		if (IS_ERR(data->dev)) {
+		dev_set_name(&data->dev, "hwsim%d", i);
+		data->dev.parent = hwsim_virtual_parent;
+		data->dev.bus = &hwsim_bus;
+		data->dev.release = hwsim_dev_release;
+		err = device_register(&data->dev);
+		if (err) {
 			printk(KERN_DEBUG
-			       "mac80211_hwsim: device_create "
-			       "failed (%ld)\n", PTR_ERR(data->dev));
-			err = -ENOMEM;
+			       "mac80211_hwsim: device_register failed (%d)\n",
+			       err);
 			goto failed_drvdata;
 		}
-		data->dev->driver = &mac80211_hwsim_driver;
 
-		SET_IEEE80211_DEV(hw, data->dev);
+		SET_IEEE80211_DEV(hw, &data->dev);
 		addr[3] = i >> 8;
 		addr[4] = i;
 		memcpy(data->addresses[0].addr, addr, ETH_ALEN);
@@ -1513,7 +1539,7 @@  failed_mon:
 	return err;
 
 failed_hw:
-	device_unregister(data->dev);
+	device_unregister(&data->dev);
 failed_drvdata:
 	ieee80211_free_hw(hw);
 failed: