提交 0324e745 编写于 作者: L Linus Torvalds

Merge tag 'driver-core-3.13-rc1' of...

Merge tag 'driver-core-3.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core

Pull driver core / sysfs patches from Greg KH:
 "Here's the big driver core / sysfs update for 3.13-rc1.

  There's lots of dev_groups updates for different subsystems, as they
  all get slowly migrated over to the safe versions of the attribute
  groups (removing userspace races with the creation of the sysfs
  files.) Also in here are some kobject updates, devres expansions, and
  the first round of Tejun's sysfs reworking to enable it to be used by
  other subsystems as a backend for an in-kernel filesystem.

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'driver-core-3.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (83 commits)
  sysfs: rename sysfs_assoc_lock and explain what it's about
  sysfs: use generic_file_llseek() for sysfs_file_operations
  sysfs: return correct error code on unimplemented mmap()
  mdio_bus: convert bus code to use dev_groups
  device: Make dev_WARN/dev_WARN_ONCE print device as well as driver name
  sysfs: separate out dup filename warning into a separate function
  sysfs: move sysfs_hash_and_remove() to fs/sysfs/dir.c
  sysfs: remove unused sysfs_get_dentry() prototype
  sysfs: honor bin_attr.attr.ignore_lockdep
  sysfs: merge sysfs_elem_bin_attr into sysfs_elem_attr
  devres: restore zeroing behavior of devres_alloc()
  sysfs: fix sysfs_write_file for bin file
  input: gameport: convert bus code to use dev_groups
  input: serio: remove bus usage of dev_attrs
  input: serio: use DEVICE_ATTR_RO()
  i2o: convert bus code to use dev_groups
  memstick: convert bus code to use dev_groups
  tifm: convert bus code to use dev_groups
  virtio: convert bus code to use dev_groups
  ipack: convert bus code to use dev_groups
  ...
......@@ -91,7 +91,6 @@
<title>The Filesystem for Exporting Kernel Objects</title>
!Efs/sysfs/file.c
!Efs/sysfs/symlink.c
!Efs/sysfs/bin.c
</chapter>
<chapter id="debugfs">
......
......@@ -292,6 +292,7 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
return rc;
return count;
}
static BUS_ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe);
static ssize_t ibmebus_store_remove(struct bus_type *bus,
const char *buf, size_t count)
......@@ -317,13 +318,14 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus,
return -ENODEV;
}
}
static BUS_ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove);
static struct bus_attribute ibmebus_bus_attrs[] = {
__ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe),
__ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove),
__ATTR_NULL
static struct attribute *ibmbus_bus_attrs[] = {
&bus_attr_probe.attr,
&bus_attr_remove.attr,
NULL,
};
ATTRIBUTE_GROUPS(ibmbus_bus);
static int ibmebus_bus_bus_match(struct device *dev, struct device_driver *drv)
{
......@@ -713,7 +715,7 @@ static struct dev_pm_ops ibmebus_bus_dev_pm_ops = {
struct bus_type ibmebus_bus_type = {
.name = "ibmebus",
.uevent = of_device_uevent_modalias,
.bus_attrs = ibmebus_bus_attrs,
.bus_groups = ibmbus_bus_groups,
.match = ibmebus_bus_bus_match,
.probe = ibmebus_bus_device_probe,
.remove = ibmebus_bus_device_remove,
......
......@@ -997,21 +997,36 @@ static struct device_attribute vio_cmo_dev_attrs[] = {
/* sysfs bus functions and data structures for CMO */
#define viobus_cmo_rd_attr(name) \
static ssize_t \
viobus_cmo_##name##_show(struct bus_type *bt, char *buf) \
static ssize_t cmo_##name##_show(struct bus_type *bt, char *buf) \
{ \
return sprintf(buf, "%lu\n", vio_cmo.name); \
}
} \
static BUS_ATTR_RO(cmo_##name)
#define viobus_cmo_pool_rd_attr(name, var) \
static ssize_t \
viobus_cmo_##name##_pool_show_##var(struct bus_type *bt, char *buf) \
cmo_##name##_##var##_show(struct bus_type *bt, char *buf) \
{ \
return sprintf(buf, "%lu\n", vio_cmo.name.var); \
} \
static BUS_ATTR_RO(cmo_##name##_##var)
viobus_cmo_rd_attr(entitled);
viobus_cmo_rd_attr(spare);
viobus_cmo_rd_attr(min);
viobus_cmo_rd_attr(desired);
viobus_cmo_rd_attr(curr);
viobus_cmo_pool_rd_attr(reserve, size);
viobus_cmo_pool_rd_attr(excess, size);
viobus_cmo_pool_rd_attr(excess, free);
static ssize_t cmo_high_show(struct bus_type *bt, char *buf)
{
return sprintf(buf, "%lu\n", vio_cmo.high);
}
static ssize_t viobus_cmo_high_reset(struct bus_type *bt, const char *buf,
size_t count)
static ssize_t cmo_high_store(struct bus_type *bt, const char *buf,
size_t count)
{
unsigned long flags;
......@@ -1021,35 +1036,26 @@ static ssize_t viobus_cmo_high_reset(struct bus_type *bt, const char *buf,
return count;
}
viobus_cmo_rd_attr(entitled);
viobus_cmo_pool_rd_attr(reserve, size);
viobus_cmo_pool_rd_attr(excess, size);
viobus_cmo_pool_rd_attr(excess, free);
viobus_cmo_rd_attr(spare);
viobus_cmo_rd_attr(min);
viobus_cmo_rd_attr(desired);
viobus_cmo_rd_attr(curr);
viobus_cmo_rd_attr(high);
static struct bus_attribute vio_cmo_bus_attrs[] = {
__ATTR(cmo_entitled, S_IRUGO, viobus_cmo_entitled_show, NULL),
__ATTR(cmo_reserve_size, S_IRUGO, viobus_cmo_reserve_pool_show_size, NULL),
__ATTR(cmo_excess_size, S_IRUGO, viobus_cmo_excess_pool_show_size, NULL),
__ATTR(cmo_excess_free, S_IRUGO, viobus_cmo_excess_pool_show_free, NULL),
__ATTR(cmo_spare, S_IRUGO, viobus_cmo_spare_show, NULL),
__ATTR(cmo_min, S_IRUGO, viobus_cmo_min_show, NULL),
__ATTR(cmo_desired, S_IRUGO, viobus_cmo_desired_show, NULL),
__ATTR(cmo_curr, S_IRUGO, viobus_cmo_curr_show, NULL),
__ATTR(cmo_high, S_IWUSR|S_IRUSR|S_IWGRP|S_IRGRP|S_IROTH,
viobus_cmo_high_show, viobus_cmo_high_reset),
__ATTR_NULL
static BUS_ATTR_RW(cmo_high);
static struct attribute *vio_bus_attrs[] = {
&bus_attr_cmo_entitled.attr,
&bus_attr_cmo_spare.attr,
&bus_attr_cmo_min.attr,
&bus_attr_cmo_desired.attr,
&bus_attr_cmo_curr.attr,
&bus_attr_cmo_high.attr,
&bus_attr_cmo_reserve_size.attr,
&bus_attr_cmo_excess_size.attr,
&bus_attr_cmo_excess_free.attr,
NULL,
};
ATTRIBUTE_GROUPS(vio_bus);
static void vio_cmo_sysfs_init(void)
{
vio_bus_type.dev_attrs = vio_cmo_dev_attrs;
vio_bus_type.bus_attrs = vio_cmo_bus_attrs;
vio_bus_type.bus_groups = vio_bus_groups;
}
#else /* CONFIG_PPC_SMLPAR */
int vio_cmo_entitlement_update(size_t new_entitlement) { return 0; }
......
......@@ -591,37 +591,6 @@ void bus_remove_device(struct device *dev)
bus_put(dev->bus);
}
static int driver_add_attrs(struct bus_type *bus, struct device_driver *drv)
{
int error = 0;
int i;
if (bus->drv_attrs) {
for (i = 0; bus->drv_attrs[i].attr.name; i++) {
error = driver_create_file(drv, &bus->drv_attrs[i]);
if (error)
goto err;
}
}
done:
return error;
err:
while (--i >= 0)
driver_remove_file(drv, &bus->drv_attrs[i]);
goto done;
}
static void driver_remove_attrs(struct bus_type *bus,
struct device_driver *drv)
{
int i;
if (bus->drv_attrs) {
for (i = 0; bus->drv_attrs[i].attr.name; i++)
driver_remove_file(drv, &bus->drv_attrs[i]);
}
}
static int __must_check add_bind_files(struct device_driver *drv)
{
int ret;
......@@ -720,16 +689,12 @@ int bus_add_driver(struct device_driver *drv)
printk(KERN_ERR "%s: uevent attr (%s) failed\n",
__func__, drv->name);
}
error = driver_add_attrs(bus, drv);
error = driver_add_groups(drv, bus->drv_groups);
if (error) {
/* How the hell do we get out of this pickle? Give up */
printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
__func__, drv->name);
}
error = driver_add_groups(drv, bus->drv_groups);
if (error)
printk(KERN_ERR "%s: driver_create_groups(%s) failed\n",
__func__, drv->name);
}
if (!drv->suppress_bind_attrs) {
error = add_bind_files(drv);
......@@ -766,7 +731,6 @@ void bus_remove_driver(struct device_driver *drv)
if (!drv->suppress_bind_attrs)
remove_bind_files(drv);
driver_remove_attrs(drv->bus, drv);
driver_remove_groups(drv, drv->bus->drv_groups);
driver_remove_file(drv, &driver_attr_uevent);
klist_remove(&drv->p->knode_bus);
......@@ -846,42 +810,6 @@ struct bus_type *find_bus(char *name)
}
#endif /* 0 */
/**
* bus_add_attrs - Add default attributes for this bus.
* @bus: Bus that has just been registered.
*/
static int bus_add_attrs(struct bus_type *bus)
{
int error = 0;
int i;
if (bus->bus_attrs) {
for (i = 0; bus->bus_attrs[i].attr.name; i++) {
error = bus_create_file(bus, &bus->bus_attrs[i]);
if (error)
goto err;
}
}
done:
return error;
err:
while (--i >= 0)
bus_remove_file(bus, &bus->bus_attrs[i]);
goto done;
}
static void bus_remove_attrs(struct bus_type *bus)
{
int i;
if (bus->bus_attrs) {
for (i = 0; bus->bus_attrs[i].attr.name; i++)
bus_remove_file(bus, &bus->bus_attrs[i]);
}
}
static int bus_add_groups(struct bus_type *bus,
const struct attribute_group **groups)
{
......@@ -983,9 +911,6 @@ int bus_register(struct bus_type *bus)
if (retval)
goto bus_probe_files_fail;
retval = bus_add_attrs(bus);
if (retval)
goto bus_attrs_fail;
retval = bus_add_groups(bus, bus->bus_groups);
if (retval)
goto bus_groups_fail;
......@@ -994,8 +919,6 @@ int bus_register(struct bus_type *bus)
return 0;
bus_groups_fail:
bus_remove_attrs(bus);
bus_attrs_fail:
remove_probe_files(bus);
bus_probe_files_fail:
kset_unregister(bus->p->drivers_kset);
......@@ -1024,7 +947,6 @@ void bus_unregister(struct bus_type *bus)
pr_debug("bus: '%s': unregistering\n", bus->name);
if (bus->dev_root)
device_unregister(bus->dev_root);
bus_remove_attrs(bus);
bus_remove_groups(bus, bus->bus_groups);
remove_probe_files(bus);
kset_unregister(bus->p->drivers_kset);
......
......@@ -47,18 +47,6 @@ static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr,
return ret;
}
static const void *class_attr_namespace(struct kobject *kobj,
const struct attribute *attr)
{
struct class_attribute *class_attr = to_class_attr(attr);
struct subsys_private *cp = to_subsys_private(kobj);
const void *ns = NULL;
if (class_attr->namespace)
ns = class_attr->namespace(cp->class, class_attr);
return ns;
}
static void class_release(struct kobject *kobj)
{
struct subsys_private *cp = to_subsys_private(kobj);
......@@ -86,7 +74,6 @@ static const struct kobj_ns_type_operations *class_child_ns_type(struct kobject
static const struct sysfs_ops class_sysfs_ops = {
.show = class_attr_show,
.store = class_attr_store,
.namespace = class_attr_namespace,
};
static struct kobj_type class_ktype = {
......@@ -99,21 +86,23 @@ static struct kobj_type class_ktype = {
static struct kset *class_kset;
int class_create_file(struct class *cls, const struct class_attribute *attr)
int class_create_file_ns(struct class *cls, const struct class_attribute *attr,
const void *ns)
{
int error;
if (cls)
error = sysfs_create_file(&cls->p->subsys.kobj,
&attr->attr);
error = sysfs_create_file_ns(&cls->p->subsys.kobj,
&attr->attr, ns);
else
error = -EINVAL;
return error;
}
void class_remove_file(struct class *cls, const struct class_attribute *attr)
void class_remove_file_ns(struct class *cls, const struct class_attribute *attr,
const void *ns)
{
if (cls)
sysfs_remove_file(&cls->p->subsys.kobj, &attr->attr);
sysfs_remove_file_ns(&cls->p->subsys.kobj, &attr->attr, ns);
}
static struct class *class_get(struct class *cls)
......@@ -600,8 +589,8 @@ int __init classes_init(void)
return 0;
}
EXPORT_SYMBOL_GPL(class_create_file);
EXPORT_SYMBOL_GPL(class_remove_file);
EXPORT_SYMBOL_GPL(class_create_file_ns);
EXPORT_SYMBOL_GPL(class_remove_file_ns);
EXPORT_SYMBOL_GPL(class_unregister);
EXPORT_SYMBOL_GPL(class_destroy);
......
......@@ -455,64 +455,6 @@ static ssize_t online_store(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RW(online);
static int device_add_attributes(struct device *dev,
struct device_attribute *attrs)
{
int error = 0;
int i;
if (attrs) {
for (i = 0; attrs[i].attr.name; i++) {
error = device_create_file(dev, &attrs[i]);
if (error)
break;
}
if (error)
while (--i >= 0)
device_remove_file(dev, &attrs[i]);
}
return error;
}
static void device_remove_attributes(struct device *dev,
struct device_attribute *attrs)
{
int i;
if (attrs)
for (i = 0; attrs[i].attr.name; i++)
device_remove_file(dev, &attrs[i]);
}
static int device_add_bin_attributes(struct device *dev,
struct bin_attribute *attrs)
{
int error = 0;
int i;
if (attrs) {
for (i = 0; attrs[i].attr.name; i++) {
error = device_create_bin_file(dev, &attrs[i]);
if (error)
break;
}
if (error)
while (--i >= 0)
device_remove_bin_file(dev, &attrs[i]);
}
return error;
}
static void device_remove_bin_attributes(struct device *dev,
struct bin_attribute *attrs)
{
int i;
if (attrs)
for (i = 0; attrs[i].attr.name; i++)
device_remove_bin_file(dev, &attrs[i]);
}
int device_add_groups(struct device *dev, const struct attribute_group **groups)
{
return sysfs_create_groups(&dev->kobj, groups);
......@@ -534,18 +476,12 @@ static int device_add_attrs(struct device *dev)
error = device_add_groups(dev, class->dev_groups);
if (error)
return error;
error = device_add_attributes(dev, class->dev_attrs);
if (error)
goto err_remove_class_groups;
error = device_add_bin_attributes(dev, class->dev_bin_attrs);
if (error)
goto err_remove_class_attrs;
}
if (type) {
error = device_add_groups(dev, type->groups);
if (error)
goto err_remove_class_bin_attrs;
goto err_remove_class_groups;
}
error = device_add_groups(dev, dev->groups);
......@@ -563,12 +499,6 @@ static int device_add_attrs(struct device *dev)
err_remove_type_groups:
if (type)
device_remove_groups(dev, type->groups);
err_remove_class_bin_attrs:
if (class)
device_remove_bin_attributes(dev, class->dev_bin_attrs);
err_remove_class_attrs:
if (class)
device_remove_attributes(dev, class->dev_attrs);
err_remove_class_groups:
if (class)
device_remove_groups(dev, class->dev_groups);
......@@ -587,11 +517,8 @@ static void device_remove_attrs(struct device *dev)
if (type)
device_remove_groups(dev, type->groups);
if (class) {
device_remove_attributes(dev, class->dev_attrs);
device_remove_bin_attributes(dev, class->dev_bin_attrs);
if (class)
device_remove_groups(dev, class->dev_groups);
}
}
static ssize_t dev_show(struct device *dev, struct device_attribute *attr,
......@@ -1881,6 +1808,7 @@ EXPORT_SYMBOL_GPL(device_destroy);
*/
int device_rename(struct device *dev, const char *new_name)
{
struct kobject *kobj = &dev->kobj;
char *old_device_name = NULL;
int error;
......@@ -1888,8 +1816,7 @@ int device_rename(struct device *dev, const char *new_name)
if (!dev)
return -EINVAL;
pr_debug("device: '%s': %s: renaming to '%s'\n", dev_name(dev),
__func__, new_name);
dev_dbg(dev, "renaming to %s\n", new_name);
old_device_name = kstrdup(dev_name(dev), GFP_KERNEL);
if (!old_device_name) {
......@@ -1898,13 +1825,14 @@ int device_rename(struct device *dev, const char *new_name)
}
if (dev->class) {
error = sysfs_rename_link(&dev->class->p->subsys.kobj,
&dev->kobj, old_device_name, new_name);
error = sysfs_rename_link_ns(&dev->class->p->subsys.kobj,
kobj, old_device_name,
new_name, kobject_namespace(kobj));
if (error)
goto out;
}
error = kobject_rename(&dev->kobj, new_name);
error = kobject_rename(kobj, new_name);
if (error)
goto out;
......
......@@ -91,7 +91,8 @@ static __always_inline struct devres * alloc_dr(dr_release_t release,
if (unlikely(!dr))
return NULL;
memset(dr, 0, tot_size);
memset(dr, 0, offsetof(struct devres, data));
INIT_LIST_HEAD(&dr->node.entry);
dr->node.release = release;
return dr;
......@@ -110,7 +111,7 @@ void * __devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
{
struct devres *dr;
dr = alloc_dr(release, size, gfp);
dr = alloc_dr(release, size, gfp | __GFP_ZERO);
if (unlikely(!dr))
return NULL;
set_node_dbginfo(&dr->node, name, size);
......@@ -135,7 +136,7 @@ void * devres_alloc(dr_release_t release, size_t size, gfp_t gfp)
{
struct devres *dr;
dr = alloc_dr(release, size, gfp);
dr = alloc_dr(release, size, gfp | __GFP_ZERO);
if (unlikely(!dr))
return NULL;
return dr->data;
......@@ -745,58 +746,62 @@ void devm_remove_action(struct device *dev, void (*action)(void *), void *data)
EXPORT_SYMBOL_GPL(devm_remove_action);
/*
* Managed kzalloc/kfree
* Managed kmalloc/kfree
*/
static void devm_kzalloc_release(struct device *dev, void *res)
static void devm_kmalloc_release(struct device *dev, void *res)
{
/* noop */
}
static int devm_kzalloc_match(struct device *dev, void *res, void *data)
static int devm_kmalloc_match(struct device *dev, void *res, void *data)
{
return res == data;
}
/**
* devm_kzalloc - Resource-managed kzalloc
* devm_kmalloc - Resource-managed kmalloc
* @dev: Device to allocate memory for
* @size: Allocation size
* @gfp: Allocation gfp flags
*
* Managed kzalloc. Memory allocated with this function is
* Managed kmalloc. Memory allocated with this function is
* automatically freed on driver detach. Like all other devres
* resources, guaranteed alignment is unsigned long long.
*
* RETURNS:
* Pointer to allocated memory on success, NULL on failure.
*/
void * devm_kzalloc(struct device *dev, size_t size, gfp_t gfp)
void * devm_kmalloc(struct device *dev, size_t size, gfp_t gfp)
{
struct devres *dr;
/* use raw alloc_dr for kmalloc caller tracing */
dr = alloc_dr(devm_kzalloc_release, size, gfp);
dr = alloc_dr(devm_kmalloc_release, size, gfp);
if (unlikely(!dr))
return NULL;
/*
* This is named devm_kzalloc_release for historical reasons
* The initial implementation did not support kmalloc, only kzalloc
*/
set_node_dbginfo(&dr->node, "devm_kzalloc_release", size);
devres_add(dev, dr->data);
return dr->data;
}
EXPORT_SYMBOL_GPL(devm_kzalloc);
EXPORT_SYMBOL_GPL(devm_kmalloc);
/**
* devm_kfree - Resource-managed kfree
* @dev: Device this memory belongs to
* @p: Memory to free
*
* Free memory allocated with devm_kzalloc().
* Free memory allocated with devm_kmalloc().
*/
void devm_kfree(struct device *dev, void *p)
{
int rc;
rc = devres_destroy(dev, devm_kzalloc_release, devm_kzalloc_match, p);
rc = devres_destroy(dev, devm_kmalloc_release, devm_kmalloc_match, p);
WARN_ON(rc);
}
EXPORT_SYMBOL_GPL(devm_kfree);
......@@ -282,31 +282,35 @@ static noinline_for_stack long fw_file_size(struct file *file)
return st.size;
}
static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
{
long size;
char *buf;
int rc;
size = fw_file_size(file);
if (size <= 0)
return false;
return -EINVAL;
buf = vmalloc(size);
if (!buf)
return false;
if (kernel_read(file, 0, buf, size) != size) {
return -ENOMEM;
rc = kernel_read(file, 0, buf, size);
if (rc != size) {
if (rc > 0)
rc = -EIO;
vfree(buf);
return false;
return rc;
}
fw_buf->data = buf;
fw_buf->size = size;
return true;
return 0;
}
static bool fw_get_filesystem_firmware(struct device *device,
static int fw_get_filesystem_firmware(struct device *device,
struct firmware_buf *buf)
{
int i;
bool success = false;
int rc = -ENOENT;
char *path = __getname();
for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
......@@ -321,14 +325,17 @@ static bool fw_get_filesystem_firmware(struct device *device,
file = filp_open(path, O_RDONLY, 0);
if (IS_ERR(file))
continue;
success = fw_read_file_contents(file, buf);
rc = fw_read_file_contents(file, buf);
fput(file);
if (success)
if (rc)
dev_warn(device, "firmware, attempted to load %s, but failed with error %d\n",
path, rc);
else
break;
}
__putname(path);
if (success) {
if (!rc) {
dev_dbg(device, "firmware: direct-loading firmware %s\n",
buf->fw_id);
mutex_lock(&fw_lock);
......@@ -337,7 +344,7 @@ static bool fw_get_filesystem_firmware(struct device *device,
mutex_unlock(&fw_lock);
}
return success;
return rc;
}
/* firmware holds the ownership of pages */
......@@ -1086,9 +1093,14 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
}
}
if (!fw_get_filesystem_firmware(device, fw->priv))
ret = fw_get_filesystem_firmware(device, fw->priv);
if (ret) {
dev_warn(device, "Direct firmware load failed with error %d\n",
ret);
dev_warn(device, "Falling back to user helper\n");
ret = fw_load_from_user_helper(fw, name, device,
uevent, nowait, timeout);
}
/* don't cache firmware handled without uevent */
if (!ret)
......
......@@ -488,6 +488,11 @@ static int platform_drv_probe(struct device *_dev)
if (ret && ACPI_HANDLE(_dev))
acpi_dev_pm_detach(_dev, true);
if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
dev_warn(_dev, "probe deferral not supported\n");
ret = -ENXIO;
}
return ret;
}
......@@ -553,8 +558,7 @@ EXPORT_SYMBOL_GPL(platform_driver_unregister);
/**
* platform_driver_probe - register driver for non-hotpluggable device
* @drv: platform driver structure
* @probe: the driver probe routine, probably from an __init section,
* must not return -EPROBE_DEFER.
* @probe: the driver probe routine, probably from an __init section
*
* Use this instead of platform_driver_register() when you know the device
* is not hotpluggable and has already been registered, and you want to
......@@ -565,8 +569,7 @@ EXPORT_SYMBOL_GPL(platform_driver_unregister);
* into system-on-chip processors, where the controller devices have been
* configured as part of board setup.
*
* This is incompatible with deferred probing so probe() must not
* return -EPROBE_DEFER.
* Note that this is incompatible with deferred probing.
*
* Returns zero if the driver registered and bound to a device, else returns
* a negative error code and with the driver not registered.
......@@ -576,6 +579,12 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv,
{
int retval, code;
/*
* Prevent driver from requesting probe deferral to avoid further
* futile probe attempts.
*/
drv->prevent_deferred_probe = true;
/* make sure driver won't have bind/unbind attributes */
drv->driver.suppress_bind_attrs = true;
......
......@@ -30,28 +30,37 @@ static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, cha
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
return sprintf(buf, "0x%03X\n", core->id.manuf);
}
static DEVICE_ATTR_RO(manuf);
static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
return sprintf(buf, "0x%03X\n", core->id.id);
}
static DEVICE_ATTR_RO(id);
static ssize_t rev_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
return sprintf(buf, "0x%02X\n", core->id.rev);
}
static DEVICE_ATTR_RO(rev);
static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
return sprintf(buf, "0x%X\n", core->id.class);
}
static struct device_attribute bcma_device_attrs[] = {
__ATTR_RO(manuf),
__ATTR_RO(id),
__ATTR_RO(rev),
__ATTR_RO(class),
__ATTR_NULL,
static DEVICE_ATTR_RO(class);
static struct attribute *bcma_device_attrs[] = {
&dev_attr_manuf.attr,
&dev_attr_id.attr,
&dev_attr_rev.attr,
&dev_attr_class.attr,
NULL,
};
ATTRIBUTE_GROUPS(bcma_device);
static struct bus_type bcma_bus_type = {
.name = "bcma",
......@@ -59,7 +68,7 @@ static struct bus_type bcma_bus_type = {
.probe = bcma_device_probe,
.remove = bcma_device_remove,
.uevent = bcma_device_uevent,
.dev_attrs = bcma_device_attrs,
.dev_groups = bcma_device_groups,
};
static u16 bcma_cc_core_id(struct bcma_bus *bus)
......
......@@ -408,7 +408,7 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,
IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
if (!value_sd) {
value_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value");
value_sd = sysfs_get_dirent(dev->kobj.sd, "value");
if (!value_sd) {
ret = -ENODEV;
goto err_out;
......
......@@ -33,11 +33,13 @@ static ssize_t modalias_show(struct device *dev,
{
return sprintf(buf, "hsi:%s\n", dev_name(dev));
}
static DEVICE_ATTR_RO(modalias);
static struct device_attribute hsi_bus_dev_attrs[] = {
__ATTR_RO(modalias),
__ATTR_NULL,
static struct attribute *hsi_bus_dev_attrs[] = {
&dev_attr_modalias.attr,
NULL,
};
ATTRIBUTE_GROUPS(hsi_bus_dev);
static int hsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
{
......@@ -53,7 +55,7 @@ static int hsi_bus_match(struct device *dev, struct device_driver *driver)
static struct bus_type hsi_bus_type = {
.name = "hsi",
.dev_attrs = hsi_bus_dev_attrs,
.dev_groups = hsi_bus_dev_groups,
.match = hsi_bus_match,
.uevent = hsi_bus_uevent,
};
......
......@@ -25,6 +25,7 @@ static ssize_t media_show(struct device *dev, struct device_attribute *attr,
ide_drive_t *drive = to_ide_device(dev);
return sprintf(buf, "%s\n", ide_media_string(drive));
}
static DEVICE_ATTR_RO(media);
static ssize_t drivename_show(struct device *dev, struct device_attribute *attr,
char *buf)
......@@ -32,6 +33,7 @@ static ssize_t drivename_show(struct device *dev, struct device_attribute *attr,
ide_drive_t *drive = to_ide_device(dev);
return sprintf(buf, "%s\n", drive->name);
}
static DEVICE_ATTR_RO(drivename);
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
char *buf)
......@@ -39,6 +41,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
ide_drive_t *drive = to_ide_device(dev);
return sprintf(buf, "ide:m-%s\n", ide_media_string(drive));
}
static DEVICE_ATTR_RO(modalias);
static ssize_t model_show(struct device *dev, struct device_attribute *attr,
char *buf)
......@@ -46,6 +49,7 @@ static ssize_t model_show(struct device *dev, struct device_attribute *attr,
ide_drive_t *drive = to_ide_device(dev);
return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]);
}
static DEVICE_ATTR_RO(model);
static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,
char *buf)
......@@ -53,6 +57,7 @@ static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,
ide_drive_t *drive = to_ide_device(dev);
return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_FW_REV]);
}
static DEVICE_ATTR_RO(firmware);
static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
char *buf)
......@@ -60,16 +65,28 @@ static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
ide_drive_t *drive = to_ide_device(dev);
return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]);
}
static DEVICE_ATTR(serial, 0400, serial_show, NULL);
static DEVICE_ATTR(unload_heads, 0644, ide_park_show, ide_park_store);
static struct attribute *ide_attrs[] = {
&dev_attr_media.attr,
&dev_attr_drivename.attr,
&dev_attr_modalias.attr,
&dev_attr_model.attr,
&dev_attr_firmware.attr,
&dev_attr_serial.attr,
&dev_attr_unload_heads.attr,
NULL,
};
static const struct attribute_group ide_attr_group = {
.attrs = ide_attrs,
};
struct device_attribute ide_dev_attrs[] = {
__ATTR_RO(media),
__ATTR_RO(drivename),
__ATTR_RO(modalias),
__ATTR_RO(model),
__ATTR_RO(firmware),
__ATTR(serial, 0400, serial_show, NULL),
__ATTR(unload_heads, 0644, ide_park_show, ide_park_store),
__ATTR_NULL
const struct attribute_group *ide_dev_groups[] = {
&ide_attr_group,
NULL,
};
static ssize_t store_delete_devices(struct device *portdev,
......
......@@ -158,7 +158,7 @@ struct bus_type ide_bus_type = {
.probe = generic_ide_probe,
.remove = generic_ide_remove,
.shutdown = generic_ide_shutdown,
.dev_attrs = ide_dev_attrs,
.dev_groups = ide_dev_groups,
.suspend = generic_ide_suspend,
.resume = generic_ide_resume,
};
......
......@@ -422,14 +422,15 @@ static struct gameport *gameport_get_pending_child(struct gameport *parent)
* Gameport port operations
*/
static ssize_t gameport_show_description(struct device *dev, struct device_attribute *attr, char *buf)
static ssize_t gameport_description_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct gameport *gameport = to_gameport_port(dev);
return sprintf(buf, "%s\n", gameport->name);
}
static DEVICE_ATTR(description, S_IRUGO, gameport_description_show, NULL);
static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
static ssize_t drvctl_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct gameport *gameport = to_gameport_port(dev);
struct device_driver *drv;
......@@ -457,12 +458,14 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut
return error ? error : count;
}
static DEVICE_ATTR_WO(drvctl);
static struct device_attribute gameport_device_attrs[] = {
__ATTR(description, S_IRUGO, gameport_show_description, NULL),
__ATTR(drvctl, S_IWUSR, NULL, gameport_rebind_driver),
__ATTR_NULL
static struct attribute *gameport_device_attrs[] = {
&dev_attr_description.attr,
&dev_attr_drvctl.attr,
NULL,
};
ATTRIBUTE_GROUPS(gameport_device);
static void gameport_release_port(struct device *dev)
{
......@@ -750,7 +753,7 @@ static int gameport_bus_match(struct device *dev, struct device_driver *drv)
static struct bus_type gameport_bus = {
.name = "gameport",
.dev_attrs = gameport_device_attrs,
.dev_groups = gameport_device_groups,
.drv_groups = gameport_driver_groups,
.match = gameport_bus_match,
.probe = gameport_driver_probe,
......
......@@ -365,7 +365,7 @@ static ssize_t serio_show_description(struct device *dev, struct device_attribut
return sprintf(buf, "%s\n", serio->name);
}
static ssize_t serio_show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct serio *serio = to_serio_port(dev);
......@@ -373,54 +373,31 @@ static ssize_t serio_show_modalias(struct device *dev, struct device_attribute *
serio->id.type, serio->id.proto, serio->id.id, serio->id.extra);
}
static ssize_t serio_show_id_type(struct device *dev, struct device_attribute *attr, char *buf)
static ssize_t type_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct serio *serio = to_serio_port(dev);
return sprintf(buf, "%02x\n", serio->id.type);
}
static ssize_t serio_show_id_proto(struct device *dev, struct device_attribute *attr, char *buf)
static ssize_t proto_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct serio *serio = to_serio_port(dev);
return sprintf(buf, "%02x\n", serio->id.proto);
}
static ssize_t serio_show_id_id(struct device *dev, struct device_attribute *attr, char *buf)
static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct serio *serio = to_serio_port(dev);
return sprintf(buf, "%02x\n", serio->id.id);
}
static ssize_t serio_show_id_extra(struct device *dev, struct device_attribute *attr, char *buf)
static ssize_t extra_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct serio *serio = to_serio_port(dev);
return sprintf(buf, "%02x\n", serio->id.extra);
}
static DEVICE_ATTR(type, S_IRUGO, serio_show_id_type, NULL);
static DEVICE_ATTR(proto, S_IRUGO, serio_show_id_proto, NULL);
static DEVICE_ATTR(id, S_IRUGO, serio_show_id_id, NULL);
static DEVICE_ATTR(extra, S_IRUGO, serio_show_id_extra, NULL);
static struct attribute *serio_device_id_attrs[] = {
&dev_attr_type.attr,
&dev_attr_proto.attr,
&dev_attr_id.attr,
&dev_attr_extra.attr,
NULL
};
static struct attribute_group serio_id_attr_group = {
.name = "id",
.attrs = serio_device_id_attrs,
};
static const struct attribute_group *serio_device_attr_groups[] = {
&serio_id_attr_group,
NULL
};
static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
static ssize_t drvctl_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct serio *serio = to_serio_port(dev);
struct device_driver *drv;
......@@ -474,14 +451,36 @@ static ssize_t serio_set_bind_mode(struct device *dev, struct device_attribute *
return retval;
}
static struct device_attribute serio_device_attrs[] = {
__ATTR(description, S_IRUGO, serio_show_description, NULL),
__ATTR(modalias, S_IRUGO, serio_show_modalias, NULL),
__ATTR(drvctl, S_IWUSR, NULL, serio_rebind_driver),
__ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode),
__ATTR_NULL
static DEVICE_ATTR_RO(type);
static DEVICE_ATTR_RO(proto);
static DEVICE_ATTR_RO(id);
static DEVICE_ATTR_RO(extra);
static DEVICE_ATTR_RO(modalias);
static DEVICE_ATTR_WO(drvctl);
static DEVICE_ATTR(description, S_IRUGO, serio_show_description, NULL);
static DEVICE_ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode);
static struct attribute *serio_device_id_attrs[] = {
&dev_attr_type.attr,
&dev_attr_proto.attr,
&dev_attr_id.attr,
&dev_attr_extra.attr,
&dev_attr_modalias.attr,
&dev_attr_description.attr,
&dev_attr_drvctl.attr,
&dev_attr_bind_mode.attr,
NULL
};
static struct attribute_group serio_id_attr_group = {
.name = "id",
.attrs = serio_device_id_attrs,
};
static const struct attribute_group *serio_device_attr_groups[] = {
&serio_id_attr_group,
NULL
};
static void serio_release_port(struct device *dev)
{
......@@ -996,7 +995,6 @@ EXPORT_SYMBOL(serio_interrupt);
static struct bus_type serio_bus = {
.name = "serio",
.dev_attrs = serio_device_attrs,
.drv_groups = serio_driver_groups,
.match = serio_bus_match,
.uevent = serio_uevent,
......
......@@ -180,20 +180,28 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
ipack_device_attr(id_format, "0x%hhu\n");
static struct device_attribute ipack_dev_attrs[] = {
__ATTR_RO(id),
__ATTR_RO(id_device),
__ATTR_RO(id_format),
__ATTR_RO(id_vendor),
__ATTR_RO(modalias),
static DEVICE_ATTR_RO(id);
static DEVICE_ATTR_RO(id_device);
static DEVICE_ATTR_RO(id_format);
static DEVICE_ATTR_RO(id_vendor);
static DEVICE_ATTR_RO(modalias);
static struct attribute *ipack_attrs[] = {
&dev_attr_id.attr,
&dev_attr_id_device.attr,
&dev_attr_id_format.attr,
&dev_attr_id_vendor.attr,
&dev_attr_modalias.attr,
NULL,
};
ATTRIBUTE_GROUPS(ipack);
static struct bus_type ipack_bus_type = {
.name = "ipack",
.probe = ipack_bus_probe,
.match = ipack_bus_match,
.remove = ipack_bus_remove,
.dev_attrs = ipack_dev_attrs,
.dev_groups = ipack_groups,
.uevent = ipack_uevent,
};
......
......@@ -1654,9 +1654,9 @@ int bitmap_create(struct mddev *mddev)
bitmap->mddev = mddev;
if (mddev->kobj.sd)
bm = sysfs_get_dirent(mddev->kobj.sd, NULL, "bitmap");
bm = sysfs_get_dirent(mddev->kobj.sd, "bitmap");
if (bm) {
bitmap->sysfs_can_clear = sysfs_get_dirent(bm, NULL, "can_clear");
bitmap->sysfs_can_clear = sysfs_get_dirent(bm, "can_clear");
sysfs_put(bm);
} else
bitmap->sysfs_can_clear = NULL;
......
......@@ -3555,7 +3555,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
printk(KERN_WARNING
"md: cannot register extra attributes for %s\n",
mdname(mddev));
mddev->sysfs_action = sysfs_get_dirent(mddev->kobj.sd, NULL, "sync_action");
mddev->sysfs_action = sysfs_get_dirent(mddev->kobj.sd, "sync_action");
}
if (mddev->pers->sync_request != NULL &&
pers->sync_request == NULL) {
......
......@@ -501,7 +501,7 @@ extern struct attribute_group md_bitmap_group;
static inline struct sysfs_dirent *sysfs_get_dirent_safe(struct sysfs_dirent *sd, char *name)
{
if (sd)
return sysfs_get_dirent(sd, NULL, name);
return sysfs_get_dirent(sd, name);
return sd;
}
static inline void sysfs_notify_dirent_safe(struct sysfs_dirent *sd)
......
......@@ -153,24 +153,24 @@ static ssize_t name##_show(struct device *dev, struct device_attribute *attr, \
struct memstick_dev *card = container_of(dev, struct memstick_dev, \
dev); \
return sprintf(buf, format, card->id.name); \
}
} \
static DEVICE_ATTR_RO(name);
MEMSTICK_ATTR(type, "%02X");
MEMSTICK_ATTR(category, "%02X");
MEMSTICK_ATTR(class, "%02X");
#define MEMSTICK_ATTR_RO(name) __ATTR(name, S_IRUGO, name##_show, NULL)
static struct device_attribute memstick_dev_attrs[] = {
MEMSTICK_ATTR_RO(type),
MEMSTICK_ATTR_RO(category),
MEMSTICK_ATTR_RO(class),
__ATTR_NULL
static struct attribute *memstick_dev_attrs[] = {
&dev_attr_type.attr,
&dev_attr_category.attr,
&dev_attr_class.attr,
NULL,
};
ATTRIBUTE_GROUPS(memstick_dev);
static struct bus_type memstick_bus_type = {
.name = "memstick",
.dev_attrs = memstick_dev_attrs,
.dev_groups = memstick_dev_groups,
.match = memstick_bus_match,
.uevent = memstick_uevent,
.probe = memstick_device_probe,
......
......@@ -33,7 +33,7 @@ extern int __init i2o_pci_init(void);
extern void __exit i2o_pci_exit(void);
/* device */
extern struct device_attribute i2o_device_attrs[];
extern const struct attribute_group *i2o_device_groups[];
extern void i2o_device_remove(struct i2o_device *);
extern int i2o_device_parse_lct(struct i2o_controller *);
......
......@@ -138,45 +138,55 @@ static void i2o_device_release(struct device *dev)
}
/**
* i2o_device_show_class_id - Displays class id of I2O device
* class_id_show - Displays class id of I2O device
* @dev: device of which the class id should be displayed
* @attr: pointer to device attribute
* @buf: buffer into which the class id should be printed
*
* Returns the number of bytes which are printed into the buffer.
*/
static ssize_t i2o_device_show_class_id(struct device *dev,
struct device_attribute *attr,
char *buf)
static ssize_t class_id_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct i2o_device *i2o_dev = to_i2o_device(dev);
sprintf(buf, "0x%03x\n", i2o_dev->lct_data.class_id);
return strlen(buf) + 1;
}
static DEVICE_ATTR_RO(class_id);
/**
* i2o_device_show_tid - Displays TID of I2O device
* tid_show - Displays TID of I2O device
* @dev: device of which the TID should be displayed
* @attr: pointer to device attribute
* @buf: buffer into which the TID should be printed
*
* Returns the number of bytes which are printed into the buffer.
*/
static ssize_t i2o_device_show_tid(struct device *dev,
struct device_attribute *attr, char *buf)
static ssize_t tid_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct i2o_device *i2o_dev = to_i2o_device(dev);
sprintf(buf, "0x%03x\n", i2o_dev->lct_data.tid);
return strlen(buf) + 1;
}
static DEVICE_ATTR_RO(tid);
/* I2O device attributes */
struct device_attribute i2o_device_attrs[] = {
__ATTR(class_id, S_IRUGO, i2o_device_show_class_id, NULL),
__ATTR(tid, S_IRUGO, i2o_device_show_tid, NULL),
__ATTR_NULL
static struct attribute *i2o_device_attrs[] = {
&dev_attr_class_id.attr,
&dev_attr_tid.attr,
NULL,
};
static const struct attribute_group i2o_device_group = {
.attrs = i2o_device_attrs,
};
const struct attribute_group *i2o_device_groups[] = {
&i2o_device_group,
NULL,
};
/**
......
......@@ -62,7 +62,7 @@ static int i2o_bus_match(struct device *dev, struct device_driver *drv)
struct bus_type i2o_bus_type = {
.name = "i2o",
.match = i2o_bus_match,
.dev_attrs = i2o_device_attrs
.dev_groups = i2o_device_groups,
};
/**
......
......@@ -374,8 +374,7 @@ static int mic_probe(struct pci_dev *pdev,
"device_create_with_groups failed rc %d\n", rc);
goto smpt_uninit;
}
mdev->state_sysfs = sysfs_get_dirent(mdev->sdev->kobj.sd,
NULL, "state");
mdev->state_sysfs = sysfs_get_dirent(mdev->sdev->kobj.sd, "state");
if (!mdev->state_sysfs) {
rc = -ENODEV;
dev_err(&pdev->dev, "sysfs_get_dirent failed rc %d\n", rc);
......
......@@ -145,15 +145,17 @@ static ssize_t type_show(struct device *dev, struct device_attribute *attr,
struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
return sprintf(buf, "%x", sock->type);
}
static DEVICE_ATTR_RO(type);
static struct device_attribute tifm_dev_attrs[] = {
__ATTR(type, S_IRUGO, type_show, NULL),
__ATTR_NULL
static struct attribute *tifm_dev_attrs[] = {
&dev_attr_type.attr,
NULL,
};
ATTRIBUTE_GROUPS(tifm_dev);
static struct bus_type tifm_bus_type = {
.name = "tifm",
.dev_attrs = tifm_dev_attrs,
.dev_groups = tifm_dev_groups,
.match = tifm_bus_match,
.uevent = tifm_uevent,
.probe = tifm_device_probe,
......
......@@ -27,7 +27,7 @@
#define to_mmc_driver(d) container_of(d, struct mmc_driver, drv)
static ssize_t mmc_type_show(struct device *dev,
static ssize_t type_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct mmc_card *card = mmc_dev_to_card(dev);
......@@ -45,11 +45,13 @@ static ssize_t mmc_type_show(struct device *dev,
return -EFAULT;
}
}
static DEVICE_ATTR_RO(type);
static struct device_attribute mmc_dev_attrs[] = {
__ATTR(type, S_IRUGO, mmc_type_show, NULL),
__ATTR_NULL,
static struct attribute *mmc_dev_attrs[] = {
&dev_attr_type.attr,
NULL,
};
ATTRIBUTE_GROUPS(mmc_dev);
/*
* This currently matches any MMC driver to any MMC card - drivers
......@@ -218,7 +220,7 @@ static const struct dev_pm_ops mmc_bus_pm_ops = {
static struct bus_type mmc_bus_type = {
.name = "mmc",
.dev_attrs = mmc_dev_attrs,
.dev_groups = mmc_dev_groups,
.match = mmc_bus_match,
.uevent = mmc_bus_uevent,
.probe = mmc_bus_probe,
......
......@@ -34,7 +34,8 @@ field##_show(struct device *dev, struct device_attribute *attr, char *buf) \
\
func = dev_to_sdio_func (dev); \
return sprintf (buf, format_string, func->field); \
}
} \
static DEVICE_ATTR_RO(field)
sdio_config_attr(class, "0x%02x\n");
sdio_config_attr(vendor, "0x%04x\n");
......@@ -47,14 +48,16 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "sdio:c%02Xv%04Xd%04X\n",
func->class, func->vendor, func->device);
}
static struct device_attribute sdio_dev_attrs[] = {
__ATTR_RO(class),
__ATTR_RO(vendor),
__ATTR_RO(device),
__ATTR_RO(modalias),
__ATTR_NULL,
static DEVICE_ATTR_RO(modalias);
static struct attribute *sdio_dev_attrs[] = {
&dev_attr_class.attr,
&dev_attr_vendor.attr,
&dev_attr_device.attr,
&dev_attr_modalias.attr,
NULL,
};
ATTRIBUTE_GROUPS(sdio_dev);
static const struct sdio_device_id *sdio_match_one(struct sdio_func *func,
const struct sdio_device_id *id)
......@@ -225,7 +228,7 @@ static const struct dev_pm_ops sdio_bus_pm_ops = {
static struct bus_type sdio_bus_type = {
.name = "sdio",
.dev_attrs = sdio_dev_attrs,
.dev_groups = sdio_dev_groups,
.match = sdio_bus_match,
.uevent = sdio_bus_uevent,
.probe = sdio_bus_probe,
......
......@@ -655,7 +655,7 @@ static const struct mmc_host_ops mvsd_ops = {
.enable_sdio_irq = mvsd_enable_sdio_irq,
};
static void __init
static void
mv_conf_mbus_windows(struct mvsd_host *host,
const struct mbus_dram_target_info *dram)
{
......@@ -677,7 +677,7 @@ mv_conf_mbus_windows(struct mvsd_host *host,
}
}
static int __init mvsd_probe(struct platform_device *pdev)
static int mvsd_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct mmc_host *mmc = NULL;
......@@ -819,7 +819,7 @@ static int __init mvsd_probe(struct platform_device *pdev)
return ret;
}
static int __exit mvsd_remove(struct platform_device *pdev)
static int mvsd_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
......@@ -872,7 +872,8 @@ static const struct of_device_id mvsdio_dt_ids[] = {
MODULE_DEVICE_TABLE(of, mvsdio_dt_ids);
static struct platform_driver mvsd_driver = {
.remove = __exit_p(mvsd_remove),
.probe = mvsd_probe,
.remove = mvsd_remove,
.suspend = mvsd_suspend,
.resume = mvsd_resume,
.driver = {
......@@ -881,7 +882,7 @@ static struct platform_driver mvsd_driver = {
},
};
module_platform_driver_probe(mvsd_driver, mvsd_probe);
module_platform_driver(mvsd_driver);
/* maximum card clock frequency (default 50MHz) */
module_param(maxfreq, int, 0);
......
......@@ -1139,7 +1139,7 @@ static int pmecc_choose_ecc(struct atmel_nand_host *host,
return 0;
}
static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev,
static int atmel_pmecc_nand_init_params(struct platform_device *pdev,
struct atmel_nand_host *host)
{
struct mtd_info *mtd = &host->mtd;
......@@ -1548,7 +1548,7 @@ static int atmel_of_init_port(struct atmel_nand_host *host,
}
#endif
static int __init atmel_hw_nand_init_params(struct platform_device *pdev,
static int atmel_hw_nand_init_params(struct platform_device *pdev,
struct atmel_nand_host *host)
{
struct mtd_info *mtd = &host->mtd;
......@@ -1987,7 +1987,7 @@ static struct platform_driver atmel_nand_nfc_driver;
/*
* Probe for the NAND device.
*/
static int __init atmel_nand_probe(struct platform_device *pdev)
static int atmel_nand_probe(struct platform_device *pdev)
{
struct atmel_nand_host *host;
struct mtd_info *mtd;
......@@ -2184,7 +2184,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
/*
* Remove a NAND device.
*/
static int __exit atmel_nand_remove(struct platform_device *pdev)
static int atmel_nand_remove(struct platform_device *pdev)
{
struct atmel_nand_host *host = platform_get_drvdata(pdev);
struct mtd_info *mtd = &host->mtd;
......@@ -2270,7 +2270,8 @@ static struct platform_driver atmel_nand_nfc_driver = {
};
static struct platform_driver atmel_nand_driver = {
.remove = __exit_p(atmel_nand_remove),
.probe = atmel_nand_probe,
.remove = atmel_nand_remove,
.driver = {
.name = "atmel_nand",
.owner = THIS_MODULE,
......@@ -2278,7 +2279,7 @@ static struct platform_driver atmel_nand_driver = {
},
};
module_platform_driver_probe(atmel_nand_driver, atmel_nand_probe);
module_platform_driver(atmel_nand_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rick Bronson");
......
......@@ -149,14 +149,6 @@ static ssize_t bonding_store_bonds(struct class *cls,
return -EPERM;
}
static const void *bonding_namespace(struct class *cls,
const struct class_attribute *attr)
{
const struct bond_net *bn =
container_of(attr, struct bond_net, class_attr_bonding_masters);
return bn->net;
}
/* class attribute for bond_masters file. This ends up in /sys/class/net */
static const struct class_attribute class_attr_bonding_masters = {
.attr = {
......@@ -165,7 +157,6 @@ static const struct class_attribute class_attr_bonding_masters = {
},
.show = bonding_show_bonds,
.store = bonding_store_bonds,
.namespace = bonding_namespace,
};
int bond_create_slave_symlinks(struct net_device *master,
......@@ -1787,7 +1778,8 @@ int bond_create_sysfs(struct bond_net *bn)
bn->class_attr_bonding_masters = class_attr_bonding_masters;
sysfs_attr_init(&bn->class_attr_bonding_masters.attr);
ret = netdev_class_create_file(&bn->class_attr_bonding_masters);
ret = netdev_class_create_file_ns(&bn->class_attr_bonding_masters,
bn->net);
/*
* Permit multiple loads of the module by ignoring failures to
* create the bonding_masters sysfs file. Bonding devices
......@@ -1817,7 +1809,7 @@ int bond_create_sysfs(struct bond_net *bn)
*/
void bond_destroy_sysfs(struct bond_net *bn)
{
netdev_class_remove_file(&bn->class_attr_bonding_masters);
netdev_class_remove_file_ns(&bn->class_attr_bonding_masters, bn->net);
}
/*
......
......@@ -438,17 +438,19 @@ phy_id_show(struct device *dev, struct device_attribute *attr, char *buf)
return sprintf(buf, "0x%.8lx\n", (unsigned long)phydev->phy_id);
}
static DEVICE_ATTR_RO(phy_id);
static struct device_attribute mdio_dev_attrs[] = {
__ATTR_RO(phy_id),
__ATTR_NULL
static struct attribute *mdio_dev_attrs[] = {
&dev_attr_phy_id.attr,
NULL,
};
ATTRIBUTE_GROUPS(mdio_dev);
struct bus_type mdio_bus_type = {
.name = "mdio_bus",
.match = mdio_bus_match,
.pm = MDIO_BUS_PM_OPS,
.dev_attrs = mdio_dev_attrs,
.dev_groups = mdio_dev_groups,
};
EXPORT_SYMBOL(mdio_bus_type);
......
......@@ -135,6 +135,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
return retval;
return count;
}
static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
/**
* store_remove_id - remove a PCI device ID from this driver
......@@ -180,12 +181,14 @@ store_remove_id(struct device_driver *driver, const char *buf, size_t count)
return retval;
return count;
}
static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id);
static struct driver_attribute pci_drv_attrs[] = {
__ATTR(new_id, S_IWUSR, NULL, store_new_id),
__ATTR(remove_id, S_IWUSR, NULL, store_remove_id),
__ATTR_NULL,
static struct attribute *pci_drv_attrs[] = {
&driver_attr_new_id.attr,
&driver_attr_remove_id.attr,
NULL,
};
ATTRIBUTE_GROUPS(pci_drv);
/**
* pci_match_id - See if a pci device matches a given pci_id table
......@@ -1317,8 +1320,8 @@ struct bus_type pci_bus_type = {
.remove = pci_device_remove,
.shutdown = pci_device_shutdown,
.dev_attrs = pci_dev_attrs,
.bus_attrs = pci_bus_attrs,
.drv_attrs = pci_drv_attrs,
.bus_groups = pci_bus_groups,
.drv_groups = pci_drv_groups,
.pm = PCI_PM_OPS_PTR,
};
......
......@@ -302,10 +302,20 @@ static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf,
}
return count;
}
static BUS_ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store);
struct bus_attribute pci_bus_attrs[] = {
__ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store),
__ATTR_NULL
struct attribute *pci_bus_attrs[] = {
&bus_attr_rescan.attr,
NULL,
};
static const struct attribute_group pci_bus_group = {
.attrs = pci_bus_attrs,
};
const struct attribute_group *pci_bus_groups[] = {
&pci_bus_group,
NULL,
};
static ssize_t
......
......@@ -156,7 +156,7 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
extern struct device_attribute pci_dev_attrs[];
extern const struct attribute_group *pcibus_groups[];
extern struct device_type pci_dev_type;
extern struct bus_attribute pci_bus_attrs[];
extern const struct attribute_group *pci_bus_groups[];
/**
......
......@@ -245,7 +245,7 @@ static int at91_cf_dt_init(struct platform_device *pdev)
}
#endif
static int __init at91_cf_probe(struct platform_device *pdev)
static int at91_cf_probe(struct platform_device *pdev)
{
struct at91_cf_socket *cf;
struct at91_cf_data *board = pdev->dev.platform_data;
......@@ -354,7 +354,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
return status;
}
static int __exit at91_cf_remove(struct platform_device *pdev)
static int at91_cf_remove(struct platform_device *pdev)
{
struct at91_cf_socket *cf = platform_get_drvdata(pdev);
......@@ -404,14 +404,13 @@ static struct platform_driver at91_cf_driver = {
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(at91_cf_dt_ids),
},
.remove = __exit_p(at91_cf_remove),
.probe = at91_cf_probe,
.remove = at91_cf_remove,
.suspend = at91_cf_suspend,
.resume = at91_cf_resume,
};
/*--------------------------------------------------------------------------*/
module_platform_driver_probe(at91_cf_driver, at91_cf_probe);
module_platform_driver(at91_cf_driver);
MODULE_DESCRIPTION("AT91 Compact Flash Driver");
MODULE_AUTHOR("David Brownell");
......
......@@ -992,16 +992,17 @@ static ssize_t field##_show (struct device *dev, struct device_attribute *attr,
{ \
struct pcmcia_device *p_dev = to_pcmcia_dev(dev); \
return p_dev->test ? sprintf(buf, format, p_dev->field) : -ENODEV; \
}
} \
static DEVICE_ATTR_RO(field);
#define pcmcia_device_stringattr(name, field) \
static ssize_t name##_show (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pcmcia_device *p_dev = to_pcmcia_dev(dev); \
return p_dev->field ? sprintf(buf, "%s\n", p_dev->field) : -ENODEV; \
}
} \
static DEVICE_ATTR_RO(name);
pcmcia_device_attr(func, socket, "0x%02x\n");
pcmcia_device_attr(func_id, has_func_id, "0x%02x\n");
pcmcia_device_attr(manf_id, has_manf_id, "0x%04x\n");
pcmcia_device_attr(card_id, has_card_id, "0x%04x\n");
......@@ -1010,8 +1011,16 @@ pcmcia_device_stringattr(prod_id2, prod_id[1]);
pcmcia_device_stringattr(prod_id3, prod_id[2]);
pcmcia_device_stringattr(prod_id4, prod_id[3]);
static ssize_t pcmcia_show_resources(struct device *dev,
struct device_attribute *attr, char *buf)
static ssize_t function_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
return p_dev->socket ? sprintf(buf, "0x%02x\n", p_dev->func) : -ENODEV;
}
static DEVICE_ATTR_RO(function);
static ssize_t resources_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
char *str = buf;
......@@ -1022,8 +1031,9 @@ static ssize_t pcmcia_show_resources(struct device *dev,
return str - buf;
}
static DEVICE_ATTR_RO(resources);
static ssize_t pcmcia_show_pm_state(struct device *dev, struct device_attribute *attr, char *buf)
static ssize_t pm_state_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
......@@ -1033,8 +1043,8 @@ static ssize_t pcmcia_show_pm_state(struct device *dev, struct device_attribute
return sprintf(buf, "on\n");
}
static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
static ssize_t pm_state_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
int ret = 0;
......@@ -1049,7 +1059,7 @@ static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute
return ret ? ret : count;
}
static DEVICE_ATTR_RW(pm_state);
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
{
......@@ -1072,8 +1082,9 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
p_dev->func, p_dev->device_no,
hash[0], hash[1], hash[2], hash[3]);
}
static DEVICE_ATTR_RO(modalias);
static ssize_t pcmcia_store_allow_func_id_match(struct device *dev,
static ssize_t allow_func_id_match_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
......@@ -1088,22 +1099,24 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev,
return count;
}
static struct device_attribute pcmcia_dev_attrs[] = {
__ATTR(function, 0444, func_show, NULL),
__ATTR(pm_state, 0644, pcmcia_show_pm_state, pcmcia_store_pm_state),
__ATTR(resources, 0444, pcmcia_show_resources, NULL),
__ATTR_RO(func_id),
__ATTR_RO(manf_id),
__ATTR_RO(card_id),
__ATTR_RO(prod_id1),
__ATTR_RO(prod_id2),
__ATTR_RO(prod_id3),
__ATTR_RO(prod_id4),
__ATTR_RO(modalias),
__ATTR(allow_func_id_match, 0200, NULL, pcmcia_store_allow_func_id_match),
__ATTR_NULL,
static DEVICE_ATTR_WO(allow_func_id_match);
static struct attribute *pcmcia_dev_attrs[] = {
&dev_attr_resources.attr,
&dev_attr_pm_state.attr,
&dev_attr_function.attr,
&dev_attr_func_id.attr,
&dev_attr_manf_id.attr,
&dev_attr_card_id.attr,
&dev_attr_prod_id1.attr,
&dev_attr_prod_id2.attr,
&dev_attr_prod_id3.attr,
&dev_attr_prod_id4.attr,
&dev_attr_modalias.attr,
&dev_attr_allow_func_id_match.attr,
NULL,
};
ATTRIBUTE_GROUPS(pcmcia_dev);
/* PM support, also needed for reset */
......@@ -1389,7 +1402,7 @@ struct bus_type pcmcia_bus_type = {
.name = "pcmcia",
.uevent = pcmcia_bus_uevent,
.match = pcmcia_bus_match,
.dev_attrs = pcmcia_dev_attrs,
.dev_groups = pcmcia_dev_groups,
.probe = pcmcia_device_probe,
.remove = pcmcia_device_remove,
.suspend = pcmcia_dev_suspend,
......
......@@ -4,7 +4,7 @@
*/
extern spinlock_t pnp_lock;
extern struct device_attribute pnp_interface_attrs[];
extern const struct attribute_group *pnp_dev_groups[];
void *pnp_alloc(long size);
int pnp_register_protocol(struct pnp_protocol *protocol);
......
......@@ -246,7 +246,7 @@ struct bus_type pnp_bus_type = {
.remove = pnp_device_remove,
.shutdown = pnp_device_shutdown,
.pm = &pnp_bus_dev_pm_ops,
.dev_attrs = pnp_interface_attrs,
.dev_groups = pnp_dev_groups,
};
int pnp_register_driver(struct pnp_driver *drv)
......
......@@ -203,8 +203,8 @@ static void pnp_print_option(pnp_info_buffer_t * buffer, char *space,
}
}
static ssize_t pnp_show_options(struct device *dmdev,
struct device_attribute *attr, char *buf)
static ssize_t options_show(struct device *dmdev, struct device_attribute *attr,
char *buf)
{
struct pnp_dev *dev = to_pnp_dev(dmdev);
pnp_info_buffer_t *buffer;
......@@ -241,10 +241,10 @@ static ssize_t pnp_show_options(struct device *dmdev,
kfree(buffer);
return ret;
}
static DEVICE_ATTR_RO(options);
static ssize_t pnp_show_current_resources(struct device *dmdev,
struct device_attribute *attr,
char *buf)
static ssize_t resources_show(struct device *dmdev,
struct device_attribute *attr, char *buf)
{
struct pnp_dev *dev = to_pnp_dev(dmdev);
pnp_info_buffer_t *buffer;
......@@ -331,9 +331,9 @@ static char *pnp_get_resource_value(char *buf,
return buf;
}
static ssize_t pnp_set_current_resources(struct device *dmdev,
struct device_attribute *attr,
const char *ubuf, size_t count)
static ssize_t resources_store(struct device *dmdev,
struct device_attribute *attr, const char *ubuf,
size_t count)
{
struct pnp_dev *dev = to_pnp_dev(dmdev);
char *buf = (void *)ubuf;
......@@ -434,9 +434,10 @@ static ssize_t pnp_set_current_resources(struct device *dmdev,
return retval;
return count;
}
static DEVICE_ATTR_RW(resources);
static ssize_t pnp_show_current_ids(struct device *dmdev,
struct device_attribute *attr, char *buf)
static ssize_t id_show(struct device *dmdev, struct device_attribute *attr,
char *buf)
{
char *str = buf;
struct pnp_dev *dev = to_pnp_dev(dmdev);
......@@ -448,12 +449,20 @@ static ssize_t pnp_show_current_ids(struct device *dmdev,
}
return (str - buf);
}
static DEVICE_ATTR_RO(id);
struct device_attribute pnp_interface_attrs[] = {
__ATTR(resources, S_IRUGO | S_IWUSR,
pnp_show_current_resources,
pnp_set_current_resources),
__ATTR(options, S_IRUGO, pnp_show_options, NULL),
__ATTR(id, S_IRUGO, pnp_show_current_ids, NULL),
__ATTR_NULL,
static struct attribute *pnp_dev_attrs[] = {
&dev_attr_resources.attr,
&dev_attr_options.attr,
&dev_attr_id.attr,
NULL,
};
static const struct attribute_group pnp_dev_group = {
.attrs = pnp_dev_attrs,
};
const struct attribute_group *pnp_dev_groups[] = {
&pnp_dev_group,
NULL,
};
......@@ -223,8 +223,8 @@ struct device rio_bus = {
struct bus_type rio_bus_type = {
.name = "rapidio",
.match = rio_match_bus,
.dev_attrs = rio_dev_attrs,
.bus_attrs = rio_bus_attrs,
.dev_groups = rio_dev_groups,
.bus_groups = rio_bus_groups,
.probe = rio_device_probe,
.remove = rio_device_remove,
.uevent = rio_uevent,
......
......@@ -27,6 +27,7 @@ field##_show(struct device *dev, struct device_attribute *attr, char *buf) \
\
return sprintf(buf, format_string, rdev->field); \
} \
static DEVICE_ATTR_RO(field);
rio_config_attr(did, "0x%04x\n");
rio_config_attr(vid, "0x%04x\n");
......@@ -54,6 +55,7 @@ static ssize_t routes_show(struct device *dev, struct device_attribute *attr, ch
return (str - buf);
}
static DEVICE_ATTR_RO(routes);
static ssize_t lprev_show(struct device *dev,
struct device_attribute *attr, char *buf)
......@@ -63,6 +65,7 @@ static ssize_t lprev_show(struct device *dev,
return sprintf(buf, "%s\n",
(rdev->prev) ? rio_name(rdev->prev) : "root");
}
static DEVICE_ATTR_RO(lprev);
static ssize_t lnext_show(struct device *dev,
struct device_attribute *attr, char *buf)
......@@ -83,6 +86,7 @@ static ssize_t lnext_show(struct device *dev,
return str - buf;
}
static DEVICE_ATTR_RO(lnext);
static ssize_t modalias_show(struct device *dev,
struct device_attribute *attr, char *buf)
......@@ -92,23 +96,29 @@ static ssize_t modalias_show(struct device *dev,
return sprintf(buf, "rapidio:v%04Xd%04Xav%04Xad%04X\n",
rdev->vid, rdev->did, rdev->asm_vid, rdev->asm_did);
}
static DEVICE_ATTR_RO(modalias);
static struct attribute *rio_dev_attrs[] = {
&dev_attr_did.attr,
&dev_attr_vid.attr,
&dev_attr_device_rev.attr,
&dev_attr_asm_did.attr,
&dev_attr_asm_vid.attr,
&dev_attr_asm_rev.attr,
&dev_attr_lprev.attr,
&dev_attr_destid.attr,
&dev_attr_modalias.attr,
NULL,
};
struct device_attribute rio_dev_attrs[] = {
__ATTR_RO(did),
__ATTR_RO(vid),
__ATTR_RO(device_rev),
__ATTR_RO(asm_did),
__ATTR_RO(asm_vid),
__ATTR_RO(asm_rev),
__ATTR_RO(lprev),
__ATTR_RO(destid),
__ATTR_RO(modalias),
__ATTR_NULL,
static const struct attribute_group rio_dev_group = {
.attrs = rio_dev_attrs,
};
static DEVICE_ATTR(routes, S_IRUGO, routes_show, NULL);
static DEVICE_ATTR(lnext, S_IRUGO, lnext_show, NULL);
static DEVICE_ATTR(hopcount, S_IRUGO, hopcount_show, NULL);
const struct attribute_group *rio_dev_groups[] = {
&rio_dev_group,
NULL,
};
static ssize_t
rio_read_config(struct file *filp, struct kobject *kobj,
......@@ -316,8 +326,18 @@ static ssize_t bus_scan_store(struct bus_type *bus, const char *buf,
return rc;
}
static BUS_ATTR(scan, (S_IWUSR|S_IWGRP), NULL, bus_scan_store);
static struct attribute *rio_bus_attrs[] = {
&bus_attr_scan.attr,
NULL,
};
static const struct attribute_group rio_bus_group = {
.attrs = rio_bus_attrs,
};
struct bus_attribute rio_bus_attrs[] = {
__ATTR(scan, (S_IWUSR|S_IWGRP), NULL, bus_scan_store),
__ATTR_NULL
const struct attribute_group *rio_bus_groups[] = {
&rio_bus_group,
NULL,
};
......@@ -48,8 +48,8 @@ extern struct rio_mport *rio_find_mport(int mport_id);
extern int rio_mport_scan(int mport_id);
/* Structures internal to the RIO core code */
extern struct device_attribute rio_dev_attrs[];
extern struct bus_attribute rio_bus_attrs[];
extern const struct attribute_group *rio_dev_groups[];
extern const struct attribute_group *rio_bus_groups[];
#define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16))
#define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16))
......@@ -553,16 +553,20 @@ static struct device_type fcoe_fcf_device_type = {
.release = fcoe_fcf_device_release,
};
static struct bus_attribute fcoe_bus_attr_group[] = {
__ATTR(ctlr_create, S_IWUSR, NULL, fcoe_ctlr_create_store),
__ATTR(ctlr_destroy, S_IWUSR, NULL, fcoe_ctlr_destroy_store),
__ATTR_NULL
static BUS_ATTR(ctlr_create, S_IWUSR, NULL, fcoe_ctlr_create_store);
static BUS_ATTR(ctlr_destroy, S_IWUSR, NULL, fcoe_ctlr_destroy_store);
static struct attribute *fcoe_bus_attrs[] = {
&bus_attr_ctlr_create.attr,
&bus_attr_ctlr_destroy.attr,
NULL,
};
ATTRIBUTE_GROUPS(fcoe_bus);
static struct bus_type fcoe_bus_type = {
.name = "fcoe",
.match = &fcoe_bus_match,
.bus_attrs = fcoe_bus_attr_group,
.bus_groups = fcoe_bus_groups,
};
/**
......
......@@ -374,7 +374,8 @@ static ssize_t \
attrib##_show(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return sprintf(buf, format_string, dev_to_ssb_dev(dev)->field); \
}
} \
static DEVICE_ATTR_RO(attrib);
ssb_config_attr(core_num, core_index, "%u\n")
ssb_config_attr(coreid, id.coreid, "0x%04x\n")
......@@ -387,16 +388,18 @@ name_show(struct device *dev, struct device_attribute *attr, char *buf)
return sprintf(buf, "%s\n",
ssb_core_name(dev_to_ssb_dev(dev)->id.coreid));
}
static struct device_attribute ssb_device_attrs[] = {
__ATTR_RO(name),
__ATTR_RO(core_num),
__ATTR_RO(coreid),
__ATTR_RO(vendor),
__ATTR_RO(revision),
__ATTR_RO(irq),
__ATTR_NULL,
static DEVICE_ATTR_RO(name);
static struct attribute *ssb_device_attrs[] = {
&dev_attr_name.attr,
&dev_attr_core_num.attr,
&dev_attr_coreid.attr,
&dev_attr_vendor.attr,
&dev_attr_revision.attr,
&dev_attr_irq.attr,
NULL,
};
ATTRIBUTE_GROUPS(ssb_device);
static struct bus_type ssb_bustype = {
.name = "ssb",
......@@ -407,7 +410,7 @@ static struct bus_type ssb_bustype = {
.suspend = ssb_device_suspend,
.resume = ssb_device_resume,
.uevent = ssb_device_uevent,
.dev_attrs = ssb_device_attrs,
.dev_groups = ssb_device_groups,
};
static void ssb_buses_lock(void)
......
......@@ -201,6 +201,7 @@ static ssize_t capability_id_show(struct device *dev, struct device_attribute *a
return sprintf(buf, "0x%02x\n", umc->cap_id);
}
static DEVICE_ATTR_RO(capability_id);
static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf)
{
......@@ -208,12 +209,14 @@ static ssize_t version_show(struct device *dev, struct device_attribute *attr, c
return sprintf(buf, "0x%04x\n", umc->version);
}
static DEVICE_ATTR_RO(version);
static struct device_attribute umc_dev_attrs[] = {
__ATTR_RO(capability_id),
__ATTR_RO(version),
__ATTR_NULL,
static struct attribute *umc_dev_attrs[] = {
&dev_attr_capability_id.attr,
&dev_attr_version.attr,
NULL,
};
ATTRIBUTE_GROUPS(umc_dev);
struct bus_type umc_bus_type = {
.name = "umc",
......@@ -222,7 +225,7 @@ struct bus_type umc_bus_type = {
.remove = umc_device_remove,
.suspend = umc_device_suspend,
.resume = umc_device_resume,
.dev_attrs = umc_dev_attrs,
.dev_groups = umc_dev_groups,
};
EXPORT_SYMBOL_GPL(umc_bus_type);
......
......@@ -118,7 +118,7 @@ static const struct backlight_ops atmel_pwm_bl_ops = {
.update_status = atmel_pwm_bl_set_intensity,
};
static int __init atmel_pwm_bl_probe(struct platform_device *pdev)
static int atmel_pwm_bl_probe(struct platform_device *pdev)
{
struct backlight_properties props;
const struct atmel_pwm_bl_platform_data *pdata;
......@@ -202,7 +202,7 @@ static int __init atmel_pwm_bl_probe(struct platform_device *pdev)
return retval;
}
static int __exit atmel_pwm_bl_remove(struct platform_device *pdev)
static int atmel_pwm_bl_remove(struct platform_device *pdev)
{
struct atmel_pwm_bl *pwmbl = platform_get_drvdata(pdev);
......@@ -220,10 +220,11 @@ static struct platform_driver atmel_pwm_bl_driver = {
.name = "atmel-pwm-bl",
},
/* REVISIT add suspend() and resume() */
.remove = __exit_p(atmel_pwm_bl_remove),
.probe = atmel_pwm_bl_probe,
.remove = atmel_pwm_bl_remove,
};
module_platform_driver_probe(atmel_pwm_bl_driver, atmel_pwm_bl_probe);
module_platform_driver(atmel_pwm_bl_driver);
MODULE_AUTHOR("Hans-Christian egtvedt <hans-christian.egtvedt@atmel.com>");
MODULE_DESCRIPTION("Atmel PWM backlight driver");
......
......@@ -13,18 +13,24 @@ static ssize_t device_show(struct device *_d,
struct virtio_device *dev = dev_to_virtio(_d);
return sprintf(buf, "0x%04x\n", dev->id.device);
}
static DEVICE_ATTR_RO(device);
static ssize_t vendor_show(struct device *_d,
struct device_attribute *attr, char *buf)
{
struct virtio_device *dev = dev_to_virtio(_d);
return sprintf(buf, "0x%04x\n", dev->id.vendor);
}
static DEVICE_ATTR_RO(vendor);
static ssize_t status_show(struct device *_d,
struct device_attribute *attr, char *buf)
{
struct virtio_device *dev = dev_to_virtio(_d);
return sprintf(buf, "0x%08x\n", dev->config->get_status(dev));
}
static DEVICE_ATTR_RO(status);
static ssize_t modalias_show(struct device *_d,
struct device_attribute *attr, char *buf)
{
......@@ -32,6 +38,8 @@ static ssize_t modalias_show(struct device *_d,
return sprintf(buf, "virtio:d%08Xv%08X\n",
dev->id.device, dev->id.vendor);
}
static DEVICE_ATTR_RO(modalias);
static ssize_t features_show(struct device *_d,
struct device_attribute *attr, char *buf)
{
......@@ -47,14 +55,17 @@ static ssize_t features_show(struct device *_d,
len += sprintf(buf+len, "\n");
return len;
}
static struct device_attribute virtio_dev_attrs[] = {
__ATTR_RO(device),
__ATTR_RO(vendor),
__ATTR_RO(status),
__ATTR_RO(modalias),
__ATTR_RO(features),
__ATTR_NULL
static DEVICE_ATTR_RO(features);
static struct attribute *virtio_dev_attrs[] = {
&dev_attr_device.attr,
&dev_attr_vendor.attr,
&dev_attr_status.attr,
&dev_attr_modalias.attr,
&dev_attr_features.attr,
NULL,
};
ATTRIBUTE_GROUPS(virtio_dev);
static inline int virtio_id_match(const struct virtio_device *dev,
const struct virtio_device_id *id)
......@@ -165,7 +176,7 @@ static int virtio_dev_remove(struct device *_d)
static struct bus_type virtio_bus = {
.name = "virtio",
.match = virtio_dev_match,
.dev_attrs = virtio_dev_attrs,
.dev_groups = virtio_dev_groups,
.uevent = virtio_uevent,
.probe = virtio_dev_probe,
.remove = virtio_dev_remove,
......
......@@ -384,12 +384,14 @@ static ssize_t nodename_show(struct device *dev,
{
return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename);
}
static DEVICE_ATTR_RO(nodename);
static ssize_t devtype_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype);
}
static DEVICE_ATTR_RO(devtype);
static ssize_t modalias_show(struct device *dev,
struct device_attribute *attr, char *buf)
......@@ -397,14 +399,24 @@ static ssize_t modalias_show(struct device *dev,
return sprintf(buf, "%s:%s\n", dev->bus->name,
to_xenbus_device(dev)->devicetype);
}
static DEVICE_ATTR_RO(modalias);
struct device_attribute xenbus_dev_attrs[] = {
__ATTR_RO(nodename),
__ATTR_RO(devtype),
__ATTR_RO(modalias),
__ATTR_NULL
static struct attribute *xenbus_dev_attrs[] = {
&dev_attr_nodename.attr,
&dev_attr_devtype.attr,
&dev_attr_modalias.attr,
NULL,
};
EXPORT_SYMBOL_GPL(xenbus_dev_attrs);
static const struct attribute_group xenbus_dev_group = {
.attrs = xenbus_dev_attrs,
};
const struct attribute_group *xenbus_dev_groups[] = {
&xenbus_dev_group,
NULL,
};
EXPORT_SYMBOL_GPL(xenbus_dev_groups);
int xenbus_probe_node(struct xen_bus_type *bus,
const char *type,
......
......@@ -54,7 +54,7 @@ enum xenstore_init {
XS_LOCAL,
};
extern struct device_attribute xenbus_dev_attrs[];
extern const struct attribute_group *xenbus_dev_groups[];
extern int xenbus_match(struct device *_dev, struct device_driver *_drv);
extern int xenbus_dev_probe(struct device *_dev);
......
......@@ -200,7 +200,7 @@ static struct xen_bus_type xenbus_backend = {
.probe = xenbus_dev_probe,
.remove = xenbus_dev_remove,
.shutdown = xenbus_dev_shutdown,
.dev_attrs = xenbus_dev_attrs,
.dev_groups = xenbus_dev_groups,
},
};
......
......@@ -154,7 +154,7 @@ static struct xen_bus_type xenbus_frontend = {
.probe = xenbus_frontend_dev_probe,
.remove = xenbus_dev_remove,
.shutdown = xenbus_dev_shutdown,
.dev_attrs = xenbus_dev_attrs,
.dev_groups = xenbus_dev_groups,
.pm = &xenbus_pm_ops,
},
......
......@@ -2,5 +2,4 @@
# Makefile for the sysfs virtual filesystem
#
obj-y := inode.o file.o dir.o symlink.o mount.o bin.o \
group.o
obj-y := inode.o file.o dir.o symlink.o mount.o group.o
/*
* fs/sysfs/bin.c - sysfs binary file implementation
*
* Copyright (c) 2003 Patrick Mochel
* Copyright (c) 2003 Matthew Wilcox
* Copyright (c) 2004 Silicon Graphics, Inc.
* Copyright (c) 2007 SUSE Linux Products GmbH
* Copyright (c) 2007 Tejun Heo <teheo@suse.de>
*
* This file is released under the GPLv2.
*
* Please see Documentation/filesystems/sysfs.txt for more information.
*/
#undef DEBUG
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/mm.h>
#include <linux/uaccess.h>
#include "sysfs.h"
/*
* There's one bin_buffer for each open file.
*
* filp->private_data points to bin_buffer and
* sysfs_dirent->s_bin_attr.buffers points to a the bin_buffer s
* sysfs_dirent->s_bin_attr.buffers is protected by sysfs_bin_lock
*/
static DEFINE_MUTEX(sysfs_bin_lock);
struct bin_buffer {
struct mutex mutex;
void *buffer;
int mmapped;
const struct vm_operations_struct *vm_ops;
struct file *file;
struct hlist_node list;
};
static int
fill_read(struct file *file, char *buffer, loff_t off, size_t count)
{
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
int rc;
/* need attr_sd for attr, its parent for kobj */
if (!sysfs_get_active(attr_sd))
return -ENODEV;
rc = -EIO;
if (attr->read)
rc = attr->read(file, kobj, attr, buffer, off, count);
sysfs_put_active(attr_sd);
return rc;
}
static ssize_t
read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
{
struct bin_buffer *bb = file->private_data;
int size = file_inode(file)->i_size;
loff_t offs = *off;
int count = min_t(size_t, bytes, PAGE_SIZE);
char *temp;
if (!bytes)
return 0;
if (size) {
if (offs > size)
return 0;
if (offs + count > size)
count = size - offs;
}
temp = kmalloc(count, GFP_KERNEL);
if (!temp)
return -ENOMEM;
mutex_lock(&bb->mutex);
count = fill_read(file, bb->buffer, offs, count);
if (count < 0) {
mutex_unlock(&bb->mutex);
goto out_free;
}
memcpy(temp, bb->buffer, count);
mutex_unlock(&bb->mutex);
if (copy_to_user(userbuf, temp, count)) {
count = -EFAULT;
goto out_free;
}
pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count);
*off = offs + count;
out_free:
kfree(temp);
return count;
}
static int
flush_write(struct file *file, char *buffer, loff_t offset, size_t count)
{
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
int rc;
/* need attr_sd for attr, its parent for kobj */
if (!sysfs_get_active(attr_sd))
return -ENODEV;
rc = -EIO;
if (attr->write)
rc = attr->write(file, kobj, attr, buffer, offset, count);
sysfs_put_active(attr_sd);
return rc;
}
static ssize_t write(struct file *file, const char __user *userbuf,
size_t bytes, loff_t *off)
{
struct bin_buffer *bb = file->private_data;
int size = file_inode(file)->i_size;
loff_t offs = *off;
int count = min_t(size_t, bytes, PAGE_SIZE);
char *temp;
if (!bytes)
return 0;
if (size) {
if (offs > size)
return 0;
if (offs + count > size)
count = size - offs;
}
temp = memdup_user(userbuf, count);
if (IS_ERR(temp))
return PTR_ERR(temp);
mutex_lock(&bb->mutex);
memcpy(bb->buffer, temp, count);
count = flush_write(file, bb->buffer, offs, count);
mutex_unlock(&bb->mutex);
if (count > 0)
*off = offs + count;
kfree(temp);
return count;
}
static void bin_vma_open(struct vm_area_struct *vma)
{
struct file *file = vma->vm_file;
struct bin_buffer *bb = file->private_data;
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
if (!bb->vm_ops)
return;
if (!sysfs_get_active(attr_sd))
return;
if (bb->vm_ops->open)
bb->vm_ops->open(vma);
sysfs_put_active(attr_sd);
}
static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct file *file = vma->vm_file;
struct bin_buffer *bb = file->private_data;
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
int ret;
if (!bb->vm_ops)
return VM_FAULT_SIGBUS;
if (!sysfs_get_active(attr_sd))
return VM_FAULT_SIGBUS;
ret = VM_FAULT_SIGBUS;
if (bb->vm_ops->fault)
ret = bb->vm_ops->fault(vma, vmf);
sysfs_put_active(attr_sd);
return ret;
}
static int bin_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct file *file = vma->vm_file;
struct bin_buffer *bb = file->private_data;
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
int ret;
if (!bb->vm_ops)
return VM_FAULT_SIGBUS;
if (!sysfs_get_active(attr_sd))
return VM_FAULT_SIGBUS;
ret = 0;
if (bb->vm_ops->page_mkwrite)
ret = bb->vm_ops->page_mkwrite(vma, vmf);
else
file_update_time(file);
sysfs_put_active(attr_sd);
return ret;
}
static int bin_access(struct vm_area_struct *vma, unsigned long addr,
void *buf, int len, int write)
{
struct file *file = vma->vm_file;
struct bin_buffer *bb = file->private_data;
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
int ret;
if (!bb->vm_ops)
return -EINVAL;
if (!sysfs_get_active(attr_sd))
return -EINVAL;
ret = -EINVAL;
if (bb->vm_ops->access)
ret = bb->vm_ops->access(vma, addr, buf, len, write);
sysfs_put_active(attr_sd);
return ret;
}
#ifdef CONFIG_NUMA
static int bin_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
{
struct file *file = vma->vm_file;
struct bin_buffer *bb = file->private_data;
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
int ret;
if (!bb->vm_ops)
return 0;
if (!sysfs_get_active(attr_sd))
return -EINVAL;
ret = 0;
if (bb->vm_ops->set_policy)
ret = bb->vm_ops->set_policy(vma, new);
sysfs_put_active(attr_sd);
return ret;
}
static struct mempolicy *bin_get_policy(struct vm_area_struct *vma,
unsigned long addr)
{
struct file *file = vma->vm_file;
struct bin_buffer *bb = file->private_data;
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
struct mempolicy *pol;
if (!bb->vm_ops)
return vma->vm_policy;
if (!sysfs_get_active(attr_sd))
return vma->vm_policy;
pol = vma->vm_policy;
if (bb->vm_ops->get_policy)
pol = bb->vm_ops->get_policy(vma, addr);
sysfs_put_active(attr_sd);
return pol;
}
static int bin_migrate(struct vm_area_struct *vma, const nodemask_t *from,
const nodemask_t *to, unsigned long flags)
{
struct file *file = vma->vm_file;
struct bin_buffer *bb = file->private_data;
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
int ret;
if (!bb->vm_ops)
return 0;
if (!sysfs_get_active(attr_sd))
return 0;
ret = 0;
if (bb->vm_ops->migrate)
ret = bb->vm_ops->migrate(vma, from, to, flags);
sysfs_put_active(attr_sd);
return ret;
}
#endif
static const struct vm_operations_struct bin_vm_ops = {
.open = bin_vma_open,
.fault = bin_fault,
.page_mkwrite = bin_page_mkwrite,
.access = bin_access,
#ifdef CONFIG_NUMA
.set_policy = bin_set_policy,
.get_policy = bin_get_policy,
.migrate = bin_migrate,
#endif
};
static int mmap(struct file *file, struct vm_area_struct *vma)
{
struct bin_buffer *bb = file->private_data;
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
int rc;
mutex_lock(&bb->mutex);
/* need attr_sd for attr, its parent for kobj */
rc = -ENODEV;
if (!sysfs_get_active(attr_sd))
goto out_unlock;
rc = -EINVAL;
if (!attr->mmap)
goto out_put;
rc = attr->mmap(file, kobj, attr, vma);
if (rc)
goto out_put;
/*
* PowerPC's pci_mmap of legacy_mem uses shmem_zero_setup()
* to satisfy versions of X which crash if the mmap fails: that
* substitutes a new vm_file, and we don't then want bin_vm_ops.
*/
if (vma->vm_file != file)
goto out_put;
rc = -EINVAL;
if (bb->mmapped && bb->vm_ops != vma->vm_ops)
goto out_put;
/*
* It is not possible to successfully wrap close.
* So error if someone is trying to use close.
*/
rc = -EINVAL;
if (vma->vm_ops && vma->vm_ops->close)
goto out_put;
rc = 0;
bb->mmapped = 1;
bb->vm_ops = vma->vm_ops;
vma->vm_ops = &bin_vm_ops;
out_put:
sysfs_put_active(attr_sd);
out_unlock:
mutex_unlock(&bb->mutex);
return rc;
}
static int open(struct inode *inode, struct file *file)
{
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
struct bin_buffer *bb = NULL;
int error;
/* binary file operations requires both @sd and its parent */
if (!sysfs_get_active(attr_sd))
return -ENODEV;
error = -EACCES;
if ((file->f_mode & FMODE_WRITE) && !(attr->write || attr->mmap))
goto err_out;
if ((file->f_mode & FMODE_READ) && !(attr->read || attr->mmap))
goto err_out;
error = -ENOMEM;
bb = kzalloc(sizeof(*bb), GFP_KERNEL);
if (!bb)
goto err_out;
bb->buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!bb->buffer)
goto err_out;
mutex_init(&bb->mutex);
bb->file = file;
file->private_data = bb;
mutex_lock(&sysfs_bin_lock);
hlist_add_head(&bb->list, &attr_sd->s_bin_attr.buffers);
mutex_unlock(&sysfs_bin_lock);
/* open succeeded, put active references */
sysfs_put_active(attr_sd);
return 0;
err_out:
sysfs_put_active(attr_sd);
kfree(bb);
return error;
}
static int release(struct inode *inode, struct file *file)
{
struct bin_buffer *bb = file->private_data;
mutex_lock(&sysfs_bin_lock);
hlist_del(&bb->list);
mutex_unlock(&sysfs_bin_lock);
kfree(bb->buffer);
kfree(bb);
return 0;
}
const struct file_operations bin_fops = {
.read = read,
.write = write,
.mmap = mmap,
.llseek = generic_file_llseek,
.open = open,
.release = release,
};
void unmap_bin_file(struct sysfs_dirent *attr_sd)
{
struct bin_buffer *bb;
if (sysfs_type(attr_sd) != SYSFS_KOBJ_BIN_ATTR)
return;
mutex_lock(&sysfs_bin_lock);
hlist_for_each_entry(bb, &attr_sd->s_bin_attr.buffers, list) {
struct inode *inode = file_inode(bb->file);
unmap_mapping_range(inode->i_mapping, 0, 0, 1);
}
mutex_unlock(&sysfs_bin_lock);
}
/**
* sysfs_create_bin_file - create binary file for object.
* @kobj: object.
* @attr: attribute descriptor.
*/
int sysfs_create_bin_file(struct kobject *kobj,
const struct bin_attribute *attr)
{
BUG_ON(!kobj || !kobj->sd || !attr);
return sysfs_add_file(kobj->sd, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
}
EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
/**
* sysfs_remove_bin_file - remove binary file for object.
* @kobj: object.
* @attr: attribute descriptor.
*/
void sysfs_remove_bin_file(struct kobject *kobj,
const struct bin_attribute *attr)
{
sysfs_hash_and_remove(kobj->sd, NULL, attr->attr.name);
}
EXPORT_SYMBOL_GPL(sysfs_remove_bin_file);
此差异已折叠。
此差异已折叠。
......@@ -26,7 +26,7 @@ static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
if (grp->attrs)
for (attr = grp->attrs; *attr; attr++)
sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name);
sysfs_hash_and_remove(dir_sd, (*attr)->name, NULL);
if (grp->bin_attrs)
for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++)
sysfs_remove_bin_file(kobj, *bin_attr);
......@@ -49,16 +49,17 @@ static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
* re-adding (if required) the file.
*/
if (update)
sysfs_hash_and_remove(dir_sd, NULL,
(*attr)->name);
sysfs_hash_and_remove(dir_sd, (*attr)->name,
NULL);
if (grp->is_visible) {
mode = grp->is_visible(kobj, *attr, i);
if (!mode)
continue;
}
error = sysfs_add_file_mode(dir_sd, *attr,
SYSFS_KOBJ_ATTR,
(*attr)->mode | mode);
error = sysfs_add_file_mode_ns(dir_sd, *attr,
SYSFS_KOBJ_ATTR,
(*attr)->mode | mode,
NULL);
if (unlikely(error))
break;
}
......@@ -110,7 +111,7 @@ static int internal_create_group(struct kobject *kobj, int update,
error = create_files(sd, kobj, grp, update);
if (error) {
if (grp->name)
sysfs_remove_subdir(sd);
sysfs_remove(sd);
}
sysfs_put(sd);
return error;
......@@ -206,7 +207,7 @@ void sysfs_remove_group(struct kobject *kobj,
struct sysfs_dirent *sd;
if (grp->name) {
sd = sysfs_get_dirent(dir_sd, NULL, grp->name);
sd = sysfs_get_dirent(dir_sd, grp->name);
if (!sd) {
WARN(!sd, KERN_WARNING
"sysfs group %p not found for kobject '%s'\n",
......@@ -218,7 +219,7 @@ void sysfs_remove_group(struct kobject *kobj,
remove_files(sd, kobj, grp);
if (grp->name)
sysfs_remove_subdir(sd);
sysfs_remove(sd);
sysfs_put(sd);
}
......@@ -261,7 +262,7 @@ int sysfs_merge_group(struct kobject *kobj,
struct attribute *const *attr;
int i;
dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name);
dir_sd = sysfs_get_dirent(kobj->sd, grp->name);
if (!dir_sd)
return -ENOENT;
......@@ -269,7 +270,7 @@ int sysfs_merge_group(struct kobject *kobj,
error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
if (error) {
while (--i >= 0)
sysfs_hash_and_remove(dir_sd, NULL, (*--attr)->name);
sysfs_hash_and_remove(dir_sd, (*--attr)->name, NULL);
}
sysfs_put(dir_sd);
......@@ -288,10 +289,10 @@ void sysfs_unmerge_group(struct kobject *kobj,
struct sysfs_dirent *dir_sd;
struct attribute *const *attr;
dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name);
dir_sd = sysfs_get_dirent(kobj->sd, grp->name);
if (dir_sd) {
for (attr = grp->attrs; *attr; ++attr)
sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name);
sysfs_hash_and_remove(dir_sd, (*attr)->name, NULL);
sysfs_put(dir_sd);
}
}
......@@ -310,7 +311,7 @@ int sysfs_add_link_to_group(struct kobject *kobj, const char *group_name,
struct sysfs_dirent *dir_sd;
int error = 0;
dir_sd = sysfs_get_dirent(kobj->sd, NULL, group_name);
dir_sd = sysfs_get_dirent(kobj->sd, group_name);
if (!dir_sd)
return -ENOENT;
......@@ -332,9 +333,9 @@ void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name,
{
struct sysfs_dirent *dir_sd;
dir_sd = sysfs_get_dirent(kobj->sd, NULL, group_name);
dir_sd = sysfs_get_dirent(kobj->sd, group_name);
if (dir_sd) {
sysfs_hash_and_remove(dir_sd, NULL, link_name);
sysfs_hash_and_remove(dir_sd, link_name, NULL);
sysfs_put(dir_sd);
}
}
......
......@@ -258,9 +258,9 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
inode->i_fop = &sysfs_file_operations;
break;
case SYSFS_KOBJ_BIN_ATTR:
bin_attr = sd->s_bin_attr.bin_attr;
bin_attr = sd->s_attr.bin_attr;
inode->i_size = bin_attr->size;
inode->i_fop = &bin_fops;
inode->i_fop = &sysfs_bin_operations;
break;
case SYSFS_KOBJ_LINK:
inode->i_op = &sysfs_symlink_inode_operations;
......@@ -314,32 +314,6 @@ void sysfs_evict_inode(struct inode *inode)
sysfs_put(sd);
}
int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns,
const char *name)
{
struct sysfs_addrm_cxt acxt;
struct sysfs_dirent *sd;
if (!dir_sd) {
WARN(1, KERN_WARNING "sysfs: can not remove '%s', no directory\n",
name);
return -ENOENT;
}
sysfs_addrm_start(&acxt, dir_sd);
sd = sysfs_find_dirent(dir_sd, ns, name);
if (sd)
sysfs_remove_one(&acxt, sd);
sysfs_addrm_finish(&acxt);
if (sd)
return 0;
else
return -ENOENT;
}
int sysfs_permission(struct inode *inode, int mask)
{
struct sysfs_dirent *sd;
......
......@@ -36,7 +36,7 @@ static const struct super_operations sysfs_ops = {
struct sysfs_dirent sysfs_root = {
.s_name = "",
.s_count = ATOMIC_INIT(1),
.s_flags = SYSFS_DIR | (KOBJ_NS_TYPE_NONE << SYSFS_NS_TYPE_SHIFT),
.s_flags = SYSFS_DIR,
.s_mode = S_IFDIR | S_IRUGO | S_IXUGO,
.s_ino = 1,
};
......@@ -77,14 +77,8 @@ static int sysfs_test_super(struct super_block *sb, void *data)
{
struct sysfs_super_info *sb_info = sysfs_info(sb);
struct sysfs_super_info *info = data;
enum kobj_ns_type type;
int found = 1;
for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) {
if (sb_info->ns[type] != info->ns[type])
found = 0;
}
return found;
return sb_info->ns == info->ns;
}
static int sysfs_set_super(struct super_block *sb, void *data)
......@@ -98,9 +92,7 @@ static int sysfs_set_super(struct super_block *sb, void *data)
static void free_sysfs_super_info(struct sysfs_super_info *info)
{
int type;
for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++)
kobj_ns_drop(type, info->ns[type]);
kobj_ns_drop(KOBJ_NS_TYPE_NET, info->ns);
kfree(info);
}
......@@ -108,7 +100,6 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
struct sysfs_super_info *info;
enum kobj_ns_type type;
struct super_block *sb;
int error;
......@@ -116,18 +107,15 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
if (!capable(CAP_SYS_ADMIN) && !fs_fully_visible(fs_type))
return ERR_PTR(-EPERM);
for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) {
if (!kobj_ns_current_may_mount(type))
return ERR_PTR(-EPERM);
}
if (!kobj_ns_current_may_mount(KOBJ_NS_TYPE_NET))
return ERR_PTR(-EPERM);
}
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return ERR_PTR(-ENOMEM);
for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++)
info->ns[type] = kobj_ns_grab_current(type);
info->ns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
sb = sget(fs_type, sysfs_test_super, sysfs_set_super, flags, info);
if (IS_ERR(sb) || sb->s_fs_info != info)
......
......@@ -28,18 +28,19 @@ static int sysfs_do_create_link_sd(struct sysfs_dirent *parent_sd,
struct sysfs_dirent *target_sd = NULL;
struct sysfs_dirent *sd = NULL;
struct sysfs_addrm_cxt acxt;
enum kobj_ns_type ns_type;
int error;
BUG_ON(!name || !parent_sd);
/* target->sd can go away beneath us but is protected with
* sysfs_assoc_lock. Fetch target_sd from it.
/*
* We don't own @target and it may be removed at any time.
* Synchronize using sysfs_symlink_target_lock. See
* sysfs_remove_dir() for details.
*/
spin_lock(&sysfs_assoc_lock);
spin_lock(&sysfs_symlink_target_lock);
if (target->sd)
target_sd = sysfs_get(target->sd);
spin_unlock(&sysfs_assoc_lock);
spin_unlock(&sysfs_symlink_target_lock);
error = -ENOENT;
if (!target_sd)
......@@ -50,29 +51,15 @@ static int sysfs_do_create_link_sd(struct sysfs_dirent *parent_sd,
if (!sd)
goto out_put;
ns_type = sysfs_ns_type(parent_sd);
if (ns_type)
sd->s_ns = target->ktype->namespace(target);
sd->s_ns = target_sd->s_ns;
sd->s_symlink.target_sd = target_sd;
target_sd = NULL; /* reference is now owned by the symlink */
sysfs_addrm_start(&acxt, parent_sd);
/* Symlinks must be between directories with the same ns_type */
if (!ns_type ||
(ns_type == sysfs_ns_type(sd->s_symlink.target_sd->s_parent))) {
if (warn)
error = sysfs_add_one(&acxt, sd);
else
error = __sysfs_add_one(&acxt, sd);
} else {
error = -EINVAL;
WARN(1, KERN_WARNING
"sysfs: symlink across ns_types %s/%s -> %s/%s\n",
parent_sd->s_name,
sd->s_name,
sd->s_symlink.target_sd->s_parent->s_name,
sd->s_symlink.target_sd->s_name);
}
sysfs_addrm_start(&acxt);
if (warn)
error = sysfs_add_one(&acxt, sd, parent_sd);
else
error = __sysfs_add_one(&acxt, sd, parent_sd);
sysfs_addrm_finish(&acxt);
if (error)
......@@ -155,11 +142,17 @@ void sysfs_delete_link(struct kobject *kobj, struct kobject *targ,
const char *name)
{
const void *ns = NULL;
spin_lock(&sysfs_assoc_lock);
if (targ->sd && sysfs_ns_type(kobj->sd))
/*
* We don't own @target and it may be removed at any time.
* Synchronize using sysfs_symlink_target_lock. See
* sysfs_remove_dir() for details.
*/
spin_lock(&sysfs_symlink_target_lock);
if (targ->sd)
ns = targ->sd->s_ns;
spin_unlock(&sysfs_assoc_lock);
sysfs_hash_and_remove(kobj->sd, ns, name);
spin_unlock(&sysfs_symlink_target_lock);
sysfs_hash_and_remove(kobj->sd, name, ns);
}
/**
......@@ -176,24 +169,25 @@ void sysfs_remove_link(struct kobject *kobj, const char *name)
else
parent_sd = kobj->sd;
sysfs_hash_and_remove(parent_sd, NULL, name);
sysfs_hash_and_remove(parent_sd, name, NULL);
}
EXPORT_SYMBOL_GPL(sysfs_remove_link);
/**
* sysfs_rename_link - rename symlink in object's directory.
* sysfs_rename_link_ns - rename symlink in object's directory.
* @kobj: object we're acting for.
* @targ: object we're pointing to.
* @old: previous name of the symlink.
* @new: new name of the symlink.
* @new_ns: new namespace of the symlink.
*
* A helper function for the common rename symlink idiom.
*/
int sysfs_rename_link(struct kobject *kobj, struct kobject *targ,
const char *old, const char *new)
int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *targ,
const char *old, const char *new, const void *new_ns)
{
struct sysfs_dirent *parent_sd, *sd = NULL;
const void *old_ns = NULL, *new_ns = NULL;
const void *old_ns = NULL;
int result;
if (!kobj)
......@@ -205,7 +199,7 @@ int sysfs_rename_link(struct kobject *kobj, struct kobject *targ,
old_ns = targ->sd->s_ns;
result = -ENOENT;
sd = sysfs_get_dirent(parent_sd, old_ns, old);
sd = sysfs_get_dirent_ns(parent_sd, old, old_ns);
if (!sd)
goto out;
......@@ -215,16 +209,13 @@ int sysfs_rename_link(struct kobject *kobj, struct kobject *targ,
if (sd->s_symlink.target_sd->s_dir.kobj != targ)
goto out;
if (sysfs_ns_type(parent_sd))
new_ns = targ->ktype->namespace(targ);
result = sysfs_rename(sd, parent_sd, new_ns, new);
result = sysfs_rename(sd, parent_sd, new, new_ns);
out:
sysfs_put(sd);
return result;
}
EXPORT_SYMBOL_GPL(sysfs_rename_link);
EXPORT_SYMBOL_GPL(sysfs_rename_link_ns);
static int sysfs_get_target_path(struct sysfs_dirent *parent_sd,
struct sysfs_dirent *target_sd, char *path)
......
此差异已折叠。
......@@ -206,6 +206,12 @@ static inline struct dentry *debugfs_create_size_t(const char *name, umode_t mod
return ERR_PTR(-ENODEV);
}
static inline struct dentry *debugfs_create_atomic_t(const char *name, umode_t mode,
struct dentry *parent, atomic_t *value)
{
return ERR_PTR(-ENODEV);
}
static inline struct dentry *debugfs_create_bool(const char *name, umode_t mode,
struct dentry *parent,
u32 *value)
......@@ -227,6 +233,12 @@ static inline struct dentry *debugfs_create_regset32(const char *name,
return ERR_PTR(-ENODEV);
}
static inline int debugfs_print_regs32(struct seq_file *s, const struct debugfs_reg32 *regs,
int nregs, void __iomem *base, char *prefix)
{
return 0;
}
static inline bool debugfs_initialized(void)
{
return false;
......
此差异已折叠。
......@@ -1514,7 +1514,7 @@ static inline void ide_set_max_pio(ide_drive_t *drive)
char *ide_media_string(ide_drive_t *);
extern struct device_attribute ide_dev_attrs[];
extern const struct attribute_group *ide_dev_groups[];
extern struct bus_type ide_bus_type;
extern struct class *ide_port_class;
......
#ifndef _KOBJ_COMPLETION_H_
#define _KOBJ_COMPLETION_H_
#include <linux/kobject.h>
#include <linux/completion.h>
struct kobj_completion {
struct kobject kc_kobj;
struct completion kc_unregister;
};
#define kobj_to_kobj_completion(kobj) \
container_of(kobj, struct kobj_completion, kc_kobj)
void kobj_completion_init(struct kobj_completion *kc, struct kobj_type *ktype);
void kobj_completion_release(struct kobject *kobj);
void kobj_completion_del_and_wait(struct kobj_completion *kc);
#endif /* _KOBJ_COMPLETION_H_ */
......@@ -107,6 +107,7 @@ extern int __must_check kobject_move(struct kobject *, struct kobject *);
extern struct kobject *kobject_get(struct kobject *kobj);
extern void kobject_put(struct kobject *kobj);
extern const void *kobject_namespace(struct kobject *kobj);
extern char *kobject_get_path(struct kobject *kobj, gfp_t flag);
struct kobj_type {
......
......@@ -2874,8 +2874,20 @@ extern int __init dev_proc_init(void);
#define dev_proc_init() 0
#endif
extern int netdev_class_create_file(struct class_attribute *class_attr);
extern void netdev_class_remove_file(struct class_attribute *class_attr);
extern int netdev_class_create_file_ns(struct class_attribute *class_attr,
const void *ns);
extern void netdev_class_remove_file_ns(struct class_attribute *class_attr,
const void *ns);
static inline int netdev_class_create_file(struct class_attribute *class_attr)
{
return netdev_class_create_file_ns(class_attr, NULL);
}
static inline void netdev_class_remove_file(struct class_attribute *class_attr)
{
netdev_class_remove_file_ns(class_attr, NULL);
}
extern struct kobj_ns_type_operations net_ns_type_operations;
......
......@@ -178,6 +178,7 @@ struct platform_driver {
int (*resume)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
bool prevent_deferred_probe;
};
#define to_platform_driver(drv) (container_of((drv), struct platform_driver, \
......
此差异已折叠。
......@@ -6292,6 +6292,7 @@ type_show(struct device *dev, struct device_attribute *attr, char *page)
return snprintf(page, PAGE_SIZE-1, "%d\n", pmu->type);
}
static DEVICE_ATTR_RO(type);
static ssize_t
perf_event_mux_interval_ms_show(struct device *dev,
......@@ -6336,17 +6337,19 @@ perf_event_mux_interval_ms_store(struct device *dev,
return count;
}
static DEVICE_ATTR_RW(perf_event_mux_interval_ms);
static struct device_attribute pmu_dev_attrs[] = {
__ATTR_RO(type),
__ATTR_RW(perf_event_mux_interval_ms),
__ATTR_NULL,
static struct attribute *pmu_dev_attrs[] = {
&dev_attr_type.attr,
&dev_attr_perf_event_mux_interval_ms.attr,
NULL,
};
ATTRIBUTE_GROUPS(pmu_dev);
static int pmu_bus_running;
static struct bus_type pmu_bus = {
.name = "event_source",
.dev_attrs = pmu_dev_attrs,
.dev_groups = pmu_dev_groups,
};
static void pmu_dev_release(struct device *dev)
......
此差异已折叠。
......@@ -1344,17 +1344,19 @@ int netdev_register_kobject(struct net_device *net)
return error;
}
int netdev_class_create_file(struct class_attribute *class_attr)
int netdev_class_create_file_ns(struct class_attribute *class_attr,
const void *ns)
{
return class_create_file(&net_class, class_attr);
return class_create_file_ns(&net_class, class_attr, ns);
}
EXPORT_SYMBOL(netdev_class_create_file);
EXPORT_SYMBOL(netdev_class_create_file_ns);
void netdev_class_remove_file(struct class_attribute *class_attr)
void netdev_class_remove_file_ns(struct class_attribute *class_attr,
const void *ns)
{
class_remove_file(&net_class, class_attr);
class_remove_file_ns(&net_class, class_attr, ns);
}
EXPORT_SYMBOL(netdev_class_remove_file);
EXPORT_SYMBOL(netdev_class_remove_file_ns);
int netdev_kobject_init(void)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
新手
引导
客服 返回
顶部