All of lore.kernel.org
 help / color / mirror / Atom feed
* [GIT PATCH] Driver core patches for 2.6.20
@ 2007-02-08  0:29 Greg KH
  2007-02-08  0:29 ` [PATCH 1/28] Kobject: make kobject apis more robust in handling NULL pointers Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:29 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton; +Cc: linux-kernel

Here are a bunch of Driver core, sysfs, and driver model patches for
2.6.20-git

They include the conversion of the network drivers to use 'struct
device' instead of 'struct class' (the patch has been in -mm for over 6
months and was acked by David Miller) some module sysfs additions to
make userspace tools simpler, and lots of cleanups and fixes.  See the
full log below for details.

All of these have been in the -mm tree for quite a while.

Please pull from:
	master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6.git/

Patches will be sent as a follow-on to this message to lkml for people
to see.

thanks,

greg k-h

 Documentation/HOWTO                       |    1 +
 drivers/base/class.c                      |   21 ++-
 drivers/base/core.c                       |  203 +++++++++++++-------
 drivers/base/dd.c                         |   21 ++-
 drivers/base/firmware_class.c             |    2 +-
 drivers/base/platform.c                   |   11 +-
 drivers/ide/setup-pci.c                   |    7 +-
 drivers/infiniband/ulp/ipoib/ipoib_main.c |   33 ++--
 drivers/infiniband/ulp/ipoib/ipoib_vlan.c |   11 +-
 drivers/input/serio/serio.c               |    6 +-
 drivers/net/arm/at91_ether.c              |    2 +-
 drivers/net/arm/etherh.c                  |    2 +-
 drivers/net/bonding/bond_sysfs.c          |  287 +++++++++++++++++-----------
 drivers/net/iseries_veth.c                |    2 +-
 drivers/net/macb.c                        |   36 ++--
 drivers/net/smc911x.c                     |    2 +-
 drivers/net/smc91x.c                      |    2 +-
 drivers/net/wireless/hostap/hostap_main.c |    2 +-
 drivers/net/wireless/orinoco.c            |    4 +-
 drivers/net/wireless/orinoco_cs.c         |    2 +-
 drivers/net/wireless/spectrum_cs.c        |    2 +-
 drivers/pci/pci-driver.c                  |    4 +-
 drivers/pcmcia/cs.c                       |   34 ++--
 drivers/pcmcia/cs_internal.h              |    4 +-
 drivers/pcmcia/ds.c                       |   14 +-
 drivers/pcmcia/i82092.c                   |    2 +-
 drivers/pcmcia/i82365.c                   |    2 +-
 drivers/pcmcia/pcmcia_ioctl.c             |    1 -
 drivers/pcmcia/pcmcia_resource.c          |    1 -
 drivers/pcmcia/pd6729.c                   |    2 +-
 drivers/pcmcia/rsrc_nonstatic.c           |   56 +++---
 drivers/pcmcia/soc_common.c               |    6 +-
 drivers/pcmcia/socket_sysfs.c             |  104 ++++++-----
 drivers/pcmcia/tcic.c                     |    2 +-
 drivers/pcmcia/yenta_socket.c             |    2 +-
 drivers/spi/pxa2xx_spi.c                  |    2 +-
 drivers/spi/spi.c                         |   32 ++--
 drivers/spi/spi_bitbang.c                 |    6 +-
 drivers/spi/spi_butterfly.c               |    4 +-
 drivers/usb/core/driver.c                 |    4 +-
 drivers/usb/input/hid-lgff.c              |    4 +-
 fs/sysfs/bin.c                            |    6 +-
 fs/sysfs/dir.c                            |  214 ++++++++++++++++++----
 fs/sysfs/file.c                           |   82 ++++++---
 fs/sysfs/group.c                          |    2 +
 fs/sysfs/inode.c                          |   36 ++++-
 fs/sysfs/mount.c                          |   11 +-
 fs/sysfs/symlink.c                        |    1 +
 fs/sysfs/sysfs.h                          |   21 ++
 include/linux/device.h                    |   12 +-
 include/linux/ide.h                       |    4 +-
 include/linux/kobject.h                   |    4 +
 include/linux/module.h                    |    3 +-
 include/linux/netdevice.h                 |    5 +-
 include/linux/pci.h                       |    5 +-
 include/linux/serio.h                     |    5 +
 include/linux/spi/spi.h                   |   10 +-
 include/linux/sysfs.h                     |   24 ++-
 include/linux/usb.h                       |    5 +-
 include/pcmcia/ss.h                       |    2 +-
 kernel/module.c                           |   76 ++++++--
 kernel/params.c                           |   28 ++-
 lib/kobject.c                             |   73 ++++++--
 net/bridge/br_if.c                        |    2 +-
 net/bridge/br_sysfs_br.c                  |  234 +++++++++++++-----------
 net/bridge/br_sysfs_if.c                  |    2 +-
 net/core/dev.c                            |    6 +-
 net/core/net-sysfs.c                      |  175 ++++++++++--------
 net/core/skbuff.c                         |    2 +-
 69 files changed, 1286 insertions(+), 709 deletions(-)

---------------

Cornelia Huck (6):
      driver core: Remove device_is_registered() in device_move().
      driver core: Allow device_move(dev, NULL).
      driver core fixes: make_class_name() retval checks
      driver core fixes: device_register() retval check in platform.c
      driver core: Don't stop probing on ->probe errors.
      driver core: Change function call order in device_bind_driver().

Dave Jones (1):
      Driver Core: Increase the default timeout value of the firmware subsystem

Eric W. Biederman (1):
      sysfs: Shadow directory support

Frank Haverkamp (1):
      SYSFS: Fix missing include of list.h in sysfs.h

Frederik Deweerdt (1):
      sysfs: suppress lockdep warnings

Greg Kroah-Hartman (8):
      Kobject: make kobject apis more robust in handling NULL pointers
      Driver core: convert pcmcia code to use struct device
      Driver core: convert SPI code to use struct device
      Network: convert network devices to use struct device instead of class_device
      Modules: only add drivers/ direcory if needed
      PCI: add the sysfs driver name to all modules
      SERIO: add the sysfs driver name to all modules
      USB: add the sysfs driver name to all modules

Kay Sievers (5):
      MODULES: add the module name for built in kernel drivers
      /sys/modules/*/holders
      Driver core: add uevent vars for devices of a class
      Driver core: add device_type to struct device
      Driver core: allow to delay the uevent at device creation time

Mariusz Kozlowski (2):
      sysfs: kobject_put cleanup
      kobject: kobject_put cleanup

Oliver Neukum (2):
      Driver core: fix race in sysfs between sysfs_remove_file() and read()/write()
      sysfs: error handling in sysfs, fill_read_buffer()

Robert P. J. Day (1):
      HOWTO: Add a reference to Harbison and Steele


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 1/28] Kobject: make kobject apis more robust in handling NULL pointers
  2007-02-08  0:29 [GIT PATCH] Driver core patches for 2.6.20 Greg KH
@ 2007-02-08  0:29 ` Greg KH
  2007-02-08  0:29   ` [PATCH 2/28] Driver core: convert pcmcia code to use struct device Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:29 UTC (permalink / raw)
  To: linux-kernel; +Cc: Greg Kroah-Hartman

From: Greg Kroah-Hartman <gregkh@suse.de>

It should be ok to pass in NULL for some kobject functions, so add error
checking for all exported kobject functions to be more robust.

Cc: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 lib/kobject.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/lib/kobject.c b/lib/kobject.c
index 7ce6dc1..9aed594 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -126,6 +126,8 @@ EXPORT_SYMBOL_GPL(kobject_get_path);
  */
 void kobject_init(struct kobject * kobj)
 {
+	if (!kobj)
+		return;
 	kref_init(&kobj->kref);
 	INIT_LIST_HEAD(&kobj->entry);
 	init_waitqueue_head(&kobj->poll);
@@ -366,6 +368,8 @@ out:
 
 void kobject_del(struct kobject * kobj)
 {
+	if (!kobj)
+		return;
 	sysfs_remove_dir(kobj);
 	unlink(kobj);
 }
@@ -377,6 +381,8 @@ void kobject_del(struct kobject * kobj)
 
 void kobject_unregister(struct kobject * kobj)
 {
+	if (!kobj)
+		return;
 	pr_debug("kobject %s: unregistering\n",kobject_name(kobj));
 	kobject_uevent(kobj, KOBJ_REMOVE);
 	kobject_del(kobj);
@@ -523,6 +529,8 @@ int kset_add(struct kset * k)
 
 int kset_register(struct kset * k)
 {
+	if (!k)
+		return -EINVAL;
 	kset_init(k);
 	return kset_add(k);
 }
@@ -535,6 +543,8 @@ int kset_register(struct kset * k)
 
 void kset_unregister(struct kset * k)
 {
+	if (!k)
+		return;
 	kobject_unregister(&k->kobj);
 }
 
@@ -586,6 +596,9 @@ int subsystem_register(struct subsystem * s)
 {
 	int error;
 
+	if (!s)
+		return -EINVAL;
+
 	subsystem_init(s);
 	pr_debug("subsystem %s: registering\n",s->kset.kobj.name);
 
@@ -598,6 +611,8 @@ int subsystem_register(struct subsystem * s)
 
 void subsystem_unregister(struct subsystem * s)
 {
+	if (!s)
+		return;
 	pr_debug("subsystem %s: unregistering\n",s->kset.kobj.name);
 	kset_unregister(&s->kset);
 }
@@ -612,6 +627,10 @@ void subsystem_unregister(struct subsystem * s)
 int subsys_create_file(struct subsystem * s, struct subsys_attribute * a)
 {
 	int error = 0;
+
+	if (!s || !a)
+		return -EINVAL;
+
 	if (subsys_get(s)) {
 		error = sysfs_create_file(&s->kset.kobj,&a->attr);
 		subsys_put(s);
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 2/28] Driver core: convert pcmcia code to use struct device
  2007-02-08  0:29 ` [PATCH 1/28] Kobject: make kobject apis more robust in handling NULL pointers Greg KH
@ 2007-02-08  0:29   ` Greg KH
  2007-02-08  0:29     ` [PATCH 3/28] Driver core: convert SPI " Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:29 UTC (permalink / raw)
  To: linux-kernel; +Cc: Greg Kroah-Hartman

From: Greg Kroah-Hartman <gregkh@suse.de>

Converts from using struct "class_device" to "struct device" making
everything show up properly in /sys/devices/ with symlinks from the
/sys/class directory.

Cc: <linux-pcmcia@lists.infradead.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/pcmcia/cs.c              |   34 ++++++------
 drivers/pcmcia/cs_internal.h     |    4 +-
 drivers/pcmcia/ds.c              |   14 +++---
 drivers/pcmcia/i82092.c          |    2 +-
 drivers/pcmcia/i82365.c          |    2 +-
 drivers/pcmcia/pcmcia_ioctl.c    |    1 -
 drivers/pcmcia/pcmcia_resource.c |    1 -
 drivers/pcmcia/pd6729.c          |    2 +-
 drivers/pcmcia/rsrc_nonstatic.c  |   56 +++++++++++---------
 drivers/pcmcia/soc_common.c      |    6 +-
 drivers/pcmcia/socket_sysfs.c    |  104 ++++++++++++++++++++++----------------
 drivers/pcmcia/tcic.c            |    2 +-
 drivers/pcmcia/yenta_socket.c    |    2 +-
 include/pcmcia/ss.h              |    2 +-
 14 files changed, 127 insertions(+), 105 deletions(-)

diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 606a467..ac00424 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -110,7 +110,7 @@ int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state)
 
 	down_read(&pcmcia_socket_list_rwsem);
 	list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
-		if (socket->dev.dev != dev)
+		if (socket->dev.parent != dev)
 			continue;
 		mutex_lock(&socket->skt_mutex);
 		socket_suspend(socket);
@@ -128,7 +128,7 @@ int pcmcia_socket_dev_resume(struct device *dev)
 
 	down_read(&pcmcia_socket_list_rwsem);
 	list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
-		if (socket->dev.dev != dev)
+		if (socket->dev.parent != dev)
 			continue;
 		mutex_lock(&socket->skt_mutex);
 		socket_resume(socket);
@@ -143,12 +143,12 @@ EXPORT_SYMBOL(pcmcia_socket_dev_resume);
 
 struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt)
 {
-	struct class_device *cl_dev = class_device_get(&skt->dev);
-	if (!cl_dev)
+	struct device *dev = get_device(&skt->dev);
+	if (!dev)
 		return NULL;
-	skt = class_get_devdata(cl_dev);
+	skt = dev_get_drvdata(dev);
 	if (!try_module_get(skt->owner)) {
-		class_device_put(&skt->dev);
+		put_device(&skt->dev);
 		return NULL;
 	}
 	return (skt);
@@ -159,14 +159,14 @@ EXPORT_SYMBOL(pcmcia_get_socket);
 void pcmcia_put_socket(struct pcmcia_socket *skt)
 {
 	module_put(skt->owner);
-	class_device_put(&skt->dev);
+	put_device(&skt->dev);
 }
 EXPORT_SYMBOL(pcmcia_put_socket);
 
 
-static void pcmcia_release_socket(struct class_device *class_dev)
+static void pcmcia_release_socket(struct device *dev)
 {
-	struct pcmcia_socket *socket = class_get_devdata(class_dev);
+	struct pcmcia_socket *socket = dev_get_drvdata(dev);
 
 	complete(&socket->socket_released);
 }
@@ -181,7 +181,7 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
 	struct task_struct *tsk;
 	int ret;
 
-	if (!socket || !socket->ops || !socket->dev.dev || !socket->resource_ops)
+	if (!socket || !socket->ops || !socket->dev.parent || !socket->resource_ops)
 		return -EINVAL;
 
 	cs_dbg(socket, 0, "pcmcia_register_socket(0x%p)\n", socket->ops);
@@ -226,9 +226,9 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
 #endif
 
 	/* set proper values in socket->dev */
-	socket->dev.class_data = socket;
+	dev_set_drvdata(&socket->dev, socket);
 	socket->dev.class = &pcmcia_socket_class;
-	snprintf(socket->dev.class_id, BUS_ID_SIZE, "pcmcia_socket%u", socket->sock);
+	snprintf(socket->dev.bus_id, BUS_ID_SIZE, "pcmcia_socket%u", socket->sock);
 
 	/* base address = 0, map = 0 */
 	socket->cis_mem.flags = 0;
@@ -640,7 +640,7 @@ static int pccardd(void *__skt)
 	skt->ops->set_socket(skt, &skt->socket);
 
 	/* register with the device core */
-	ret = class_device_register(&skt->dev);
+	ret = device_register(&skt->dev);
 	if (ret) {
 		printk(KERN_WARNING "PCMCIA: unable to register socket 0x%p\n",
 			skt);
@@ -689,7 +689,7 @@ static int pccardd(void *__skt)
 	remove_wait_queue(&skt->thread_wait, &wait);
 
 	/* remove from the device core */
-	class_device_unregister(&skt->dev);
+	device_unregister(&skt->dev);
 
 	return 0;
 }
@@ -904,7 +904,7 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
 EXPORT_SYMBOL(pcmcia_insert_card);
 
 
-static int pcmcia_socket_uevent(struct class_device *dev, char **envp,
+static int pcmcia_socket_uevent(struct device *dev, char **envp,
 			        int num_envp, char *buffer, int buffer_size)
 {
 	struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev);
@@ -930,8 +930,8 @@ static void pcmcia_release_socket_class(struct class *data)
 
 struct class pcmcia_socket_class = {
 	.name = "pcmcia_socket",
-	.uevent = pcmcia_socket_uevent,
-	.release = pcmcia_release_socket,
+	.dev_uevent = pcmcia_socket_uevent,
+	.dev_release = pcmcia_release_socket,
 	.class_release = pcmcia_release_socket_class,
 };
 EXPORT_SYMBOL(pcmcia_socket_class);
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index f573ea0..9fa207e 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -142,7 +142,7 @@ struct pcmcia_callback{
 
 int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c);
 
-#define cs_socket_name(skt)	((skt)->dev.class_id)
+#define cs_socket_name(skt)	((skt)->dev.bus_id)
 
 #ifdef DEBUG
 extern int cs_debug_level(int);
@@ -158,6 +158,6 @@ extern int cs_debug_level(int);
 #endif
 
 #define cs_err(skt, fmt, arg...) \
-	printk(KERN_ERR "cs: %s: " fmt, (skt)->dev.class_id , ## arg)
+	printk(KERN_ERR "cs: %s: " fmt, (skt)->dev.bus_id , ## arg)
 
 #endif /* _LINUX_CS_INTERNAL_H */
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 7355eb4..18e111e 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -572,7 +572,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
 	p_dev->func   = function;
 
 	p_dev->dev.bus = &pcmcia_bus_type;
-	p_dev->dev.parent = s->dev.dev;
+	p_dev->dev.parent = s->dev.parent;
 	p_dev->dev.release = pcmcia_release_dev;
 	bus_id_len = sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);
 
@@ -1328,10 +1328,10 @@ static struct pcmcia_callback pcmcia_bus_callback = {
 	.resume = pcmcia_bus_resume,
 };
 
-static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev,
+static int __devinit pcmcia_bus_add_socket(struct device *dev,
 					   struct class_interface *class_intf)
 {
-	struct pcmcia_socket *socket = class_get_devdata(class_dev);
+	struct pcmcia_socket *socket = dev_get_drvdata(dev);
 	int ret;
 
 	socket = pcmcia_get_socket(socket);
@@ -1364,10 +1364,10 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev,
 	return 0;
 }
 
-static void pcmcia_bus_remove_socket(struct class_device *class_dev,
+static void pcmcia_bus_remove_socket(struct device *dev,
 				     struct class_interface *class_intf)
 {
-	struct pcmcia_socket *socket = class_get_devdata(class_dev);
+	struct pcmcia_socket *socket = dev_get_drvdata(dev);
 
 	if (!socket)
 		return;
@@ -1389,8 +1389,8 @@ static void pcmcia_bus_remove_socket(struct class_device *class_dev,
 /* the pcmcia_bus_interface is used to handle pcmcia socket devices */
 static struct class_interface pcmcia_bus_interface = {
 	.class = &pcmcia_socket_class,
-	.add = &pcmcia_bus_add_socket,
-	.remove = &pcmcia_bus_remove_socket,
+	.add_dev = &pcmcia_bus_add_socket,
+	.remove_dev = &pcmcia_bus_remove_socket,
 };
 
 
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index c2ea07a..df21e2d 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -161,7 +161,7 @@ static int __devinit i82092aa_pci_probe(struct pci_dev *dev, const struct pci_de
 	pci_set_drvdata(dev, &sockets[i].socket);
 
 	for (i = 0; i<socket_count; i++) {
-		sockets[i].socket.dev.dev = &dev->dev;
+		sockets[i].socket.dev.parent = &dev->dev;
 		sockets[i].socket.ops = &i82092aa_operations;
 		sockets[i].socket.resource_ops = &pccard_nonstatic_ops;
 		ret = pcmcia_register_socket(&sockets[i].socket);
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index ea74f98..72ff2f6 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -1298,7 +1298,7 @@ static int __init init_i82365(void)
     
     /* register sockets with the pcmcia core */
     for (i = 0; i < sockets; i++) {
-	    socket[i].socket.dev.dev = &i82365_device->dev;
+	    socket[i].socket.dev.parent = &i82365_device->dev;
 	    socket[i].socket.ops = &pcic_operations;
 	    socket[i].socket.resource_ops = &pccard_nonstatic_ops;
 	    socket[i].socket.owner = THIS_MODULE;
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 327372b..8849414 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -59,7 +59,6 @@ typedef struct user_info_t {
 
 #ifdef DEBUG
 extern int ds_pc_debug;
-#define cs_socket_name(skt)    ((skt)->dev.class_id)
 
 #define ds_dbg(lvl, fmt, arg...) do {		\
 	if (ds_pc_debug >= lvl)				\
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index b9201c2..0ce39de 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -48,7 +48,6 @@ static u8 pcmcia_used_irq[NR_IRQS];
 
 #ifdef DEBUG
 extern int ds_pc_debug;
-#define cs_socket_name(skt)    ((skt)->dev.class_id)
 
 #define ds_dbg(skt, lvl, fmt, arg...) do {			\
 	if (ds_pc_debug >= lvl)					\
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index 360c248..dd0ddf1 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -682,7 +682,7 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,
 
 		socket[i].socket.ops = &pd6729_operations;
 		socket[i].socket.resource_ops = &pccard_nonstatic_ops;
-		socket[i].socket.dev.dev = &dev->dev;
+		socket[i].socket.dev.parent = &dev->dev;
 		socket[i].socket.driver_data = &socket[i];
 	}
 
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index c3176b1..bfcaad6 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -616,7 +616,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star
 static struct resource *nonstatic_find_io_region(unsigned long base, int num,
 		   unsigned long align, struct pcmcia_socket *s)
 {
-	struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.class_id);
+	struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.bus_id);
 	struct socket_data *s_data = s->resource_data;
 	struct pcmcia_align_data data;
 	unsigned long min = base;
@@ -650,7 +650,7 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num,
 static struct resource * nonstatic_find_mem_region(u_long base, u_long num,
 		u_long align, int low, struct pcmcia_socket *s)
 {
-	struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.class_id);
+	struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.bus_id);
 	struct socket_data *s_data = s->resource_data;
 	struct pcmcia_align_data data;
 	unsigned long min, max;
@@ -897,9 +897,10 @@ EXPORT_SYMBOL(pccard_nonstatic_ops);
 
 /* sysfs interface to the resource database */
 
-static ssize_t show_io_db(struct class_device *class_dev, char *buf)
+static ssize_t show_io_db(struct device *dev,
+			  struct device_attribute *attr, char *buf)
 {
-	struct pcmcia_socket *s = class_get_devdata(class_dev);
+	struct pcmcia_socket *s = dev_get_drvdata(dev);
 	struct socket_data *data;
 	struct resource_map *p;
 	ssize_t ret = 0;
@@ -920,9 +921,11 @@ static ssize_t show_io_db(struct class_device *class_dev, char *buf)
 	return (ret);
 }
 
-static ssize_t store_io_db(struct class_device *class_dev, const char *buf, size_t count)
+static ssize_t store_io_db(struct device *dev,
+			   struct device_attribute *attr,
+			   const char *buf, size_t count)
 {
-	struct pcmcia_socket *s = class_get_devdata(class_dev);
+	struct pcmcia_socket *s = dev_get_drvdata(dev);
 	unsigned long start_addr, end_addr;
 	unsigned int add = ADD_MANAGED_RESOURCE;
 	ssize_t ret = 0;
@@ -947,11 +950,12 @@ static ssize_t store_io_db(struct class_device *class_dev, const char *buf, size
 
 	return ret ? ret : count;
 }
-static CLASS_DEVICE_ATTR(available_resources_io, 0600, show_io_db, store_io_db);
+static DEVICE_ATTR(available_resources_io, 0600, show_io_db, store_io_db);
 
-static ssize_t show_mem_db(struct class_device *class_dev, char *buf)
+static ssize_t show_mem_db(struct device *dev,
+			   struct device_attribute *attr, char *buf)
 {
-	struct pcmcia_socket *s = class_get_devdata(class_dev);
+	struct pcmcia_socket *s = dev_get_drvdata(dev);
 	struct socket_data *data;
 	struct resource_map *p;
 	ssize_t ret = 0;
@@ -972,9 +976,11 @@ static ssize_t show_mem_db(struct class_device *class_dev, char *buf)
 	return (ret);
 }
 
-static ssize_t store_mem_db(struct class_device *class_dev, const char *buf, size_t count)
+static ssize_t store_mem_db(struct device *dev,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
 {
-	struct pcmcia_socket *s = class_get_devdata(class_dev);
+	struct pcmcia_socket *s = dev_get_drvdata(dev);
 	unsigned long start_addr, end_addr;
 	unsigned int add = ADD_MANAGED_RESOURCE;
 	ssize_t ret = 0;
@@ -999,25 +1005,25 @@ static ssize_t store_mem_db(struct class_device *class_dev, const char *buf, siz
 
 	return ret ? ret : count;
 }
-static CLASS_DEVICE_ATTR(available_resources_mem, 0600, show_mem_db, store_mem_db);
+static DEVICE_ATTR(available_resources_mem, 0600, show_mem_db, store_mem_db);
 
-static struct class_device_attribute *pccard_rsrc_attributes[] = {
-	&class_device_attr_available_resources_io,
-	&class_device_attr_available_resources_mem,
+static struct device_attribute *pccard_rsrc_attributes[] = {
+	&dev_attr_available_resources_io,
+	&dev_attr_available_resources_mem,
 	NULL,
 };
 
-static int __devinit pccard_sysfs_add_rsrc(struct class_device *class_dev,
+static int __devinit pccard_sysfs_add_rsrc(struct device *dev,
 					   struct class_interface *class_intf)
 {
-	struct pcmcia_socket *s = class_get_devdata(class_dev);
-	struct class_device_attribute **attr;
+	struct pcmcia_socket *s = dev_get_drvdata(dev);
+	struct device_attribute **attr;
 	int ret = 0;
 	if (s->resource_ops != &pccard_nonstatic_ops)
 		return 0;
 
 	for (attr = pccard_rsrc_attributes; *attr; attr++) {
-		ret = class_device_create_file(class_dev, *attr);
+		ret = device_create_file(dev, *attr);
 		if (ret)
 			break;
 	}
@@ -1025,23 +1031,23 @@ static int __devinit pccard_sysfs_add_rsrc(struct class_device *class_dev,
 	return ret;
 }
 
-static void __devexit pccard_sysfs_remove_rsrc(struct class_device *class_dev,
+static void __devexit pccard_sysfs_remove_rsrc(struct device *dev,
 					       struct class_interface *class_intf)
 {
-	struct pcmcia_socket *s = class_get_devdata(class_dev);
-	struct class_device_attribute **attr;
+	struct pcmcia_socket *s = dev_get_drvdata(dev);
+	struct device_attribute **attr;
 
 	if (s->resource_ops != &pccard_nonstatic_ops)
 		return;
 
 	for (attr = pccard_rsrc_attributes; *attr; attr++)
-		class_device_remove_file(class_dev, *attr);
+		device_remove_file(dev, *attr);
 }
 
 static struct class_interface pccard_rsrc_interface = {
 	.class = &pcmcia_socket_class,
-	.add = &pccard_sysfs_add_rsrc,
-	.remove = __devexit_p(&pccard_sysfs_remove_rsrc),
+	.add_dev = &pccard_sysfs_add_rsrc,
+	.remove_dev = __devexit_p(&pccard_sysfs_remove_rsrc),
 };
 
 static int __init nonstatic_sysfs_init(void)
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index e433704..d2a3bea 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -478,10 +478,10 @@ dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, i
  *
  * Returns: the number of characters added to the buffer
  */
-static ssize_t show_status(struct class_device *class_dev, char *buf)
+static ssize_t show_status(struct device *dev, char *buf)
 {
 	struct soc_pcmcia_socket *skt =
-		container_of(class_dev, struct soc_pcmcia_socket, socket.dev);
+		container_of(dev, struct soc_pcmcia_socket, socket.dev);
 	char *p = buf;
 
 	p+=sprintf(p, "slot     : %d\n", skt->nr);
@@ -747,7 +747,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
 
 		add_timer(&skt->poll_timer);
 
-		class_device_create_file(&skt->socket.dev, &class_device_attr_status);
+		device_create_file(&skt->socket.dev, &device_attr_status);
 	}
 
 	dev_set_drvdata(dev, sinfo);
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index b005602..ea5765c 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -40,7 +40,8 @@
 
 #define to_socket(_dev) container_of(_dev, struct pcmcia_socket, dev)
 
-static ssize_t pccard_show_type(struct class_device *dev, char *buf)
+static ssize_t pccard_show_type(struct device *dev, struct device_attribute *attr,
+				char *buf)
 {
 	struct pcmcia_socket *s = to_socket(dev);
 
@@ -50,9 +51,10 @@ static ssize_t pccard_show_type(struct class_device *dev, char *buf)
 		return sprintf(buf, "32-bit\n");
 	return sprintf(buf, "16-bit\n");
 }
-static CLASS_DEVICE_ATTR(card_type, 0444, pccard_show_type, NULL);
+static DEVICE_ATTR(card_type, 0444, pccard_show_type, NULL);
 
-static ssize_t pccard_show_voltage(struct class_device *dev, char *buf)
+static ssize_t pccard_show_voltage(struct device *dev, struct device_attribute *attr,
+				   char *buf)
 {
 	struct pcmcia_socket *s = to_socket(dev);
 
@@ -63,28 +65,31 @@ static ssize_t pccard_show_voltage(struct class_device *dev, char *buf)
 			       s->socket.Vcc % 10);
 	return sprintf(buf, "X.XV\n");
 }
-static CLASS_DEVICE_ATTR(card_voltage, 0444, pccard_show_voltage, NULL);
+static DEVICE_ATTR(card_voltage, 0444, pccard_show_voltage, NULL);
 
-static ssize_t pccard_show_vpp(struct class_device *dev, char *buf)
+static ssize_t pccard_show_vpp(struct device *dev, struct device_attribute *attr,
+			       char *buf)
 {
 	struct pcmcia_socket *s = to_socket(dev);
 	if (!(s->state & SOCKET_PRESENT))
 		return -ENODEV;
 	return sprintf(buf, "%d.%dV\n", s->socket.Vpp / 10, s->socket.Vpp % 10);
 }
-static CLASS_DEVICE_ATTR(card_vpp, 0444, pccard_show_vpp, NULL);
+static DEVICE_ATTR(card_vpp, 0444, pccard_show_vpp, NULL);
 
-static ssize_t pccard_show_vcc(struct class_device *dev, char *buf)
+static ssize_t pccard_show_vcc(struct device *dev, struct device_attribute *attr,
+			       char *buf)
 {
 	struct pcmcia_socket *s = to_socket(dev);
 	if (!(s->state & SOCKET_PRESENT))
 		return -ENODEV;
 	return sprintf(buf, "%d.%dV\n", s->socket.Vcc / 10, s->socket.Vcc % 10);
 }
-static CLASS_DEVICE_ATTR(card_vcc, 0444, pccard_show_vcc, NULL);
+static DEVICE_ATTR(card_vcc, 0444, pccard_show_vcc, NULL);
 
 
-static ssize_t pccard_store_insert(struct class_device *dev, const char *buf, size_t count)
+static ssize_t pccard_store_insert(struct device *dev, struct device_attribute *attr,
+				   const char *buf, size_t count)
 {
 	ssize_t ret;
 	struct pcmcia_socket *s = to_socket(dev);
@@ -96,16 +101,20 @@ static ssize_t pccard_store_insert(struct class_device *dev, const char *buf, si
 
 	return ret ? ret : count;
 }
-static CLASS_DEVICE_ATTR(card_insert, 0200, NULL, pccard_store_insert);
+static DEVICE_ATTR(card_insert, 0200, NULL, pccard_store_insert);
 
 
-static ssize_t pccard_show_card_pm_state(struct class_device *dev, char *buf)
+static ssize_t pccard_show_card_pm_state(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
 {
 	struct pcmcia_socket *s = to_socket(dev);
 	return sprintf(buf, "%s\n", s->state & SOCKET_SUSPEND ? "off" : "on");
 }
 
-static ssize_t pccard_store_card_pm_state(struct class_device *dev, const char *buf, size_t count)
+static ssize_t pccard_store_card_pm_state(struct device *dev,
+					  struct device_attribute *attr,
+					  const char *buf, size_t count)
 {
 	ssize_t ret = -EINVAL;
 	struct pcmcia_socket *s = to_socket(dev);
@@ -120,9 +129,11 @@ static ssize_t pccard_store_card_pm_state(struct class_device *dev, const char *
 
 	return ret ? -ENODEV : count;
 }
-static CLASS_DEVICE_ATTR(card_pm_state, 0644, pccard_show_card_pm_state, pccard_store_card_pm_state);
+static DEVICE_ATTR(card_pm_state, 0644, pccard_show_card_pm_state, pccard_store_card_pm_state);
 
-static ssize_t pccard_store_eject(struct class_device *dev, const char *buf, size_t count)
+static ssize_t pccard_store_eject(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
 {
 	ssize_t ret;
 	struct pcmcia_socket *s = to_socket(dev);
@@ -134,16 +145,20 @@ static ssize_t pccard_store_eject(struct class_device *dev, const char *buf, siz
 
 	return ret ? ret : count;
 }
-static CLASS_DEVICE_ATTR(card_eject, 0200, NULL, pccard_store_eject);
+static DEVICE_ATTR(card_eject, 0200, NULL, pccard_store_eject);
 
 
-static ssize_t pccard_show_irq_mask(struct class_device *dev, char *buf)
+static ssize_t pccard_show_irq_mask(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
 {
 	struct pcmcia_socket *s = to_socket(dev);
 	return sprintf(buf, "0x%04x\n", s->irq_mask);
 }
 
-static ssize_t pccard_store_irq_mask(struct class_device *dev, const char *buf, size_t count)
+static ssize_t pccard_store_irq_mask(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
 {
 	ssize_t ret;
 	struct pcmcia_socket *s = to_socket(dev);
@@ -161,16 +176,19 @@ static ssize_t pccard_store_irq_mask(struct class_device *dev, const char *buf,
 
 	return ret ? ret : count;
 }
-static CLASS_DEVICE_ATTR(card_irq_mask, 0600, pccard_show_irq_mask, pccard_store_irq_mask);
+static DEVICE_ATTR(card_irq_mask, 0600, pccard_show_irq_mask, pccard_store_irq_mask);
 
 
-static ssize_t pccard_show_resource(struct class_device *dev, char *buf)
+static ssize_t pccard_show_resource(struct device *dev,
+				    struct device_attribute *attr, char *buf)
 {
 	struct pcmcia_socket *s = to_socket(dev);
 	return sprintf(buf, "%s\n", s->resource_setup_done ? "yes" : "no");
 }
 
-static ssize_t pccard_store_resource(struct class_device *dev, const char *buf, size_t count)
+static ssize_t pccard_store_resource(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
 {
 	unsigned long flags;
 	struct pcmcia_socket *s = to_socket(dev);
@@ -196,7 +214,7 @@ static ssize_t pccard_store_resource(struct class_device *dev, const char *buf,
 
 	return count;
 }
-static CLASS_DEVICE_ATTR(available_resources_setup_done, 0600, pccard_show_resource, pccard_store_resource);
+static DEVICE_ATTR(available_resources_setup_done, 0600, pccard_show_resource, pccard_store_resource);
 
 
 static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf, loff_t off, size_t count)
@@ -279,7 +297,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size
 		if (off + count > size)
 			count = size - off;
 
-		s = to_socket(container_of(kobj, struct class_device, kobj));
+		s = to_socket(container_of(kobj, struct device, kobj));
 
 		if (!(s->state & SOCKET_PRESENT))
 			return -ENODEV;
@@ -296,7 +314,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size
 
 static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, size_t count)
 {
-	struct pcmcia_socket *s = to_socket(container_of(kobj, struct class_device, kobj));
+	struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj));
 	cisdump_t *cis;
 	int error;
 
@@ -335,16 +353,16 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, siz
 }
 
 
-static struct class_device_attribute *pccard_socket_attributes[] = {
-	&class_device_attr_card_type,
-	&class_device_attr_card_voltage,
-	&class_device_attr_card_vpp,
-	&class_device_attr_card_vcc,
-	&class_device_attr_card_insert,
-	&class_device_attr_card_pm_state,
-	&class_device_attr_card_eject,
-	&class_device_attr_card_irq_mask,
-	&class_device_attr_available_resources_setup_done,
+static struct device_attribute *pccard_socket_attributes[] = {
+	&dev_attr_card_type,
+	&dev_attr_card_voltage,
+	&dev_attr_card_vpp,
+	&dev_attr_card_vcc,
+	&dev_attr_card_insert,
+	&dev_attr_card_pm_state,
+	&dev_attr_card_eject,
+	&dev_attr_card_irq_mask,
+	&dev_attr_available_resources_setup_done,
 	NULL,
 };
 
@@ -355,35 +373,35 @@ static struct bin_attribute pccard_cis_attr = {
 	.write = pccard_store_cis,
 };
 
-static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev,
+static int __devinit pccard_sysfs_add_socket(struct device *dev,
 					     struct class_interface *class_intf)
 {
-	struct class_device_attribute **attr;
+	struct device_attribute **attr;
 	int ret = 0;
 
 	for (attr = pccard_socket_attributes; *attr; attr++) {
-		ret = class_device_create_file(class_dev, *attr);
+		ret = device_create_file(dev, *attr);
 		if (ret)
 			break;
 	}
 	if (!ret)
-		ret = sysfs_create_bin_file(&class_dev->kobj, &pccard_cis_attr);
+		ret = sysfs_create_bin_file(&dev->kobj, &pccard_cis_attr);
 
 	return ret;
 }
 
-static void __devexit pccard_sysfs_remove_socket(struct class_device *class_dev,
+static void __devexit pccard_sysfs_remove_socket(struct device *dev,
 						 struct class_interface *class_intf)
 {
-	struct class_device_attribute **attr;
+	struct device_attribute **attr;
 
-	sysfs_remove_bin_file(&class_dev->kobj, &pccard_cis_attr);
+	sysfs_remove_bin_file(&dev->kobj, &pccard_cis_attr);
 	for (attr = pccard_socket_attributes; *attr; attr++)
-		class_device_remove_file(class_dev, *attr);
+		device_remove_file(dev, *attr);
 }
 
 struct class_interface pccard_sysfs_interface = {
 	.class = &pcmcia_socket_class,
-	.add = &pccard_sysfs_add_socket,
-	.remove = __devexit_p(&pccard_sysfs_remove_socket),
+	.add_dev = &pccard_sysfs_add_socket,
+	.remove_dev = __devexit_p(&pccard_sysfs_remove_socket),
 };
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index 2d2f415..c158cf3 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -512,7 +512,7 @@ static int __init init_tcic(void)
     for (i = 0; i < sockets; i++) {
 	    socket_table[i].socket.ops = &tcic_operations;
 	    socket_table[i].socket.resource_ops = &pccard_nonstatic_ops;
-	    socket_table[i].socket.dev.dev = &tcic_device.dev;
+	    socket_table[i].socket.dev.parent = &tcic_device.dev;
 	    ret = pcmcia_register_socket(&socket_table[i].socket);
 	    if (ret && i)
 		    pcmcia_unregister_socket(&socket_table[0].socket);
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index da471bd..a61d768 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -1104,7 +1104,7 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
 	/* prepare pcmcia_socket */
 	socket->socket.ops = &yenta_socket_operations;
 	socket->socket.resource_ops = &pccard_nonstatic_ops;
-	socket->socket.dev.dev = &dev->dev;
+	socket->socket.dev.parent = &dev->dev;
 	socket->socket.driver_data = socket;
 	socket->socket.owner = THIS_MODULE;
 	socket->socket.features = SS_CAP_PAGE_REGS | SS_CAP_PCCARD;
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index 623a0fc..6e84258 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -284,7 +284,7 @@ struct pcmcia_socket {
 #endif
 
 	/* socket device */
-	struct class_device		dev;
+	struct device			dev;
 	void				*driver_data;	/* data internal to the socket driver */
 
 };
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 3/28] Driver core: convert SPI code to use struct device
  2007-02-08  0:29   ` [PATCH 2/28] Driver core: convert pcmcia code to use struct device Greg KH
@ 2007-02-08  0:29     ` Greg KH
  2007-02-08  0:29       ` [PATCH 4/28] Network: convert network devices to use struct device instead of class_device Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:29 UTC (permalink / raw)
  To: linux-kernel; +Cc: Greg Kroah-Hartman

From: Greg Kroah-Hartman <gregkh@suse.de>

Converts from using struct "class_device" to "struct device" making
everything show up properly in /sys/devices/ with symlinks from the
/sys/class directory.

Cc: <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/spi/pxa2xx_spi.c    |    2 +-
 drivers/spi/spi.c           |   32 ++++++++++++++++----------------
 drivers/spi/spi_bitbang.c   |    6 +++---
 drivers/spi/spi_butterfly.c |    4 ++--
 include/linux/spi/spi.h     |   10 +++++-----
 5 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 8b41f9c..dccdc50 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -1234,7 +1234,7 @@ static int init_queue(struct driver_data *drv_data)
 
 	INIT_WORK(&drv_data->pump_messages, pump_messages);
 	drv_data->workqueue = create_singlethread_workqueue(
-					drv_data->master->cdev.dev->bus_id);
+					drv_data->master->dev.parent->bus_id);
 	if (drv_data->workqueue == NULL)
 		return -EBUSY;
 
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 6307428..35d8c01 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -193,7 +193,7 @@ struct spi_device *__init_or_module
 spi_new_device(struct spi_master *master, struct spi_board_info *chip)
 {
 	struct spi_device	*proxy;
-	struct device		*dev = master->cdev.dev;
+	struct device		*dev = &master->dev;
 	int			status;
 
 	/* NOTE:  caller did any chip->bus_num checks necessary */
@@ -215,7 +215,7 @@ spi_new_device(struct spi_master *master, struct spi_board_info *chip)
 	proxy->modalias = chip->modalias;
 
 	snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id,
-			"%s.%u", master->cdev.class_id,
+			"%s.%u", master->dev.bus_id,
 			chip->chip_select);
 	proxy->dev.parent = dev;
 	proxy->dev.bus = &spi_bus_type;
@@ -290,7 +290,7 @@ static void __init_or_module
 scan_boardinfo(struct spi_master *master)
 {
 	struct boardinfo	*bi;
-	struct device		*dev = master->cdev.dev;
+	struct device		*dev = master->dev.parent;
 
 	down(&board_lock);
 	list_for_each_entry(bi, &board_list, list) {
@@ -319,18 +319,18 @@ scan_boardinfo(struct spi_master *master)
 
 /*-------------------------------------------------------------------------*/
 
-static void spi_master_release(struct class_device *cdev)
+static void spi_master_release(struct device *dev)
 {
 	struct spi_master *master;
 
-	master = container_of(cdev, struct spi_master, cdev);
+	master = container_of(dev, struct spi_master, dev);
 	kfree(master);
 }
 
 static struct class spi_master_class = {
 	.name		= "spi_master",
 	.owner		= THIS_MODULE,
-	.release	= spi_master_release,
+	.dev_release	= spi_master_release,
 };
 
 
@@ -364,9 +364,9 @@ spi_alloc_master(struct device *dev, unsigned size)
 	if (!master)
 		return NULL;
 
-	class_device_initialize(&master->cdev);
-	master->cdev.class = &spi_master_class;
-	master->cdev.dev = get_device(dev);
+	device_initialize(&master->dev);
+	master->dev.class = &spi_master_class;
+	master->dev.parent = get_device(dev);
 	spi_master_set_devdata(master, &master[1]);
 
 	return master;
@@ -396,7 +396,7 @@ int __init_or_module
 spi_register_master(struct spi_master *master)
 {
 	static atomic_t		dyn_bus_id = ATOMIC_INIT((1<<16) - 1);
-	struct device		*dev = master->cdev.dev;
+	struct device		*dev = master->dev.parent;
 	int			status = -ENODEV;
 	int			dynamic = 0;
 
@@ -412,12 +412,12 @@ spi_register_master(struct spi_master *master)
 	/* register the device, then userspace will see it.
 	 * registration fails if the bus ID is in use.
 	 */
-	snprintf(master->cdev.class_id, sizeof master->cdev.class_id,
+	snprintf(master->dev.bus_id, sizeof master->dev.bus_id,
 		"spi%u", master->bus_num);
-	status = class_device_add(&master->cdev);
+	status = device_add(&master->dev);
 	if (status < 0)
 		goto done;
-	dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id,
+	dev_dbg(dev, "registered master %s%s\n", master->dev.bus_id,
 			dynamic ? " (dynamic)" : "");
 
 	/* populate children from any spi device tables */
@@ -449,8 +449,8 @@ void spi_unregister_master(struct spi_master *master)
 {
 	int dummy;
 
-	dummy = device_for_each_child(master->cdev.dev, NULL, __unregister);
-	class_device_unregister(&master->cdev);
+	dummy = device_for_each_child(&master->dev, NULL, __unregister);
+	device_unregister(&master->dev);
 }
 EXPORT_SYMBOL_GPL(spi_unregister_master);
 
@@ -471,7 +471,7 @@ struct spi_master *spi_busnum_to_master(u16 bus_num)
 
 	down(&spi_master_class.sem);
 	list_for_each_entry(cdev, &spi_master_class.children, node) {
-		m = container_of(cdev, struct spi_master, cdev);
+		m = container_of(cdev, struct spi_master, dev.kobj);
 		if (m->bus_num == bus_num) {
 			master = spi_master_get(m);
 			break;
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
index 57289b6..4638e6c 100644
--- a/drivers/spi/spi_bitbang.c
+++ b/drivers/spi/spi_bitbang.c
@@ -479,7 +479,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
 	/* this task is the only thing to touch the SPI bits */
 	bitbang->busy = 0;
 	bitbang->workqueue = create_singlethread_workqueue(
-			bitbang->master->cdev.dev->bus_id);
+			bitbang->master->dev.parent->bus_id);
 	if (bitbang->workqueue == NULL) {
 		status = -EBUSY;
 		goto err1;
@@ -513,14 +513,14 @@ int spi_bitbang_stop(struct spi_bitbang *bitbang)
 	while (!list_empty(&bitbang->queue) && limit--) {
 		spin_unlock_irq(&bitbang->lock);
 
-		dev_dbg(bitbang->master->cdev.dev, "wait for queue\n");
+		dev_dbg(&bitbang->master->dev, "wait for queue\n");
 		msleep(10);
 
 		spin_lock_irq(&bitbang->lock);
 	}
 	spin_unlock_irq(&bitbang->lock);
 	if (!list_empty(&bitbang->queue)) {
-		dev_err(bitbang->master->cdev.dev, "queue didn't empty\n");
+		dev_err(&bitbang->master->dev, "queue didn't empty\n");
 		return -EBUSY;
 	}
 
diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c
index 312987a..31b7970 100644
--- a/drivers/spi/spi_butterfly.c
+++ b/drivers/spi/spi_butterfly.c
@@ -246,7 +246,7 @@ static void butterfly_attach(struct parport *p)
 	 * and no way to be selective about what it binds to.
 	 */
 
-	/* FIXME where should master->cdev.dev come from?
+	/* FIXME where should master->dev.parent come from?
 	 * e.g. /sys/bus/pnp0/00:0b, some PCI thing, etc
 	 * setting up a platform device like this is an ugly kluge...
 	 */
@@ -386,7 +386,7 @@ static void butterfly_detach(struct parport *p)
 	butterfly = NULL;
 
 	/* stop() unregisters child devices too */
-	pdev = to_platform_device(pp->bitbang.master->cdev.dev);
+	pdev = to_platform_device(pp->bitbang.master->dev.parent);
 	status = spi_bitbang_stop(&pp->bitbang);
 
 	/* turn off VCC */
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 176f6e3..8c2edd8 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -170,7 +170,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  * message's completion function when the transaction completes.
  */
 struct spi_master {
-	struct class_device	cdev;
+	struct device		dev;
 
 	/* other than negative (== assign one dynamically), bus_num is fully
 	 * board-specific.  usually that simplifies to being SOC-specific.
@@ -216,17 +216,17 @@ struct spi_master {
 
 static inline void *spi_master_get_devdata(struct spi_master *master)
 {
-	return class_get_devdata(&master->cdev);
+	return dev_get_drvdata(&master->dev);
 }
 
 static inline void spi_master_set_devdata(struct spi_master *master, void *data)
 {
-	class_set_devdata(&master->cdev, data);
+	dev_set_drvdata(&master->dev, data);
 }
 
 static inline struct spi_master *spi_master_get(struct spi_master *master)
 {
-	if (!master || !class_device_get(&master->cdev))
+	if (!master || !get_device(&master->dev))
 		return NULL;
 	return master;
 }
@@ -234,7 +234,7 @@ static inline struct spi_master *spi_master_get(struct spi_master *master)
 static inline void spi_master_put(struct spi_master *master)
 {
 	if (master)
-		class_device_put(&master->cdev);
+		put_device(&master->dev);
 }
 
 
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 4/28] Network: convert network devices to use struct device instead of class_device
  2007-02-08  0:29     ` [PATCH 3/28] Driver core: convert SPI " Greg KH
@ 2007-02-08  0:29       ` Greg KH
  2007-02-08  0:29         ` [PATCH 5/28] driver core: Remove device_is_registered() in device_move() Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:29 UTC (permalink / raw)
  To: linux-kernel; +Cc: Greg Kroah-Hartman

From: Greg Kroah-Hartman <gregkh@suse.de>

This lets the network core have the ability to handle suspend/resume
issues, if it wants to.

Thanks to Frederik Deweerdt <frederik.deweerdt@gmail.com> for the arm
driver fixes.

Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/infiniband/ulp/ipoib/ipoib_main.c |   33 ++--
 drivers/infiniband/ulp/ipoib/ipoib_vlan.c |   11 +-
 drivers/net/arm/at91_ether.c              |    2 +-
 drivers/net/arm/etherh.c                  |    2 +-
 drivers/net/bonding/bond_sysfs.c          |  287 +++++++++++++++++-----------
 drivers/net/iseries_veth.c                |    2 +-
 drivers/net/macb.c                        |   36 ++--
 drivers/net/smc911x.c                     |    2 +-
 drivers/net/smc91x.c                      |    2 +-
 drivers/net/wireless/hostap/hostap_main.c |    2 +-
 drivers/net/wireless/orinoco.c            |    4 +-
 drivers/net/wireless/orinoco_cs.c         |    2 +-
 drivers/net/wireless/spectrum_cs.c        |    2 +-
 include/linux/netdevice.h                 |    5 +-
 net/bridge/br_if.c                        |    2 +-
 net/bridge/br_sysfs_br.c                  |  234 +++++++++++++-----------
 net/bridge/br_sysfs_if.c                  |    2 +-
 net/core/dev.c                            |    6 +-
 net/core/net-sysfs.c                      |  175 ++++++++++--------
 net/core/skbuff.c                         |    2 +-
 20 files changed, 451 insertions(+), 362 deletions(-)

diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 705eb1d..af5ee2e 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -958,16 +958,17 @@ struct ipoib_dev_priv *ipoib_intf_alloc(const char *name)
 	return netdev_priv(dev);
 }
 
-static ssize_t show_pkey(struct class_device *cdev, char *buf)
+static ssize_t show_pkey(struct device *dev,
+			 struct device_attribute *attr, char *buf)
 {
-	struct ipoib_dev_priv *priv =
-		netdev_priv(container_of(cdev, struct net_device, class_dev));
+	struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(dev));
 
 	return sprintf(buf, "0x%04x\n", priv->pkey);
 }
-static CLASS_DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL);
+static DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL);
 
-static ssize_t create_child(struct class_device *cdev,
+static ssize_t create_child(struct device *dev,
+			    struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
 	int pkey;
@@ -985,14 +986,14 @@ static ssize_t create_child(struct class_device *cdev,
 	 */
 	pkey |= 0x8000;
 
-	ret = ipoib_vlan_add(container_of(cdev, struct net_device, class_dev),
-			     pkey);
+	ret = ipoib_vlan_add(to_net_dev(dev), pkey);
 
 	return ret ? ret : count;
 }
-static CLASS_DEVICE_ATTR(create_child, S_IWUGO, NULL, create_child);
+static DEVICE_ATTR(create_child, S_IWUGO, NULL, create_child);
 
-static ssize_t delete_child(struct class_device *cdev,
+static ssize_t delete_child(struct device *dev,
+			    struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
 	int pkey;
@@ -1004,18 +1005,16 @@ static ssize_t delete_child(struct class_device *cdev,
 	if (pkey < 0 || pkey > 0xffff)
 		return -EINVAL;
 
-	ret = ipoib_vlan_delete(container_of(cdev, struct net_device, class_dev),
-				pkey);
+	ret = ipoib_vlan_delete(to_net_dev(dev), pkey);
 
 	return ret ? ret : count;
 
 }
-static CLASS_DEVICE_ATTR(delete_child, S_IWUGO, NULL, delete_child);
+static DEVICE_ATTR(delete_child, S_IWUGO, NULL, delete_child);
 
 int ipoib_add_pkey_attr(struct net_device *dev)
 {
-	return class_device_create_file(&dev->class_dev,
-					&class_device_attr_pkey);
+	return device_create_file(&dev->dev, &dev_attr_pkey);
 }
 
 static struct net_device *ipoib_add_port(const char *format,
@@ -1083,11 +1082,9 @@ static struct net_device *ipoib_add_port(const char *format,
 
 	if (ipoib_add_pkey_attr(priv->dev))
 		goto sysfs_failed;
-	if (class_device_create_file(&priv->dev->class_dev,
-				     &class_device_attr_create_child))
+	if (device_create_file(&priv->dev->dev, &dev_attr_create_child))
 		goto sysfs_failed;
-	if (class_device_create_file(&priv->dev->class_dev,
-				     &class_device_attr_delete_child))
+	if (device_create_file(&priv->dev->dev, &dev_attr_delete_child))
 		goto sysfs_failed;
 
 	return priv->dev;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index f887780..085eafe 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -42,15 +42,15 @@
 
 #include "ipoib.h"
 
-static ssize_t show_parent(struct class_device *class_dev, char *buf)
+static ssize_t show_parent(struct device *d, struct device_attribute *attr,
+			   char *buf)
 {
-	struct net_device *dev =
-		container_of(class_dev, struct net_device, class_dev);
+	struct net_device *dev = to_net_dev(d);
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
 	return sprintf(buf, "%s\n", priv->parent->name);
 }
-static CLASS_DEVICE_ATTR(parent, S_IRUGO, show_parent, NULL);
+static DEVICE_ATTR(parent, S_IRUGO, show_parent, NULL);
 
 int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
 {
@@ -118,8 +118,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
 	if (ipoib_add_pkey_attr(priv->dev))
 		goto sysfs_failed;
 
-	if (class_device_create_file(&priv->dev->class_dev,
-				     &class_device_attr_parent))
+	if (device_create_file(&priv->dev->dev, &dev_attr_parent))
 		goto sysfs_failed;
 
 	list_add_tail(&priv->list, &ppriv->child_intfs);
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
index fada15d..1621b8f 100644
--- a/drivers/net/arm/at91_ether.c
+++ b/drivers/net/arm/at91_ether.c
@@ -641,7 +641,7 @@ static void at91ether_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo
 {
 	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
 	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-	strlcpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info));
+	strlcpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info));
 }
 
 static const struct ethtool_ops at91ether_ethtool_ops = {
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
index f3faa4f..72c41f5 100644
--- a/drivers/net/arm/etherh.c
+++ b/drivers/net/arm/etherh.c
@@ -587,7 +587,7 @@ static void etherh_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *i
 {
 	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
 	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-	strlcpy(info->bus_info, dev->class_dev.dev->bus_id,
+	strlcpy(info->bus_info, dev->dev.parent->bus_id,
 		sizeof(info->bus_info));
 }
 
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index ced9ed8..0e610aa 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -39,8 +39,7 @@
 
 /* #define BONDING_DEBUG 1 */
 #include "bonding.h"
-#define to_class_dev(obj) container_of(obj,struct class_device,kobj)
-#define to_net_dev(class) container_of(class, struct net_device, class_dev)
+#define to_dev(obj)	container_of(obj,struct device,kobj)
 #define to_bond(cd)	((struct bonding *)(to_net_dev(cd)->priv))
 
 /*---------------------------- Declarations -------------------------------*/
@@ -154,7 +153,7 @@ static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t
 				 * If it's > expected, then there's a file open,
 				 * and we have to fail.
 				 */
-				if (atomic_read(&bond->dev->class_dev.kobj.kref.refcount)
+				if (atomic_read(&bond->dev->dev.kobj.kref.refcount)
 							> expected_refcount){
 					rtnl_unlock();
 					printk(KERN_INFO DRV_NAME
@@ -201,13 +200,13 @@ int bond_create_slave_symlinks(struct net_device *master, struct net_device *sla
 	int ret = 0;
 
 	/* first, create a link from the slave back to the master */
-	ret = sysfs_create_link(&(slave->class_dev.kobj), &(master->class_dev.kobj),
+	ret = sysfs_create_link(&(slave->dev.kobj), &(master->dev.kobj),
 				"master");
 	if (ret)
 		return ret;
 	/* next, create a link from the master to the slave */
 	sprintf(linkname,"slave_%s",slave->name);
-	ret = sysfs_create_link(&(master->class_dev.kobj), &(slave->class_dev.kobj),
+	ret = sysfs_create_link(&(master->dev.kobj), &(slave->dev.kobj),
 				linkname);
 	return ret;
 
@@ -217,20 +216,21 @@ void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *s
 {
 	char linkname[IFNAMSIZ+7];
 
-	sysfs_remove_link(&(slave->class_dev.kobj), "master");
+	sysfs_remove_link(&(slave->dev.kobj), "master");
 	sprintf(linkname,"slave_%s",slave->name);
-	sysfs_remove_link(&(master->class_dev.kobj), linkname);
+	sysfs_remove_link(&(master->dev.kobj), linkname);
 }
 
 
 /*
  * Show the slaves in the current bond.
  */
-static ssize_t bonding_show_slaves(struct class_device *cd, char *buf)
+static ssize_t bonding_show_slaves(struct device *d,
+				   struct device_attribute *attr, char *buf)
 {
 	struct slave *slave;
 	int i, res = 0;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	read_lock_bh(&bond->lock);
 	bond_for_each_slave(bond, slave, i) {
@@ -254,14 +254,16 @@ static ssize_t bonding_show_slaves(struct class_device *cd, char *buf)
  * up for this to succeed.
  * This function is largely the same flow as bonding_update_bonds().
  */
-static ssize_t bonding_store_slaves(struct class_device *cd, const char *buffer, size_t count)
+static ssize_t bonding_store_slaves(struct device *d,
+				    struct device_attribute *attr,
+				    const char *buffer, size_t count)
 {
 	char command[IFNAMSIZ + 1] = { 0, };
 	char *ifname;
 	int i, res, found, ret = count;
 	struct slave *slave;
 	struct net_device *dev = NULL;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	/* Quick sanity check -- is the bond interface up? */
 	if (!(bond->dev->flags & IFF_UP)) {
@@ -387,25 +389,28 @@ out:
 	return ret;
 }
 
-static CLASS_DEVICE_ATTR(slaves, S_IRUGO | S_IWUSR, bonding_show_slaves, bonding_store_slaves);
+static DEVICE_ATTR(slaves, S_IRUGO | S_IWUSR, bonding_show_slaves, bonding_store_slaves);
 
 /*
  * Show and set the bonding mode.  The bond interface must be down to
  * change the mode.
  */
-static ssize_t bonding_show_mode(struct class_device *cd, char *buf)
+static ssize_t bonding_show_mode(struct device *d,
+				 struct device_attribute *attr, char *buf)
 {
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	return sprintf(buf, "%s %d\n",
 			bond_mode_tbl[bond->params.mode].modename,
 			bond->params.mode) + 1;
 }
 
-static ssize_t bonding_store_mode(struct class_device *cd, const char *buf, size_t count)
+static ssize_t bonding_store_mode(struct device *d,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
 {
 	int new_value, ret = count;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	if (bond->dev->flags & IFF_UP) {
 		printk(KERN_ERR DRV_NAME
@@ -438,16 +443,18 @@ static ssize_t bonding_store_mode(struct class_device *cd, const char *buf, size
 out:
 	return ret;
 }
-static CLASS_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, bonding_show_mode, bonding_store_mode);
+static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, bonding_show_mode, bonding_store_mode);
 
 /*
  * Show and set the bonding transmit hash method.  The bond interface must be down to
  * change the xmit hash policy.
  */
-static ssize_t bonding_show_xmit_hash(struct class_device *cd, char *buf)
+static ssize_t bonding_show_xmit_hash(struct device *d,
+				      struct device_attribute *attr,
+				      char *buf)
 {
 	int count;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	if ((bond->params.mode != BOND_MODE_XOR) &&
 	    (bond->params.mode != BOND_MODE_8023AD)) {
@@ -462,10 +469,12 @@ static ssize_t bonding_show_xmit_hash(struct class_device *cd, char *buf)
 	return count;
 }
 
-static ssize_t bonding_store_xmit_hash(struct class_device *cd, const char *buf, size_t count)
+static ssize_t bonding_store_xmit_hash(struct device *d,
+				       struct device_attribute *attr,
+				       const char *buf, size_t count)
 {
 	int new_value, ret = count;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	if (bond->dev->flags & IFF_UP) {
 		printk(KERN_ERR DRV_NAME
@@ -501,24 +510,28 @@ static ssize_t bonding_store_xmit_hash(struct class_device *cd, const char *buf,
 out:
 	return ret;
 }
-static CLASS_DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, bonding_show_xmit_hash, bonding_store_xmit_hash);
+static DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, bonding_show_xmit_hash, bonding_store_xmit_hash);
 
 /*
  * Show and set arp_validate.
  */
-static ssize_t bonding_show_arp_validate(struct class_device *cd, char *buf)
+static ssize_t bonding_show_arp_validate(struct device *d,
+					 struct device_attribute *attr,
+					 char *buf)
 {
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	return sprintf(buf, "%s %d\n",
 		       arp_validate_tbl[bond->params.arp_validate].modename,
 		       bond->params.arp_validate) + 1;
 }
 
-static ssize_t bonding_store_arp_validate(struct class_device *cd, const char *buf, size_t count)
+static ssize_t bonding_store_arp_validate(struct device *d,
+					  struct device_attribute *attr,
+					  const char *buf, size_t count)
 {
 	int new_value;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	new_value = bond_parse_parm((char *)buf, arp_validate_tbl);
 	if (new_value < 0) {
@@ -548,7 +561,7 @@ static ssize_t bonding_store_arp_validate(struct class_device *cd, const char *b
 	return count;
 }
 
-static CLASS_DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate);
+static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate);
 
 /*
  * Show and set the arp timer interval.  There are two tricky bits
@@ -556,17 +569,21 @@ static CLASS_DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_valid
  * MII monitoring.  Second, if the ARP timer isn't running, we must
  * start it.
  */
-static ssize_t bonding_show_arp_interval(struct class_device *cd, char *buf)
+static ssize_t bonding_show_arp_interval(struct device *d,
+					 struct device_attribute *attr,
+					 char *buf)
 {
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	return sprintf(buf, "%d\n", bond->params.arp_interval) + 1;
 }
 
-static ssize_t bonding_store_arp_interval(struct class_device *cd, const char *buf, size_t count)
+static ssize_t bonding_store_arp_interval(struct device *d,
+					  struct device_attribute *attr,
+					  const char *buf, size_t count)
 {
 	int new_value, ret = count;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
 		printk(KERN_ERR DRV_NAME
@@ -638,15 +655,17 @@ static ssize_t bonding_store_arp_interval(struct class_device *cd, const char *b
 out:
 	return ret;
 }
-static CLASS_DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR , bonding_show_arp_interval, bonding_store_arp_interval);
+static DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR , bonding_show_arp_interval, bonding_store_arp_interval);
 
 /*
  * Show and set the arp targets.
  */
-static ssize_t bonding_show_arp_targets(struct class_device *cd, char *buf)
+static ssize_t bonding_show_arp_targets(struct device *d,
+					struct device_attribute *attr,
+					char *buf)
 {
 	int i, res = 0;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
 		if (bond->params.arp_targets[i])
@@ -660,11 +679,13 @@ static ssize_t bonding_show_arp_targets(struct class_device *cd, char *buf)
 	return res;
 }
 
-static ssize_t bonding_store_arp_targets(struct class_device *cd, const char *buf, size_t count)
+static ssize_t bonding_store_arp_targets(struct device *d,
+					 struct device_attribute *attr,
+					 const char *buf, size_t count)
 {
 	u32 newtarget;
 	int i = 0, done = 0, ret = count;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 	u32 *targets;
 
 	targets = bond->params.arp_targets;
@@ -742,24 +763,28 @@ static ssize_t bonding_store_arp_targets(struct class_device *cd, const char *bu
 out:
 	return ret;
 }
-static CLASS_DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets);
+static DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets);
 
 /*
  * Show and set the up and down delays.  These must be multiples of the
  * MII monitoring value, and are stored internally as the multiplier.
  * Thus, we must translate to MS for the real world.
  */
-static ssize_t bonding_show_downdelay(struct class_device *cd, char *buf)
+static ssize_t bonding_show_downdelay(struct device *d,
+				      struct device_attribute *attr,
+				      char *buf)
 {
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	return sprintf(buf, "%d\n", bond->params.downdelay * bond->params.miimon) + 1;
 }
 
-static ssize_t bonding_store_downdelay(struct class_device *cd, const char *buf, size_t count)
+static ssize_t bonding_store_downdelay(struct device *d,
+				       struct device_attribute *attr,
+				       const char *buf, size_t count)
 {
 	int new_value, ret = count;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	if (!(bond->params.miimon)) {
 		printk(KERN_ERR DRV_NAME
@@ -800,20 +825,24 @@ static ssize_t bonding_store_downdelay(struct class_device *cd, const char *buf,
 out:
 	return ret;
 }
-static CLASS_DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR , bonding_show_downdelay, bonding_store_downdelay);
+static DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR , bonding_show_downdelay, bonding_store_downdelay);
 
-static ssize_t bonding_show_updelay(struct class_device *cd, char *buf)
+static ssize_t bonding_show_updelay(struct device *d,
+				    struct device_attribute *attr,
+				    char *buf)
 {
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	return sprintf(buf, "%d\n", bond->params.updelay * bond->params.miimon) + 1;
 
 }
 
-static ssize_t bonding_store_updelay(struct class_device *cd, const char *buf, size_t count)
+static ssize_t bonding_store_updelay(struct device *d,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
 {
 	int new_value, ret = count;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	if (!(bond->params.miimon)) {
 		printk(KERN_ERR DRV_NAME
@@ -854,25 +883,29 @@ static ssize_t bonding_store_updelay(struct class_device *cd, const char *buf, s
 out:
 	return ret;
 }
-static CLASS_DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR , bonding_show_updelay, bonding_store_updelay);
+static DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR , bonding_show_updelay, bonding_store_updelay);
 
 /*
  * Show and set the LACP interval.  Interface must be down, and the mode
  * must be set to 802.3ad mode.
  */
-static ssize_t bonding_show_lacp(struct class_device *cd, char *buf)
+static ssize_t bonding_show_lacp(struct device *d,
+				 struct device_attribute *attr,
+				 char *buf)
 {
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	return sprintf(buf, "%s %d\n",
 		bond_lacp_tbl[bond->params.lacp_fast].modename,
 		bond->params.lacp_fast) + 1;
 }
 
-static ssize_t bonding_store_lacp(struct class_device *cd, const char *buf, size_t count)
+static ssize_t bonding_store_lacp(struct device *d,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
 {
 	int new_value, ret = count;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	if (bond->dev->flags & IFF_UP) {
 		printk(KERN_ERR DRV_NAME
@@ -906,7 +939,7 @@ static ssize_t bonding_store_lacp(struct class_device *cd, const char *buf, size
 out:
 	return ret;
 }
-static CLASS_DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp);
+static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp);
 
 /*
  * Show and set the MII monitor interval.  There are two tricky bits
@@ -914,17 +947,21 @@ static CLASS_DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bondin
  * ARP monitoring.  Second, if the timer isn't running, we must
  * start it.
  */
-static ssize_t bonding_show_miimon(struct class_device *cd, char *buf)
+static ssize_t bonding_show_miimon(struct device *d,
+				   struct device_attribute *attr,
+				   char *buf)
 {
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	return sprintf(buf, "%d\n", bond->params.miimon) + 1;
 }
 
-static ssize_t bonding_store_miimon(struct class_device *cd, const char *buf, size_t count)
+static ssize_t bonding_store_miimon(struct device *d,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
 {
 	int new_value, ret = count;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
 		printk(KERN_ERR DRV_NAME
@@ -1000,7 +1037,7 @@ static ssize_t bonding_store_miimon(struct class_device *cd, const char *buf, si
 out:
 	return ret;
 }
-static CLASS_DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, bonding_show_miimon, bonding_store_miimon);
+static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, bonding_show_miimon, bonding_store_miimon);
 
 /*
  * Show and set the primary slave.  The store function is much
@@ -1009,10 +1046,12 @@ static CLASS_DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, bonding_show_miimon, bonding
  * The bond must be a mode that supports a primary for this be
  * set.
  */
-static ssize_t bonding_show_primary(struct class_device *cd, char *buf)
+static ssize_t bonding_show_primary(struct device *d,
+				    struct device_attribute *attr,
+				    char *buf)
 {
 	int count = 0;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	if (bond->primary_slave)
 		count = sprintf(buf, "%s\n", bond->primary_slave->dev->name) + 1;
@@ -1022,11 +1061,13 @@ static ssize_t bonding_show_primary(struct class_device *cd, char *buf)
 	return count;
 }
 
-static ssize_t bonding_store_primary(struct class_device *cd, const char *buf, size_t count)
+static ssize_t bonding_store_primary(struct device *d,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
 {
 	int i;
 	struct slave *slave;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	write_lock_bh(&bond->lock);
 	if (!USES_PRIMARY(bond->params.mode)) {
@@ -1065,22 +1106,26 @@ out:
 	write_unlock_bh(&bond->lock);
 	return count;
 }
-static CLASS_DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary);
+static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary);
 
 /*
  * Show and set the use_carrier flag.
  */
-static ssize_t bonding_show_carrier(struct class_device *cd, char *buf)
+static ssize_t bonding_show_carrier(struct device *d,
+				    struct device_attribute *attr,
+				    char *buf)
 {
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	return sprintf(buf, "%d\n", bond->params.use_carrier) + 1;
 }
 
-static ssize_t bonding_store_carrier(struct class_device *cd, const char *buf, size_t count)
+static ssize_t bonding_store_carrier(struct device *d,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
 {
 	int new_value, ret = count;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
@@ -1102,16 +1147,18 @@ static ssize_t bonding_store_carrier(struct class_device *cd, const char *buf, s
 out:
 	return count;
 }
-static CLASS_DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR, bonding_show_carrier, bonding_store_carrier);
+static DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR, bonding_show_carrier, bonding_store_carrier);
 
 
 /*
  * Show and set currently active_slave.
  */
-static ssize_t bonding_show_active_slave(struct class_device *cd, char *buf)
+static ssize_t bonding_show_active_slave(struct device *d,
+					 struct device_attribute *attr,
+					 char *buf)
 {
 	struct slave *curr;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 	int count;
 
 
@@ -1126,13 +1173,15 @@ static ssize_t bonding_show_active_slave(struct class_device *cd, char *buf)
 	return count;
 }
 
-static ssize_t bonding_store_active_slave(struct class_device *cd, const char *buf, size_t count)
+static ssize_t bonding_store_active_slave(struct device *d,
+					  struct device_attribute *attr,
+					  const char *buf, size_t count)
 {
 	int i;
 	struct slave *slave;
         struct slave *old_active = NULL;
         struct slave *new_active = NULL;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	write_lock_bh(&bond->lock);
 	if (!USES_PRIMARY(bond->params.mode)) {
@@ -1194,16 +1243,18 @@ out:
 	return count;
 
 }
-static CLASS_DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR, bonding_show_active_slave, bonding_store_active_slave);
+static DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR, bonding_show_active_slave, bonding_store_active_slave);
 
 
 /*
  * Show link status of the bond interface.
  */
-static ssize_t bonding_show_mii_status(struct class_device *cd, char *buf)
+static ssize_t bonding_show_mii_status(struct device *d,
+				       struct device_attribute *attr,
+				       char *buf)
 {
 	struct slave *curr;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	read_lock(&bond->curr_slave_lock);
 	curr = bond->curr_active_slave;
@@ -1211,16 +1262,18 @@ static ssize_t bonding_show_mii_status(struct class_device *cd, char *buf)
 
 	return sprintf(buf, "%s\n", (curr) ? "up" : "down") + 1;
 }
-static CLASS_DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL);
+static DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL);
 
 
 /*
  * Show current 802.3ad aggregator ID.
  */
-static ssize_t bonding_show_ad_aggregator(struct class_device *cd, char *buf)
+static ssize_t bonding_show_ad_aggregator(struct device *d,
+					  struct device_attribute *attr,
+					  char *buf)
 {
 	int count = 0;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	if (bond->params.mode == BOND_MODE_8023AD) {
 		struct ad_info ad_info;
@@ -1231,16 +1284,18 @@ static ssize_t bonding_show_ad_aggregator(struct class_device *cd, char *buf)
 
 	return count;
 }
-static CLASS_DEVICE_ATTR(ad_aggregator, S_IRUGO, bonding_show_ad_aggregator, NULL);
+static DEVICE_ATTR(ad_aggregator, S_IRUGO, bonding_show_ad_aggregator, NULL);
 
 
 /*
  * Show number of active 802.3ad ports.
  */
-static ssize_t bonding_show_ad_num_ports(struct class_device *cd, char *buf)
+static ssize_t bonding_show_ad_num_ports(struct device *d,
+					 struct device_attribute *attr,
+					 char *buf)
 {
 	int count = 0;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	if (bond->params.mode == BOND_MODE_8023AD) {
 		struct ad_info ad_info;
@@ -1251,16 +1306,18 @@ static ssize_t bonding_show_ad_num_ports(struct class_device *cd, char *buf)
 
 	return count;
 }
-static CLASS_DEVICE_ATTR(ad_num_ports, S_IRUGO, bonding_show_ad_num_ports, NULL);
+static DEVICE_ATTR(ad_num_ports, S_IRUGO, bonding_show_ad_num_ports, NULL);
 
 
 /*
  * Show current 802.3ad actor key.
  */
-static ssize_t bonding_show_ad_actor_key(struct class_device *cd, char *buf)
+static ssize_t bonding_show_ad_actor_key(struct device *d,
+					 struct device_attribute *attr,
+					 char *buf)
 {
 	int count = 0;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	if (bond->params.mode == BOND_MODE_8023AD) {
 		struct ad_info ad_info;
@@ -1271,16 +1328,18 @@ static ssize_t bonding_show_ad_actor_key(struct class_device *cd, char *buf)
 
 	return count;
 }
-static CLASS_DEVICE_ATTR(ad_actor_key, S_IRUGO, bonding_show_ad_actor_key, NULL);
+static DEVICE_ATTR(ad_actor_key, S_IRUGO, bonding_show_ad_actor_key, NULL);
 
 
 /*
  * Show current 802.3ad partner key.
  */
-static ssize_t bonding_show_ad_partner_key(struct class_device *cd, char *buf)
+static ssize_t bonding_show_ad_partner_key(struct device *d,
+					   struct device_attribute *attr,
+					   char *buf)
 {
 	int count = 0;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	if (bond->params.mode == BOND_MODE_8023AD) {
 		struct ad_info ad_info;
@@ -1291,16 +1350,18 @@ static ssize_t bonding_show_ad_partner_key(struct class_device *cd, char *buf)
 
 	return count;
 }
-static CLASS_DEVICE_ATTR(ad_partner_key, S_IRUGO, bonding_show_ad_partner_key, NULL);
+static DEVICE_ATTR(ad_partner_key, S_IRUGO, bonding_show_ad_partner_key, NULL);
 
 
 /*
  * Show current 802.3ad partner mac.
  */
-static ssize_t bonding_show_ad_partner_mac(struct class_device *cd, char *buf)
+static ssize_t bonding_show_ad_partner_mac(struct device *d,
+					   struct device_attribute *attr,
+					   char *buf)
 {
 	int count = 0;
-	struct bonding *bond = to_bond(cd);
+	struct bonding *bond = to_bond(d);
 
 	if (bond->params.mode == BOND_MODE_8023AD) {
 		struct ad_info ad_info;
@@ -1319,30 +1380,30 @@ static ssize_t bonding_show_ad_partner_mac(struct class_device *cd, char *buf)
 
 	return count;
 }
-static CLASS_DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
+static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
 
 
 
 static struct attribute *per_bond_attrs[] = {
-	&class_device_attr_slaves.attr,
-	&class_device_attr_mode.attr,
-	&class_device_attr_arp_validate.attr,
-	&class_device_attr_arp_interval.attr,
-	&class_device_attr_arp_ip_target.attr,
-	&class_device_attr_downdelay.attr,
-	&class_device_attr_updelay.attr,
-	&class_device_attr_lacp_rate.attr,
-	&class_device_attr_xmit_hash_policy.attr,
-	&class_device_attr_miimon.attr,
-	&class_device_attr_primary.attr,
-	&class_device_attr_use_carrier.attr,
-	&class_device_attr_active_slave.attr,
-	&class_device_attr_mii_status.attr,
-	&class_device_attr_ad_aggregator.attr,
-	&class_device_attr_ad_num_ports.attr,
-	&class_device_attr_ad_actor_key.attr,
-	&class_device_attr_ad_partner_key.attr,
-	&class_device_attr_ad_partner_mac.attr,
+	&dev_attr_slaves.attr,
+	&dev_attr_mode.attr,
+	&dev_attr_arp_validate.attr,
+	&dev_attr_arp_interval.attr,
+	&dev_attr_arp_ip_target.attr,
+	&dev_attr_downdelay.attr,
+	&dev_attr_updelay.attr,
+	&dev_attr_lacp_rate.attr,
+	&dev_attr_xmit_hash_policy.attr,
+	&dev_attr_miimon.attr,
+	&dev_attr_primary.attr,
+	&dev_attr_use_carrier.attr,
+	&dev_attr_active_slave.attr,
+	&dev_attr_mii_status.attr,
+	&dev_attr_ad_aggregator.attr,
+	&dev_attr_ad_num_ports.attr,
+	&dev_attr_ad_actor_key.attr,
+	&dev_attr_ad_partner_key.attr,
+	&dev_attr_ad_partner_mac.attr,
 	NULL,
 };
 
@@ -1367,7 +1428,7 @@ int bond_create_sysfs(void)
 	if (!firstbond)
 		return -ENODEV;
 
-	netdev_class = firstbond->dev->class_dev.class;
+	netdev_class = firstbond->dev->dev.class;
 	if (!netdev_class)
 		return -ENODEV;
 
@@ -1395,13 +1456,13 @@ int bond_create_sysfs_entry(struct bonding *bond)
 	struct net_device *dev = bond->dev;
 	int err;
 
-	err = sysfs_create_group(&(dev->class_dev.kobj), &bonding_group);
+	err = sysfs_create_group(&(dev->dev.kobj), &bonding_group);
 	if (err) {
 		printk(KERN_EMERG "eek! didn't create group!\n");
 	}
 
 	if (expected_refcount < 1)
-		expected_refcount = atomic_read(&bond->dev->class_dev.kobj.kref.refcount);
+		expected_refcount = atomic_read(&bond->dev->dev.kobj.kref.refcount);
 
 	return err;
 }
@@ -1412,6 +1473,6 @@ void bond_destroy_sysfs_entry(struct bonding *bond)
 {
 	struct net_device *dev = bond->dev;
 
-	sysfs_remove_group(&(dev->class_dev.kobj), &bonding_group);
+	sysfs_remove_group(&(dev->dev.kobj), &bonding_group);
 }
 
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index 2194b56..0e9ba3c 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -1102,7 +1102,7 @@ static struct net_device * __init veth_probe_one(int vlan,
 	}
 
 	kobject_init(&port->kobject);
-	port->kobject.parent = &dev->class_dev.kobj;
+	port->kobject.parent = &dev->dev.kobj;
 	port->kobject.ktype  = &veth_port_ktype;
 	kobject_set_name(&port->kobject, "veth_port");
 	if (0 != kobject_add(&port->kobject))
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 25b559b..2af2045 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -27,8 +27,6 @@
 
 #include "macb.h"
 
-#define to_net_dev(class) container_of(class, struct net_device, class_dev)
-
 #define RX_BUFFER_SIZE		128
 #define RX_RING_SIZE		512
 #define RX_RING_BYTES		(sizeof(struct dma_desc) * RX_RING_SIZE)
@@ -945,10 +943,10 @@ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	return ret;
 }
 
-static ssize_t macb_mii_show(const struct class_device *cd, char *buf,
+static ssize_t macb_mii_show(const struct device *_dev, char *buf,
 			unsigned long addr)
 {
-	struct net_device *dev = to_net_dev(cd);
+	struct net_device *dev = to_net_dev(_dev);
 	struct macb *bp = netdev_priv(dev);
 	ssize_t ret = -EINVAL;
 
@@ -962,11 +960,13 @@ static ssize_t macb_mii_show(const struct class_device *cd, char *buf,
 }
 
 #define MII_ENTRY(name, addr)					\
-static ssize_t show_##name(struct class_device *cd, char *buf)	\
+static ssize_t show_##name(struct device *_dev,			\
+			   struct device_attribute *attr,	\
+			   char *buf)				\
 {								\
-	return macb_mii_show(cd, buf, addr);			\
+	return macb_mii_show(_dev, buf, addr);			\
 }								\
-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
 
 MII_ENTRY(bmcr, MII_BMCR);
 MII_ENTRY(bmsr, MII_BMSR);
@@ -977,13 +977,13 @@ MII_ENTRY(lpa, MII_LPA);
 MII_ENTRY(expansion, MII_EXPANSION);
 
 static struct attribute *macb_mii_attrs[] = {
-	&class_device_attr_bmcr.attr,
-	&class_device_attr_bmsr.attr,
-	&class_device_attr_physid1.attr,
-	&class_device_attr_physid2.attr,
-	&class_device_attr_advertise.attr,
-	&class_device_attr_lpa.attr,
-	&class_device_attr_expansion.attr,
+	&dev_attr_bmcr.attr,
+	&dev_attr_bmsr.attr,
+	&dev_attr_physid1.attr,
+	&dev_attr_physid2.attr,
+	&dev_attr_advertise.attr,
+	&dev_attr_lpa.attr,
+	&dev_attr_expansion.attr,
 	NULL,
 };
 
@@ -994,17 +994,17 @@ static struct attribute_group macb_mii_group = {
 
 static void macb_unregister_sysfs(struct net_device *net)
 {
-	struct class_device *class_dev = &net->class_dev;
+	struct device *_dev = &net->dev;
 
-	sysfs_remove_group(&class_dev->kobj, &macb_mii_group);
+	sysfs_remove_group(&_dev->kobj, &macb_mii_group);
 }
 
 static int macb_register_sysfs(struct net_device *net)
 {
-	struct class_device *class_dev = &net->class_dev;
+	struct device *_dev = &net->dev;
 	int ret;
 
-	ret = sysfs_create_group(&class_dev->kobj, &macb_mii_group);
+	ret = sysfs_create_group(&_dev->kobj, &macb_mii_group);
 	if (ret)
 		printk(KERN_WARNING
 		       "%s: sysfs mii attribute registration failed: %d\n",
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 43af614..c956141 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -1659,7 +1659,7 @@ smc911x_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
 	strncpy(info->driver, CARDNAME, sizeof(info->driver));
 	strncpy(info->version, version, sizeof(info->version));
-	strncpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info));
+	strncpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info));
 }
 
 static int smc911x_ethtool_nwayreset(struct net_device *dev)
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index e62a958..49f4b77 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -1712,7 +1712,7 @@ smc_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
 	strncpy(info->driver, CARDNAME, sizeof(info->driver));
 	strncpy(info->version, version, sizeof(info->version));
-	strncpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info));
+	strncpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info));
 }
 
 static int smc_ethtool_nwayreset(struct net_device *dev)
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 04c19ce..9077e6e 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -84,7 +84,7 @@ struct net_device * hostap_add_interface(struct local_info *local,
 	if (strchr(dev->name, '%'))
 		ret = dev_alloc_name(dev, dev->name);
 
-	SET_NETDEV_DEV(dev, mdev->class_dev.dev);
+	SET_NETDEV_DEV(dev, mdev->dev.parent);
 	if (ret >= 0)
 		ret = register_netdevice(dev);
 
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 936c888..656f216 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -4293,8 +4293,8 @@ static void orinoco_get_drvinfo(struct net_device *dev,
 	strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1);
 	strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1);
 	strncpy(info->fw_version, priv->fw_name, sizeof(info->fw_version) - 1);
-	if (dev->class_dev.dev)
-		strncpy(info->bus_info, dev->class_dev.dev->bus_id,
+	if (dev->dev.parent)
+		strncpy(info->bus_info, dev->dev.parent->bus_id,
 			sizeof(info->bus_info) - 1);
 	else
 		snprintf(info->bus_info, sizeof(info->bus_info) - 1,
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index d08ae8d..d1e5022 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -332,7 +332,7 @@ orinoco_cs_config(struct pcmcia_device *link)
 
 	/* Finally, report what we've done */
 	printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
-	       "0x%04x-0x%04x\n", dev->name, dev->class_dev.dev->bus_id,
+	       "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id,
 	       link->irq.AssignedIRQ, link->io.BasePort1,
 	       link->io.BasePort1 + link->io.NumPorts1 - 1);
 
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index cf2d148..af70460 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -806,7 +806,7 @@ spectrum_cs_config(struct pcmcia_device *link)
 
 	/* Finally, report what we've done */
 	printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
-	       "0x%04x-0x%04x\n", dev->name, dev->class_dev.dev->bus_id,
+	       "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id,
 	       link->irq.AssignedIRQ, link->io.BasePort1,
 	       link->io.BasePort1 + link->io.NumPorts1 - 1);
 
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index fea0d9d..2e37f50 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -529,10 +529,11 @@ struct net_device
 	struct net_bridge_port	*br_port;
 
 	/* class/net/name entry */
-	struct class_device	class_dev;
+	struct device		dev;
 	/* space for optional statistics and wireless sysfs groups */
 	struct attribute_group  *sysfs_groups[3];
 };
+#define to_net_dev(d) container_of(d, struct net_device, dev)
 
 #define	NETDEV_ALIGN		32
 #define	NETDEV_ALIGN_CONST	(NETDEV_ALIGN - 1)
@@ -548,7 +549,7 @@ static inline void *netdev_priv(struct net_device *dev)
 /* Set the sysfs physical device reference for the network logical device
  * if set prior to registration will cause a symlink during initialization.
  */
-#define SET_NETDEV_DEV(net, pdev)	((net)->class_dev.dev = (pdev))
+#define SET_NETDEV_DEV(net, pdev)	((net)->dev.parent = (pdev))
 
 struct packet_type {
 	__be16			type;	/* This is really htons(ether_type). */
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 55bb263..2b7c2c7 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -286,7 +286,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
 	kobject_init(&p->kobj);
 	kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR);
 	p->kobj.ktype = &brport_ktype;
-	p->kobj.parent = &(dev->class_dev.kobj);
+	p->kobj.parent = &(dev->dev.kobj);
 	p->kobj.kset = NULL;
 
 	return p;
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index de9d1a9..ce10464 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -21,18 +21,17 @@
 
 #include "br_private.h"
 
-#define to_class_dev(obj) container_of(obj,struct class_device,kobj)
-#define to_net_dev(class) container_of(class, struct net_device, class_dev)
+#define to_dev(obj)	container_of(obj, struct device, kobj)
 #define to_bridge(cd)	((struct net_bridge *)(to_net_dev(cd)->priv))
 
 /*
  * Common code for storing bridge parameters.
  */
-static ssize_t store_bridge_parm(struct class_device *cd,
+static ssize_t store_bridge_parm(struct device *d,
 				 const char *buf, size_t len,
 				 void (*set)(struct net_bridge *, unsigned long))
 {
-	struct net_bridge *br = to_bridge(cd);
+	struct net_bridge *br = to_bridge(d);
 	char *endp;
 	unsigned long val;
 
@@ -50,9 +49,10 @@ static ssize_t store_bridge_parm(struct class_device *cd,
 }
 
 
-static ssize_t show_forward_delay(struct class_device *cd, char *buf)
+static ssize_t show_forward_delay(struct device *d,
+				  struct device_attribute *attr, char *buf)
 {
-	struct net_bridge *br = to_bridge(cd);
+	struct net_bridge *br = to_bridge(d);
 	return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay));
 }
 
@@ -64,18 +64,20 @@ static void set_forward_delay(struct net_bridge *br, unsigned long val)
 		br->bridge_forward_delay = delay;
 }
 
-static ssize_t store_forward_delay(struct class_device *cd, const char *buf,
-				   size_t len)
+static ssize_t store_forward_delay(struct device *d,
+				   struct device_attribute *attr,
+				   const char *buf, size_t len)
 {
-	return store_bridge_parm(cd, buf, len, set_forward_delay);
+	return store_bridge_parm(d, buf, len, set_forward_delay);
 }
-static CLASS_DEVICE_ATTR(forward_delay, S_IRUGO | S_IWUSR,
-			 show_forward_delay, store_forward_delay);
+static DEVICE_ATTR(forward_delay, S_IRUGO | S_IWUSR,
+		   show_forward_delay, store_forward_delay);
 
-static ssize_t show_hello_time(struct class_device *cd, char *buf)
+static ssize_t show_hello_time(struct device *d, struct device_attribute *attr,
+			       char *buf)
 {
 	return sprintf(buf, "%lu\n",
-		       jiffies_to_clock_t(to_bridge(cd)->hello_time));
+		       jiffies_to_clock_t(to_bridge(d)->hello_time));
 }
 
 static void set_hello_time(struct net_bridge *br, unsigned long val)
@@ -86,19 +88,20 @@ static void set_hello_time(struct net_bridge *br, unsigned long val)
 		br->bridge_hello_time = t;
 }
 
-static ssize_t store_hello_time(struct class_device *cd, const char *buf,
+static ssize_t store_hello_time(struct device *d,
+				struct device_attribute *attr, const char *buf,
 				size_t len)
 {
-	return store_bridge_parm(cd, buf, len, set_hello_time);
+	return store_bridge_parm(d, buf, len, set_hello_time);
 }
+static DEVICE_ATTR(hello_time, S_IRUGO | S_IWUSR, show_hello_time,
+		   store_hello_time);
 
-static CLASS_DEVICE_ATTR(hello_time, S_IRUGO | S_IWUSR, show_hello_time,
-			 store_hello_time);
-
-static ssize_t show_max_age(struct class_device *cd, char *buf)
+static ssize_t show_max_age(struct device *d, struct device_attribute *attr,
+			    char *buf)
 {
 	return sprintf(buf, "%lu\n",
-		       jiffies_to_clock_t(to_bridge(cd)->max_age));
+		       jiffies_to_clock_t(to_bridge(d)->max_age));
 }
 
 static void set_max_age(struct net_bridge *br, unsigned long val)
@@ -109,18 +112,17 @@ static void set_max_age(struct net_bridge *br, unsigned long val)
 		br->bridge_max_age = t;
 }
 
-static ssize_t store_max_age(struct class_device *cd, const char *buf,
-				size_t len)
+static ssize_t store_max_age(struct device *d, struct device_attribute *attr,
+			     const char *buf, size_t len)
 {
-	return store_bridge_parm(cd, buf, len, set_max_age);
+	return store_bridge_parm(d, buf, len, set_max_age);
 }
+static DEVICE_ATTR(max_age, S_IRUGO | S_IWUSR, show_max_age, store_max_age);
 
-static CLASS_DEVICE_ATTR(max_age, S_IRUGO | S_IWUSR, show_max_age,
-			 store_max_age);
-
-static ssize_t show_ageing_time(struct class_device *cd, char *buf)
+static ssize_t show_ageing_time(struct device *d,
+				struct device_attribute *attr, char *buf)
 {
-	struct net_bridge *br = to_bridge(cd);
+	struct net_bridge *br = to_bridge(d);
 	return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->ageing_time));
 }
 
@@ -129,17 +131,19 @@ static void set_ageing_time(struct net_bridge *br, unsigned long val)
 	br->ageing_time = clock_t_to_jiffies(val);
 }
 
-static ssize_t store_ageing_time(struct class_device *cd, const char *buf,
-				 size_t len)
+static ssize_t store_ageing_time(struct device *d,
+				 struct device_attribute *attr,
+				 const char *buf, size_t len)
 {
-	return store_bridge_parm(cd, buf, len, set_ageing_time);
+	return store_bridge_parm(d, buf, len, set_ageing_time);
 }
+static DEVICE_ATTR(ageing_time, S_IRUGO | S_IWUSR, show_ageing_time,
+		   store_ageing_time);
 
-static CLASS_DEVICE_ATTR(ageing_time, S_IRUGO | S_IWUSR, show_ageing_time,
-			 store_ageing_time);
-static ssize_t show_stp_state(struct class_device *cd, char *buf)
+static ssize_t show_stp_state(struct device *d,
+			      struct device_attribute *attr, char *buf)
 {
-	struct net_bridge *br = to_bridge(cd);
+	struct net_bridge *br = to_bridge(d);
 	return sprintf(buf, "%d\n", br->stp_enabled);
 }
 
@@ -148,18 +152,19 @@ static void set_stp_state(struct net_bridge *br, unsigned long val)
 	br->stp_enabled = val;
 }
 
-static ssize_t store_stp_state(struct class_device *cd,
-			       const char *buf, size_t len)
+static ssize_t store_stp_state(struct device *d,
+			       struct device_attribute *attr, const char *buf,
+			       size_t len)
 {
-	return store_bridge_parm(cd, buf, len, set_stp_state);
+	return store_bridge_parm(d, buf, len, set_stp_state);
 }
+static DEVICE_ATTR(stp_state, S_IRUGO | S_IWUSR, show_stp_state,
+		   store_stp_state);
 
-static CLASS_DEVICE_ATTR(stp_state, S_IRUGO | S_IWUSR, show_stp_state,
-			 store_stp_state);
-
-static ssize_t show_priority(struct class_device *cd, char *buf)
+static ssize_t show_priority(struct device *d, struct device_attribute *attr,
+			     char *buf)
 {
-	struct net_bridge *br = to_bridge(cd);
+	struct net_bridge *br = to_bridge(d);
 	return sprintf(buf, "%d\n",
 		       (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]);
 }
@@ -169,92 +174,107 @@ static void set_priority(struct net_bridge *br, unsigned long val)
 	br_stp_set_bridge_priority(br, (u16) val);
 }
 
-static ssize_t store_priority(struct class_device *cd,
+static ssize_t store_priority(struct device *d, struct device_attribute *attr,
 			       const char *buf, size_t len)
 {
-	return store_bridge_parm(cd, buf, len, set_priority);
+	return store_bridge_parm(d, buf, len, set_priority);
 }
-static CLASS_DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, show_priority,
-			 store_priority);
+static DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, show_priority, store_priority);
 
-static ssize_t show_root_id(struct class_device *cd, char *buf)
+static ssize_t show_root_id(struct device *d, struct device_attribute *attr,
+			    char *buf)
 {
-	return br_show_bridge_id(buf, &to_bridge(cd)->designated_root);
+	return br_show_bridge_id(buf, &to_bridge(d)->designated_root);
 }
-static CLASS_DEVICE_ATTR(root_id, S_IRUGO, show_root_id, NULL);
+static DEVICE_ATTR(root_id, S_IRUGO, show_root_id, NULL);
 
-static ssize_t show_bridge_id(struct class_device *cd, char *buf)
+static ssize_t show_bridge_id(struct device *d, struct device_attribute *attr,
+			      char *buf)
 {
-	return br_show_bridge_id(buf, &to_bridge(cd)->bridge_id);
+	return br_show_bridge_id(buf, &to_bridge(d)->bridge_id);
 }
-static CLASS_DEVICE_ATTR(bridge_id, S_IRUGO, show_bridge_id, NULL);
+static DEVICE_ATTR(bridge_id, S_IRUGO, show_bridge_id, NULL);
 
-static ssize_t show_root_port(struct class_device *cd, char *buf)
+static ssize_t show_root_port(struct device *d, struct device_attribute *attr,
+			      char *buf)
 {
-	return sprintf(buf, "%d\n", to_bridge(cd)->root_port);
+	return sprintf(buf, "%d\n", to_bridge(d)->root_port);
 }
-static CLASS_DEVICE_ATTR(root_port, S_IRUGO, show_root_port, NULL);
+static DEVICE_ATTR(root_port, S_IRUGO, show_root_port, NULL);
 
-static ssize_t show_root_path_cost(struct class_device *cd, char *buf)
+static ssize_t show_root_path_cost(struct device *d,
+				   struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%d\n", to_bridge(cd)->root_path_cost);
+	return sprintf(buf, "%d\n", to_bridge(d)->root_path_cost);
 }
-static CLASS_DEVICE_ATTR(root_path_cost, S_IRUGO, show_root_path_cost, NULL);
+static DEVICE_ATTR(root_path_cost, S_IRUGO, show_root_path_cost, NULL);
 
-static ssize_t show_topology_change(struct class_device *cd, char *buf)
+static ssize_t show_topology_change(struct device *d,
+				    struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%d\n", to_bridge(cd)->topology_change);
+	return sprintf(buf, "%d\n", to_bridge(d)->topology_change);
 }
-static CLASS_DEVICE_ATTR(topology_change, S_IRUGO, show_topology_change, NULL);
+static DEVICE_ATTR(topology_change, S_IRUGO, show_topology_change, NULL);
 
-static ssize_t show_topology_change_detected(struct class_device *cd, char *buf)
+static ssize_t show_topology_change_detected(struct device *d,
+					     struct device_attribute *attr,
+					     char *buf)
 {
-	struct net_bridge *br = to_bridge(cd);
+	struct net_bridge *br = to_bridge(d);
 	return sprintf(buf, "%d\n", br->topology_change_detected);
 }
-static CLASS_DEVICE_ATTR(topology_change_detected, S_IRUGO, show_topology_change_detected, NULL);
+static DEVICE_ATTR(topology_change_detected, S_IRUGO,
+		   show_topology_change_detected, NULL);
 
-static ssize_t show_hello_timer(struct class_device *cd, char *buf)
+static ssize_t show_hello_timer(struct device *d,
+				struct device_attribute *attr, char *buf)
 {
-	struct net_bridge *br = to_bridge(cd);
+	struct net_bridge *br = to_bridge(d);
 	return sprintf(buf, "%ld\n", br_timer_value(&br->hello_timer));
 }
-static CLASS_DEVICE_ATTR(hello_timer, S_IRUGO, show_hello_timer, NULL);
+static DEVICE_ATTR(hello_timer, S_IRUGO, show_hello_timer, NULL);
 
-static ssize_t show_tcn_timer(struct class_device *cd, char *buf)
+static ssize_t show_tcn_timer(struct device *d, struct device_attribute *attr,
+			      char *buf)
 {
-	struct net_bridge *br = to_bridge(cd);
+	struct net_bridge *br = to_bridge(d);
 	return sprintf(buf, "%ld\n", br_timer_value(&br->tcn_timer));
 }
-static CLASS_DEVICE_ATTR(tcn_timer, S_IRUGO, show_tcn_timer, NULL);
+static DEVICE_ATTR(tcn_timer, S_IRUGO, show_tcn_timer, NULL);
 
-static ssize_t show_topology_change_timer(struct class_device *cd, char *buf)
+static ssize_t show_topology_change_timer(struct device *d,
+					  struct device_attribute *attr,
+					  char *buf)
 {
-	struct net_bridge *br = to_bridge(cd);
+	struct net_bridge *br = to_bridge(d);
 	return sprintf(buf, "%ld\n", br_timer_value(&br->topology_change_timer));
 }
-static CLASS_DEVICE_ATTR(topology_change_timer, S_IRUGO, show_topology_change_timer, NULL);
+static DEVICE_ATTR(topology_change_timer, S_IRUGO, show_topology_change_timer,
+		   NULL);
 
-static ssize_t show_gc_timer(struct class_device *cd, char *buf)
+static ssize_t show_gc_timer(struct device *d, struct device_attribute *attr,
+			     char *buf)
 {
-	struct net_bridge *br = to_bridge(cd);
+	struct net_bridge *br = to_bridge(d);
 	return sprintf(buf, "%ld\n", br_timer_value(&br->gc_timer));
 }
-static CLASS_DEVICE_ATTR(gc_timer, S_IRUGO, show_gc_timer, NULL);
+static DEVICE_ATTR(gc_timer, S_IRUGO, show_gc_timer, NULL);
 
-static ssize_t show_group_addr(struct class_device *cd, char *buf)
+static ssize_t show_group_addr(struct device *d,
+			       struct device_attribute *attr, char *buf)
 {
-	struct net_bridge *br = to_bridge(cd);
+	struct net_bridge *br = to_bridge(d);
 	return sprintf(buf, "%x:%x:%x:%x:%x:%x\n",
 		       br->group_addr[0], br->group_addr[1],
 		       br->group_addr[2], br->group_addr[3],
 		       br->group_addr[4], br->group_addr[5]);
 }
 
-static ssize_t store_group_addr(struct class_device *cd, const char *buf,
-				    size_t len)
+static ssize_t store_group_addr(struct device *d,
+				struct device_attribute *attr,
+				const char *buf, size_t len)
 {
-	struct net_bridge *br = to_bridge(cd);
+	struct net_bridge *br = to_bridge(d);
 	unsigned new_addr[6];
 	int i;
 
@@ -286,28 +306,28 @@ static ssize_t store_group_addr(struct class_device *cd, const char *buf,
 	return len;
 }
 
-static CLASS_DEVICE_ATTR(group_addr, S_IRUGO | S_IWUSR,
-			 show_group_addr, store_group_addr);
+static DEVICE_ATTR(group_addr, S_IRUGO | S_IWUSR,
+		   show_group_addr, store_group_addr);
 
 
 static struct attribute *bridge_attrs[] = {
-	&class_device_attr_forward_delay.attr,
-	&class_device_attr_hello_time.attr,
-	&class_device_attr_max_age.attr,
-	&class_device_attr_ageing_time.attr,
-	&class_device_attr_stp_state.attr,
-	&class_device_attr_priority.attr,
-	&class_device_attr_bridge_id.attr,
-	&class_device_attr_root_id.attr,
-	&class_device_attr_root_path_cost.attr,
-	&class_device_attr_root_port.attr,
-	&class_device_attr_topology_change.attr,
-	&class_device_attr_topology_change_detected.attr,
-	&class_device_attr_hello_timer.attr,
-	&class_device_attr_tcn_timer.attr,
-	&class_device_attr_topology_change_timer.attr,
-	&class_device_attr_gc_timer.attr,
-	&class_device_attr_group_addr.attr,
+	&dev_attr_forward_delay.attr,
+	&dev_attr_hello_time.attr,
+	&dev_attr_max_age.attr,
+	&dev_attr_ageing_time.attr,
+	&dev_attr_stp_state.attr,
+	&dev_attr_priority.attr,
+	&dev_attr_bridge_id.attr,
+	&dev_attr_root_id.attr,
+	&dev_attr_root_path_cost.attr,
+	&dev_attr_root_port.attr,
+	&dev_attr_topology_change.attr,
+	&dev_attr_topology_change_detected.attr,
+	&dev_attr_hello_timer.attr,
+	&dev_attr_tcn_timer.attr,
+	&dev_attr_topology_change_timer.attr,
+	&dev_attr_gc_timer.attr,
+	&dev_attr_group_addr.attr,
 	NULL
 };
 
@@ -325,8 +345,8 @@ static struct attribute_group bridge_group = {
 static ssize_t brforward_read(struct kobject *kobj, char *buf,
 			   loff_t off, size_t count)
 {
-	struct class_device *cdev = to_class_dev(kobj);
-	struct net_bridge *br = to_bridge(cdev);
+	struct device *dev = to_dev(kobj);
+	struct net_bridge *br = to_bridge(dev);
 	int n;
 
 	/* must read whole records */
@@ -363,7 +383,7 @@ static struct bin_attribute bridge_forward = {
  */
 int br_sysfs_addbr(struct net_device *dev)
 {
-	struct kobject *brobj = &dev->class_dev.kobj;
+	struct kobject *brobj = &dev->dev.kobj;
 	struct net_bridge *br = netdev_priv(dev);
 	int err;
 
@@ -395,9 +415,9 @@ int br_sysfs_addbr(struct net_device *dev)
 	}
 	return 0;
  out3:
-	sysfs_remove_bin_file(&dev->class_dev.kobj, &bridge_forward);
+	sysfs_remove_bin_file(&dev->dev.kobj, &bridge_forward);
  out2:
-	sysfs_remove_group(&dev->class_dev.kobj, &bridge_group);
+	sysfs_remove_group(&dev->dev.kobj, &bridge_group);
  out1:
 	return err;
 
@@ -405,7 +425,7 @@ int br_sysfs_addbr(struct net_device *dev)
 
 void br_sysfs_delbr(struct net_device *dev)
 {
-	struct kobject *kobj = &dev->class_dev.kobj;
+	struct kobject *kobj = &dev->dev.kobj;
 	struct net_bridge *br = netdev_priv(dev);
 
 	kobject_unregister(&br->ifobj);
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index c51c9e4..0bc2aef 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -211,7 +211,7 @@ int br_sysfs_addif(struct net_bridge_port *p)
 	struct brport_attribute **a;
 	int err;
 
-	err = sysfs_create_link(&p->kobj, &br->dev->class_dev.kobj, 
+	err = sysfs_create_link(&p->kobj, &br->dev->dev.kobj,
 				SYSFS_BRIDGE_PORT_LINK);
 	if (err)
 		goto out2;
diff --git a/net/core/dev.c b/net/core/dev.c
index e660cb5..455d589 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -751,7 +751,7 @@ int dev_change_name(struct net_device *dev, char *newname)
 	else
 		strlcpy(dev->name, newname, IFNAMSIZ);
 
-	err = class_device_rename(&dev->class_dev, dev->name);
+	err = device_rename(&dev->dev, dev->name);
 	if (!err) {
 		hlist_del(&dev->name_hlist);
 		hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name));
@@ -3221,8 +3221,8 @@ void free_netdev(struct net_device *dev)
 	BUG_ON(dev->reg_state != NETREG_UNREGISTERED);
 	dev->reg_state = NETREG_RELEASED;
 
-	/* will free via class release */
-	class_device_put(&dev->class_dev);
+	/* will free via device release */
+	put_device(&dev->dev);
 #else
 	kfree((char *)dev - dev->padded);
 #endif
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index f47f319..44db095 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -18,9 +18,6 @@
 #include <linux/wireless.h>
 #include <net/iw_handler.h>
 
-#define to_class_dev(obj) container_of(obj,struct class_device,kobj)
-#define to_net_dev(class) container_of(class, struct net_device, class_dev)
-
 static const char fmt_hex[] = "%#x\n";
 static const char fmt_long_hex[] = "%#lx\n";
 static const char fmt_dec[] = "%d\n";
@@ -32,10 +29,11 @@ static inline int dev_isalive(const struct net_device *dev)
 }
 
 /* use same locking rules as GIF* ioctl's */
-static ssize_t netdev_show(const struct class_device *cd, char *buf,
+static ssize_t netdev_show(const struct device *dev,
+			   struct device_attribute *attr, char *buf,
 			   ssize_t (*format)(const struct net_device *, char *))
 {
-	struct net_device *net = to_net_dev(cd);
+	struct net_device *net = to_net_dev(dev);
 	ssize_t ret = -EINVAL;
 
 	read_lock(&dev_base_lock);
@@ -52,14 +50,15 @@ static ssize_t format_##field(const struct net_device *net, char *buf)	\
 {									\
 	return sprintf(buf, format_string, net->field);			\
 }									\
-static ssize_t show_##field(struct class_device *cd, char *buf)		\
+static ssize_t show_##field(struct device *dev,				\
+			    struct device_attribute *attr, char *buf)	\
 {									\
-	return netdev_show(cd, buf, format_##field);			\
+	return netdev_show(dev, attr, buf, format_##field);		\
 }
 
 
 /* use same locking and permission rules as SIF* ioctl's */
-static ssize_t netdev_store(struct class_device *dev,
+static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
 			    const char *buf, size_t len,
 			    int (*set)(struct net_device *, unsigned long))
 {
@@ -104,7 +103,8 @@ static ssize_t format_addr(char *buf, const unsigned char *addr, int len)
 	return cp - buf;
 }
 
-static ssize_t show_address(struct class_device *dev, char *buf)
+static ssize_t show_address(struct device *dev, struct device_attribute *attr,
+			    char *buf)
 {
 	struct net_device *net = to_net_dev(dev);
 	ssize_t ret = -EINVAL;
@@ -116,7 +116,8 @@ static ssize_t show_address(struct class_device *dev, char *buf)
 	return ret;
 }
 
-static ssize_t show_broadcast(struct class_device *dev, char *buf)
+static ssize_t show_broadcast(struct device *dev,
+			    struct device_attribute *attr, char *buf)
 {
 	struct net_device *net = to_net_dev(dev);
 	if (dev_isalive(net))
@@ -124,7 +125,8 @@ static ssize_t show_broadcast(struct class_device *dev, char *buf)
 	return -EINVAL;
 }
 
-static ssize_t show_carrier(struct class_device *dev, char *buf)
+static ssize_t show_carrier(struct device *dev,
+			    struct device_attribute *attr, char *buf)
 {
 	struct net_device *netdev = to_net_dev(dev);
 	if (netif_running(netdev)) {
@@ -133,7 +135,8 @@ static ssize_t show_carrier(struct class_device *dev, char *buf)
 	return -EINVAL;
 }
 
-static ssize_t show_dormant(struct class_device *dev, char *buf)
+static ssize_t show_dormant(struct device *dev,
+			    struct device_attribute *attr, char *buf)
 {
 	struct net_device *netdev = to_net_dev(dev);
 
@@ -153,7 +156,8 @@ static const char *operstates[] = {
 	"up"
 };
 
-static ssize_t show_operstate(struct class_device *dev, char *buf)
+static ssize_t show_operstate(struct device *dev,
+			      struct device_attribute *attr, char *buf)
 {
 	const struct net_device *netdev = to_net_dev(dev);
 	unsigned char operstate;
@@ -178,9 +182,10 @@ static int change_mtu(struct net_device *net, unsigned long new_mtu)
 	return dev_set_mtu(net, (int) new_mtu);
 }
 
-static ssize_t store_mtu(struct class_device *dev, const char *buf, size_t len)
+static ssize_t store_mtu(struct device *dev, struct device_attribute *attr,
+			 const char *buf, size_t len)
 {
-	return netdev_store(dev, buf, len, change_mtu);
+	return netdev_store(dev, attr, buf, len, change_mtu);
 }
 
 NETDEVICE_SHOW(flags, fmt_hex);
@@ -190,9 +195,10 @@ static int change_flags(struct net_device *net, unsigned long new_flags)
 	return dev_change_flags(net, (unsigned) new_flags);
 }
 
-static ssize_t store_flags(struct class_device *dev, const char *buf, size_t len)
+static ssize_t store_flags(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t len)
 {
-	return netdev_store(dev, buf, len, change_flags);
+	return netdev_store(dev, attr, buf, len, change_flags);
 }
 
 NETDEVICE_SHOW(tx_queue_len, fmt_ulong);
@@ -203,9 +209,11 @@ static int change_tx_queue_len(struct net_device *net, unsigned long new_len)
 	return 0;
 }
 
-static ssize_t store_tx_queue_len(struct class_device *dev, const char *buf, size_t len)
+static ssize_t store_tx_queue_len(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t len)
 {
-	return netdev_store(dev, buf, len, change_tx_queue_len);
+	return netdev_store(dev, attr, buf, len, change_tx_queue_len);
 }
 
 NETDEVICE_SHOW(weight, fmt_dec);
@@ -216,12 +224,13 @@ static int change_weight(struct net_device *net, unsigned long new_weight)
 	return 0;
 }
 
-static ssize_t store_weight(struct class_device *dev, const char *buf, size_t len)
+static ssize_t store_weight(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t len)
 {
-	return netdev_store(dev, buf, len, change_weight);
+	return netdev_store(dev, attr, buf, len, change_weight);
 }
 
-static struct class_device_attribute net_class_attributes[] = {
+static struct device_attribute net_class_attributes[] = {
 	__ATTR(addr_len, S_IRUGO, show_addr_len, NULL),
 	__ATTR(iflink, S_IRUGO, show_iflink, NULL),
 	__ATTR(ifindex, S_IRUGO, show_ifindex, NULL),
@@ -242,10 +251,11 @@ static struct class_device_attribute net_class_attributes[] = {
 };
 
 /* Show a given an attribute in the statistics group */
-static ssize_t netstat_show(const struct class_device *cd, char *buf, 
+static ssize_t netstat_show(const struct device *d,
+			    struct device_attribute *attr, char *buf,
 			    unsigned long offset)
 {
-	struct net_device *dev = to_net_dev(cd);
+	struct net_device *dev = to_net_dev(d);
 	struct net_device_stats *stats;
 	ssize_t ret = -EINVAL;
 
@@ -265,12 +275,13 @@ static ssize_t netstat_show(const struct class_device *cd, char *buf,
 
 /* generate a read-only statistics attribute */
 #define NETSTAT_ENTRY(name)						\
-static ssize_t show_##name(struct class_device *cd, char *buf) 		\
+static ssize_t show_##name(struct device *d,				\
+			   struct device_attribute *attr, char *buf) 	\
 {									\
-	return netstat_show(cd, buf, 					\
+	return netstat_show(d, attr, buf,				\
 			    offsetof(struct net_device_stats, name));	\
 }									\
-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
 
 NETSTAT_ENTRY(rx_packets);
 NETSTAT_ENTRY(tx_packets);
@@ -297,29 +308,29 @@ NETSTAT_ENTRY(rx_compressed);
 NETSTAT_ENTRY(tx_compressed);
 
 static struct attribute *netstat_attrs[] = {
-	&class_device_attr_rx_packets.attr,
-	&class_device_attr_tx_packets.attr,
-	&class_device_attr_rx_bytes.attr,
-	&class_device_attr_tx_bytes.attr,
-	&class_device_attr_rx_errors.attr,
-	&class_device_attr_tx_errors.attr,
-	&class_device_attr_rx_dropped.attr,
-	&class_device_attr_tx_dropped.attr,
-	&class_device_attr_multicast.attr,
-	&class_device_attr_collisions.attr,
-	&class_device_attr_rx_length_errors.attr,
-	&class_device_attr_rx_over_errors.attr,
-	&class_device_attr_rx_crc_errors.attr,
-	&class_device_attr_rx_frame_errors.attr,
-	&class_device_attr_rx_fifo_errors.attr,
-	&class_device_attr_rx_missed_errors.attr,
-	&class_device_attr_tx_aborted_errors.attr,
-	&class_device_attr_tx_carrier_errors.attr,
-	&class_device_attr_tx_fifo_errors.attr,
-	&class_device_attr_tx_heartbeat_errors.attr,
-	&class_device_attr_tx_window_errors.attr,
-	&class_device_attr_rx_compressed.attr,
-	&class_device_attr_tx_compressed.attr,
+	&dev_attr_rx_packets.attr,
+	&dev_attr_tx_packets.attr,
+	&dev_attr_rx_bytes.attr,
+	&dev_attr_tx_bytes.attr,
+	&dev_attr_rx_errors.attr,
+	&dev_attr_tx_errors.attr,
+	&dev_attr_rx_dropped.attr,
+	&dev_attr_tx_dropped.attr,
+	&dev_attr_multicast.attr,
+	&dev_attr_collisions.attr,
+	&dev_attr_rx_length_errors.attr,
+	&dev_attr_rx_over_errors.attr,
+	&dev_attr_rx_crc_errors.attr,
+	&dev_attr_rx_frame_errors.attr,
+	&dev_attr_rx_fifo_errors.attr,
+	&dev_attr_rx_missed_errors.attr,
+	&dev_attr_tx_aborted_errors.attr,
+	&dev_attr_tx_carrier_errors.attr,
+	&dev_attr_tx_fifo_errors.attr,
+	&dev_attr_tx_heartbeat_errors.attr,
+	&dev_attr_tx_window_errors.attr,
+	&dev_attr_rx_compressed.attr,
+	&dev_attr_tx_compressed.attr,
 	NULL
 };
 
@@ -331,11 +342,11 @@ static struct attribute_group netstat_group = {
 
 #ifdef WIRELESS_EXT
 /* helper function that does all the locking etc for wireless stats */
-static ssize_t wireless_show(struct class_device *cd, char *buf,
+static ssize_t wireless_show(struct device *d, char *buf,
 			     ssize_t (*format)(const struct iw_statistics *,
 					       char *))
 {
-	struct net_device *dev = to_net_dev(cd);
+	struct net_device *dev = to_net_dev(d);
 	const struct iw_statistics *iw = NULL;
 	ssize_t ret = -EINVAL;
 	
@@ -358,11 +369,12 @@ static ssize_t format_iw_##name(const struct iw_statistics *iw, char *buf) \
 {									\
 	return sprintf(buf, format_string, iw->field);			\
 }									\
-static ssize_t show_iw_##name(struct class_device *cd, char *buf)	\
+static ssize_t show_iw_##name(struct device *d,				\
+			      struct device_attribute *attr, char *buf)	\
 {									\
-	return wireless_show(cd, buf, format_iw_##name);		\
+	return wireless_show(d, buf, format_iw_##name);			\
 }									\
-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_iw_##name, NULL)
+static DEVICE_ATTR(name, S_IRUGO, show_iw_##name, NULL)
 
 WIRELESS_SHOW(status, status, fmt_hex);
 WIRELESS_SHOW(link, qual.qual, fmt_dec);
@@ -376,16 +388,16 @@ WIRELESS_SHOW(retries, discard.retries, fmt_dec);
 WIRELESS_SHOW(beacon, miss.beacon, fmt_dec);
 
 static struct attribute *wireless_attrs[] = {
-	&class_device_attr_status.attr,
-	&class_device_attr_link.attr,
-	&class_device_attr_level.attr,
-	&class_device_attr_noise.attr,
-	&class_device_attr_nwid.attr,
-	&class_device_attr_crypt.attr,
-	&class_device_attr_fragment.attr,
-	&class_device_attr_retries.attr,
-	&class_device_attr_misc.attr,
-	&class_device_attr_beacon.attr,
+	&dev_attr_status.attr,
+	&dev_attr_link.attr,
+	&dev_attr_level.attr,
+	&dev_attr_noise.attr,
+	&dev_attr_nwid.attr,
+	&dev_attr_crypt.attr,
+	&dev_attr_fragment.attr,
+	&dev_attr_retries.attr,
+	&dev_attr_misc.attr,
+	&dev_attr_beacon.attr,
 	NULL
 };
 
@@ -396,10 +408,10 @@ static struct attribute_group wireless_group = {
 #endif
 
 #ifdef CONFIG_HOTPLUG
-static int netdev_uevent(struct class_device *cd, char **envp,
+static int netdev_uevent(struct device *d, char **envp,
 			 int num_envp, char *buf, int size)
 {
-	struct net_device *dev = to_net_dev(cd);
+	struct net_device *dev = to_net_dev(d);
 	int i = 0;
 	int n;
 
@@ -419,12 +431,11 @@ static int netdev_uevent(struct class_device *cd, char **envp,
 
 /*
  *	netdev_release -- destroy and free a dead device. 
- *	Called when last reference to class_device kobject is gone.
+ *	Called when last reference to device kobject is gone.
  */
-static void netdev_release(struct class_device *cd)
+static void netdev_release(struct device *d)
 {
-	struct net_device *dev 
-		= container_of(cd, struct net_device, class_dev);
+	struct net_device *dev = to_net_dev(d);
 
 	BUG_ON(dev->reg_state != NETREG_RELEASED);
 
@@ -433,31 +444,31 @@ static void netdev_release(struct class_device *cd)
 
 static struct class net_class = {
 	.name = "net",
-	.release = netdev_release,
-	.class_dev_attrs = net_class_attributes,
+	.dev_release = netdev_release,
+	.dev_attrs = net_class_attributes,
 #ifdef CONFIG_HOTPLUG
-	.uevent = netdev_uevent,
+	.dev_uevent = netdev_uevent,
 #endif
 };
 
 void netdev_unregister_sysfs(struct net_device * net)
 {
-	class_device_del(&(net->class_dev));
+	device_del(&(net->dev));
 }
 
 /* Create sysfs entries for network device. */
 int netdev_register_sysfs(struct net_device *net)
 {
-	struct class_device *class_dev = &(net->class_dev);
+	struct device *dev = &(net->dev);
 	struct attribute_group **groups = net->sysfs_groups;
 
-	class_device_initialize(class_dev);
-	class_dev->class = &net_class;
-	class_dev->class_data = net;
-	class_dev->groups = groups;
+	device_initialize(dev);
+	dev->class = &net_class;
+	dev->platform_data = net;
+	dev->groups = groups;
 
 	BUILD_BUG_ON(BUS_ID_SIZE < IFNAMSIZ);
-	strlcpy(class_dev->class_id, net->name, BUS_ID_SIZE);
+	strlcpy(dev->bus_id, net->name, BUS_ID_SIZE);
 
 	if (net->get_stats)
 		*groups++ = &netstat_group;
@@ -467,7 +478,7 @@ int netdev_register_sysfs(struct net_device *net)
 		*groups++ = &wireless_group;
 #endif
 
-	return class_device_add(class_dev);
+	return device_add(dev);
 }
 
 int netdev_sysfs_init(void)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index de7801d..f3404ae 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -268,7 +268,7 @@ nodata:
 struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
 		unsigned int length, gfp_t gfp_mask)
 {
-	int node = dev->class_dev.dev ? dev_to_node(dev->class_dev.dev) : -1;
+	int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
 	struct sk_buff *skb;
 
  	skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, node);
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 5/28] driver core: Remove device_is_registered() in device_move().
  2007-02-08  0:29       ` [PATCH 4/28] Network: convert network devices to use struct device instead of class_device Greg KH
@ 2007-02-08  0:29         ` Greg KH
  2007-02-08  0:29           ` [PATCH 6/28] driver core: Allow device_move(dev, NULL) Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:29 UTC (permalink / raw)
  To: linux-kernel; +Cc: Cornelia Huck, Greg Kroah-Hartman

From: Cornelia Huck <cornelia.huck@de.ibm.com>

device_is_registered() will always be false for a device with no bus. Remove
this check and trust the caller to know what they're doing.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/base/core.c |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/drivers/base/core.c b/drivers/base/core.c
index 67b79a7..36eedfd 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1004,10 +1004,6 @@ int device_move(struct device *dev, struct device *new_parent)
 	if (!dev)
 		return -EINVAL;
 
-	if (!device_is_registered(dev)) {
-		error = -EINVAL;
-		goto out;
-	}
 	new_parent = get_device(new_parent);
 	if (!new_parent) {
 		error = -EINVAL;
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 6/28] driver core: Allow device_move(dev, NULL).
  2007-02-08  0:29         ` [PATCH 5/28] driver core: Remove device_is_registered() in device_move() Greg KH
@ 2007-02-08  0:29           ` Greg KH
  2007-02-08  0:29             ` [PATCH 7/28] MODULES: add the module name for built in kernel drivers Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:29 UTC (permalink / raw)
  To: linux-kernel; +Cc: Cornelia Huck, Greg Kroah-Hartman

From: Cornelia Huck <cornelia.huck@de.ibm.com>

If we allow NULL as the new parent in device_move(), we need to make sure
that the device is placed into the same place as it would if it was
newly registered:

- Consider the device virtual tree. In order to be able to reuse code,
  setup_parent() has been tweaked a bit.
- kobject_move() can fall back to the kset's kobject.
- sysfs_move_dir() uses the sysfs root dir as fallback.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/base/core.c |   76 +++++++++++++++++++++++++++++++-------------------
 fs/sysfs/dir.c      |    6 +---
 lib/kobject.c       |    6 ++--
 3 files changed, 52 insertions(+), 36 deletions(-)

diff --git a/drivers/base/core.c b/drivers/base/core.c
index 36eedfd..c60114d 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -390,22 +390,23 @@ void device_initialize(struct device *dev)
 }
 
 #ifdef CONFIG_SYSFS_DEPRECATED
-static int setup_parent(struct device *dev, struct device *parent)
+static struct kobject * get_device_parent(struct device *dev,
+					  struct device *parent)
 {
 	/* Set the parent to the class, not the parent device */
 	/* this keeps sysfs from having a symlink to make old udevs happy */
 	if (dev->class)
-		dev->kobj.parent = &dev->class->subsys.kset.kobj;
+		return &dev->class->subsys.kset.kobj;
 	else if (parent)
-		dev->kobj.parent = &parent->kobj;
+		return &parent->kobj;
 
-	return 0;
+	return NULL;
 }
 #else
-static int virtual_device_parent(struct device *dev)
+static struct kobject * virtual_device_parent(struct device *dev)
 {
 	if (!dev->class)
-		return -ENODEV;
+		return ERR_PTR(-ENODEV);
 
 	if (!dev->class->virtual_dir) {
 		static struct kobject *virtual_dir = NULL;
@@ -415,25 +416,31 @@ static int virtual_device_parent(struct device *dev)
 		dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name);
 	}
 
-	dev->kobj.parent = dev->class->virtual_dir;
-	return 0;
+	return dev->class->virtual_dir;
 }
 
-static int setup_parent(struct device *dev, struct device *parent)
+static struct kobject * get_device_parent(struct device *dev,
+					  struct device *parent)
 {
-	int error;
-
 	/* if this is a class device, and has no parent, create one */
 	if ((dev->class) && (parent == NULL)) {
-		error = virtual_device_parent(dev);
-		if (error)
-			return error;
+		return virtual_device_parent(dev);
 	} else if (parent)
-		dev->kobj.parent = &parent->kobj;
+		return &parent->kobj;
+	return NULL;
+}
 
+#endif
+static int setup_parent(struct device *dev, struct device *parent)
+{
+	struct kobject *kobj;
+	kobj = get_device_parent(dev, parent);
+	if (IS_ERR(kobj))
+		return PTR_ERR(kobj);
+	if (kobj)
+		dev->kobj.parent = kobj;
 	return 0;
 }
-#endif
 
 /**
  *	device_add - add device to device hierarchy.
@@ -976,12 +983,18 @@ static int device_move_class_links(struct device *dev,
 		sysfs_remove_link(&dev->kobj, "device");
 		sysfs_remove_link(&old_parent->kobj, class_name);
 	}
-	error = sysfs_create_link(&dev->kobj, &new_parent->kobj, "device");
-	if (error)
-		goto out;
-	error = sysfs_create_link(&new_parent->kobj, &dev->kobj, class_name);
-	if (error)
-		sysfs_remove_link(&dev->kobj, "device");
+	if (new_parent) {
+		error = sysfs_create_link(&dev->kobj, &new_parent->kobj,
+					  "device");
+		if (error)
+			goto out;
+		error = sysfs_create_link(&new_parent->kobj, &dev->kobj,
+					  class_name);
+		if (error)
+			sysfs_remove_link(&dev->kobj, "device");
+	}
+	else
+		error = 0;
 out:
 	kfree(class_name);
 	return error;
@@ -993,25 +1006,28 @@ out:
 /**
  * device_move - moves a device to a new parent
  * @dev: the pointer to the struct device to be moved
- * @new_parent: the new parent of the device
+ * @new_parent: the new parent of the device (can by NULL)
  */
 int device_move(struct device *dev, struct device *new_parent)
 {
 	int error;
 	struct device *old_parent;
+	struct kobject *new_parent_kobj;
 
 	dev = get_device(dev);
 	if (!dev)
 		return -EINVAL;
 
 	new_parent = get_device(new_parent);
-	if (!new_parent) {
-		error = -EINVAL;
+	new_parent_kobj = get_device_parent (dev, new_parent);
+	if (IS_ERR(new_parent_kobj)) {
+		error = PTR_ERR(new_parent_kobj);
+		put_device(new_parent);
 		goto out;
 	}
 	pr_debug("DEVICE: moving '%s' to '%s'\n", dev->bus_id,
-		new_parent->bus_id);
-	error = kobject_move(&dev->kobj, &new_parent->kobj);
+		 new_parent ? new_parent->bus_id : "<NULL>");
+	error = kobject_move(&dev->kobj, new_parent_kobj);
 	if (error) {
 		put_device(new_parent);
 		goto out;
@@ -1020,7 +1036,8 @@ int device_move(struct device *dev, struct device *new_parent)
 	dev->parent = new_parent;
 	if (old_parent)
 		klist_remove(&dev->knode_parent);
-	klist_add_tail(&dev->knode_parent, &new_parent->klist_children);
+	if (new_parent)
+		klist_add_tail(&dev->knode_parent, &new_parent->klist_children);
 	if (!dev->class)
 		goto out_put;
 	error = device_move_class_links(dev, old_parent, new_parent);
@@ -1028,7 +1045,8 @@ int device_move(struct device *dev, struct device *new_parent)
 		/* We ignore errors on cleanup since we're hosed anyway... */
 		device_move_class_links(dev, new_parent, old_parent);
 		if (!kobject_move(&dev->kobj, &old_parent->kobj)) {
-			klist_remove(&dev->knode_parent);
+			if (new_parent)
+				klist_remove(&dev->knode_parent);
 			if (old_parent)
 				klist_add_tail(&dev->knode_parent,
 					       &old_parent->klist_children);
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 511edef..2bab1b4 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -378,12 +378,10 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent)
 	struct sysfs_dirent *new_parent_sd, *sd;
 	int error;
 
-	if (!new_parent)
-		return -EINVAL;
-
 	old_parent_dentry = kobj->parent ?
 		kobj->parent->dentry : sysfs_mount->mnt_sb->s_root;
-	new_parent_dentry = new_parent->dentry;
+	new_parent_dentry = new_parent ?
+		new_parent->dentry : sysfs_mount->mnt_sb->s_root;
 
 again:
 	mutex_lock(&old_parent_dentry->d_inode->i_mutex);
diff --git a/lib/kobject.c b/lib/kobject.c
index 9aed594..c033dc8 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -314,7 +314,7 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
 /**
  *	kobject_move - move object to another parent
  *	@kobj:	object in question.
- *	@new_parent: object's new parent
+ *	@new_parent: object's new parent (can be NULL)
  */
 
 int kobject_move(struct kobject *kobj, struct kobject *new_parent)
@@ -330,8 +330,8 @@ int kobject_move(struct kobject *kobj, struct kobject *new_parent)
 		return -EINVAL;
 	new_parent = kobject_get(new_parent);
 	if (!new_parent) {
-		error = -EINVAL;
-		goto out;
+		if (kobj->kset)
+			new_parent = kobject_get(&kobj->kset->kobj);
 	}
 	/* old object path */
 	devpath = kobject_get_path(kobj, GFP_KERNEL);
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 7/28] MODULES: add the module name for built in kernel drivers
  2007-02-08  0:29           ` [PATCH 6/28] driver core: Allow device_move(dev, NULL) Greg KH
@ 2007-02-08  0:29             ` Greg KH
  2007-02-08  0:29               ` [PATCH 8/28] Modules: only add drivers/ direcory if needed Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:29 UTC (permalink / raw)
  To: linux-kernel; +Cc: Kay Sievers, Greg Kroah-Hartman

From: Kay Sievers <kay.sievers@vrfy.org>

Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 include/linux/device.h |    1 +
 include/linux/module.h |    2 +-
 kernel/module.c        |   33 ++++++++++++++++++++++++---------
 kernel/params.c        |   12 +++++-------
 4 files changed, 31 insertions(+), 17 deletions(-)

diff --git a/include/linux/device.h b/include/linux/device.h
index f44247f..da72219 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -126,6 +126,7 @@ struct device_driver {
 	struct klist_node	knode_bus;
 
 	struct module		* owner;
+	const char 		* mod_name;	/* used for built-in modules */
 
 	int	(*probe)	(struct device * dev);
 	int	(*remove)	(struct device * dev);
diff --git a/include/linux/module.h b/include/linux/module.h
index 10f771a..90dc254 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -58,6 +58,7 @@ struct module_kobject
 {
 	struct kobject kobj;
 	struct module *mod;
+	struct kobject *drivers_dir;
 };
 
 /* These are either module local, or the kernel's dummy ones. */
@@ -263,7 +264,6 @@ struct module
 	struct module_attribute *modinfo_attrs;
 	const char *version;
 	const char *srcversion;
-	struct kobject *drivers_dir;
 
 	/* Exported symbols */
 	const struct kernel_symbol *syms;
diff --git a/kernel/module.c b/kernel/module.c
index d0f2260..0f4489a 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1131,8 +1131,8 @@ static int mod_sysfs_setup(struct module *mod,
 	if (err)
 		goto out;
 
-	mod->drivers_dir = kobject_add_dir(&mod->mkobj.kobj, "drivers");
-	if (!mod->drivers_dir) {
+	mod->mkobj.drivers_dir = kobject_add_dir(&mod->mkobj.kobj, "drivers");
+	if (!mod->mkobj.drivers_dir) {
 		err = -ENOMEM;
 		goto out_unreg;
 	}
@@ -1151,7 +1151,7 @@ static int mod_sysfs_setup(struct module *mod,
 out_unreg_param:
 	module_param_sysfs_remove(mod);
 out_unreg_drivers:
-	kobject_unregister(mod->drivers_dir);
+	kobject_unregister(mod->mkobj.drivers_dir);
 out_unreg:
 	kobject_del(&mod->mkobj.kobj);
 	kobject_put(&mod->mkobj.kobj);
@@ -1163,7 +1163,7 @@ static void mod_kobject_remove(struct module *mod)
 {
 	module_remove_modinfo_attrs(mod);
 	module_param_sysfs_remove(mod);
-	kobject_unregister(mod->drivers_dir);
+	kobject_unregister(mod->mkobj.drivers_dir);
 
 	kobject_unregister(&mod->mkobj.kobj);
 }
@@ -2344,15 +2344,30 @@ void module_add_driver(struct module *mod, struct device_driver *drv)
 {
 	char *driver_name;
 	int no_warn;
+	struct module_kobject *mk = NULL;
 
-	if (!mod || !drv)
+	if (!drv)
+		return;
+
+	if (mod)
+		mk = &mod->mkobj;
+	else if (drv->mod_name) {
+		struct kobject *mkobj;
+
+		/* Lookup built-in module entry in /sys/modules */
+		mkobj = kset_find_obj(&module_subsys.kset, drv->mod_name);
+		if (mkobj)
+			mk = container_of(mkobj, struct module_kobject, kobj);
+	}
+
+	if (!mk)
 		return;
 
 	/* Don't check return codes; these calls are idempotent */
-	no_warn = sysfs_create_link(&drv->kobj, &mod->mkobj.kobj, "module");
+	no_warn = sysfs_create_link(&drv->kobj, &mk->kobj, "module");
 	driver_name = make_driver_name(drv);
 	if (driver_name) {
-		no_warn = sysfs_create_link(mod->drivers_dir, &drv->kobj,
+		no_warn = sysfs_create_link(mk->drivers_dir, &drv->kobj,
 					    driver_name);
 		kfree(driver_name);
 	}
@@ -2367,10 +2382,10 @@ void module_remove_driver(struct device_driver *drv)
 		return;
 
 	sysfs_remove_link(&drv->kobj, "module");
-	if (drv->owner && drv->owner->drivers_dir) {
+	if (drv->owner && drv->owner->mkobj.drivers_dir) {
 		driver_name = make_driver_name(drv);
 		if (driver_name) {
-			sysfs_remove_link(drv->owner->drivers_dir,
+			sysfs_remove_link(drv->owner->mkobj.drivers_dir,
 					  driver_name);
 			kfree(driver_name);
 		}
diff --git a/kernel/params.c b/kernel/params.c
index 718945d..737b7c5 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -561,14 +561,12 @@ static void __init kernel_param_sysfs_setup(const char *name,
 	mk->mod = THIS_MODULE;
 	kobj_set_kset_s(mk, module_subsys);
 	kobject_set_name(&mk->kobj, name);
-	ret = kobject_register(&mk->kobj);
+	kobject_init(&mk->kobj);
+	ret = kobject_add(&mk->kobj);
 	BUG_ON(ret < 0);
-
-	/* no need to keep the kobject if no parameter is exported */
-	if (!param_sysfs_setup(mk, kparam, num_params, name_skip)) {
-		kobject_unregister(&mk->kobj);
-		kfree(mk);
-	}
+	param_sysfs_setup(mk, kparam, num_params, name_skip);
+	mk->drivers_dir = kobject_add_dir(&mk->kobj, "drivers");
+	kobject_uevent(&mk->kobj, KOBJ_ADD);
 }
 
 /*
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 8/28] Modules: only add drivers/ direcory if needed
  2007-02-08  0:29             ` [PATCH 7/28] MODULES: add the module name for built in kernel drivers Greg KH
@ 2007-02-08  0:29               ` Greg KH
  2007-02-08  0:29                 ` [PATCH 9/28] PCI: add the sysfs driver name to all modules Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:29 UTC (permalink / raw)
  To: linux-kernel; +Cc: Greg Kroah-Hartman

From: Greg Kroah-Hartman <gregkh@suse.de>

This changes the module core to only create the drivers/ directory if we
are going to put something in it.

Cc: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 kernel/module.c |   20 +++++++++++---------
 kernel/params.c |    1 -
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/kernel/module.c b/kernel/module.c
index 0f4489a..9de4209 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1131,12 +1131,6 @@ static int mod_sysfs_setup(struct module *mod,
 	if (err)
 		goto out;
 
-	mod->mkobj.drivers_dir = kobject_add_dir(&mod->mkobj.kobj, "drivers");
-	if (!mod->mkobj.drivers_dir) {
-		err = -ENOMEM;
-		goto out_unreg;
-	}
-
 	err = module_param_sysfs_setup(mod, kparam, num_params);
 	if (err)
 		goto out_unreg_drivers;
@@ -1151,8 +1145,6 @@ static int mod_sysfs_setup(struct module *mod,
 out_unreg_param:
 	module_param_sysfs_remove(mod);
 out_unreg_drivers:
-	kobject_unregister(mod->mkobj.drivers_dir);
-out_unreg:
 	kobject_del(&mod->mkobj.kobj);
 	kobject_put(&mod->mkobj.kobj);
 out:
@@ -1163,7 +1155,8 @@ static void mod_kobject_remove(struct module *mod)
 {
 	module_remove_modinfo_attrs(mod);
 	module_param_sysfs_remove(mod);
-	kobject_unregister(mod->mkobj.drivers_dir);
+	if (mod->mkobj.drivers_dir)
+		kobject_unregister(mod->mkobj.drivers_dir);
 
 	kobject_unregister(&mod->mkobj.kobj);
 }
@@ -2340,6 +2333,14 @@ static char *make_driver_name(struct device_driver *drv)
 	return driver_name;
 }
 
+static void module_create_drivers_dir(struct module_kobject *mk)
+{
+	if (!mk || mk->drivers_dir)
+		return;
+
+	mk->drivers_dir = kobject_add_dir(&mk->kobj, "drivers");
+}
+
 void module_add_driver(struct module *mod, struct device_driver *drv)
 {
 	char *driver_name;
@@ -2367,6 +2368,7 @@ void module_add_driver(struct module *mod, struct device_driver *drv)
 	no_warn = sysfs_create_link(&drv->kobj, &mk->kobj, "module");
 	driver_name = make_driver_name(drv);
 	if (driver_name) {
+		module_create_drivers_dir(mk);
 		no_warn = sysfs_create_link(mk->drivers_dir, &drv->kobj,
 					    driver_name);
 		kfree(driver_name);
diff --git a/kernel/params.c b/kernel/params.c
index 737b7c5..cbaac85 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -565,7 +565,6 @@ static void __init kernel_param_sysfs_setup(const char *name,
 	ret = kobject_add(&mk->kobj);
 	BUG_ON(ret < 0);
 	param_sysfs_setup(mk, kparam, num_params, name_skip);
-	mk->drivers_dir = kobject_add_dir(&mk->kobj, "drivers");
 	kobject_uevent(&mk->kobj, KOBJ_ADD);
 }
 
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 9/28] PCI: add the sysfs driver name to all modules
  2007-02-08  0:29               ` [PATCH 8/28] Modules: only add drivers/ direcory if needed Greg KH
@ 2007-02-08  0:29                 ` Greg KH
  2007-02-08  0:29                   ` [PATCH 10/28] SERIO: " Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:29 UTC (permalink / raw)
  To: linux-kernel; +Cc: Greg Kroah-Hartman

From: Greg Kroah-Hartman <gregkh@suse.de>

This adds the module name to all PCI drivers, if they are built into the
kernel or not.  It will show up in /sys/modules/MODULE_NAME/drivers/

It also fixes up the IDE core, which was calling __pci_register_driver()
directly.

Cc: Kay Sievers <kay.sievers@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/ide/setup-pci.c  |    7 ++++---
 drivers/pci/pci-driver.c |    4 +++-
 include/linux/ide.h      |    4 ++--
 include/linux/pci.h      |    5 +++--
 4 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 695e239..a52c80f 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -783,10 +783,11 @@ static LIST_HEAD(ide_pci_drivers);
  *	Returns are the same as for pci_register_driver
  */
 
-int __ide_pci_register_driver(struct pci_driver *driver, struct module *module)
+int __ide_pci_register_driver(struct pci_driver *driver, struct module *module,
+			      const char *mod_name)
 {
 	if(!pre_init)
-		return __pci_register_driver(driver, module);
+		return __pci_register_driver(driver, module, mod_name);
 	driver->driver.owner = module;
 	list_add_tail(&driver->node, &ide_pci_drivers);
 	return 0;
@@ -862,6 +863,6 @@ void __init ide_scan_pcibus (int scan_direction)
 	{
 		list_del(l);
 		d = list_entry(l, struct pci_driver, node);
-		__pci_register_driver(d, d->driver.owner);
+		__pci_register_driver(d, d->driver.owner, d->driver.mod_name);
 	}
 }
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 92d5e8d..3587668 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -422,7 +422,8 @@ static struct kobj_type pci_driver_kobj_type = {
  * If no error occurred, the driver remains registered even if 
  * no device was claimed during registration.
  */
-int __pci_register_driver(struct pci_driver *drv, struct module *owner)
+int __pci_register_driver(struct pci_driver *drv, struct module *owner,
+			  const char *mod_name)
 {
 	int error;
 
@@ -430,6 +431,7 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner)
 	drv->driver.name = drv->name;
 	drv->driver.bus = &pci_bus_type;
 	drv->driver.owner = owner;
+	drv->driver.mod_name = mod_name;
 	drv->driver.kobj.ktype = &pci_driver_kobj_type;
 
 	if (pci_multithread_probe)
diff --git a/include/linux/ide.h b/include/linux/ide.h
index e26a039..827688f 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1192,8 +1192,8 @@ void ide_init_disk(struct gendisk *, ide_drive_t *);
 extern int ideprobe_init(void);
 
 extern void ide_scan_pcibus(int scan_direction) __init;
-extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *owner);
-#define ide_pci_register_driver(d) __ide_pci_register_driver(d, THIS_MODULE)
+extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *owner, const char *mod_name);
+#define ide_pci_register_driver(d) __ide_pci_register_driver(d, THIS_MODULE, KBUILD_MODNAME)
 void ide_pci_setup_ports(struct pci_dev *, struct ide_pci_device_s *, int, ata_index_t *);
 extern void ide_setup_pci_noise (struct pci_dev *dev, struct ide_pci_device_s *d);
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index f3c617e..cb899eb 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -573,10 +573,11 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
 void pci_enable_bridges(struct pci_bus *bus);
 
 /* Proper probing supporting hot-pluggable devices */
-int __must_check __pci_register_driver(struct pci_driver *, struct module *);
+int __must_check __pci_register_driver(struct pci_driver *, struct module *,
+				       const char *mod_name);
 static inline int __must_check pci_register_driver(struct pci_driver *driver)
 {
-	return __pci_register_driver(driver, THIS_MODULE);
+	return __pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);
 }
 
 void pci_unregister_driver(struct pci_driver *);
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 10/28] SERIO: add the sysfs driver name to all modules
  2007-02-08  0:29                 ` [PATCH 9/28] PCI: add the sysfs driver name to all modules Greg KH
@ 2007-02-08  0:29                   ` Greg KH
  2007-02-08  0:29                     ` [PATCH 11/28] USB: " Greg KH
  2007-02-08 17:20                     ` [PATCH 10/28] SERIO: add the sysfs driver name to all modules Dmitry Torokhov
  0 siblings, 2 replies; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:29 UTC (permalink / raw)
  To: linux-kernel; +Cc: Greg Kroah-Hartman

From: Greg Kroah-Hartman <gregkh@suse.de>

This adds the module name to all SERIO drivers, if they are built into
the kernel or not.  It will show up in /sys/modules/MODULE_NAME/drivers/

Cc: Kay Sievers <kay.sievers@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/input/serio/serio.c |    6 ++++--
 include/linux/serio.h       |    5 +++++
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index f0ce822..17c8c63 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -45,7 +45,7 @@ EXPORT_SYMBOL(serio_interrupt);
 EXPORT_SYMBOL(__serio_register_port);
 EXPORT_SYMBOL(serio_unregister_port);
 EXPORT_SYMBOL(serio_unregister_child_port);
-EXPORT_SYMBOL(serio_register_driver);
+EXPORT_SYMBOL(__serio_register_driver);
 EXPORT_SYMBOL(serio_unregister_driver);
 EXPORT_SYMBOL(serio_open);
 EXPORT_SYMBOL(serio_close);
@@ -789,12 +789,14 @@ static void serio_attach_driver(struct serio_driver *drv)
 			drv->driver.name, error);
 }
 
-int serio_register_driver(struct serio_driver *drv)
+int __serio_register_driver(struct serio_driver *drv, struct module *owner, const char *mod_name)
 {
 	int manual_bind = drv->manual_bind;
 	int error;
 
 	drv->driver.bus = &serio_bus;
+	drv->driver.owner = owner;
+	drv->driver.mod_name = mod_name;
 
 	/*
 	 * Temporarily disable automatic binding because probing
diff --git a/include/linux/serio.h b/include/linux/serio.h
index 0f478a8..ac2c70e 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -86,6 +86,11 @@ static inline void serio_register_port(struct serio *serio)
 void serio_unregister_port(struct serio *serio);
 void serio_unregister_child_port(struct serio *serio);
 
+int __serio_register_driver(struct serio_driver *drv, struct module *owner, const char *mod_name);
+static inline int serio_register_driver(struct serio_driver *drv)
+{
+	return __serio_register_driver(drv, THIS_MODULE, KBUILD_MODNAME);
+}
 int serio_register_driver(struct serio_driver *drv);
 void serio_unregister_driver(struct serio_driver *drv);
 
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 11/28] USB: add the sysfs driver name to all modules
  2007-02-08  0:29                   ` [PATCH 10/28] SERIO: " Greg KH
@ 2007-02-08  0:29                     ` Greg KH
  2007-02-08  0:30                       ` [PATCH 12/28] /sys/modules/*/holders Greg KH
  2007-02-08 17:20                     ` [PATCH 10/28] SERIO: add the sysfs driver name to all modules Dmitry Torokhov
  1 sibling, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:29 UTC (permalink / raw)
  To: linux-kernel; +Cc: Greg Kroah-Hartman

From: Greg Kroah-Hartman <gregkh@suse.de>

This adds the module name to all USB drivers, if they are built into the
kernel or not.  It will show up in /sys/modules/MODULE_NAME/drivers/

Cc: Kay Sievers <kay.sievers@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/usb/core/driver.c |    4 +++-
 include/linux/usb.h       |    5 +++--
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index d6eb5ce..d505926 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -750,7 +750,8 @@ EXPORT_SYMBOL_GPL(usb_deregister_device_driver);
  * usb_register_dev() to enable that functionality.  This function no longer
  * takes care of that.
  */
-int usb_register_driver(struct usb_driver *new_driver, struct module *owner)
+int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
+			const char *mod_name)
 {
 	int retval = 0;
 
@@ -763,6 +764,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner)
 	new_driver->drvwrap.driver.probe = usb_probe_interface;
 	new_driver->drvwrap.driver.remove = usb_unbind_interface;
 	new_driver->drvwrap.driver.owner = owner;
+	new_driver->drvwrap.driver.mod_name = mod_name;
 	spin_lock_init(&new_driver->dynids.lock);
 	INIT_LIST_HEAD(&new_driver->dynids.list);
 
diff --git a/include/linux/usb.h b/include/linux/usb.h
index aab5b1b..733f38d 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -868,10 +868,11 @@ struct usb_class_driver {
  * use these in module_init()/module_exit()
  * and don't forget MODULE_DEVICE_TABLE(usb, ...)
  */
-extern int usb_register_driver(struct usb_driver *, struct module *);
+extern int usb_register_driver(struct usb_driver *, struct module *,
+			       const char *);
 static inline int usb_register(struct usb_driver *driver)
 {
-	return usb_register_driver(driver, THIS_MODULE);
+	return usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);
 }
 extern void usb_deregister(struct usb_driver *);
 
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 12/28] /sys/modules/*/holders
  2007-02-08  0:29                     ` [PATCH 11/28] USB: " Greg KH
@ 2007-02-08  0:30                       ` Greg KH
  2007-02-08  0:30                         ` [PATCH 13/28] driver core fixes: make_class_name() retval checks Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: Kay Sievers, Greg Kroah-Hartman

From: Kay Sievers <kay.sievers@vrfy.org>

  /sys/module/usbcore/
  |-- drivers
  |   |-- usb:hub -> ../../../subsystem/usb/drivers/hub
  |   |-- usb:usb -> ../../../subsystem/usb/drivers/usb
  |   `-- usb:usbfs -> ../../../subsystem/usb/drivers/usbfs
  |-- holders
  |   |-- ehci_hcd -> ../../../module/ehci_hcd
  |   |-- uhci_hcd -> ../../../module/uhci_hcd
  |   |-- usb_storage -> ../../../module/usb_storage
  |   `-- usbhid -> ../../../module/usbhid
  |-- initstate

Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 include/linux/module.h |    1 +
 kernel/module.c        |   37 +++++++++++++++++++++++++++++++------
 kernel/params.c        |   17 ++++++++++++++++-
 3 files changed, 48 insertions(+), 7 deletions(-)

diff --git a/include/linux/module.h b/include/linux/module.h
index 90dc254..419d3ef 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -264,6 +264,7 @@ struct module
 	struct module_attribute *modinfo_attrs;
 	const char *version;
 	const char *srcversion;
+	struct kobject *holders_dir;
 
 	/* Exported symbols */
 	const struct kernel_symbol *syms;
diff --git a/kernel/module.c b/kernel/module.c
index 9de4209..8a94e05 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -537,6 +537,8 @@ static int already_uses(struct module *a, struct module *b)
 static int use_module(struct module *a, struct module *b)
 {
 	struct module_use *use;
+	int no_warn;
+
 	if (b == NULL || already_uses(a, b)) return 1;
 
 	if (!strong_try_module_get(b))
@@ -552,6 +554,7 @@ static int use_module(struct module *a, struct module *b)
 
 	use->module_which_uses = a;
 	list_add(&use->list, &b->modules_which_use_me);
+	no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name);
 	return 1;
 }
 
@@ -569,6 +572,7 @@ static void module_unload_free(struct module *mod)
 				module_put(i);
 				list_del(&use->list);
 				kfree(use);
+				sysfs_remove_link(i->holders_dir, mod->name);
 				/* There can be at most one match. */
 				break;
 			}
@@ -1106,9 +1110,7 @@ static void module_remove_modinfo_attrs(struct module *mod)
 	kfree(mod->modinfo_attrs);
 }
 
-static int mod_sysfs_setup(struct module *mod,
-			   struct kernel_param *kparam,
-			   unsigned int num_params)
+static int mod_sysfs_init(struct module *mod)
 {
 	int err;
 
@@ -1125,15 +1127,30 @@ static int mod_sysfs_setup(struct module *mod,
 	kobj_set_kset_s(&mod->mkobj, module_subsys);
 	mod->mkobj.mod = mod;
 
-	/* delay uevent until full sysfs population */
 	kobject_init(&mod->mkobj.kobj);
+
+out:
+	return err;
+}
+
+static int mod_sysfs_setup(struct module *mod,
+			   struct kernel_param *kparam,
+			   unsigned int num_params)
+{
+	int err;
+
+	/* delay uevent until full sysfs population */
 	err = kobject_add(&mod->mkobj.kobj);
 	if (err)
 		goto out;
 
+	mod->holders_dir = kobject_add_dir(&mod->mkobj.kobj, "holders");
+	if (!mod->holders_dir)
+		goto out_unreg;
+
 	err = module_param_sysfs_setup(mod, kparam, num_params);
 	if (err)
-		goto out_unreg_drivers;
+		goto out_unreg_holders;
 
 	err = module_add_modinfo_attrs(mod);
 	if (err)
@@ -1144,7 +1161,9 @@ static int mod_sysfs_setup(struct module *mod,
 
 out_unreg_param:
 	module_param_sysfs_remove(mod);
-out_unreg_drivers:
+out_unreg_holders:
+	kobject_unregister(mod->holders_dir);
+out_unreg:
 	kobject_del(&mod->mkobj.kobj);
 	kobject_put(&mod->mkobj.kobj);
 out:
@@ -1157,6 +1176,8 @@ static void mod_kobject_remove(struct module *mod)
 	module_param_sysfs_remove(mod);
 	if (mod->mkobj.drivers_dir)
 		kobject_unregister(mod->mkobj.drivers_dir);
+	if (mod->holders_dir)
+		kobject_unregister(mod->holders_dir);
 
 	kobject_unregister(&mod->mkobj.kobj);
 }
@@ -1761,6 +1782,10 @@ static struct module *load_module(void __user *umod,
 	/* Now we've moved module, initialize linked lists, etc. */
 	module_unload_init(mod);
 
+	/* Initialize kobject, so we can reference it. */
+	if (mod_sysfs_init(mod) != 0)
+		goto cleanup;
+
 	/* Set up license info based on the info section */
 	set_license(mod, get_modinfo(sechdrs, infoindex, "license"));
 
diff --git a/kernel/params.c b/kernel/params.c
index cbaac85..553cf7d 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -30,6 +30,8 @@
 #define DEBUGP(fmt, a...)
 #endif
 
+static struct kobj_type module_ktype;
+
 static inline char dash2underscore(char c)
 {
 	if (c == '-')
@@ -671,6 +673,19 @@ static struct sysfs_ops module_sysfs_ops = {
 	.store = module_attr_store,
 };
 
+static int uevent_filter(struct kset *kset, struct kobject *kobj)
+{
+	struct kobj_type *ktype = get_ktype(kobj);
+
+	if (ktype == &module_ktype)
+		return 1;
+	return 0;
+}
+
+static struct kset_uevent_ops module_uevent_ops = {
+	.filter = uevent_filter,
+};
+
 #else
 static struct sysfs_ops module_sysfs_ops = {
 	.show = NULL,
@@ -682,7 +697,7 @@ static struct kobj_type module_ktype = {
 	.sysfs_ops =	&module_sysfs_ops,
 };
 
-decl_subsys(module, &module_ktype, NULL);
+decl_subsys(module, &module_ktype, &module_uevent_ops);
 
 /*
  * param_sysfs_init - wrapper for built-in params support
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 13/28] driver core fixes: make_class_name() retval checks
  2007-02-08  0:30                       ` [PATCH 12/28] /sys/modules/*/holders Greg KH
@ 2007-02-08  0:30                         ` Greg KH
  2007-02-08  0:30                           ` [PATCH 14/28] driver core fixes: device_register() retval check in platform.c Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: Cornelia Huck, Greg Kroah-Hartman

From: Cornelia Huck <cornelia.huck@de.ibm.com>

Make make_class_name() return NULL on error and fixup callers in the
driver core.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/base/class.c |   21 ++++++++++++++-------
 drivers/base/core.c  |   17 +++++++++++------
 2 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/drivers/base/class.c b/drivers/base/class.c
index 8bf2ca2..96def1d 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -364,7 +364,7 @@ char *make_class_name(const char *name, struct kobject *kobj)
 
 	class_name = kmalloc(size, GFP_KERNEL);
 	if (!class_name)
-		return ERR_PTR(-ENOMEM);
+		return NULL;
 
 	strcpy(class_name, name);
 	strcat(class_name, ":");
@@ -411,8 +411,11 @@ static int make_deprecated_class_device_links(struct class_device *class_dev)
 		return 0;
 
 	class_name = make_class_name(class_dev->class->name, &class_dev->kobj);
-	error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
-				  class_name);
+	if (class_name)
+		error = sysfs_create_link(&class_dev->dev->kobj,
+					  &class_dev->kobj, class_name);
+	else
+		error = -ENOMEM;
 	kfree(class_name);
 	return error;
 }
@@ -425,7 +428,8 @@ static void remove_deprecated_class_device_links(struct class_device *class_dev)
 		return;
 
 	class_name = make_class_name(class_dev->class->name, &class_dev->kobj);
-	sysfs_remove_link(&class_dev->dev->kobj, class_name);
+	if (class_name)
+		sysfs_remove_link(&class_dev->dev->kobj, class_name);
 	kfree(class_name);
 }
 #else
@@ -863,9 +867,12 @@ int class_device_rename(struct class_device *class_dev, char *new_name)
 	if (class_dev->dev) {
 		new_class_name = make_class_name(class_dev->class->name,
 						 &class_dev->kobj);
-		sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
-				  new_class_name);
-		sysfs_remove_link(&class_dev->dev->kobj, old_class_name);
+		if (new_class_name)
+			sysfs_create_link(&class_dev->dev->kobj,
+					  &class_dev->kobj, new_class_name);
+		if (old_class_name)
+			sysfs_remove_link(&class_dev->dev->kobj,
+						old_class_name);
 	}
 #endif
 	class_device_put(class_dev);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index c60114d..6fee3e6 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -527,9 +527,13 @@ int device_add(struct device *dev)
 					  &dev->kobj, dev->bus_id);
 #ifdef CONFIG_SYSFS_DEPRECATED
 		if (parent) {
-			sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device");
-			class_name = make_class_name(dev->class->name, &dev->kobj);
-			sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name);
+			sysfs_create_link(&dev->kobj, &dev->parent->kobj,
+							"device");
+			class_name = make_class_name(dev->class->name,
+							&dev->kobj);
+			if (class_name)
+				sysfs_create_link(&dev->parent->kobj,
+						  &dev->kobj, class_name);
 		}
 #endif
 	}
@@ -672,7 +676,9 @@ void device_del(struct device * dev)
 		if (parent) {
 			char *class_name = make_class_name(dev->class->name,
 							   &dev->kobj);
-			sysfs_remove_link(&dev->parent->kobj, class_name);
+			if (class_name)
+				sysfs_remove_link(&dev->parent->kobj,
+						  class_name);
 			kfree(class_name);
 			sysfs_remove_link(&dev->kobj, "device");
 		}
@@ -975,8 +981,7 @@ static int device_move_class_links(struct device *dev,
 
 	class_name = make_class_name(dev->class->name, &dev->kobj);
 	if (!class_name) {
-		error = PTR_ERR(class_name);
-		class_name = NULL;
+		error = -ENOMEM;
 		goto out;
 	}
 	if (old_parent) {
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 14/28] driver core fixes: device_register() retval check in platform.c
  2007-02-08  0:30                         ` [PATCH 13/28] driver core fixes: make_class_name() retval checks Greg KH
@ 2007-02-08  0:30                           ` Greg KH
  2007-02-08  0:30                             ` [PATCH 15/28] driver core: Don't stop probing on ->probe errors Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: Cornelia Huck, Greg Kroah-Hartman

From: Cornelia Huck <cornelia.huck@de.ibm.com>

Check the return value of device_register() in platform_bus_init().

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/base/platform.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index f9c903b..30480f6 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -611,8 +611,15 @@ EXPORT_SYMBOL_GPL(platform_bus_type);
 
 int __init platform_bus_init(void)
 {
-	device_register(&platform_bus);
-	return bus_register(&platform_bus_type);
+	int error;
+
+	error = device_register(&platform_bus);
+	if (error)
+		return error;
+	error =  bus_register(&platform_bus_type);
+	if (error)
+		device_unregister(&platform_bus);
+	return error;
 }
 
 #ifndef ARCH_HAS_DMA_GET_REQUIRED_MASK
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 15/28] driver core: Don't stop probing on ->probe errors.
  2007-02-08  0:30                           ` [PATCH 14/28] driver core fixes: device_register() retval check in platform.c Greg KH
@ 2007-02-08  0:30                             ` Greg KH
  2007-02-08  0:30                               ` [PATCH 16/28] driver core: Change function call order in device_bind_driver() Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: Cornelia Huck, Greg Kroah-Hartman

From: Cornelia Huck <cornelia.huck@de.ibm.com>

Don't stop on the first ->probe error that is not -ENODEV/-ENXIO.

There might be a driver registered returning an unresonable return code, and
this stops probing completely even though it may make sense to try the next
possible driver. At worst, we may end up with an unbound device.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/base/dd.c |   13 ++++++-------
 1 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 510e788..f705137 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -136,18 +136,17 @@ probe_failed:
 	driver_sysfs_remove(dev);
 	dev->driver = NULL;
 
-	if (ret == -ENODEV || ret == -ENXIO) {
-		/* Driver matched, but didn't support device
-		 * or device not found.
-		 * Not an error; keep going.
-		 */
-		ret = 0;
-	} else {
+	if (ret != -ENODEV && ret != -ENXIO) {
 		/* driver matched but the probe failed */
 		printk(KERN_WARNING
 		       "%s: probe of %s failed with error %d\n",
 		       drv->name, dev->bus_id, ret);
 	}
+	/*
+	 * Ignore errors returned by ->probe so that the next driver can try
+	 * its luck.
+	 */
+	ret = 0;
 done:
 	kfree(data);
 	atomic_dec(&probe_count);
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 16/28] driver core: Change function call order in device_bind_driver().
  2007-02-08  0:30                             ` [PATCH 15/28] driver core: Don't stop probing on ->probe errors Greg KH
@ 2007-02-08  0:30                               ` Greg KH
  2007-02-08  0:30                                 ` [PATCH 17/28] Driver core: fix race in sysfs between sysfs_remove_file() and read()/write() Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: Cornelia Huck, Greg Kroah-Hartman

From: Cornelia Huck <cornelia.huck@de.ibm.com>

Change function call order in device_bind_driver().

If we create symlinks (which might fail) before adding the device to the list
we don't have to clean up afterwards (which we didn't).

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/base/dd.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index f705137..b5bf243 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -86,8 +86,12 @@ static void driver_sysfs_remove(struct device *dev)
  */
 int device_bind_driver(struct device *dev)
 {
-	driver_bound(dev);
-	return driver_sysfs_add(dev);
+	int ret;
+
+	ret = driver_sysfs_add(dev);
+	if (!ret)
+		driver_bound(dev);
+	return ret;
 }
 
 struct stupid_thread_structure {
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 17/28] Driver core: fix race in sysfs between sysfs_remove_file() and read()/write()
  2007-02-08  0:30                               ` [PATCH 16/28] driver core: Change function call order in device_bind_driver() Greg KH
@ 2007-02-08  0:30                                 ` Greg KH
  2007-02-08  0:30                                   ` [PATCH 18/28] sysfs: suppress lockdep warnings Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: Oliver Neukum, Oliver Neukum, Greg Kroah-Hartman

From: Oliver Neukum <oliver@neukum.org>

This patch prevents a race between IO and removing a file from sysfs.
It introduces a list of sysfs_buffers associated with a file at the inode.
Upon removal of a file the list is walked and the buffers marked orphaned.
IO to orphaned buffers fails with -ENODEV. The driver can safely free
associated data structures or be unloaded.

Signed-off-by: Oliver Neukum <oliver@neukum.name>
Acked-by: Maneesh Soni <maneesh@in.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 fs/sysfs/bin.c     |    1 +
 fs/sysfs/dir.c     |    1 +
 fs/sysfs/file.c    |   67 ++++++++++++++++++++++++++++++++++++++-------------
 fs/sysfs/group.c   |    1 +
 fs/sysfs/inode.c   |   24 ++++++++++++++++++
 fs/sysfs/mount.c   |    9 +++++++
 fs/sysfs/symlink.c |    1 +
 fs/sysfs/sysfs.h   |   16 ++++++++++++
 8 files changed, 103 insertions(+), 17 deletions(-)

diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index e8f540d..9ec1c85 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 
 #include <asm/uaccess.h>
+#include <asm/semaphore.h>
 
 #include "sysfs.h"
 
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 2bab1b4..9ff0449 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -9,6 +9,7 @@
 #include <linux/module.h>
 #include <linux/kobject.h>
 #include <linux/namei.h>
+#include <asm/semaphore.h>
 #include "sysfs.h"
 
 DECLARE_RWSEM(sysfs_rename_sem);
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 9cfe53e..cba4c1c 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -7,6 +7,7 @@
 #include <linux/kobject.h>
 #include <linux/namei.h>
 #include <linux/poll.h>
+#include <linux/list.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 
@@ -50,17 +51,29 @@ static struct sysfs_ops subsys_sysfs_ops = {
 	.store	= subsys_attr_store,
 };
 
+/**
+ *	add_to_collection - add buffer to a collection
+ *	@buffer:	buffer to be added
+ *	@node		inode of set to add to
+ */
 
-struct sysfs_buffer {
-	size_t			count;
-	loff_t			pos;
-	char			* page;
-	struct sysfs_ops	* ops;
-	struct semaphore	sem;
-	int			needs_read_fill;
-	int			event;
-};
+static inline void
+add_to_collection(struct sysfs_buffer *buffer, struct inode *node)
+{
+	struct sysfs_buffer_collection *set = node->i_private;
 
+	mutex_lock(&node->i_mutex);
+	list_add(&buffer->associates, &set->associates);
+	mutex_unlock(&node->i_mutex);
+}
+
+static inline void
+remove_from_collection(struct sysfs_buffer *buffer, struct inode *node)
+{
+	mutex_lock(&node->i_mutex);
+	list_del(&buffer->associates);
+	mutex_unlock(&node->i_mutex);
+}
 
 /**
  *	fill_read_buffer - allocate and fill buffer from object.
@@ -153,6 +166,10 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 	ssize_t retval = 0;
 
 	down(&buffer->sem);
+	if (buffer->orphaned) {
+		retval = -ENODEV;
+		goto out;
+	}
 	if (buffer->needs_read_fill) {
 		if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
 			goto out;
@@ -165,7 +182,6 @@ out:
 	return retval;
 }
 
-
 /**
  *	fill_write_buffer - copy buffer from userspace.
  *	@buffer:	data buffer for file.
@@ -243,19 +259,25 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t
 	ssize_t len;
 
 	down(&buffer->sem);
+	if (buffer->orphaned) {
+		len = -ENODEV;
+		goto out;
+	}
 	len = fill_write_buffer(buffer, buf, count);
 	if (len > 0)
 		len = flush_write_buffer(file->f_path.dentry, buffer, len);
 	if (len > 0)
 		*ppos += len;
+out:
 	up(&buffer->sem);
 	return len;
 }
 
-static int check_perm(struct inode * inode, struct file * file)
+static int sysfs_open_file(struct inode *inode, struct file *file)
 {
 	struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
 	struct attribute * attr = to_attr(file->f_path.dentry);
+	struct sysfs_buffer_collection *set;
 	struct sysfs_buffer * buffer;
 	struct sysfs_ops * ops = NULL;
 	int error = 0;
@@ -285,6 +307,18 @@ static int check_perm(struct inode * inode, struct file * file)
 	if (!ops)
 		goto Eaccess;
 
+	/* make sure we have a collection to add our buffers to */
+	mutex_lock(&inode->i_mutex);
+	if (!(set = inode->i_private)) {
+		if (!(set = inode->i_private = kmalloc(sizeof(struct sysfs_buffer_collection), GFP_KERNEL))) {
+			error = -ENOMEM;
+			goto Done;
+		} else {
+			INIT_LIST_HEAD(&set->associates);
+		}
+	}
+	mutex_unlock(&inode->i_mutex);
+
 	/* File needs write support.
 	 * The inode's perms must say it's ok, 
 	 * and we must have a store method.
@@ -310,9 +344,11 @@ static int check_perm(struct inode * inode, struct file * file)
 	 */
 	buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL);
 	if (buffer) {
+		INIT_LIST_HEAD(&buffer->associates);
 		init_MUTEX(&buffer->sem);
 		buffer->needs_read_fill = 1;
 		buffer->ops = ops;
+		add_to_collection(buffer, inode);
 		file->private_data = buffer;
 	} else
 		error = -ENOMEM;
@@ -330,11 +366,6 @@ static int check_perm(struct inode * inode, struct file * file)
 	return error;
 }
 
-static int sysfs_open_file(struct inode * inode, struct file * filp)
-{
-	return check_perm(inode,filp);
-}
-
 static int sysfs_release(struct inode * inode, struct file * filp)
 {
 	struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
@@ -342,6 +373,8 @@ static int sysfs_release(struct inode * inode, struct file * filp)
 	struct module * owner = attr->owner;
 	struct sysfs_buffer * buffer = filp->private_data;
 
+	if (buffer)
+		remove_from_collection(buffer, inode);
 	if (kobj) 
 		kobject_put(kobj);
 	/* After this point, attr should not be accessed. */
@@ -548,7 +581,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file);
 
 void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
 {
-	sysfs_hash_and_remove(kobj->dentry,attr->name);
+	sysfs_hash_and_remove(kobj->dentry, attr->name);
 }
 
 
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 122145b..46a277b 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -13,6 +13,7 @@
 #include <linux/dcache.h>
 #include <linux/namei.h>
 #include <linux/err.h>
+#include <asm/semaphore.h>
 #include "sysfs.h"
 
 
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index e79e38d..1a81ebc 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -13,6 +13,7 @@
 #include <linux/backing-dev.h>
 #include <linux/capability.h>
 #include <linux/errno.h>
+#include <asm/semaphore.h>
 #include "sysfs.h"
 
 extern struct super_block * sysfs_sb;
@@ -209,6 +210,22 @@ const unsigned char * sysfs_get_name(struct sysfs_dirent *sd)
 	return NULL;
 }
 
+static inline void orphan_all_buffers(struct inode *node)
+{
+	struct sysfs_buffer_collection *set = node->i_private;
+	struct sysfs_buffer *buf;
+
+	mutex_lock(&node->i_mutex);
+	if (node->i_private) {
+		list_for_each_entry(buf, &set->associates, associates) {
+			down(&buf->sem);
+			buf->orphaned = 1;
+			up(&buf->sem);
+		}
+	}
+	mutex_unlock(&node->i_mutex);
+}
+
 
 /*
  * Unhashes the dentry corresponding to given sysfs_dirent
@@ -217,16 +234,23 @@ const unsigned char * sysfs_get_name(struct sysfs_dirent *sd)
 void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent)
 {
 	struct dentry * dentry = sd->s_dentry;
+	struct inode *inode;
 
 	if (dentry) {
 		spin_lock(&dcache_lock);
 		spin_lock(&dentry->d_lock);
 		if (!(d_unhashed(dentry) && dentry->d_inode)) {
+			inode = dentry->d_inode;
+			spin_lock(&inode->i_lock);
+			__iget(inode);
+			spin_unlock(&inode->i_lock);
 			dget_locked(dentry);
 			__d_drop(dentry);
 			spin_unlock(&dentry->d_lock);
 			spin_unlock(&dcache_lock);
 			simple_unlink(parent->d_inode, dentry);
+			orphan_all_buffers(inode);
+			iput(inode);
 		} else {
 			spin_unlock(&dentry->d_lock);
 			spin_unlock(&dcache_lock);
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index e503f85..a1a58b9 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -8,6 +8,7 @@
 #include <linux/mount.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
+#include <asm/semaphore.h>
 
 #include "sysfs.h"
 
@@ -18,9 +19,12 @@ struct vfsmount *sysfs_mount;
 struct super_block * sysfs_sb = NULL;
 struct kmem_cache *sysfs_dir_cachep;
 
+static void sysfs_clear_inode(struct inode *inode);
+
 static struct super_operations sysfs_ops = {
 	.statfs		= simple_statfs,
 	.drop_inode	= generic_delete_inode,
+	.clear_inode	= sysfs_clear_inode,
 };
 
 static struct sysfs_dirent sysfs_root = {
@@ -31,6 +35,11 @@ static struct sysfs_dirent sysfs_root = {
 	.s_iattr	= NULL,
 };
 
+static void sysfs_clear_inode(struct inode *inode)
+{
+	kfree(inode->i_private);
+}
+
 static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct inode *inode;
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index f50e3cc..4869f61 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -7,6 +7,7 @@
 #include <linux/module.h>
 #include <linux/kobject.h>
 #include <linux/namei.h>
+#include <asm/semaphore.h>
 
 #include "sysfs.h"
 
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index bd7cec2..39c623f 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -33,6 +33,22 @@ struct sysfs_symlink {
 	struct kobject * target_kobj;
 };
 
+struct sysfs_buffer {
+	struct list_head		associates;
+	size_t				count;
+	loff_t				pos;
+	char				* page;
+	struct sysfs_ops		* ops;
+	struct semaphore		sem;
+	int				orphaned;
+	int				needs_read_fill;
+	int				event;
+};
+
+struct sysfs_buffer_collection {
+	struct list_head	associates;
+};
+
 static inline struct kobject * to_kobj(struct dentry * dentry)
 {
 	struct sysfs_dirent * sd = dentry->d_fsdata;
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 18/28] sysfs: suppress lockdep warnings
  2007-02-08  0:30                                 ` [PATCH 17/28] Driver core: fix race in sysfs between sysfs_remove_file() and read()/write() Greg KH
@ 2007-02-08  0:30                                   ` Greg KH
  2007-02-08  0:30                                     ` [PATCH 19/28] sysfs: kobject_put cleanup Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:30 UTC (permalink / raw)
  To: linux-kernel
  Cc: Frederik Deweerdt, Frederik Deweerdt, Andrew Morton, Greg Kroah-Hartman

From: Frederik Deweerdt <deweerdt@free.fr>

Lockdep issues the following warning:
[    9.064000] =============================================
[    9.064000] [ INFO: possible recursive locking detected ]
[    9.064000] 2.6.20-rc3-mm1 #3
[    9.064000] ---------------------------------------------
[    9.064000] init/1 is trying to acquire lock:
[    9.064000]  (&sysfs_inode_imutex_key){--..}, at: [<c03e6afc>] mutex_lock+0x1c/0x1f
[    9.064000]
[    9.064000] but task is already holding lock:
[    9.064000]  (&sysfs_inode_imutex_key){--..}, at: [<c03e6afc>] mutex_lock+0x1c/0x1f
[    9.065000]
[    9.065000] other info that might help us debug this:
[    9.065000] 2 locks held by init/1:
[    9.065000]  #0:  (tty_mutex){--..}, at: [<c03e6afc>] mutex_lock+0x1c/0x1f
[    9.065000]  #1:  (&sysfs_inode_imutex_key){--..}, at: [<c03e6afc>] mutex_lock+0x1c/0x1f
[    9.065000]
[    9.065000] stack backtrace:
[    9.065000]  [<c010390d>] show_trace_log_lvl+0x1a/0x30
[    9.066000]  [<c0103935>] show_trace+0x12/0x14
[    9.066000]  [<c0103a2f>] dump_stack+0x16/0x18
[    9.066000]  [<c0138cb8>] print_deadlock_bug+0xb9/0xc3
[    9.066000]  [<c0138d17>] check_deadlock+0x55/0x5a
[    9.066000]  [<c013a953>] __lock_acquire+0x371/0xbf0
[    9.066000]  [<c013b7a9>] lock_acquire+0x69/0x83
[    9.066000]  [<c03e6b7e>] __mutex_lock_slowpath+0x75/0x2d1
[    9.066000]  [<c03e6afc>] mutex_lock+0x1c/0x1f
[    9.066000]  [<c01b249c>] sysfs_drop_dentry+0xb1/0x133
[    9.066000]  [<c01b25d1>] sysfs_hash_and_remove+0xb3/0x142
[    9.066000]  [<c01b30ed>] sysfs_remove_file+0xd/0x10
[    9.067000]  [<c02849e0>] device_remove_file+0x23/0x2e
[    9.067000]  [<c02850b2>] device_del+0x188/0x1e6
[    9.067000]  [<c028511b>] device_unregister+0xb/0x15
[    9.067000]  [<c0285318>] device_destroy+0x9c/0xa9
[    9.067000]  [<c0261431>] vcs_remove_sysfs+0x1c/0x3b
[    9.067000]  [<c0267a08>] con_close+0x5e/0x6b
[    9.067000]  [<c02598f2>] release_dev+0x4c4/0x6e5
[    9.067000]  [<c0259faa>] tty_release+0x12/0x1c
[    9.067000]  [<c0174872>] __fput+0x177/0x1a0
[    9.067000]  [<c01746f5>] fput+0x3b/0x41
[    9.068000]  [<c0172ee1>] filp_close+0x36/0x65
[    9.068000]  [<c0172f73>] sys_close+0x63/0xa4
[    9.068000]  [<c0102a96>] sysenter_past_esp+0x5f/0x99
[    9.068000]  =======================

This is due to sysfs_hash_and_remove() holding dir->d_inode->i_mutex
before calling sysfs_drop_dentry() which calls orphan_all_buffers()
which in turn takes node->i_mutex.

Signed-off-by: Frederik Deweerdt <frederik.deweerdt@gmail.com>
Cc: Oliver Neukum <oliver@neukum.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 fs/sysfs/inode.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 1a81ebc..dbd820f 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -215,7 +215,7 @@ static inline void orphan_all_buffers(struct inode *node)
 	struct sysfs_buffer_collection *set = node->i_private;
 	struct sysfs_buffer *buf;
 
-	mutex_lock(&node->i_mutex);
+	mutex_lock_nested(&node->i_mutex, I_MUTEX_CHILD);
 	if (node->i_private) {
 		list_for_each_entry(buf, &set->associates, associates) {
 			down(&buf->sem);
@@ -272,7 +272,7 @@ int sysfs_hash_and_remove(struct dentry * dir, const char * name)
 		return -ENOENT;
 
 	parent_sd = dir->d_fsdata;
-	mutex_lock(&dir->d_inode->i_mutex);
+	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
 	list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
 		if (!sd->s_element)
 			continue;
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 19/28] sysfs: kobject_put cleanup
  2007-02-08  0:30                                   ` [PATCH 18/28] sysfs: suppress lockdep warnings Greg KH
@ 2007-02-08  0:30                                     ` Greg KH
  2007-02-08  0:30                                       ` [PATCH 20/28] kobject: " Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: Mariusz Kozlowski, Greg Kroah-Hartman

From: Mariusz Kozlowski <m.kozlowski@tuxland.pl>

This patch removes redundant argument checks for kobject_put().

Signed-off-by: Mariusz Kozlowski <m.kozlowski@tuxland.pl>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 fs/sysfs/bin.c  |    5 ++---
 fs/sysfs/file.c |    5 ++---
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index 9ec1c85..d3b9f5f 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -147,7 +147,7 @@ static int open(struct inode * inode, struct file * file)
  Error:
 	module_put(attr->attr.owner);
  Done:
-	if (error && kobj)
+	if (error)
 		kobject_put(kobj);
 	return error;
 }
@@ -158,8 +158,7 @@ static int release(struct inode * inode, struct file * file)
 	struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
 	u8 * buffer = file->private_data;
 
-	if (kobj) 
-		kobject_put(kobj);
+	kobject_put(kobj);
 	module_put(attr->attr.owner);
 	kfree(buffer);
 	return 0;
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index cba4c1c..46618f8 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -361,7 +361,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
 	error = -EACCES;
 	module_put(attr->owner);
  Done:
-	if (error && kobj)
+	if (error)
 		kobject_put(kobj);
 	return error;
 }
@@ -375,8 +375,7 @@ static int sysfs_release(struct inode * inode, struct file * filp)
 
 	if (buffer)
 		remove_from_collection(buffer, inode);
-	if (kobj) 
-		kobject_put(kobj);
+	kobject_put(kobj);
 	/* After this point, attr should not be accessed. */
 	module_put(owner);
 
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 20/28] kobject: kobject_put cleanup
  2007-02-08  0:30                                     ` [PATCH 19/28] sysfs: kobject_put cleanup Greg KH
@ 2007-02-08  0:30                                       ` Greg KH
  2007-02-08  0:30                                         ` [PATCH 21/28] sysfs: error handling in sysfs, fill_read_buffer() Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: Mariusz Kozlowski, Greg Kroah-Hartman

From: Mariusz Kozlowski <m.kozlowski@tuxland.pl>

This patch removes redundant argument checks for kobject_put().

Signed-off-by: Mariusz Kozlowski <m.kozlowski@tuxland.pl>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 lib/kobject.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/lib/kobject.c b/lib/kobject.c
index c033dc8..74b8dbc 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -195,8 +195,7 @@ int kobject_add(struct kobject * kobj)
 	if (error) {
 		/* unlink does the kobject_put() for us */
 		unlink(kobj);
-		if (parent)
-			kobject_put(parent);
+		kobject_put(parent);
 
 		/* be noisy on error issues */
 		if (error == -EEXIST)
@@ -420,8 +419,7 @@ void kobject_cleanup(struct kobject * kobj)
 		t->release(kobj);
 	if (s)
 		kset_put(s);
-	if (parent) 
-		kobject_put(parent);
+	kobject_put(parent);
 }
 
 static void kobject_release(struct kref *kref)
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 21/28] sysfs: error handling in sysfs, fill_read_buffer()
  2007-02-08  0:30                                       ` [PATCH 20/28] kobject: " Greg KH
@ 2007-02-08  0:30                                         ` Greg KH
  2007-02-08  0:30                                           ` [PATCH 22/28] HOWTO: Add a reference to Harbison and Steele Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: Oliver Neukum, Greg Kroah-Hartman

From: Oliver Neukum <oliver@neukum.name>

if a driver returns an error in fill_read_buffer(), the buffer will be
marked as filled. Subsequent reads will return eof. But there is
no data because of an error, not because it has been read.
Not marking the buffer filled is the obvious fix.

Signed-off-by: Oliver Neukum <oliver@neukum.name>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 fs/sysfs/file.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 46618f8..c0e1176 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -83,7 +83,8 @@ remove_from_collection(struct sysfs_buffer *buffer, struct inode *node)
  *	Allocate @buffer->page, if it hasn't been already, then call the
  *	kobject's show() method to fill the buffer with this attribute's 
  *	data. 
- *	This is called only once, on the file's first read. 
+ *	This is called only once, on the file's first read unless an error
+ *	is returned.
  */
 static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
 {
@@ -101,12 +102,13 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
 
 	buffer->event = atomic_read(&sd->s_event);
 	count = ops->show(kobj,attr,buffer->page);
-	buffer->needs_read_fill = 0;
 	BUG_ON(count > (ssize_t)PAGE_SIZE);
-	if (count >= 0)
+	if (count >= 0) {
+		buffer->needs_read_fill = 0;
 		buffer->count = count;
-	else
+	} else {
 		ret = count;
+	}
 	return ret;
 }
 
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 22/28] HOWTO: Add a reference to Harbison and Steele
  2007-02-08  0:30                                         ` [PATCH 21/28] sysfs: error handling in sysfs, fill_read_buffer() Greg KH
@ 2007-02-08  0:30                                           ` Greg KH
  2007-02-08  0:30                                             ` [PATCH 23/28] SYSFS: Fix missing include of list.h in sysfs.h Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: Greg Kroah-Hartman

From: Robert P. J. Day <rpjday@mindspring.com>

Add a reference to Harbison and Steele's C book.

Signed-off-by: Robert P. J. Day <rpjday@mindspring.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 Documentation/HOWTO |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/Documentation/HOWTO b/Documentation/HOWTO
index 8d51c14..48123db 100644
--- a/Documentation/HOWTO
+++ b/Documentation/HOWTO
@@ -30,6 +30,7 @@ are not a good substitute for a solid C education and/or years of
 experience, the following books are good for, if anything, reference:
  - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
  - "Practical C Programming" by Steve Oualline [O'Reilly]
+ - "C:  A Reference Manual" by Harbison and Steele [Prentice Hall]
 
 The kernel is written using GNU C and the GNU toolchain.  While it
 adheres to the ISO C89 standard, it uses a number of extensions that are
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 23/28] SYSFS: Fix missing include of list.h in sysfs.h
  2007-02-08  0:30                                           ` [PATCH 22/28] HOWTO: Add a reference to Harbison and Steele Greg KH
@ 2007-02-08  0:30                                             ` Greg KH
  2007-02-08  0:30                                               ` [PATCH 24/28] Driver core: add uevent vars for devices of a class Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: Frank Haverkamp, Greg Kroah-Hartman

From: Frank Haverkamp <haver@vnet.ibm.com>

Sysfs.h uses definitions (e.g. struct list_head s_sibling) from list.h
but does not include it.

Signed-off-by: Frank Haverkamp <haver@vnet.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 include/linux/sysfs.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 2129d1b..eee4859 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -11,6 +11,7 @@
 #define _SYSFS_H_
 
 #include <linux/compiler.h>
+#include <linux/list.h>
 #include <asm/atomic.h>
 
 struct kobject;
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 24/28] Driver core: add uevent vars for devices of a class
  2007-02-08  0:30                                             ` [PATCH 23/28] SYSFS: Fix missing include of list.h in sysfs.h Greg KH
@ 2007-02-08  0:30                                               ` Greg KH
  2007-02-08  0:30                                                 ` [PATCH 25/28] Driver core: add device_type to struct device Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: Kay Sievers, Greg Kroah-Hartman

From: Kay Sievers <kay.sievers@novell.com>

Devices converted from class_device to device should have
the same uevent keys as the original class_device had. We
search up the parents until we find the first bus device and
add the (already deprecated) PHYDEV* values.

Signed-off-by: Kay Sievers <kay.sievers@novell.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/base/core.c |   46 ++++++++++++++++++++++++++++++++++------------
 1 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/drivers/base/core.c b/drivers/base/core.c
index 6fee3e6..7a5336f 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -154,25 +154,47 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
 			       "MINOR=%u", MINOR(dev->devt));
 	}
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-	/* add bus name (same as SUBSYSTEM, deprecated) */
-	if (dev->bus)
-		add_uevent_var(envp, num_envp, &i,
-			       buffer, buffer_size, &length,
-			       "PHYSDEVBUS=%s", dev->bus->name);
-#endif
-
-	/* add driver name (PHYSDEV* values are deprecated)*/
-	if (dev->driver) {
+	if (dev->driver)
 		add_uevent_var(envp, num_envp, &i,
 			       buffer, buffer_size, &length,
 			       "DRIVER=%s", dev->driver->name);
+
 #ifdef CONFIG_SYSFS_DEPRECATED
+	if (dev->class) {
+		struct device *parent = dev->parent;
+
+		/* find first bus device in parent chain */
+		while (parent && !parent->bus)
+			parent = parent->parent;
+		if (parent && parent->bus) {
+			const char *path;
+
+			path = kobject_get_path(&parent->kobj, GFP_KERNEL);
+			add_uevent_var(envp, num_envp, &i,
+				       buffer, buffer_size, &length,
+				       "PHYSDEVPATH=%s", path);
+			kfree(path);
+
+			add_uevent_var(envp, num_envp, &i,
+				       buffer, buffer_size, &length,
+				       "PHYSDEVBUS=%s", parent->bus->name);
+
+			if (parent->driver)
+				add_uevent_var(envp, num_envp, &i,
+					       buffer, buffer_size, &length,
+					       "PHYSDEVDRIVER=%s", parent->driver->name);
+		}
+	} else if (dev->bus) {
 		add_uevent_var(envp, num_envp, &i,
 			       buffer, buffer_size, &length,
-			       "PHYSDEVDRIVER=%s", dev->driver->name);
-#endif
+			       "PHYSDEVBUS=%s", dev->bus->name);
+
+		if (dev->driver)
+			add_uevent_var(envp, num_envp, &i,
+				       buffer, buffer_size, &length,
+				       "PHYSDEVDRIVER=%s", dev->driver->name);
 	}
+#endif
 
 	/* terminate, set to next free slot, shrink available space */
 	envp[i] = NULL;
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 25/28] Driver core: add device_type to struct device
  2007-02-08  0:30                                               ` [PATCH 24/28] Driver core: add uevent vars for devices of a class Greg KH
@ 2007-02-08  0:30                                                 ` Greg KH
  2007-02-08  0:30                                                   ` [PATCH 26/28] Driver core: allow to delay the uevent at device creation time Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: Kay Sievers, Greg Kroah-Hartman

From: Kay Sievers <kay.sievers@novell.com>

This allows us to add type specific attributes, uevent vars and
release funtions.

A subsystem can carry different types of devices like the "block"
subsys has disks and partitions. Both types create a different set
of attributes, but belong to the same subsystem.

This corresponds to the low level objects:
  kobject   -> device       (object/device data)
  kobj_type -> device_type  (type of object/device we are embedded in)
  kset      -> class/bus    (list of objects/devices of a subsystem)

Signed-off-by: Kay Sievers <kay.sievers@novell.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/base/core.c          |   57 ++++++++++++++++++++++++++++-------------
 drivers/usb/input/hid-lgff.c |    4 +-
 include/linux/device.h       |    8 ++++++
 3 files changed, 49 insertions(+), 20 deletions(-)

diff --git a/drivers/base/core.c b/drivers/base/core.c
index 7a5336f..34ac187 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -95,6 +95,8 @@ static void device_release(struct kobject * kobj)
 
 	if (dev->release)
 		dev->release(dev);
+	else if (dev->type && dev->type->release)
+		dev->type->release(dev);
 	else if (dev->class && dev->class->dev_release)
 		dev->class->dev_release(dev);
 	else {
@@ -206,19 +208,25 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
 	if (dev->bus && dev->bus->uevent) {
 		/* have the bus specific function add its stuff */
 		retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size);
-			if (retval) {
-			pr_debug ("%s - uevent() returned %d\n",
+		if (retval)
+			pr_debug ("%s: bus uevent() returned %d\n",
 				  __FUNCTION__, retval);
-		}
 	}
 
 	if (dev->class && dev->class->dev_uevent) {
 		/* have the class specific function add its stuff */
 		retval = dev->class->dev_uevent(dev, envp, num_envp, buffer, buffer_size);
-			if (retval) {
-				pr_debug("%s - dev_uevent() returned %d\n",
-					 __FUNCTION__, retval);
-		}
+		if (retval)
+			pr_debug("%s: class uevent() returned %d\n",
+				 __FUNCTION__, retval);
+	}
+
+	if (dev->type && dev->type->uevent) {
+		/* have the device type specific fuction add its stuff */
+		retval = dev->type->uevent(dev, envp, num_envp, buffer, buffer_size);
+		if (retval)
+			pr_debug("%s: dev_type uevent() returned %d\n",
+				 __FUNCTION__, retval);
 	}
 
 	return retval;
@@ -269,37 +277,50 @@ static void device_remove_groups(struct device *dev)
 static int device_add_attrs(struct device *dev)
 {
 	struct class *class = dev->class;
+	struct device_type *type = dev->type;
 	int error = 0;
 	int i;
 
-	if (!class)
-		return 0;
-
-	if (class->dev_attrs) {
+	if (class && class->dev_attrs) {
 		for (i = 0; attr_name(class->dev_attrs[i]); i++) {
 			error = device_create_file(dev, &class->dev_attrs[i]);
 			if (error)
 				break;
 		}
+		if (error)
+			while (--i >= 0)
+				device_remove_file(dev, &class->dev_attrs[i]);
 	}
-	if (error)
-		while (--i >= 0)
-			device_remove_file(dev, &class->dev_attrs[i]);
+
+	if (type && type->attrs) {
+		for (i = 0; attr_name(type->attrs[i]); i++) {
+			error = device_create_file(dev, &type->attrs[i]);
+			if (error)
+				break;
+		}
+		if (error)
+			while (--i >= 0)
+				device_remove_file(dev, &type->attrs[i]);
+	}
+
 	return error;
 }
 
 static void device_remove_attrs(struct device *dev)
 {
 	struct class *class = dev->class;
+	struct device_type *type = dev->type;
 	int i;
 
-	if (!class)
-		return;
-
-	if (class->dev_attrs) {
+	if (class && class->dev_attrs) {
 		for (i = 0; attr_name(class->dev_attrs[i]); i++)
 			device_remove_file(dev, &class->dev_attrs[i]);
 	}
+
+	if (type && type->attrs) {
+		for (i = 0; attr_name(type->attrs[i]); i++)
+			device_remove_file(dev, &type->attrs[i]);
+	}
 }
 
 
diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c
index e474662..4f4fc3b 100644
--- a/drivers/usb/input/hid-lgff.c
+++ b/drivers/usb/input/hid-lgff.c
@@ -32,7 +32,7 @@
 #include <linux/hid.h>
 #include "usbhid.h"
 
-struct device_type {
+struct dev_type {
 	u16 idVendor;
 	u16 idProduct;
 	const signed short *ff;
@@ -48,7 +48,7 @@ static const signed short ff_joystick[] = {
 	-1
 };
 
-static const struct device_type devices[] = {
+static const struct dev_type devices[] = {
 	{ 0x046d, 0xc211, ff_rumble },
 	{ 0x046d, 0xc219, ff_rumble },
 	{ 0x046d, 0xc283, ff_joystick },
diff --git a/include/linux/device.h b/include/linux/device.h
index da72219..e1e164f 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -328,6 +328,13 @@ extern struct class_device *class_device_create(struct class *cls,
 					__attribute__((format(printf,5,6)));
 extern void class_device_destroy(struct class *cls, dev_t devt);
 
+struct device_type {
+	struct device_attribute *attrs;
+	int (*uevent)(struct device *dev, char **envp, int num_envp,
+		      char *buffer, int buffer_size);
+	void (*release)(struct device *dev);
+};
+
 /* interface for exporting device attributes */
 struct device_attribute {
 	struct attribute	attr;
@@ -356,6 +363,7 @@ struct device {
 
 	struct kobject kobj;
 	char	bus_id[BUS_ID_SIZE];	/* position on parent bus */
+	struct device_type	*type;
 	unsigned		is_registered:1;
 	struct device_attribute uevent_attr;
 	struct device_attribute *devt_attr;
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 26/28] Driver core: allow to delay the uevent at device creation time
  2007-02-08  0:30                                                 ` [PATCH 25/28] Driver core: add device_type to struct device Greg KH
@ 2007-02-08  0:30                                                   ` Greg KH
  2007-02-08  0:30                                                     ` [PATCH 27/28] Driver Core: Increase the default timeout value of the firmware subsystem Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: Kay Sievers, Greg Kroah-Hartman

From: Kay Sievers <kay.sievers@novell.com>

For the block subsystem, we want to delay all uevents until the
disk has been scanned and allpartitons are already created before
the first event is sent out.

Signed-off-by: Kay Sievers <kay.sievers@novell.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/base/core.c    |    3 ++-
 include/linux/device.h |    3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/base/core.c b/drivers/base/core.c
index 34ac187..e136142 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -589,7 +589,8 @@ int device_add(struct device *dev)
 		goto PMError;
 	if ((error = bus_add_device(dev)))
 		goto BusError;
-	kobject_uevent(&dev->kobj, KOBJ_ADD);
+	if (!dev->uevent_suppress)
+		kobject_uevent(&dev->kobj, KOBJ_ADD);
 	if ((error = bus_attach_device(dev)))
 		goto AttachError;
 	if (parent)
diff --git a/include/linux/device.h b/include/linux/device.h
index e1e164f..5ca1cdb 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -399,9 +399,10 @@ struct device {
 
 	/* class_device migration path */
 	struct list_head	node;
-	struct class		*class;		/* optional*/
+	struct class		*class;
 	dev_t			devt;		/* dev_t, creates the sysfs "dev" */
 	struct attribute_group	**groups;	/* optional groups */
+	int			uevent_suppress;
 
 	void	(*release)(struct device * dev);
 };
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 27/28] Driver Core: Increase the default timeout value of the firmware subsystem
  2007-02-08  0:30                                                   ` [PATCH 26/28] Driver core: allow to delay the uevent at device creation time Greg KH
@ 2007-02-08  0:30                                                     ` Greg KH
  2007-02-08  0:30                                                       ` [PATCH 28/28] sysfs: Shadow directory support Greg KH
  0 siblings, 1 reply; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: Dave Jones, Greg Kroah-Hartman

From: Dave Jones <davej@redhat.com>

https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=174589

The ipw driver sometimes takes a long time to load its firmware.
Whilst the ipw driver should be using the async interface of
the firmware loader to make this a non-issue, this is a minimal fix.

Signed-off-by: Dave Jones <davej@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/base/firmware_class.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 64558f4..c0a979a 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -35,7 +35,7 @@ enum {
 	FW_STATUS_READY_NOHOTPLUG,
 };
 
-static int loading_timeout = 10;	/* In seconds */
+static int loading_timeout = 60;	/* In seconds */
 
 /* fw_lock could be moved to 'struct firmware_priv' but since it is just
  * guarding for corner cases a global lock should be OK */
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 28/28] sysfs: Shadow directory support
  2007-02-08  0:30                                                     ` [PATCH 27/28] Driver Core: Increase the default timeout value of the firmware subsystem Greg KH
@ 2007-02-08  0:30                                                       ` Greg KH
  0 siblings, 0 replies; 32+ messages in thread
From: Greg KH @ 2007-02-08  0:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: Greg Kroah-Hartman

From: Eric W. Biederman <ebiederm@xmission.com>

The problem.  When implementing a network namespace I need to be able
to have multiple network devices with the same name.  Currently this
is a problem for /sys/class/net/*.

What I want is a separate /sys/class/net directory in sysfs for each
network namespace, and I want to name each of them /sys/class/net.

I looked and the VFS actually allows that.  All that is needed is
for /sys/class/net to implement a follow link method to redirect
lookups to the real directory you want.

Implementing a follow link method that is sensitive to the current
network namespace turns out to be 3 lines of code so it looks like a
clean approach.  Modifying sysfs so it doesn't get in my was is a bit
trickier.

I am calling the concept of multiple directories all at the same path
in the filesystem shadow directories.  With the directory entry really
at that location the shadow master.

The following patch modifies sysfs so it can handle a directory
structure slightly different from the kobject tree so I can implement
the shadow directories for handling /sys/class/net/.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Cc: Maneesh Soni <maneesh@in.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 fs/sysfs/dir.c          |  207 +++++++++++++++++++++++++++++++++++++++--------
 fs/sysfs/group.c        |    1 +
 fs/sysfs/inode.c        |   10 +++
 fs/sysfs/mount.c        |    2 +-
 fs/sysfs/sysfs.h        |    5 +
 include/linux/kobject.h |    4 +
 include/linux/sysfs.h   |   23 +++++-
 lib/kobject.c           |   42 +++++++++-
 8 files changed, 249 insertions(+), 45 deletions(-)

diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 9ff0449..9dcdf55 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -33,8 +33,7 @@ static struct dentry_operations sysfs_dentry_ops = {
 /*
  * Allocates a new sysfs_dirent and links it to the parent sysfs_dirent
  */
-static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * parent_sd,
-						void * element)
+static struct sysfs_dirent * __sysfs_new_dirent(void * element)
 {
 	struct sysfs_dirent * sd;
 
@@ -46,12 +45,28 @@ static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * parent_sd,
 	atomic_set(&sd->s_count, 1);
 	atomic_set(&sd->s_event, 1);
 	INIT_LIST_HEAD(&sd->s_children);
-	list_add(&sd->s_sibling, &parent_sd->s_children);
+	INIT_LIST_HEAD(&sd->s_sibling);
 	sd->s_element = element;
 
 	return sd;
 }
 
+static void __sysfs_list_dirent(struct sysfs_dirent *parent_sd,
+			      struct sysfs_dirent *sd)
+{
+	if (sd)
+		list_add(&sd->s_sibling, &parent_sd->s_children);
+}
+
+static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent *parent_sd,
+						void * element)
+{
+	struct sysfs_dirent *sd;
+	sd = __sysfs_new_dirent(element);
+	__sysfs_list_dirent(parent_sd, sd);
+	return sd;
+}
+
 /*
  *
  * Return -EEXIST if there is already a sysfs element with the same name for
@@ -78,14 +93,14 @@ int sysfs_dirent_exist(struct sysfs_dirent *parent_sd,
 }
 
 
-int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry,
-			void * element, umode_t mode, int type)
+static struct sysfs_dirent *
+__sysfs_make_dirent(struct dentry *dentry, void *element, mode_t mode, int type)
 {
 	struct sysfs_dirent * sd;
 
-	sd = sysfs_new_dirent(parent_sd, element);
+	sd = __sysfs_new_dirent(element);
 	if (!sd)
-		return -ENOMEM;
+		goto out;
 
 	sd->s_mode = mode;
 	sd->s_type = type;
@@ -95,7 +110,19 @@ int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry,
 		dentry->d_op = &sysfs_dentry_ops;
 	}
 
-	return 0;
+out:
+	return sd;
+}
+
+int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry,
+			void * element, umode_t mode, int type)
+{
+	struct sysfs_dirent *sd;
+
+	sd = __sysfs_make_dirent(dentry, element, mode, type);
+	__sysfs_list_dirent(parent_sd, sd);
+
+	return sd ? 0 : -ENOMEM;
 }
 
 static int init_dir(struct inode * inode)
@@ -166,11 +193,11 @@ int sysfs_create_subdir(struct kobject * k, const char * n, struct dentry ** d)
 
 /**
  *	sysfs_create_dir - create a directory for an object.
- *	@parent:	parent parent object.
  *	@kobj:		object we're creating directory for. 
+ *	@shadow_parent:	parent parent object.
  */
 
-int sysfs_create_dir(struct kobject * kobj)
+int sysfs_create_dir(struct kobject * kobj, struct dentry *shadow_parent)
 {
 	struct dentry * dentry = NULL;
 	struct dentry * parent;
@@ -178,7 +205,9 @@ int sysfs_create_dir(struct kobject * kobj)
 
 	BUG_ON(!kobj);
 
-	if (kobj->parent)
+	if (shadow_parent)
+		parent = shadow_parent;
+	else if (kobj->parent)
 		parent = kobj->parent->dentry;
 	else if (sysfs_mount && sysfs_mount->mnt_sb)
 		parent = sysfs_mount->mnt_sb->s_root;
@@ -299,21 +328,12 @@ void sysfs_remove_subdir(struct dentry * d)
 }
 
 
-/**
- *	sysfs_remove_dir - remove an object's directory.
- *	@kobj:	object. 
- *
- *	The only thing special about this is that we remove any files in 
- *	the directory before we remove the directory, and we've inlined
- *	what used to be sysfs_rmdir() below, instead of calling separately.
- */
-
-void sysfs_remove_dir(struct kobject * kobj)
+static void __sysfs_remove_dir(struct dentry *dentry)
 {
-	struct dentry * dentry = dget(kobj->dentry);
 	struct sysfs_dirent * parent_sd;
 	struct sysfs_dirent * sd, * tmp;
 
+	dget(dentry);
 	if (!dentry)
 		return;
 
@@ -334,32 +354,60 @@ void sysfs_remove_dir(struct kobject * kobj)
 	 * Drop reference from dget() on entrance.
 	 */
 	dput(dentry);
+}
+
+/**
+ *	sysfs_remove_dir - remove an object's directory.
+ *	@kobj:	object.
+ *
+ *	The only thing special about this is that we remove any files in
+ *	the directory before we remove the directory, and we've inlined
+ *	what used to be sysfs_rmdir() below, instead of calling separately.
+ */
+
+void sysfs_remove_dir(struct kobject * kobj)
+{
+	__sysfs_remove_dir(kobj->dentry);
 	kobj->dentry = NULL;
 }
 
-int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
+int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent,
+		     const char *new_name)
 {
 	int error = 0;
-	struct dentry * new_dentry, * parent;
+	struct dentry * new_dentry;
 
-	if (!strcmp(kobject_name(kobj), new_name))
-		return -EINVAL;
-
-	if (!kobj->parent)
-		return -EINVAL;
+	if (!new_parent)
+		return -EFAULT;
 
 	down_write(&sysfs_rename_sem);
-	parent = kobj->parent->dentry;
+	mutex_lock(&new_parent->d_inode->i_mutex);
 
-	mutex_lock(&parent->d_inode->i_mutex);
-
-	new_dentry = lookup_one_len(new_name, parent, strlen(new_name));
+	new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name));
 	if (!IS_ERR(new_dentry)) {
-  		if (!new_dentry->d_inode) {
+		/* By allowing two different directories with the
+		 * same d_parent we allow this routine to move
+		 * between different shadows of the same directory
+		 */
+		if (kobj->dentry->d_parent->d_inode != new_parent->d_inode)
+			return -EINVAL;
+		else if (new_dentry->d_parent->d_inode != new_parent->d_inode)
+			error = -EINVAL;
+		else if (new_dentry == kobj->dentry)
+			error = -EINVAL;
+		else if (!new_dentry->d_inode) {
 			error = kobject_set_name(kobj, "%s", new_name);
 			if (!error) {
+				struct sysfs_dirent *sd, *parent_sd;
+
 				d_add(new_dentry, NULL);
 				d_move(kobj->dentry, new_dentry);
+
+				sd = kobj->dentry->d_fsdata;
+				parent_sd = new_parent->d_fsdata;
+
+				list_del_init(&sd->s_sibling);
+				list_add(&sd->s_sibling, &parent_sd->s_children);
 			}
 			else
 				d_drop(new_dentry);
@@ -367,7 +415,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
 			error = -EEXIST;
 		dput(new_dentry);
 	}
-	mutex_unlock(&parent->d_inode->i_mutex);
+	mutex_unlock(&new_parent->d_inode->i_mutex);
 	up_write(&sysfs_rename_sem);
 
 	return error;
@@ -546,6 +594,95 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
 	return offset;
 }
 
+
+/**
+ *	sysfs_make_shadowed_dir - Setup so a directory can be shadowed
+ *	@kobj:	object we're creating shadow of.
+ */
+
+int sysfs_make_shadowed_dir(struct kobject *kobj,
+	void * (*follow_link)(struct dentry *, struct nameidata *))
+{
+	struct inode *inode;
+	struct inode_operations *i_op;
+
+	inode = kobj->dentry->d_inode;
+	if (inode->i_op != &sysfs_dir_inode_operations)
+		return -EINVAL;
+
+	i_op = kmalloc(sizeof(*i_op), GFP_KERNEL);
+	if (!i_op)
+		return -ENOMEM;
+
+	memcpy(i_op, &sysfs_dir_inode_operations, sizeof(*i_op));
+	i_op->follow_link = follow_link;
+
+	/* Locking of inode->i_op?
+	 * Since setting i_op is a single word write and they
+	 * are atomic we should be ok here.
+	 */
+	inode->i_op = i_op;
+	return 0;
+}
+
+/**
+ *	sysfs_create_shadow_dir - create a shadow directory for an object.
+ *	@kobj:	object we're creating directory for.
+ *
+ *	sysfs_make_shadowed_dir must already have been called on this
+ *	directory.
+ */
+
+struct dentry *sysfs_create_shadow_dir(struct kobject *kobj)
+{
+	struct sysfs_dirent *sd;
+	struct dentry *parent, *dir, *shadow;
+	struct inode *inode;
+
+	dir = kobj->dentry;
+	inode = dir->d_inode;
+	parent = dir->d_parent;
+	shadow = ERR_PTR(-EINVAL);
+	if (!sysfs_is_shadowed_inode(inode))
+		goto out;
+
+	shadow = d_alloc(parent, &dir->d_name);
+	if (!shadow)
+		goto nomem;
+
+	sd = __sysfs_make_dirent(shadow, kobj, inode->i_mode, SYSFS_DIR);
+	if (!sd)
+		goto nomem;
+
+	d_instantiate(shadow, igrab(inode));
+	inc_nlink(inode);
+	inc_nlink(parent->d_inode);
+	shadow->d_op = &sysfs_dentry_ops;
+
+	dget(shadow);		/* Extra count - pin the dentry in core */
+
+out:
+	return shadow;
+nomem:
+	dput(shadow);
+	shadow = ERR_PTR(-ENOMEM);
+	goto out;
+}
+
+/**
+ *	sysfs_remove_shadow_dir - remove an object's directory.
+ *	@shadow: dentry of shadow directory
+ *
+ *	The only thing special about this is that we remove any files in
+ *	the directory before we remove the directory, and we've inlined
+ *	what used to be sysfs_rmdir() below, instead of calling separately.
+ */
+
+void sysfs_remove_shadow_dir(struct dentry *shadow)
+{
+	__sysfs_remove_dir(shadow);
+}
+
 const struct file_operations sysfs_dir_operations = {
 	.open		= sysfs_dir_open,
 	.release	= sysfs_dir_close,
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 46a277b..b20951c 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -13,6 +13,7 @@
 #include <linux/dcache.h>
 #include <linux/namei.h>
 #include <linux/err.h>
+#include <linux/fs.h>
 #include <asm/semaphore.h>
 #include "sysfs.h"
 
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index dbd820f..542d2bc 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -33,6 +33,16 @@ static struct inode_operations sysfs_inode_operations ={
 	.setattr	= sysfs_setattr,
 };
 
+void sysfs_delete_inode(struct inode *inode)
+{
+	/* Free the shadowed directory inode operations */
+	if (sysfs_is_shadowed_inode(inode)) {
+		kfree(inode->i_op);
+		inode->i_op = NULL;
+	}
+	return generic_delete_inode(inode);
+}
+
 int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
 {
 	struct inode * inode = dentry->d_inode;
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index a1a58b9..f6a87a8 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -23,7 +23,7 @@ static void sysfs_clear_inode(struct inode *inode);
 
 static struct super_operations sysfs_ops = {
 	.statfs		= simple_statfs,
-	.drop_inode	= generic_delete_inode,
+	.drop_inode	= sysfs_delete_inode,
 	.clear_inode	= sysfs_clear_inode,
 };
 
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 39c623f..fe1cbfd 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -2,6 +2,7 @@
 extern struct vfsmount * sysfs_mount;
 extern struct kmem_cache *sysfs_dir_cachep;
 
+extern void sysfs_delete_inode(struct inode *inode);
 extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
 extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
 
@@ -112,3 +113,7 @@ static inline void sysfs_put(struct sysfs_dirent * sd)
 		release_sysfs_dirent(sd);
 }
 
+static inline int sysfs_is_shadowed_inode(struct inode *inode)
+{
+	return S_ISDIR(inode->i_mode) && inode->i_op->follow_link;
+}
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 76538fc..b850e03 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -74,9 +74,13 @@ extern void kobject_init(struct kobject *);
 extern void kobject_cleanup(struct kobject *);
 
 extern int __must_check kobject_add(struct kobject *);
+extern int __must_check kobject_shadow_add(struct kobject *, struct dentry *);
 extern void kobject_del(struct kobject *);
 
 extern int __must_check kobject_rename(struct kobject *, const char *new_name);
+extern int __must_check kobject_shadow_rename(struct kobject *kobj,
+						struct dentry *new_parent,
+						const char *new_name);
 extern int __must_check kobject_move(struct kobject *, struct kobject *);
 
 extern int __must_check kobject_register(struct kobject *);
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index eee4859..192de3a 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -16,6 +16,7 @@
 
 struct kobject;
 struct module;
+struct nameidata;
 
 struct attribute {
 	const char		* name;
@@ -89,13 +90,13 @@ struct sysfs_dirent {
 #ifdef CONFIG_SYSFS
 
 extern int __must_check
-sysfs_create_dir(struct kobject *);
+sysfs_create_dir(struct kobject *, struct dentry *);
 
 extern void
 sysfs_remove_dir(struct kobject *);
 
 extern int __must_check
-sysfs_rename_dir(struct kobject *, const char *new_name);
+sysfs_rename_dir(struct kobject *, struct dentry *, const char *new_name);
 
 extern int __must_check
 sysfs_move_dir(struct kobject *, struct kobject *);
@@ -127,11 +128,17 @@ int __must_check sysfs_create_group(struct kobject *,
 void sysfs_remove_group(struct kobject *, const struct attribute_group *);
 void sysfs_notify(struct kobject * k, char *dir, char *attr);
 
+
+extern int sysfs_make_shadowed_dir(struct kobject *kobj,
+	void * (*follow_link)(struct dentry *, struct nameidata *));
+extern struct dentry *sysfs_create_shadow_dir(struct kobject *kobj);
+extern void sysfs_remove_shadow_dir(struct dentry *dir);
+
 extern int __must_check sysfs_init(void);
 
 #else /* CONFIG_SYSFS */
 
-static inline int sysfs_create_dir(struct kobject * k)
+static inline int sysfs_create_dir(struct kobject * k, struct dentry *shadow)
 {
 	return 0;
 }
@@ -141,7 +148,9 @@ static inline void sysfs_remove_dir(struct kobject * k)
 	;
 }
 
-static inline int sysfs_rename_dir(struct kobject * k, const char *new_name)
+static inline int sysfs_rename_dir(struct kobject * k,
+					struct dentry *new_parent,
+					const char *new_name)
 {
 	return 0;
 }
@@ -205,6 +214,12 @@ static inline void sysfs_notify(struct kobject * k, char *dir, char *attr)
 {
 }
 
+static inline int sysfs_make_shadowed_dir(struct kobject *kobj,
+	void * (*follow_link)(struct dentry *, struct nameidata *))
+{
+	return 0;
+}
+
 static inline int __must_check sysfs_init(void)
 {
 	return 0;
diff --git a/lib/kobject.c b/lib/kobject.c
index 74b8dbc..c2917ff 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -44,11 +44,11 @@ static int populate_dir(struct kobject * kobj)
 	return error;
 }
 
-static int create_dir(struct kobject * kobj)
+static int create_dir(struct kobject * kobj, struct dentry *shadow_parent)
 {
 	int error = 0;
 	if (kobject_name(kobj)) {
-		error = sysfs_create_dir(kobj);
+		error = sysfs_create_dir(kobj, shadow_parent);
 		if (!error) {
 			if ((error = populate_dir(kobj)))
 				sysfs_remove_dir(kobj);
@@ -158,9 +158,10 @@ static void unlink(struct kobject * kobj)
 /**
  *	kobject_add - add an object to the hierarchy.
  *	@kobj:	object.
+ *	@shadow_parent: sysfs directory to add to.
  */
 
-int kobject_add(struct kobject * kobj)
+int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
 {
 	int error = 0;
 	struct kobject * parent;
@@ -191,7 +192,7 @@ int kobject_add(struct kobject * kobj)
 	}
 	kobj->parent = parent;
 
-	error = create_dir(kobj);
+	error = create_dir(kobj, shadow_parent);
 	if (error) {
 		/* unlink does the kobject_put() for us */
 		unlink(kobj);
@@ -212,6 +213,15 @@ int kobject_add(struct kobject * kobj)
 	return error;
 }
 
+/**
+ *	kobject_add - add an object to the hierarchy.
+ *	@kobj:	object.
+ */
+int kobject_add(struct kobject * kobj)
+{
+	return kobject_shadow_add(kobj, NULL);
+}
+
 
 /**
  *	kobject_register - initialize and add an object.
@@ -304,7 +314,29 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
 	kobj = kobject_get(kobj);
 	if (!kobj)
 		return -EINVAL;
-	error = sysfs_rename_dir(kobj, new_name);
+	if (!kobj->parent)
+		return -EINVAL;
+	error = sysfs_rename_dir(kobj, kobj->parent->dentry, new_name);
+	kobject_put(kobj);
+
+	return error;
+}
+
+/**
+ *	kobject_rename - change the name of an object
+ *	@kobj:	object in question.
+ *	@new_name: object's new name
+ */
+
+int kobject_shadow_rename(struct kobject * kobj, struct dentry *new_parent,
+			  const char *new_name)
+{
+	int error = 0;
+
+	kobj = kobject_get(kobj);
+	if (!kobj)
+		return -EINVAL;
+	error = sysfs_rename_dir(kobj, new_parent, new_name);
 	kobject_put(kobj);
 
 	return error;
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* Re: [PATCH 10/28] SERIO: add the sysfs driver name to all modules
  2007-02-08  0:29                   ` [PATCH 10/28] SERIO: " Greg KH
  2007-02-08  0:29                     ` [PATCH 11/28] USB: " Greg KH
@ 2007-02-08 17:20                     ` Dmitry Torokhov
  2007-02-08 18:51                       ` Greg KH
  1 sibling, 1 reply; 32+ messages in thread
From: Dmitry Torokhov @ 2007-02-08 17:20 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, Greg Kroah-Hartman

Hi Greg,

On 2/7/07, Greg KH <greg@kroah.com> wrote:
> From: Greg Kroah-Hartman <gregkh@suse.de>
>
> This adds the module name to all SERIO drivers, if they are built into
> the kernel or not.  It will show up in /sys/modules/MODULE_NAME/drivers/
>

What is this needed for?

-- 
Dmitry

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 10/28] SERIO: add the sysfs driver name to all modules
  2007-02-08 17:20                     ` [PATCH 10/28] SERIO: add the sysfs driver name to all modules Dmitry Torokhov
@ 2007-02-08 18:51                       ` Greg KH
  0 siblings, 0 replies; 32+ messages in thread
From: Greg KH @ 2007-02-08 18:51 UTC (permalink / raw)
  To: Dmitry Torokhov, Kay Sievers; +Cc: linux-kernel, Greg Kroah-Hartman

On Thu, Feb 08, 2007 at 12:20:05PM -0500, Dmitry Torokhov wrote:
> Hi Greg,
> 
> On 2/7/07, Greg KH <greg@kroah.com> wrote:
> >From: Greg Kroah-Hartman <gregkh@suse.de>
> >
> >This adds the module name to all SERIO drivers, if they are built into
> >the kernel or not.  It will show up in /sys/modules/MODULE_NAME/drivers/
> >
> 
> What is this needed for?

All modules show up today in /sys/module/ no matter if they are built
into the kernel or not.

But, if they are built as a module, the /sys/module/drivers/ link was
present.  This is not consistant, as we always want to see that link, no
matter if the driver is built in or not.  So with this change, we now
always see the links.

I also fixed the PCI and USB drivers to do this as well.

Hope this helps explain it.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 8/28] Modules: only add drivers/ direcory if needed
@ 2007-02-14 20:03 Mariusz Kozlowski
  0 siblings, 0 replies; 32+ messages in thread
From: Mariusz Kozlowski @ 2007-02-14 20:03 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel

Hello, 

> @@ -1163,7 +1155,8 @@ static void mod_kobject_remove(struct module *mod)
>  {
>         module_remove_modinfo_attrs(mod);
>         module_param_sysfs_remove(mod);
> -       kobject_unregister(mod->mkobj.drivers_dir);
> +       if (mod->mkobj.drivers_dir)
> +               kobject_unregister(mod->mkobj.drivers_dir);
>  
>         kobject_unregister(&mod->mkobj.kobj);
>  }

This change looks superfluous on top of patch 1/28 where you'll find

 void kobject_unregister(struct kobject * kobj)
 {
+       if (!kobj)
+               return;

I went a bit further and prepared a patch removing all redundant
kobject_unregister argument checks.



Signed-off-by: Mariusz Kozlowski <m.kozlowski@tuxland.pl>

 drivers/base/class.c  |    3 +--
 fs/partitions/check.c |    9 +++------
 kernel/module.c       |    8 ++------
 3 files changed, 6 insertions(+), 14 deletions(-)

diff --git a/drivers/base/class.c b/drivers/base/class.c
index 96def1d..1417e5c 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -163,8 +163,7 @@ int class_register(struct class * cls)
 void class_unregister(struct class * cls)
 {
 	pr_debug("device class '%s': unregistering\n", cls->name);
-	if (cls->virtual_dir)
-		kobject_unregister(cls->virtual_dir);
+	kobject_unregister(cls->virtual_dir);
 	remove_class_attrs(cls);
 	subsystem_unregister(&cls->subsys);
 }
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index ac32a2e..22d38ff 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -358,8 +358,7 @@ void delete_partition(struct gendisk *disk, int part)
 	p->ios[0] = p->ios[1] = 0;
 	p->sectors[0] = p->sectors[1] = 0;
 	sysfs_remove_link(&p->kobj, "subsystem");
-	if (p->holder_dir)
-		kobject_unregister(p->holder_dir);
+	kobject_unregister(p->holder_dir);
 	kobject_uevent(&p->kobj, KOBJ_REMOVE);
 	kobject_del(&p->kobj);
 	kobject_put(&p->kobj);
@@ -603,10 +602,8 @@ void del_gendisk(struct gendisk *disk)
 	disk->stamp = 0;

 	kobject_uevent(&disk->kobj, KOBJ_REMOVE);
-	if (disk->holder_dir)
-		kobject_unregister(disk->holder_dir);
-	if (disk->slave_dir)
-		kobject_unregister(disk->slave_dir);
+	kobject_unregister(disk->holder_dir);
+	kobject_unregister(disk->slave_dir);
 	if (disk->driverfs_dev) {
 		char *disk_name = make_block_name(disk);
 		sysfs_remove_link(&disk->kobj, "device");
diff --git a/kernel/module.c b/kernel/module.c
index 8a94e05..53f10e8 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1174,11 +1174,8 @@ static void mod_kobject_remove(struct module *mod)
 {
 	module_remove_modinfo_attrs(mod);
 	module_param_sysfs_remove(mod);
-	if (mod->mkobj.drivers_dir)
-		kobject_unregister(mod->mkobj.drivers_dir);
-	if (mod->holders_dir)
-		kobject_unregister(mod->holders_dir);
-
+	kobject_unregister(mod->mkobj.drivers_dir);
+	kobject_unregister(mod->holders_dir);
 	kobject_unregister(&mod->mkobj.kobj);
 }

--
1.4.4.4

Regards,

	Mariusz Kozłowski

^ permalink raw reply related	[flat|nested] 32+ messages in thread

end of thread, other threads:[~2007-02-14 20:02 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-08  0:29 [GIT PATCH] Driver core patches for 2.6.20 Greg KH
2007-02-08  0:29 ` [PATCH 1/28] Kobject: make kobject apis more robust in handling NULL pointers Greg KH
2007-02-08  0:29   ` [PATCH 2/28] Driver core: convert pcmcia code to use struct device Greg KH
2007-02-08  0:29     ` [PATCH 3/28] Driver core: convert SPI " Greg KH
2007-02-08  0:29       ` [PATCH 4/28] Network: convert network devices to use struct device instead of class_device Greg KH
2007-02-08  0:29         ` [PATCH 5/28] driver core: Remove device_is_registered() in device_move() Greg KH
2007-02-08  0:29           ` [PATCH 6/28] driver core: Allow device_move(dev, NULL) Greg KH
2007-02-08  0:29             ` [PATCH 7/28] MODULES: add the module name for built in kernel drivers Greg KH
2007-02-08  0:29               ` [PATCH 8/28] Modules: only add drivers/ direcory if needed Greg KH
2007-02-08  0:29                 ` [PATCH 9/28] PCI: add the sysfs driver name to all modules Greg KH
2007-02-08  0:29                   ` [PATCH 10/28] SERIO: " Greg KH
2007-02-08  0:29                     ` [PATCH 11/28] USB: " Greg KH
2007-02-08  0:30                       ` [PATCH 12/28] /sys/modules/*/holders Greg KH
2007-02-08  0:30                         ` [PATCH 13/28] driver core fixes: make_class_name() retval checks Greg KH
2007-02-08  0:30                           ` [PATCH 14/28] driver core fixes: device_register() retval check in platform.c Greg KH
2007-02-08  0:30                             ` [PATCH 15/28] driver core: Don't stop probing on ->probe errors Greg KH
2007-02-08  0:30                               ` [PATCH 16/28] driver core: Change function call order in device_bind_driver() Greg KH
2007-02-08  0:30                                 ` [PATCH 17/28] Driver core: fix race in sysfs between sysfs_remove_file() and read()/write() Greg KH
2007-02-08  0:30                                   ` [PATCH 18/28] sysfs: suppress lockdep warnings Greg KH
2007-02-08  0:30                                     ` [PATCH 19/28] sysfs: kobject_put cleanup Greg KH
2007-02-08  0:30                                       ` [PATCH 20/28] kobject: " Greg KH
2007-02-08  0:30                                         ` [PATCH 21/28] sysfs: error handling in sysfs, fill_read_buffer() Greg KH
2007-02-08  0:30                                           ` [PATCH 22/28] HOWTO: Add a reference to Harbison and Steele Greg KH
2007-02-08  0:30                                             ` [PATCH 23/28] SYSFS: Fix missing include of list.h in sysfs.h Greg KH
2007-02-08  0:30                                               ` [PATCH 24/28] Driver core: add uevent vars for devices of a class Greg KH
2007-02-08  0:30                                                 ` [PATCH 25/28] Driver core: add device_type to struct device Greg KH
2007-02-08  0:30                                                   ` [PATCH 26/28] Driver core: allow to delay the uevent at device creation time Greg KH
2007-02-08  0:30                                                     ` [PATCH 27/28] Driver Core: Increase the default timeout value of the firmware subsystem Greg KH
2007-02-08  0:30                                                       ` [PATCH 28/28] sysfs: Shadow directory support Greg KH
2007-02-08 17:20                     ` [PATCH 10/28] SERIO: add the sysfs driver name to all modules Dmitry Torokhov
2007-02-08 18:51                       ` Greg KH
2007-02-14 20:03 [PATCH 8/28] Modules: only add drivers/ direcory if needed Mariusz Kozlowski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.