Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe9925b5 authored by Stephen Hemminger's avatar Stephen Hemminger Committed by David S. Miller
Browse files

[NET]: Create netdev attribute_groups with class_device_add



Atomically create attributes when class device is added. This avoids
the race between registering class_device (which generates hotplug
event), and the creation of attribute groups.

Signed-off-by: default avatarStephen Hemminger <shemminger@osdl.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1498221d
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -506,6 +506,8 @@ struct net_device

	/* class/net/name entry */
	struct class_device	class_dev;
	/* space for optional statistics and wireless sysfs groups */
	struct attribute_group  *sysfs_groups[3];
};

#define	NETDEV_ALIGN		32
+1 −1
Original line number Diff line number Diff line
@@ -3043,11 +3043,11 @@ void netdev_run_todo(void)

		switch(dev->reg_state) {
		case NETREG_REGISTERING:
			dev->reg_state = NETREG_REGISTERED;
			err = netdev_register_sysfs(dev);
			if (err)
				printk(KERN_ERR "%s: failed sysfs registration (%d)\n",
				       dev->name, err);
			dev->reg_state = NETREG_REGISTERED;
			break;

		case NETREG_UNREGISTERING:
+12 −37
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ static const char fmt_ulong[] = "%lu\n";

static inline int dev_isalive(const struct net_device *dev) 
{
	return dev->reg_state == NETREG_REGISTERED;
	return dev->reg_state <= NETREG_REGISTERED;
}

/* use same locking rules as GIF* ioctl's */
@@ -445,58 +445,33 @@ static struct class net_class = {

void netdev_unregister_sysfs(struct net_device * net)
{
	struct class_device * class_dev = &(net->class_dev);

	if (net->get_stats)
		sysfs_remove_group(&class_dev->kobj, &netstat_group);

#ifdef WIRELESS_EXT
	if (net->get_wireless_stats || (net->wireless_handlers &&
			net->wireless_handlers->get_wireless_stats))
		sysfs_remove_group(&class_dev->kobj, &wireless_group);
#endif
	class_device_del(class_dev);

	class_device_del(&(net->class_dev));
}

/* Create sysfs entries for network device. */
int netdev_register_sysfs(struct net_device *net)
{
	struct class_device *class_dev = &(net->class_dev);
	int ret;
	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;

	BUILD_BUG_ON(BUS_ID_SIZE < IFNAMSIZ);
	strlcpy(class_dev->class_id, net->name, BUS_ID_SIZE);
	if ((ret = class_device_register(class_dev)))
		goto out;

	if (net->get_stats &&
	    (ret = sysfs_create_group(&class_dev->kobj, &netstat_group)))
		goto out_unreg; 
	if (net->get_stats)
		*groups++ = &netstat_group;

#ifdef WIRELESS_EXT
	if (net->get_wireless_stats || (net->wireless_handlers &&
			net->wireless_handlers->get_wireless_stats)) {
		ret = sysfs_create_group(&class_dev->kobj, &wireless_group);
		if (ret)
			goto out_cleanup;
	}
	return 0;
out_cleanup:
	if (net->get_stats)
		sysfs_remove_group(&class_dev->kobj, &netstat_group);
#else
	return 0;
	if (net->get_wireless_stats
	    || (net->wireless_handlers && net->wireless_handlers->get_wireless_stats))
		*groups++ = &wireless_group;
#endif

out_unreg:
	printk(KERN_WARNING "%s: sysfs attribute registration failed %d\n",
	       net->name, ret);
	class_device_unregister(class_dev);
out:
	return ret;
	return class_device_add(class_dev);
}

int netdev_sysfs_init(void)