s390: time - convert sysdev_class to a regular subsystem

After all sysdev classes are ported to regular driver core entities, the
sysdev implementation will be entirely removed from the kernel.

Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Kay Sievers 2011-12-21 15:09:50 -08:00 committed by Greg Kroah-Hartman
parent 10fbcf4c6c
commit 3fbacffbe9

View file

@ -27,7 +27,7 @@
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/stop_machine.h> #include <linux/stop_machine.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/sysdev.h> #include <linux/device.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/smp.h> #include <linux/smp.h>
@ -1116,34 +1116,35 @@ static void etr_work_fn(struct work_struct *work)
/* /*
* Sysfs interface functions * Sysfs interface functions
*/ */
static struct sysdev_class etr_sysclass = { static struct bus_type etr_subsys = {
.name = "etr", .name = "etr",
.dev_name = "etr",
}; };
static struct sys_device etr_port0_dev = { static struct device etr_port0_dev = {
.id = 0, .id = 0,
.cls = &etr_sysclass, .bus = &etr_subsys,
}; };
static struct sys_device etr_port1_dev = { static struct device etr_port1_dev = {
.id = 1, .id = 1,
.cls = &etr_sysclass, .bus = &etr_subsys,
}; };
/* /*
* ETR class attributes * ETR subsys attributes
*/ */
static ssize_t etr_stepping_port_show(struct sysdev_class *class, static ssize_t etr_stepping_port_show(struct device *dev,
struct sysdev_class_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
return sprintf(buf, "%i\n", etr_port0.esw.p); return sprintf(buf, "%i\n", etr_port0.esw.p);
} }
static SYSDEV_CLASS_ATTR(stepping_port, 0400, etr_stepping_port_show, NULL); static DEVICE_ATTR(stepping_port, 0400, etr_stepping_port_show, NULL);
static ssize_t etr_stepping_mode_show(struct sysdev_class *class, static ssize_t etr_stepping_mode_show(struct device *dev,
struct sysdev_class_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
char *mode_str; char *mode_str;
@ -1157,12 +1158,12 @@ static ssize_t etr_stepping_mode_show(struct sysdev_class *class,
return sprintf(buf, "%s\n", mode_str); return sprintf(buf, "%s\n", mode_str);
} }
static SYSDEV_CLASS_ATTR(stepping_mode, 0400, etr_stepping_mode_show, NULL); static DEVICE_ATTR(stepping_mode, 0400, etr_stepping_mode_show, NULL);
/* /*
* ETR port attributes * ETR port attributes
*/ */
static inline struct etr_aib *etr_aib_from_dev(struct sys_device *dev) static inline struct etr_aib *etr_aib_from_dev(struct device *dev)
{ {
if (dev == &etr_port0_dev) if (dev == &etr_port0_dev)
return etr_port0_online ? &etr_port0 : NULL; return etr_port0_online ? &etr_port0 : NULL;
@ -1170,8 +1171,8 @@ static inline struct etr_aib *etr_aib_from_dev(struct sys_device *dev)
return etr_port1_online ? &etr_port1 : NULL; return etr_port1_online ? &etr_port1 : NULL;
} }
static ssize_t etr_online_show(struct sys_device *dev, static ssize_t etr_online_show(struct device *dev,
struct sysdev_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
unsigned int online; unsigned int online;
@ -1180,8 +1181,8 @@ static ssize_t etr_online_show(struct sys_device *dev,
return sprintf(buf, "%i\n", online); return sprintf(buf, "%i\n", online);
} }
static ssize_t etr_online_store(struct sys_device *dev, static ssize_t etr_online_store(struct device *dev,
struct sysdev_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
unsigned int value; unsigned int value;
@ -1218,20 +1219,20 @@ static ssize_t etr_online_store(struct sys_device *dev,
return count; return count;
} }
static SYSDEV_ATTR(online, 0600, etr_online_show, etr_online_store); static DEVICE_ATTR(online, 0600, etr_online_show, etr_online_store);
static ssize_t etr_stepping_control_show(struct sys_device *dev, static ssize_t etr_stepping_control_show(struct device *dev,
struct sysdev_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
return sprintf(buf, "%i\n", (dev == &etr_port0_dev) ? return sprintf(buf, "%i\n", (dev == &etr_port0_dev) ?
etr_eacr.e0 : etr_eacr.e1); etr_eacr.e0 : etr_eacr.e1);
} }
static SYSDEV_ATTR(stepping_control, 0400, etr_stepping_control_show, NULL); static DEVICE_ATTR(stepping_control, 0400, etr_stepping_control_show, NULL);
static ssize_t etr_mode_code_show(struct sys_device *dev, static ssize_t etr_mode_code_show(struct device *dev,
struct sysdev_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
if (!etr_port0_online && !etr_port1_online) if (!etr_port0_online && !etr_port1_online)
/* Status word is not uptodate if both ports are offline. */ /* Status word is not uptodate if both ports are offline. */
@ -1240,10 +1241,10 @@ static ssize_t etr_mode_code_show(struct sys_device *dev,
etr_port0.esw.psc0 : etr_port0.esw.psc1); etr_port0.esw.psc0 : etr_port0.esw.psc1);
} }
static SYSDEV_ATTR(state_code, 0400, etr_mode_code_show, NULL); static DEVICE_ATTR(state_code, 0400, etr_mode_code_show, NULL);
static ssize_t etr_untuned_show(struct sys_device *dev, static ssize_t etr_untuned_show(struct device *dev,
struct sysdev_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct etr_aib *aib = etr_aib_from_dev(dev); struct etr_aib *aib = etr_aib_from_dev(dev);
@ -1252,10 +1253,10 @@ static ssize_t etr_untuned_show(struct sys_device *dev,
return sprintf(buf, "%i\n", aib->edf1.u); return sprintf(buf, "%i\n", aib->edf1.u);
} }
static SYSDEV_ATTR(untuned, 0400, etr_untuned_show, NULL); static DEVICE_ATTR(untuned, 0400, etr_untuned_show, NULL);
static ssize_t etr_network_id_show(struct sys_device *dev, static ssize_t etr_network_id_show(struct device *dev,
struct sysdev_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct etr_aib *aib = etr_aib_from_dev(dev); struct etr_aib *aib = etr_aib_from_dev(dev);
@ -1264,10 +1265,10 @@ static ssize_t etr_network_id_show(struct sys_device *dev,
return sprintf(buf, "%i\n", aib->edf1.net_id); return sprintf(buf, "%i\n", aib->edf1.net_id);
} }
static SYSDEV_ATTR(network, 0400, etr_network_id_show, NULL); static DEVICE_ATTR(network, 0400, etr_network_id_show, NULL);
static ssize_t etr_id_show(struct sys_device *dev, static ssize_t etr_id_show(struct device *dev,
struct sysdev_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct etr_aib *aib = etr_aib_from_dev(dev); struct etr_aib *aib = etr_aib_from_dev(dev);
@ -1276,10 +1277,10 @@ static ssize_t etr_id_show(struct sys_device *dev,
return sprintf(buf, "%i\n", aib->edf1.etr_id); return sprintf(buf, "%i\n", aib->edf1.etr_id);
} }
static SYSDEV_ATTR(id, 0400, etr_id_show, NULL); static DEVICE_ATTR(id, 0400, etr_id_show, NULL);
static ssize_t etr_port_number_show(struct sys_device *dev, static ssize_t etr_port_number_show(struct device *dev,
struct sysdev_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct etr_aib *aib = etr_aib_from_dev(dev); struct etr_aib *aib = etr_aib_from_dev(dev);
@ -1288,10 +1289,10 @@ static ssize_t etr_port_number_show(struct sys_device *dev,
return sprintf(buf, "%i\n", aib->edf1.etr_pn); return sprintf(buf, "%i\n", aib->edf1.etr_pn);
} }
static SYSDEV_ATTR(port, 0400, etr_port_number_show, NULL); static DEVICE_ATTR(port, 0400, etr_port_number_show, NULL);
static ssize_t etr_coupled_show(struct sys_device *dev, static ssize_t etr_coupled_show(struct device *dev,
struct sysdev_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct etr_aib *aib = etr_aib_from_dev(dev); struct etr_aib *aib = etr_aib_from_dev(dev);
@ -1300,10 +1301,10 @@ static ssize_t etr_coupled_show(struct sys_device *dev,
return sprintf(buf, "%i\n", aib->edf3.c); return sprintf(buf, "%i\n", aib->edf3.c);
} }
static SYSDEV_ATTR(coupled, 0400, etr_coupled_show, NULL); static DEVICE_ATTR(coupled, 0400, etr_coupled_show, NULL);
static ssize_t etr_local_time_show(struct sys_device *dev, static ssize_t etr_local_time_show(struct device *dev,
struct sysdev_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct etr_aib *aib = etr_aib_from_dev(dev); struct etr_aib *aib = etr_aib_from_dev(dev);
@ -1312,10 +1313,10 @@ static ssize_t etr_local_time_show(struct sys_device *dev,
return sprintf(buf, "%i\n", aib->edf3.blto); return sprintf(buf, "%i\n", aib->edf3.blto);
} }
static SYSDEV_ATTR(local_time, 0400, etr_local_time_show, NULL); static DEVICE_ATTR(local_time, 0400, etr_local_time_show, NULL);
static ssize_t etr_utc_offset_show(struct sys_device *dev, static ssize_t etr_utc_offset_show(struct device *dev,
struct sysdev_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct etr_aib *aib = etr_aib_from_dev(dev); struct etr_aib *aib = etr_aib_from_dev(dev);
@ -1324,64 +1325,64 @@ static ssize_t etr_utc_offset_show(struct sys_device *dev,
return sprintf(buf, "%i\n", aib->edf3.buo); return sprintf(buf, "%i\n", aib->edf3.buo);
} }
static SYSDEV_ATTR(utc_offset, 0400, etr_utc_offset_show, NULL); static DEVICE_ATTR(utc_offset, 0400, etr_utc_offset_show, NULL);
static struct sysdev_attribute *etr_port_attributes[] = { static struct device_attribute *etr_port_attributes[] = {
&attr_online, &dev_attr_online,
&attr_stepping_control, &dev_attr_stepping_control,
&attr_state_code, &dev_attr_state_code,
&attr_untuned, &dev_attr_untuned,
&attr_network, &dev_attr_network,
&attr_id, &dev_attr_id,
&attr_port, &dev_attr_port,
&attr_coupled, &dev_attr_coupled,
&attr_local_time, &dev_attr_local_time,
&attr_utc_offset, &dev_attr_utc_offset,
NULL NULL
}; };
static int __init etr_register_port(struct sys_device *dev) static int __init etr_register_port(struct device *dev)
{ {
struct sysdev_attribute **attr; struct device_attribute **attr;
int rc; int rc;
rc = sysdev_register(dev); rc = device_register(dev);
if (rc) if (rc)
goto out; goto out;
for (attr = etr_port_attributes; *attr; attr++) { for (attr = etr_port_attributes; *attr; attr++) {
rc = sysdev_create_file(dev, *attr); rc = device_create_file(dev, *attr);
if (rc) if (rc)
goto out_unreg; goto out_unreg;
} }
return 0; return 0;
out_unreg: out_unreg:
for (; attr >= etr_port_attributes; attr--) for (; attr >= etr_port_attributes; attr--)
sysdev_remove_file(dev, *attr); device_remove_file(dev, *attr);
sysdev_unregister(dev); device_unregister(dev);
out: out:
return rc; return rc;
} }
static void __init etr_unregister_port(struct sys_device *dev) static void __init etr_unregister_port(struct device *dev)
{ {
struct sysdev_attribute **attr; struct device_attribute **attr;
for (attr = etr_port_attributes; *attr; attr++) for (attr = etr_port_attributes; *attr; attr++)
sysdev_remove_file(dev, *attr); device_remove_file(dev, *attr);
sysdev_unregister(dev); device_unregister(dev);
} }
static int __init etr_init_sysfs(void) static int __init etr_init_sysfs(void)
{ {
int rc; int rc;
rc = sysdev_class_register(&etr_sysclass); rc = subsys_system_register(&etr_subsys, NULL);
if (rc) if (rc)
goto out; goto out;
rc = sysdev_class_create_file(&etr_sysclass, &attr_stepping_port); rc = device_create_file(etr_subsys.dev_root, &dev_attr_stepping_port);
if (rc) if (rc)
goto out_unreg_class; goto out_unreg_subsys;
rc = sysdev_class_create_file(&etr_sysclass, &attr_stepping_mode); rc = device_create_file(etr_subsys.dev_root, &dev_attr_stepping_mode);
if (rc) if (rc)
goto out_remove_stepping_port; goto out_remove_stepping_port;
rc = etr_register_port(&etr_port0_dev); rc = etr_register_port(&etr_port0_dev);
@ -1395,11 +1396,11 @@ static int __init etr_init_sysfs(void)
out_remove_port0: out_remove_port0:
etr_unregister_port(&etr_port0_dev); etr_unregister_port(&etr_port0_dev);
out_remove_stepping_mode: out_remove_stepping_mode:
sysdev_class_remove_file(&etr_sysclass, &attr_stepping_mode); device_remove_file(etr_subsys.dev_root, &dev_attr_stepping_mode);
out_remove_stepping_port: out_remove_stepping_port:
sysdev_class_remove_file(&etr_sysclass, &attr_stepping_port); device_remove_file(etr_subsys.dev_root, &dev_attr_stepping_port);
out_unreg_class: out_unreg_subsys:
sysdev_class_unregister(&etr_sysclass); bus_unregister(&etr_subsys);
out: out:
return rc; return rc;
} }
@ -1599,14 +1600,15 @@ static void stp_work_fn(struct work_struct *work)
} }
/* /*
* STP class sysfs interface functions * STP subsys sysfs interface functions
*/ */
static struct sysdev_class stp_sysclass = { static struct bus_type stp_subsys = {
.name = "stp", .name = "stp",
.dev_name = "stp",
}; };
static ssize_t stp_ctn_id_show(struct sysdev_class *class, static ssize_t stp_ctn_id_show(struct device *dev,
struct sysdev_class_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
if (!stp_online) if (!stp_online)
@ -1615,10 +1617,10 @@ static ssize_t stp_ctn_id_show(struct sysdev_class *class,
*(unsigned long long *) stp_info.ctnid); *(unsigned long long *) stp_info.ctnid);
} }
static SYSDEV_CLASS_ATTR(ctn_id, 0400, stp_ctn_id_show, NULL); static DEVICE_ATTR(ctn_id, 0400, stp_ctn_id_show, NULL);
static ssize_t stp_ctn_type_show(struct sysdev_class *class, static ssize_t stp_ctn_type_show(struct device *dev,
struct sysdev_class_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
if (!stp_online) if (!stp_online)
@ -1626,10 +1628,10 @@ static ssize_t stp_ctn_type_show(struct sysdev_class *class,
return sprintf(buf, "%i\n", stp_info.ctn); return sprintf(buf, "%i\n", stp_info.ctn);
} }
static SYSDEV_CLASS_ATTR(ctn_type, 0400, stp_ctn_type_show, NULL); static DEVICE_ATTR(ctn_type, 0400, stp_ctn_type_show, NULL);
static ssize_t stp_dst_offset_show(struct sysdev_class *class, static ssize_t stp_dst_offset_show(struct device *dev,
struct sysdev_class_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
if (!stp_online || !(stp_info.vbits & 0x2000)) if (!stp_online || !(stp_info.vbits & 0x2000))
@ -1637,10 +1639,10 @@ static ssize_t stp_dst_offset_show(struct sysdev_class *class,
return sprintf(buf, "%i\n", (int)(s16) stp_info.dsto); return sprintf(buf, "%i\n", (int)(s16) stp_info.dsto);
} }
static SYSDEV_CLASS_ATTR(dst_offset, 0400, stp_dst_offset_show, NULL); static DEVICE_ATTR(dst_offset, 0400, stp_dst_offset_show, NULL);
static ssize_t stp_leap_seconds_show(struct sysdev_class *class, static ssize_t stp_leap_seconds_show(struct device *dev,
struct sysdev_class_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
if (!stp_online || !(stp_info.vbits & 0x8000)) if (!stp_online || !(stp_info.vbits & 0x8000))
@ -1648,10 +1650,10 @@ static ssize_t stp_leap_seconds_show(struct sysdev_class *class,
return sprintf(buf, "%i\n", (int)(s16) stp_info.leaps); return sprintf(buf, "%i\n", (int)(s16) stp_info.leaps);
} }
static SYSDEV_CLASS_ATTR(leap_seconds, 0400, stp_leap_seconds_show, NULL); static DEVICE_ATTR(leap_seconds, 0400, stp_leap_seconds_show, NULL);
static ssize_t stp_stratum_show(struct sysdev_class *class, static ssize_t stp_stratum_show(struct device *dev,
struct sysdev_class_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
if (!stp_online) if (!stp_online)
@ -1659,10 +1661,10 @@ static ssize_t stp_stratum_show(struct sysdev_class *class,
return sprintf(buf, "%i\n", (int)(s16) stp_info.stratum); return sprintf(buf, "%i\n", (int)(s16) stp_info.stratum);
} }
static SYSDEV_CLASS_ATTR(stratum, 0400, stp_stratum_show, NULL); static DEVICE_ATTR(stratum, 0400, stp_stratum_show, NULL);
static ssize_t stp_time_offset_show(struct sysdev_class *class, static ssize_t stp_time_offset_show(struct device *dev,
struct sysdev_class_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
if (!stp_online || !(stp_info.vbits & 0x0800)) if (!stp_online || !(stp_info.vbits & 0x0800))
@ -1670,10 +1672,10 @@ static ssize_t stp_time_offset_show(struct sysdev_class *class,
return sprintf(buf, "%i\n", (int) stp_info.tto); return sprintf(buf, "%i\n", (int) stp_info.tto);
} }
static SYSDEV_CLASS_ATTR(time_offset, 0400, stp_time_offset_show, NULL); static DEVICE_ATTR(time_offset, 0400, stp_time_offset_show, NULL);
static ssize_t stp_time_zone_offset_show(struct sysdev_class *class, static ssize_t stp_time_zone_offset_show(struct device *dev,
struct sysdev_class_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
if (!stp_online || !(stp_info.vbits & 0x4000)) if (!stp_online || !(stp_info.vbits & 0x4000))
@ -1681,11 +1683,11 @@ static ssize_t stp_time_zone_offset_show(struct sysdev_class *class,
return sprintf(buf, "%i\n", (int)(s16) stp_info.tzo); return sprintf(buf, "%i\n", (int)(s16) stp_info.tzo);
} }
static SYSDEV_CLASS_ATTR(time_zone_offset, 0400, static DEVICE_ATTR(time_zone_offset, 0400,
stp_time_zone_offset_show, NULL); stp_time_zone_offset_show, NULL);
static ssize_t stp_timing_mode_show(struct sysdev_class *class, static ssize_t stp_timing_mode_show(struct device *dev,
struct sysdev_class_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
if (!stp_online) if (!stp_online)
@ -1693,10 +1695,10 @@ static ssize_t stp_timing_mode_show(struct sysdev_class *class,
return sprintf(buf, "%i\n", stp_info.tmd); return sprintf(buf, "%i\n", stp_info.tmd);
} }
static SYSDEV_CLASS_ATTR(timing_mode, 0400, stp_timing_mode_show, NULL); static DEVICE_ATTR(timing_mode, 0400, stp_timing_mode_show, NULL);
static ssize_t stp_timing_state_show(struct sysdev_class *class, static ssize_t stp_timing_state_show(struct device *dev,
struct sysdev_class_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
if (!stp_online) if (!stp_online)
@ -1704,17 +1706,17 @@ static ssize_t stp_timing_state_show(struct sysdev_class *class,
return sprintf(buf, "%i\n", stp_info.tst); return sprintf(buf, "%i\n", stp_info.tst);
} }
static SYSDEV_CLASS_ATTR(timing_state, 0400, stp_timing_state_show, NULL); static DEVICE_ATTR(timing_state, 0400, stp_timing_state_show, NULL);
static ssize_t stp_online_show(struct sysdev_class *class, static ssize_t stp_online_show(struct device *dev,
struct sysdev_class_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
return sprintf(buf, "%i\n", stp_online); return sprintf(buf, "%i\n", stp_online);
} }
static ssize_t stp_online_store(struct sysdev_class *class, static ssize_t stp_online_store(struct device *dev,
struct sysdev_class_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
unsigned int value; unsigned int value;
@ -1736,47 +1738,47 @@ static ssize_t stp_online_store(struct sysdev_class *class,
} }
/* /*
* Can't use SYSDEV_CLASS_ATTR because the attribute should be named * Can't use DEVICE_ATTR because the attribute should be named
* stp/online but attr_online already exists in this file .. * stp/online but dev_attr_online already exists in this file ..
*/ */
static struct sysdev_class_attribute attr_stp_online = { static struct device_attribute dev_attr_stp_online = {
.attr = { .name = "online", .mode = 0600 }, .attr = { .name = "online", .mode = 0600 },
.show = stp_online_show, .show = stp_online_show,
.store = stp_online_store, .store = stp_online_store,
}; };
static struct sysdev_class_attribute *stp_attributes[] = { static struct device_attribute *stp_attributes[] = {
&attr_ctn_id, &dev_attr_ctn_id,
&attr_ctn_type, &dev_attr_ctn_type,
&attr_dst_offset, &dev_attr_dst_offset,
&attr_leap_seconds, &dev_attr_leap_seconds,
&attr_stp_online, &dev_attr_stp_online,
&attr_stratum, &dev_attr_stratum,
&attr_time_offset, &dev_attr_time_offset,
&attr_time_zone_offset, &dev_attr_time_zone_offset,
&attr_timing_mode, &dev_attr_timing_mode,
&attr_timing_state, &dev_attr_timing_state,
NULL NULL
}; };
static int __init stp_init_sysfs(void) static int __init stp_init_sysfs(void)
{ {
struct sysdev_class_attribute **attr; struct device_attribute **attr;
int rc; int rc;
rc = sysdev_class_register(&stp_sysclass); rc = subsys_system_register(&stp_subsys, NULL);
if (rc) if (rc)
goto out; goto out;
for (attr = stp_attributes; *attr; attr++) { for (attr = stp_attributes; *attr; attr++) {
rc = sysdev_class_create_file(&stp_sysclass, *attr); rc = device_create_file(stp_subsys.dev_root, *attr);
if (rc) if (rc)
goto out_unreg; goto out_unreg;
} }
return 0; return 0;
out_unreg: out_unreg:
for (; attr >= stp_attributes; attr--) for (; attr >= stp_attributes; attr--)
sysdev_class_remove_file(&stp_sysclass, *attr); device_remove_file(stp_subsys.dev_root, *attr);
sysdev_class_unregister(&stp_sysclass); bus_unregister(&stp_subsys);
out: out:
return rc; return rc;
} }