Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6: (61 commits)
  sysfs: add parameter "struct bin_attribute *" in .read/.write methods for sysfs binary attributes
  sysfs: make directory dentries and inodes reclaimable
  sysfs: implement sysfs_get_dentry()
  sysfs: move sysfs_drop_dentry() to dir.c and make it static
  sysfs: restructure add/remove paths and fix inode update
  sysfs: use sysfs_mutex to protect the sysfs_dirent tree
  sysfs: consolidate sysfs spinlocks
  sysfs: make kobj point to sysfs_dirent instead of dentry
  sysfs: implement sysfs_find_dirent() and sysfs_get_dirent()
  sysfs: implement SYSFS_FLAG_REMOVED flag
  sysfs: rename sysfs_dirent->s_type to s_flags and make room for flags
  sysfs: make sysfs_drop_dentry() access inodes using ilookup()
  sysfs: Fix oops in sysfs_drop_dentry on x86_64
  sysfs: use singly-linked list for sysfs_dirent tree
  sysfs: slim down sysfs_dirent->s_active
  sysfs: move s_active functions to fs/sysfs/dir.c
  sysfs: fix root sysfs_dirent -> root dentry association
  sysfs: use iget_locked() instead of new_inode()
  sysfs: reorganize sysfs_new_indoe() and sysfs_create()
  sysfs: fix parent refcounting during rename and move
  ...
This commit is contained in:
Linus Torvalds 2007-07-12 13:40:20 -07:00
commit dc690d8ef8
93 changed files with 2850 additions and 1522 deletions

View file

@ -78,6 +78,7 @@ static CLASS_DEVICE_ATTR(loading, 0644,
firmware_loading_show, firmware_loading_store);
static ssize_t firmware_data_read(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buffer, loff_t offset, size_t count)
{
struct class_device *class_dev = to_class_dev(kobj);
@ -88,6 +89,7 @@ static ssize_t firmware_data_read(struct kobject *kobj,
return count;
}
static ssize_t firmware_data_write(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buffer, loff_t offset, size_t count)
{
struct class_device *class_dev = to_class_dev(kobj);

View file

@ -0,0 +1,166 @@
Rules on how to access information in the Linux kernel sysfs
The kernel exported sysfs exports internal kernel implementation-details
and depends on internal kernel structures and layout. It is agreed upon
by the kernel developers that the Linux kernel does not provide a stable
internal API. As sysfs is a direct export of kernel internal
structures, the sysfs interface can not provide a stable interface eighter,
it may always change along with internal kernel changes.
To minimize the risk of breaking users of sysfs, which are in most cases
low-level userspace applications, with a new kernel release, the users
of sysfs must follow some rules to use an as abstract-as-possible way to
access this filesystem. The current udev and HAL programs already
implement this and users are encouraged to plug, if possible, into the
abstractions these programs provide instead of accessing sysfs
directly.
But if you really do want or need to access sysfs directly, please follow
the following rules and then your programs should work with future
versions of the sysfs interface.
- Do not use libsysfs
It makes assumptions about sysfs which are not true. Its API does not
offer any abstraction, it exposes all the kernel driver-core
implementation details in its own API. Therefore it is not better than
reading directories and opening the files yourself.
Also, it is not actively maintained, in the sense of reflecting the
current kernel-development. The goal of providing a stable interface
to sysfs has failed, it causes more problems, than it solves. It
violates many of the rules in this document.
- sysfs is always at /sys
Parsing /proc/mounts is a waste of time. Other mount points are a
system configuration bug you should not try to solve. For test cases,
possibly support a SYSFS_PATH environment variable to overwrite the
applications behavior, but never try to search for sysfs. Never try
to mount it, if you are not an early boot script.
- devices are only "devices"
There is no such thing like class-, bus-, physical devices,
interfaces, and such that you can rely on in userspace. Everything is
just simply a "device". Class-, bus-, physical, ... types are just
kernel implementation details, which should not be expected by
applications that look for devices in sysfs.
The properties of a device are:
o devpath (/devices/pci0000:00/0000:00:1d.1/usb2/2-2/2-2:1.0)
- identical to the DEVPATH value in the event sent from the kernel
at device creation and removal
- the unique key to the device at that point in time
- the kernels path to the device-directory without the leading
/sys, and always starting with with a slash
- all elements of a devpath must be real directories. Symlinks
pointing to /sys/devices must always be resolved to their real
target, and the target path must be used to access the device.
That way the devpath to the device matches the devpath of the
kernel used at event time.
- using or exposing symlink values as elements in a devpath string
is a bug in the application
o kernel name (sda, tty, 0000:00:1f.2, ...)
- a directory name, identical to the last element of the devpath
- applications need to handle spaces and characters like '!' in
the name
o subsystem (block, tty, pci, ...)
- simple string, never a path or a link
- retrieved by reading the "subsystem"-link and using only the
last element of the target path
o driver (tg3, ata_piix, uhci_hcd)
- a simple string, which may contain spaces, never a path or a
link
- it is retrieved by reading the "driver"-link and using only the
last element of the target path
- devices which do not have "driver"-link, just do not have a
driver; copying the driver value in a child device context, is a
bug in the application
o attributes
- the files in the device directory or files below a subdirectories
of the same device directory
- accessing attributes reached by a symlink pointing to another device,
like the "device"-link, is a bug in the application
Everything else is just a kernel driver-core implementation detail,
that should not be assumed to be stable across kernel releases.
- Properties of parent devices never belong into a child device.
Always look at the parent devices themselves for determining device
context properties. If the device 'eth0' or 'sda' does not have a
"driver"-link, then this device does not have a driver. Its value is empty.
Never copy any property of the parent-device into a child-device. Parent
device-properties may change dynamically without any notice to the
child device.
- Hierarchy in a single device-tree
There is only one valid place in sysfs where hierarchy can be examined
and this is below: /sys/devices.
It is planned, that all device directories will end up in the tree
below this directory.
- Classification by subsystem
There are currently three places for classification of devices:
/sys/block, /sys/class and /sys/bus. It is planned that these will
not contain any device-directories themselves, but only flat lists of
symlinks pointing to the unified /sys/devices tree.
All three places have completely different rules on how to access
device information. It is planned to merge all three
classification-directories into one place at /sys/subsystem,
following the layout of the bus-directories. All buses and
classes, including the converted block-subsystem, will show up
there.
The devices belonging to a subsystem will create a symlink in the
"devices" directory at /sys/subsystem/<name>/devices.
If /sys/subsystem exists, /sys/bus, /sys/class and /sys/block can be
ignored. If it does not exist, you have always to scan all three
places, as the kernel is free to move a subsystem from one place to
the other, as long as the devices are still reachable by the same
subsystem name.
Assuming /sys/class/<subsystem> and /sys/bus/<subsystem>, or
/sys/block and /sys/class/block are not interchangeable, is a bug in
the application.
- Block
The converted block-subsystem at /sys/class/block, or
/sys/subsystem/block will contain the links for disks and partitions
at the same level, never in a hierarchy. Assuming the block-subsytem to
contain only disks and not partition-devices in the same flat list is
a bug in the application.
- "device"-link and <subsystem>:<kernel name>-links
Never depend on the "device"-link. The "device"-link is a workaround
for the old layout, where class-devices are not created in
/sys/devices/ like the bus-devices. If the link-resolving of a
device-directory does not end in /sys/devices/, you can use the
"device"-link to find the parent devices in /sys/devices/. That is the
single valid use of the "device"-link, it must never appear in any
path as an element. Assuming the existence of the "device"-link for
a device in /sys/devices/ is a bug in the application.
Accessing /sys/class/net/eth0/device is a bug in the application.
Never depend on the class-specific links back to the /sys/class
directory. These links are also a workaround for the design mistake
that class-devices are not created in /sys/devices. If a device
directory does not contain directories for child devices, these links
may be used to find the child devices in /sys/class. That is the single
valid use of these links, they must never appear in any path as an
element. Assuming the existence of these links for devices which are
real child device directories in the /sys/devices tree, is a bug in
the application.
It is planned to remove all these links when when all class-device
directories live in /sys/devices.
- Position of devices along device chain can change.
Never depend on a specific parent device position in the devpath,
or the chain of parent devices. The kernel is free to insert devices into
the chain. You must always request the parent device you are looking for
by its subsystem value. You need to walk up the chain until you find
the device that matches the expected subsystem. Depending on a specific
position of a parent device, or exposing relative paths, using "../" to
access the chain of parents, is a bug in the application.

View file

@ -60,6 +60,9 @@ struct locomo {
unsigned int irq;
spinlock_t lock;
void __iomem *base;
#ifdef CONFIG_PM
void *saved_state;
#endif
};
struct locomo_dev_info {
@ -565,7 +568,7 @@ static int locomo_suspend(struct platform_device *dev, pm_message_t state)
if (!save)
return -ENOMEM;
dev->dev.power.saved_state = (void *) save;
lchip->saved_state = save;
spin_lock_irqsave(&lchip->lock, flags);
@ -605,8 +608,8 @@ static int locomo_resume(struct platform_device *dev)
struct locomo_save_data *save;
unsigned long r;
unsigned long flags;
save = (struct locomo_save_data *) dev->dev.power.saved_state;
save = lchip->saved_state;
if (!save)
return 0;
@ -628,6 +631,8 @@ static int locomo_resume(struct platform_device *dev)
locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD);
spin_unlock_irqrestore(&lchip->lock, flags);
lchip->saved_state = NULL;
kfree(save);
return 0;

View file

@ -51,6 +51,9 @@ struct sa1111 {
int irq;
spinlock_t lock;
void __iomem *base;
#ifdef CONFIG_PM
void *saved_state;
#endif
};
/*
@ -822,7 +825,7 @@ static int sa1111_suspend(struct platform_device *dev, pm_message_t state)
save = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
if (!save)
return -ENOMEM;
dev->dev.power.saved_state = save;
sachip->saved_state = save;
spin_lock_irqsave(&sachip->lock, flags);
@ -878,7 +881,7 @@ static int sa1111_resume(struct platform_device *dev)
unsigned long flags, id;
void __iomem *base;
save = (struct sa1111_save_data *)dev->dev.power.saved_state;
save = sachip->saved_state;
if (!save)
return 0;
@ -923,7 +926,7 @@ static int sa1111_resume(struct platform_device *dev)
spin_unlock_irqrestore(&sachip->lock, flags);
dev->dev.power.saved_state = NULL;
sachip->saved_state = NULL;
kfree(save);
return 0;
@ -958,8 +961,8 @@ static int sa1111_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
#ifdef CONFIG_PM
kfree(pdev->dev.power.saved_state);
pdev->dev.power.saved_state = NULL;
kfree(sachip->saved_state);
sachip->saved_state = NULL;
#endif
}

View file

@ -185,28 +185,21 @@ static int __devinit neponset_probe(struct platform_device *dev)
/*
* LDM power management.
*/
static unsigned int neponset_saved_state;
static int neponset_suspend(struct platform_device *dev, pm_message_t state)
{
/*
* Save state.
*/
if (!dev->dev.power.saved_state)
dev->dev.power.saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL);
if (!dev->dev.power.saved_state)
return -ENOMEM;
*(unsigned int *)dev->dev.power.saved_state = NCR_0;
neponset_saved_state = NCR_0;
return 0;
}
static int neponset_resume(struct platform_device *dev)
{
if (dev->dev.power.saved_state) {
NCR_0 = *(unsigned int *)dev->dev.power.saved_state;
kfree(dev->dev.power.saved_state);
dev->dev.power.saved_state = NULL;
}
NCR_0 = neponset_saved_state;
return 0;
}

View file

@ -2415,7 +2415,6 @@ static struct bin_attribute mv64xxx_hs_reg_attr = { /* Hotswap register */
.attr = {
.name = "hs_reg",
.mode = S_IRUGO | S_IWUSR,
.owner = THIS_MODULE,
},
.size = VAL_LEN_MAX,
.read = mv64xxx_hs_reg_read,

View file

@ -312,7 +312,6 @@ static struct bin_attribute ipl_parameter_attr = {
.attr = {
.name = "binary_parameter",
.mode = S_IRUGO,
.owner = THIS_MODULE,
},
.size = PAGE_SIZE,
.read = &ipl_parameter_read,
@ -336,7 +335,6 @@ static struct bin_attribute ipl_scp_data_attr = {
.attr = {
.name = "scp_data",
.mode = S_IRUGO,
.owner = THIS_MODULE,
},
.size = PAGE_SIZE,
.read = &ipl_scp_data_read,

View file

@ -18,6 +18,7 @@
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include "base.h"

View file

@ -44,6 +44,6 @@ struct class_device_attribute *to_class_dev_attr(struct attribute *_attr)
extern char *make_class_name(const char *name, struct kobject *kobj);
extern void devres_release_all(struct device *dev);
extern int devres_release_all(struct device *dev);
extern struct kset devices_subsys;

View file

@ -138,12 +138,24 @@ void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
}
}
static struct kobj_type ktype_bus = {
static struct kobj_type bus_ktype = {
.sysfs_ops = &bus_sysfs_ops,
};
static decl_subsys(bus, &ktype_bus, NULL);
static int bus_uevent_filter(struct kset *kset, struct kobject *kobj)
{
struct kobj_type *ktype = get_ktype(kobj);
if (ktype == &bus_ktype)
return 1;
return 0;
}
static struct kset_uevent_ops bus_uevent_ops = {
.filter = bus_uevent_filter,
};
static decl_subsys(bus, &bus_ktype, &bus_uevent_ops);
#ifdef CONFIG_HOTPLUG
@ -562,7 +574,6 @@ static int add_probe_files(struct bus_type *bus)
bus->drivers_probe_attr.attr.name = "drivers_probe";
bus->drivers_probe_attr.attr.mode = S_IWUSR;
bus->drivers_probe_attr.attr.owner = bus->owner;
bus->drivers_probe_attr.store = store_drivers_probe;
retval = bus_create_file(bus, &bus->drivers_probe_attr);
if (retval)
@ -570,7 +581,6 @@ static int add_probe_files(struct bus_type *bus)
bus->drivers_autoprobe_attr.attr.name = "drivers_autoprobe";
bus->drivers_autoprobe_attr.attr.mode = S_IWUSR | S_IRUGO;
bus->drivers_autoprobe_attr.attr.owner = bus->owner;
bus->drivers_autoprobe_attr.show = show_drivers_autoprobe;
bus->drivers_autoprobe_attr.store = store_drivers_autoprobe;
retval = bus_create_file(bus, &bus->drivers_autoprobe_attr);
@ -610,7 +620,8 @@ int bus_add_driver(struct device_driver *drv)
if (error)
goto out_put_bus;
drv->kobj.kset = &bus->drivers;
if ((error = kobject_register(&drv->kobj)))
error = kobject_register(&drv->kobj);
if (error)
goto out_put_bus;
if (drv->bus->drivers_autoprobe) {
@ -760,7 +771,8 @@ static int bus_add_attrs(struct bus_type * bus)
if (bus->bus_attrs) {
for (i = 0; attr_name(bus->bus_attrs[i]); i++) {
if ((error = bus_create_file(bus,&bus->bus_attrs[i])))
error = bus_create_file(bus,&bus->bus_attrs[i]);
if (error)
goto Err;
}
}

View file

@ -312,9 +312,6 @@ static void class_dev_release(struct kobject * kobj)
pr_debug("device class '%s': release.\n", cd->class_id);
kfree(cd->devt_attr);
cd->devt_attr = NULL;
if (cd->release)
cd->release(cd);
else if (cls->release)
@ -547,6 +544,9 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
return print_dev_t(buf, class_dev->devt);
}
static struct class_device_attribute class_devt_attr =
__ATTR(dev, S_IRUGO, show_dev, NULL);
static ssize_t store_uevent(struct class_device *class_dev,
const char *buf, size_t count)
{
@ -554,6 +554,9 @@ static ssize_t store_uevent(struct class_device *class_dev,
return count;
}
static struct class_device_attribute class_uevent_attr =
__ATTR(uevent, S_IWUSR, NULL, store_uevent);
void class_device_initialize(struct class_device *class_dev)
{
kobj_set_kset_s(class_dev, class_obj_subsys);
@ -603,32 +606,15 @@ int class_device_add(struct class_device *class_dev)
&parent_class->subsys.kobj, "subsystem");
if (error)
goto out3;
class_dev->uevent_attr.attr.name = "uevent";
class_dev->uevent_attr.attr.mode = S_IWUSR;
class_dev->uevent_attr.attr.owner = parent_class->owner;
class_dev->uevent_attr.store = store_uevent;
error = class_device_create_file(class_dev, &class_dev->uevent_attr);
error = class_device_create_file(class_dev, &class_uevent_attr);
if (error)
goto out3;
if (MAJOR(class_dev->devt)) {
struct class_device_attribute *attr;
attr = kzalloc(sizeof(*attr), GFP_KERNEL);
if (!attr) {
error = -ENOMEM;
error = class_device_create_file(class_dev, &class_devt_attr);
if (error)
goto out4;
}
attr->attr.name = "dev";
attr->attr.mode = S_IRUGO;
attr->attr.owner = parent_class->owner;
attr->show = show_dev;
error = class_device_create_file(class_dev, attr);
if (error) {
kfree(attr);
goto out4;
}
class_dev->devt_attr = attr;
}
error = class_device_add_attrs(class_dev);
@ -671,10 +657,10 @@ int class_device_add(struct class_device *class_dev)
out6:
class_device_remove_attrs(class_dev);
out5:
if (class_dev->devt_attr)
class_device_remove_file(class_dev, class_dev->devt_attr);
if (MAJOR(class_dev->devt))
class_device_remove_file(class_dev, &class_devt_attr);
out4:
class_device_remove_file(class_dev, &class_dev->uevent_attr);
class_device_remove_file(class_dev, &class_uevent_attr);
out3:
kobject_del(&class_dev->kobj);
out2:
@ -774,9 +760,9 @@ void class_device_del(struct class_device *class_dev)
sysfs_remove_link(&class_dev->kobj, "device");
}
sysfs_remove_link(&class_dev->kobj, "subsystem");
class_device_remove_file(class_dev, &class_dev->uevent_attr);
if (class_dev->devt_attr)
class_device_remove_file(class_dev, class_dev->devt_attr);
class_device_remove_file(class_dev, &class_uevent_attr);
if (MAJOR(class_dev->devt))
class_device_remove_file(class_dev, &class_devt_attr);
class_device_remove_attrs(class_dev);
class_device_remove_groups(class_dev);

View file

@ -310,6 +310,9 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
return count;
}
static struct device_attribute uevent_attr =
__ATTR(uevent, S_IRUGO | S_IWUSR, show_uevent, store_uevent);
static int device_add_attributes(struct device *dev,
struct device_attribute *attrs)
{
@ -423,6 +426,9 @@ static ssize_t show_dev(struct device *dev, struct device_attribute *attr,
return print_dev_t(buf, dev->devt);
}
static struct device_attribute devt_attr =
__ATTR(dev, S_IRUGO, show_dev, NULL);
/*
* devices_subsys - structure to be registered with kobject core.
*/
@ -681,35 +687,14 @@ int device_add(struct device *dev)
blocking_notifier_call_chain(&dev->bus->bus_notifier,
BUS_NOTIFY_ADD_DEVICE, dev);
dev->uevent_attr.attr.name = "uevent";
dev->uevent_attr.attr.mode = S_IRUGO | S_IWUSR;
if (dev->driver)
dev->uevent_attr.attr.owner = dev->driver->owner;
dev->uevent_attr.store = store_uevent;
dev->uevent_attr.show = show_uevent;
error = device_create_file(dev, &dev->uevent_attr);
error = device_create_file(dev, &uevent_attr);
if (error)
goto attrError;
if (MAJOR(dev->devt)) {
struct device_attribute *attr;
attr = kzalloc(sizeof(*attr), GFP_KERNEL);
if (!attr) {
error = -ENOMEM;
error = device_create_file(dev, &devt_attr);
if (error)
goto ueventattrError;
}
attr->attr.name = "dev";
attr->attr.mode = S_IRUGO;
if (dev->driver)
attr->attr.owner = dev->driver->owner;
attr->show = show_dev;
error = device_create_file(dev, attr);
if (error) {
kfree(attr);
goto ueventattrError;
}
dev->devt_attr = attr;
}
if (dev->class) {
@ -733,11 +718,14 @@ int device_add(struct device *dev)
}
}
if ((error = device_add_attrs(dev)))
error = device_add_attrs(dev);
if (error)
goto AttrsError;
if ((error = device_pm_add(dev)))
error = device_pm_add(dev);
if (error)
goto PMError;
if ((error = bus_add_device(dev)))
error = bus_add_device(dev);
if (error)
goto BusError;
kobject_uevent(&dev->kobj, KOBJ_ADD);
bus_attach_device(dev);
@ -767,10 +755,8 @@ int device_add(struct device *dev)
BUS_NOTIFY_DEL_DEVICE, dev);
device_remove_attrs(dev);
AttrsError:
if (dev->devt_attr) {
device_remove_file(dev, dev->devt_attr);
kfree(dev->devt_attr);
}
if (MAJOR(dev->devt))
device_remove_file(dev, &devt_attr);
if (dev->class) {
sysfs_remove_link(&dev->kobj, "subsystem");
@ -792,7 +778,7 @@ int device_add(struct device *dev)
}
}
ueventattrError:
device_remove_file(dev, &dev->uevent_attr);
device_remove_file(dev, &uevent_attr);
attrError:
kobject_uevent(&dev->kobj, KOBJ_REMOVE);
kobject_del(&dev->kobj);
@ -869,10 +855,8 @@ void device_del(struct device * dev)
if (parent)
klist_del(&dev->knode_parent);
if (dev->devt_attr) {
device_remove_file(dev, dev->devt_attr);
kfree(dev->devt_attr);
}
if (MAJOR(dev->devt))
device_remove_file(dev, &devt_attr);
if (dev->class) {
sysfs_remove_link(&dev->kobj, "subsystem");
/* If this is not a "fake" compatible device, remove the
@ -926,7 +910,7 @@ void device_del(struct device * dev)
up(&dev->class->sem);
}
}
device_remove_file(dev, &dev->uevent_attr);
device_remove_file(dev, &uevent_attr);
device_remove_attrs(dev);
bus_remove_device(dev);

View file

@ -281,24 +281,16 @@ int driver_attach(struct device_driver * drv)
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
/**
* device_release_driver - manually detach device from driver.
* @dev: device.
*
* Manually detach device from driver.
*
/*
* __device_release_driver() must be called with @dev->sem held.
* When called for a USB interface, @dev->parent->sem must be held
* as well.
* When called for a USB interface, @dev->parent->sem must be held as well.
*/
static void __device_release_driver(struct device * dev)
{
struct device_driver * drv;
drv = dev->driver;
drv = get_driver(dev->driver);
if (drv) {
get_driver(drv);
driver_sysfs_remove(dev);
sysfs_remove_link(&dev->kobj, "driver");
klist_remove(&dev->knode_driver);
@ -318,6 +310,13 @@ static void __device_release_driver(struct device * dev)
}
}
/**
* device_release_driver - manually detach device from driver.
* @dev: device.
*
* Manually detach device from driver.
* When called for a USB interface, @dev->parent->sem must be held.
*/
void device_release_driver(struct device * dev)
{
/*

View file

@ -10,6 +10,8 @@
#include <linux/device.h>
#include <linux/module.h>
#include "base.h"
struct devres_node {
struct list_head entry;
dr_release_t release;

View file

@ -175,7 +175,7 @@ static ssize_t firmware_loading_store(struct device *dev,
static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);
static ssize_t
firmware_data_read(struct kobject *kobj,
firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buffer, loff_t offset, size_t count)
{
struct device *dev = to_dev(kobj);
@ -240,7 +240,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
* the driver as a firmware image.
**/
static ssize_t
firmware_data_write(struct kobject *kobj,
firmware_data_write(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buffer, loff_t offset, size_t count)
{
struct device *dev = to_dev(kobj);
@ -271,7 +271,7 @@ out:
}
static struct bin_attribute firmware_attr_data_tmpl = {
.attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE},
.attr = {.name = "data", .mode = 0644},
.size = 0,
.read = firmware_data_read,
.write = firmware_data_write,

View file

@ -20,64 +20,44 @@
*/
#include <linux/device.h>
#include <linux/mutex.h>
#include "power.h"
LIST_HEAD(dpm_active);
LIST_HEAD(dpm_off);
LIST_HEAD(dpm_off_irq);
DECLARE_MUTEX(dpm_sem);
DECLARE_MUTEX(dpm_list_sem);
DEFINE_MUTEX(dpm_mtx);
DEFINE_MUTEX(dpm_list_mtx);
int (*platform_enable_wakeup)(struct device *dev, int is_on);
/**
* device_pm_set_parent - Specify power dependency.
* @dev: Device who needs power.
* @parent: Device that supplies power.
*
* This function is used to manually describe a power-dependency
* relationship. It may be used to specify a transversal relationship
* (where the power supplier is not the physical (or electrical)
* ancestor of a specific device.
* The effect of this is that the supplier will not be powered down
* before the power dependent.
*/
void device_pm_set_parent(struct device * dev, struct device * parent)
{
put_device(dev->power.pm_parent);
dev->power.pm_parent = get_device(parent);
}
EXPORT_SYMBOL_GPL(device_pm_set_parent);
int device_pm_add(struct device * dev)
int device_pm_add(struct device *dev)
{
int error;
pr_debug("PM: Adding info for %s:%s\n",
dev->bus ? dev->bus->name : "No Bus",
kobject_name(&dev->kobj));
down(&dpm_list_sem);
mutex_lock(&dpm_list_mtx);
list_add_tail(&dev->power.entry, &dpm_active);
device_pm_set_parent(dev, dev->parent);
if ((error = dpm_sysfs_add(dev)))
error = dpm_sysfs_add(dev);
if (error)
list_del(&dev->power.entry);
up(&dpm_list_sem);
mutex_unlock(&dpm_list_mtx);
return error;
}
void device_pm_remove(struct device * dev)
void device_pm_remove(struct device *dev)
{
pr_debug("PM: Removing info for %s:%s\n",
dev->bus ? dev->bus->name : "No Bus",
kobject_name(&dev->kobj));
down(&dpm_list_sem);
mutex_lock(&dpm_list_mtx);
dpm_sysfs_remove(dev);
put_device(dev->power.pm_parent);
list_del_init(&dev->power.entry);
up(&dpm_list_sem);
mutex_unlock(&dpm_list_mtx);
}

View file

@ -14,12 +14,12 @@ extern void device_shutdown(void);
/*
* Used to synchronize global power management operations.
*/
extern struct semaphore dpm_sem;
extern struct mutex dpm_mtx;
/*
* Used to serialize changes to the dpm_* lists.
*/
extern struct semaphore dpm_list_sem;
extern struct mutex dpm_list_mtx;
/*
* The PM lists.

View file

@ -29,14 +29,6 @@ int resume_device(struct device * dev)
down(&dev->sem);
if (dev->power.pm_parent
&& dev->power.pm_parent->power.power_state.event) {
dev_err(dev, "PM: resume from %d, parent %s still %d\n",
dev->power.power_state.event,
dev->power.pm_parent->bus_id,
dev->power.pm_parent->power.power_state.event);
}
if (dev->bus && dev->bus->resume) {
dev_dbg(dev,"resuming\n");
error = dev->bus->resume(dev);
@ -80,7 +72,7 @@ static int resume_device_early(struct device * dev)
*/
void dpm_resume(void)
{
down(&dpm_list_sem);
mutex_lock(&dpm_list_mtx);
while(!list_empty(&dpm_off)) {
struct list_head * entry = dpm_off.next;
struct device * dev = to_device(entry);
@ -88,13 +80,12 @@ void dpm_resume(void)
get_device(dev);
list_move_tail(entry, &dpm_active);
up(&dpm_list_sem);
if (!dev->power.prev_state.event)
resume_device(dev);
down(&dpm_list_sem);
mutex_unlock(&dpm_list_mtx);
resume_device(dev);
mutex_lock(&dpm_list_mtx);
put_device(dev);
}
up(&dpm_list_sem);
mutex_unlock(&dpm_list_mtx);
}
@ -108,9 +99,9 @@ void dpm_resume(void)
void device_resume(void)
{
might_sleep();
down(&dpm_sem);
mutex_lock(&dpm_mtx);
dpm_resume();
up(&dpm_sem);
mutex_unlock(&dpm_mtx);
}
EXPORT_SYMBOL_GPL(device_resume);

View file

@ -32,9 +32,9 @@ static void runtime_resume(struct device * dev)
void dpm_runtime_resume(struct device * dev)
{
down(&dpm_sem);
mutex_lock(&dpm_mtx);
runtime_resume(dev);
up(&dpm_sem);
mutex_unlock(&dpm_mtx);
}
EXPORT_SYMBOL(dpm_runtime_resume);
@ -49,7 +49,7 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state)
{
int error = 0;
down(&dpm_sem);
mutex_lock(&dpm_mtx);
if (dev->power.power_state.event == state.event)
goto Done;
@ -59,7 +59,7 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state)
if (!(error = suspend_device(dev, state)))
dev->power.power_state = state;
Done:
up(&dpm_sem);
mutex_unlock(&dpm_mtx);
return error;
}
EXPORT_SYMBOL(dpm_runtime_suspend);
@ -78,8 +78,8 @@ EXPORT_SYMBOL(dpm_runtime_suspend);
*/
void dpm_set_power_state(struct device * dev, pm_message_t state)
{
down(&dpm_sem);
mutex_lock(&dpm_mtx);
dev->power.power_state = state;
up(&dpm_sem);
mutex_unlock(&dpm_mtx);
}
#endif /* 0 */

View file

@ -40,6 +40,14 @@ static inline char *suspend_verb(u32 event)
}
static void
suspend_device_dbg(struct device *dev, pm_message_t state, char *info)
{
dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event),
((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ?
", may wakeup" : "");
}
/**
* suspend_device - Save state of one device.
* @dev: Device.
@ -55,49 +63,21 @@ int suspend_device(struct device * dev, pm_message_t state)
dev_dbg(dev, "PM: suspend %d-->%d\n",
dev->power.power_state.event, state.event);
}
if (dev->power.pm_parent
&& dev->power.pm_parent->power.power_state.event) {
dev_err(dev,
"PM: suspend %d->%d, parent %s already %d\n",
dev->power.power_state.event, state.event,
dev->power.pm_parent->bus_id,
dev->power.pm_parent->power.power_state.event);
}
dev->power.prev_state = dev->power.power_state;
if (dev->class && dev->class->suspend && !dev->power.power_state.event) {
dev_dbg(dev, "class %s%s\n",
suspend_verb(state.event),
((state.event == PM_EVENT_SUSPEND)
&& device_may_wakeup(dev))
? ", may wakeup"
: ""
);
if (dev->class && dev->class->suspend) {
suspend_device_dbg(dev, state, "class ");
error = dev->class->suspend(dev, state);
suspend_report_result(dev->class->suspend, error);
}
if (!error && dev->type && dev->type->suspend && !dev->power.power_state.event) {
dev_dbg(dev, "%s%s\n",
suspend_verb(state.event),
((state.event == PM_EVENT_SUSPEND)
&& device_may_wakeup(dev))
? ", may wakeup"
: ""
);
if (!error && dev->type && dev->type->suspend) {
suspend_device_dbg(dev, state, "type ");
error = dev->type->suspend(dev, state);
suspend_report_result(dev->type->suspend, error);
}
if (!error && dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
dev_dbg(dev, "%s%s\n",
suspend_verb(state.event),
((state.event == PM_EVENT_SUSPEND)
&& device_may_wakeup(dev))
? ", may wakeup"
: ""
);
if (!error && dev->bus && dev->bus->suspend) {
suspend_device_dbg(dev, state, "");
error = dev->bus->suspend(dev, state);
suspend_report_result(dev->bus->suspend, error);
}
@ -108,21 +88,15 @@ int suspend_device(struct device * dev, pm_message_t state)
/*
* This is called with interrupts off, only a single CPU
* running. We can't do down() on a semaphore (and we don't
* running. We can't acquire a mutex or semaphore (and we don't
* need the protection)
*/
static int suspend_device_late(struct device *dev, pm_message_t state)
{
int error = 0;
if (dev->bus && dev->bus->suspend_late && !dev->power.power_state.event) {
dev_dbg(dev, "LATE %s%s\n",
suspend_verb(state.event),
((state.event == PM_EVENT_SUSPEND)
&& device_may_wakeup(dev))
? ", may wakeup"
: ""
);
if (dev->bus && dev->bus->suspend_late) {
suspend_device_dbg(dev, state, "LATE ");
error = dev->bus->suspend_late(dev, state);
suspend_report_result(dev->bus->suspend_late, error);
}
@ -153,18 +127,18 @@ int device_suspend(pm_message_t state)
int error = 0;
might_sleep();
down(&dpm_sem);
down(&dpm_list_sem);
mutex_lock(&dpm_mtx);
mutex_lock(&dpm_list_mtx);
while (!list_empty(&dpm_active) && error == 0) {
struct list_head * entry = dpm_active.prev;
struct device * dev = to_device(entry);
get_device(dev);
up(&dpm_list_sem);
mutex_unlock(&dpm_list_mtx);
error = suspend_device(dev, state);
down(&dpm_list_sem);
mutex_lock(&dpm_list_mtx);
/* Check if the device got removed */
if (!list_empty(&dev->power.entry)) {
@ -179,11 +153,11 @@ int device_suspend(pm_message_t state)
error == -EAGAIN ? " (please convert to suspend_late)" : "");
put_device(dev);
}
up(&dpm_list_sem);
mutex_unlock(&dpm_list_mtx);
if (error)
dpm_resume();
up(&dpm_sem);
mutex_unlock(&dpm_mtx);
return error;
}

View file

@ -21,7 +21,7 @@
#include <linux/string.h>
#include <linux/pm.h>
#include <linux/device.h>
#include <asm/semaphore.h>
#include <linux/mutex.h>
#include "base.h"
@ -155,7 +155,7 @@ EXPORT_SYMBOL_GPL(sysdev_class_unregister);
static LIST_HEAD(sysdev_drivers);
static DECLARE_MUTEX(sysdev_drivers_lock);
static DEFINE_MUTEX(sysdev_drivers_lock);
/**
* sysdev_driver_register - Register auxillary driver
@ -172,7 +172,7 @@ static DECLARE_MUTEX(sysdev_drivers_lock);
int sysdev_driver_register(struct sysdev_class * cls,
struct sysdev_driver * drv)
{
down(&sysdev_drivers_lock);
mutex_lock(&sysdev_drivers_lock);
if (cls && kset_get(&cls->kset)) {
list_add_tail(&drv->entry, &cls->drivers);
@ -184,7 +184,7 @@ int sysdev_driver_register(struct sysdev_class * cls,
}
} else
list_add_tail(&drv->entry, &sysdev_drivers);
up(&sysdev_drivers_lock);
mutex_unlock(&sysdev_drivers_lock);
return 0;
}
@ -197,7 +197,7 @@ int sysdev_driver_register(struct sysdev_class * cls,
void sysdev_driver_unregister(struct sysdev_class * cls,
struct sysdev_driver * drv)
{
down(&sysdev_drivers_lock);
mutex_lock(&sysdev_drivers_lock);
list_del_init(&drv->entry);
if (cls) {
if (drv->remove) {
@ -207,7 +207,7 @@ void sysdev_driver_unregister(struct sysdev_class * cls,
}
kset_put(&cls->kset);
}
up(&sysdev_drivers_lock);
mutex_unlock(&sysdev_drivers_lock);
}
EXPORT_SYMBOL_GPL(sysdev_driver_register);
@ -246,7 +246,7 @@ int sysdev_register(struct sys_device * sysdev)
if (!error) {
struct sysdev_driver * drv;
down(&sysdev_drivers_lock);
mutex_lock(&sysdev_drivers_lock);
/* Generic notification is implicit, because it's that
* code that should have called us.
*/
@ -262,7 +262,7 @@ int sysdev_register(struct sys_device * sysdev)
if (drv->add)
drv->add(sysdev);
}
up(&sysdev_drivers_lock);
mutex_unlock(&sysdev_drivers_lock);
}
return error;
}
@ -271,7 +271,7 @@ void sysdev_unregister(struct sys_device * sysdev)
{
struct sysdev_driver * drv;
down(&sysdev_drivers_lock);
mutex_lock(&sysdev_drivers_lock);
list_for_each_entry(drv, &sysdev_drivers, entry) {
if (drv->remove)
drv->remove(sysdev);
@ -281,7 +281,7 @@ void sysdev_unregister(struct sys_device * sysdev)
if (drv->remove)
drv->remove(sysdev);
}
up(&sysdev_drivers_lock);
mutex_unlock(&sysdev_drivers_lock);
kobject_unregister(&sysdev->kobj);
}
@ -308,7 +308,7 @@ void sysdev_shutdown(void)
pr_debug("Shutting Down System Devices\n");
down(&sysdev_drivers_lock);
mutex_lock(&sysdev_drivers_lock);
list_for_each_entry_reverse(cls, &system_subsys.list,
kset.kobj.entry) {
struct sys_device * sysdev;
@ -337,7 +337,7 @@ void sysdev_shutdown(void)
cls->shutdown(sysdev);
}
}
up(&sysdev_drivers_lock);
mutex_unlock(&sysdev_drivers_lock);
}
static void __sysdev_resume(struct sys_device *dev)

View file

@ -146,8 +146,7 @@ static void pkt_kobj_release(struct kobject *kobj)
**********************************************************/
#define DEF_ATTR(_obj,_name,_mode) \
static struct attribute _obj = { \
.name = _name, .owner = THIS_MODULE, .mode = _mode }
static struct attribute _obj = { .name = _name, .mode = _mode }
/**********************************************************
/sys/class/pktcdvd/pktcdvd[0-7]/

View file

@ -2171,52 +2171,42 @@ static int create_files(struct bmc_device *bmc)
int err;
bmc->device_id_attr.attr.name = "device_id";
bmc->device_id_attr.attr.owner = THIS_MODULE;
bmc->device_id_attr.attr.mode = S_IRUGO;
bmc->device_id_attr.show = device_id_show;
bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs";
bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE;
bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO;
bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show;
bmc->revision_attr.attr.name = "revision";
bmc->revision_attr.attr.owner = THIS_MODULE;
bmc->revision_attr.attr.mode = S_IRUGO;
bmc->revision_attr.show = revision_show;
bmc->firmware_rev_attr.attr.name = "firmware_revision";
bmc->firmware_rev_attr.attr.owner = THIS_MODULE;
bmc->firmware_rev_attr.attr.mode = S_IRUGO;
bmc->firmware_rev_attr.show = firmware_rev_show;
bmc->version_attr.attr.name = "ipmi_version";
bmc->version_attr.attr.owner = THIS_MODULE;
bmc->version_attr.attr.mode = S_IRUGO;
bmc->version_attr.show = ipmi_version_show;
bmc->add_dev_support_attr.attr.name = "additional_device_support";
bmc->add_dev_support_attr.attr.owner = THIS_MODULE;
bmc->add_dev_support_attr.attr.mode = S_IRUGO;
bmc->add_dev_support_attr.show = add_dev_support_show;
bmc->manufacturer_id_attr.attr.name = "manufacturer_id";
bmc->manufacturer_id_attr.attr.owner = THIS_MODULE;
bmc->manufacturer_id_attr.attr.mode = S_IRUGO;
bmc->manufacturer_id_attr.show = manufacturer_id_show;
bmc->product_id_attr.attr.name = "product_id";
bmc->product_id_attr.attr.owner = THIS_MODULE;
bmc->product_id_attr.attr.mode = S_IRUGO;
bmc->product_id_attr.show = product_id_show;
bmc->guid_attr.attr.name = "guid";
bmc->guid_attr.attr.owner = THIS_MODULE;
bmc->guid_attr.attr.mode = S_IRUGO;
bmc->guid_attr.show = guid_show;
bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision";
bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE;
bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO;
bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show;

View file

@ -25,8 +25,7 @@ static spinlock_t cpufreq_stats_lock;
#define CPUFREQ_STATDEVICE_ATTR(_name,_mode,_show) \
static struct freq_attr _attr_##_name = {\
.attr = {.name = __stringify(_name), .owner = THIS_MODULE, \
.mode = _mode, }, \
.attr = {.name = __stringify(_name), .mode = _mode, }, \
.show = _show,\
};

View file

@ -120,7 +120,7 @@ store_speed (struct cpufreq_policy *policy, const char *buf, size_t count)
static struct freq_attr freq_attr_scaling_setspeed =
{
.attr = { .name = "scaling_setspeed", .mode = 0644, .owner = THIS_MODULE },
.attr = { .name = "scaling_setspeed", .mode = 0644 },
.show = show_speed,
.store = store_speed,
};

View file

@ -199,7 +199,6 @@ static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf)
struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
.attr = { .name = "scaling_available_frequencies",
.mode = 0444,
.owner=THIS_MODULE
},
.show = show_available_freqs,
};

View file

@ -84,4 +84,13 @@ config DCDBAS
Say Y or M here to enable the driver for use by Dell systems
management software such as Dell OpenManage.
config DMIID
bool "Export DMI identification via sysfs to userspace"
depends on DMI
default y
help
Say Y here if you want to query SMBIOS/DMI system identification
information from userspace through /sys/class/dmi/id/ or if you want
DMI-based module auto-loading.
endmenu

View file

@ -7,3 +7,4 @@ obj-$(CONFIG_EFI_VARS) += efivars.o
obj-$(CONFIG_EFI_PCDP) += pcdp.o
obj-$(CONFIG_DELL_RBU) += dell_rbu.o
obj-$(CONFIG_DCDBAS) += dcdbas.o
obj-$(CONFIG_DMIID) += dmi-id.o

View file

@ -149,8 +149,9 @@ static ssize_t smi_data_buf_size_store(struct device *dev,
return count;
}
static ssize_t smi_data_read(struct kobject *kobj, char *buf, loff_t pos,
size_t count)
static ssize_t smi_data_read(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t pos, size_t count)
{
size_t max_read;
ssize_t ret;
@ -170,8 +171,9 @@ out:
return ret;
}
static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos,
size_t count)
static ssize_t smi_data_write(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t pos, size_t count)
{
ssize_t ret;

View file

@ -67,8 +67,7 @@
#define DCDBAS_BIN_ATTR_RW(_name) \
struct bin_attribute bin_attr_##_name = { \
.attr = { .name = __stringify(_name), \
.mode = 0600, \
.owner = THIS_MODULE }, \
.mode = 0600 }, \
.read = _name##_read, \
.write = _name##_write, \
}

View file

@ -543,8 +543,9 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
return ret_count;
}
static ssize_t read_rbu_data(struct kobject *kobj, char *buffer,
loff_t pos, size_t count)
static ssize_t read_rbu_data(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buffer, loff_t pos, size_t count)
{
ssize_t ret_count = 0;
@ -591,8 +592,9 @@ static void callbackfn_rbu(const struct firmware *fw, void *context)
spin_unlock(&rbu_data.lock);
}
static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
loff_t pos, size_t count)
static ssize_t read_rbu_image_type(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buffer, loff_t pos, size_t count)
{
int size = 0;
if (!pos)
@ -600,8 +602,9 @@ static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
return size;
}
static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer,
loff_t pos, size_t count)
static ssize_t write_rbu_image_type(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buffer, loff_t pos, size_t count)
{
int rc = count;
int req_firm_rc = 0;
@ -660,8 +663,9 @@ static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer,
return rc;
}
static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer,
loff_t pos, size_t count)
static ssize_t read_rbu_packet_size(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buffer, loff_t pos, size_t count)
{
int size = 0;
if (!pos) {
@ -672,8 +676,9 @@ static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer,
return size;
}
static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer,
loff_t pos, size_t count)
static ssize_t write_rbu_packet_size(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buffer, loff_t pos, size_t count)
{
unsigned long temp;
spin_lock(&rbu_data.lock);
@ -687,18 +692,18 @@ static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer,
}
static struct bin_attribute rbu_data_attr = {
.attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444},
.attr = {.name = "data", .mode = 0444},
.read = read_rbu_data,
};
static struct bin_attribute rbu_image_type_attr = {
.attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644},
.attr = {.name = "image_type", .mode = 0644},
.read = read_rbu_image_type,
.write = write_rbu_image_type,
};
static struct bin_attribute rbu_packet_size_attr = {
.attr = {.name = "packet_size",.owner = THIS_MODULE,.mode = 0644},
.attr = {.name = "packet_size", .mode = 0644},
.read = read_rbu_packet_size,
.write = write_rbu_packet_size,
};

222
drivers/firmware/dmi-id.c Normal file
View file

@ -0,0 +1,222 @@
/*
* Export SMBIOS/DMI info via sysfs to userspace
*
* Copyright 2007, Lennart Poettering
*
* Licensed under GPLv2
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/dmi.h>
#include <linux/device.h>
#include <linux/autoconf.h>
#define DEFINE_DMI_ATTR(_name, _mode, _show) \
static struct device_attribute sys_dmi_##_name##_attr = \
__ATTR(_name, _mode, _show, NULL);
#define DEFINE_DMI_ATTR_WITH_SHOW(_name, _mode, _field) \
static ssize_t sys_dmi_##_name##_show(struct device *dev, \
struct device_attribute *attr, \
char *page) \
{ \
ssize_t len; \
len = scnprintf(page, PAGE_SIZE, "%s\n", dmi_get_system_info(_field)); \
page[len-1] = '\n'; \
return len; \
} \
DEFINE_DMI_ATTR(_name, _mode, sys_dmi_##_name##_show);
DEFINE_DMI_ATTR_WITH_SHOW(bios_vendor, 0444, DMI_BIOS_VENDOR);
DEFINE_DMI_ATTR_WITH_SHOW(bios_version, 0444, DMI_BIOS_VERSION);
DEFINE_DMI_ATTR_WITH_SHOW(bios_date, 0444, DMI_BIOS_DATE);
DEFINE_DMI_ATTR_WITH_SHOW(sys_vendor, 0444, DMI_SYS_VENDOR);
DEFINE_DMI_ATTR_WITH_SHOW(product_name, 0444, DMI_PRODUCT_NAME);
DEFINE_DMI_ATTR_WITH_SHOW(product_version, 0444, DMI_PRODUCT_VERSION);
DEFINE_DMI_ATTR_WITH_SHOW(product_serial, 0400, DMI_PRODUCT_SERIAL);
DEFINE_DMI_ATTR_WITH_SHOW(product_uuid, 0400, DMI_PRODUCT_UUID);
DEFINE_DMI_ATTR_WITH_SHOW(board_vendor, 0444, DMI_BOARD_VENDOR);
DEFINE_DMI_ATTR_WITH_SHOW(board_name, 0444, DMI_BOARD_NAME);
DEFINE_DMI_ATTR_WITH_SHOW(board_version, 0444, DMI_BOARD_VERSION);
DEFINE_DMI_ATTR_WITH_SHOW(board_serial, 0400, DMI_BOARD_SERIAL);
DEFINE_DMI_ATTR_WITH_SHOW(board_asset_tag, 0444, DMI_BOARD_ASSET_TAG);
DEFINE_DMI_ATTR_WITH_SHOW(chassis_vendor, 0444, DMI_CHASSIS_VENDOR);
DEFINE_DMI_ATTR_WITH_SHOW(chassis_type, 0444, DMI_CHASSIS_TYPE);
DEFINE_DMI_ATTR_WITH_SHOW(chassis_version, 0444, DMI_CHASSIS_VERSION);
DEFINE_DMI_ATTR_WITH_SHOW(chassis_serial, 0400, DMI_CHASSIS_SERIAL);
DEFINE_DMI_ATTR_WITH_SHOW(chassis_asset_tag, 0444, DMI_CHASSIS_ASSET_TAG);
static void ascii_filter(char *d, const char *s)
{
/* Filter out characters we don't want to see in the modalias string */
for (; *s; s++)
if (*s > ' ' && *s < 127 && *s != ':')
*(d++) = *s;
*d = 0;
}
static ssize_t get_modalias(char *buffer, size_t buffer_size)
{
static const struct mafield {
const char *prefix;
int field;
} fields[] = {
{ "bvn", DMI_BIOS_VENDOR },
{ "bvr", DMI_BIOS_VERSION },
{ "bd", DMI_BIOS_DATE },
{ "svn", DMI_SYS_VENDOR },
{ "pn", DMI_PRODUCT_NAME },
{ "pvr", DMI_PRODUCT_VERSION },
{ "rvn", DMI_BOARD_VENDOR },
{ "rn", DMI_BOARD_NAME },
{ "rvr", DMI_BOARD_VERSION },
{ "cvn", DMI_CHASSIS_VENDOR },
{ "ct", DMI_CHASSIS_TYPE },
{ "cvr", DMI_CHASSIS_VERSION },
{ NULL, DMI_NONE }
};
ssize_t l, left;
char *p;
const struct mafield *f;
strcpy(buffer, "dmi");
p = buffer + 3; left = buffer_size - 4;
for (f = fields; f->prefix && left > 0; f++) {
const char *c;
char *t;
c = dmi_get_system_info(f->field);
if (!c)
continue;
t = kmalloc(strlen(c) + 1, GFP_KERNEL);
if (!t)
break;
ascii_filter(t, c);
l = scnprintf(p, left, ":%s%s", f->prefix, t);
kfree(t);
p += l;
left -= l;
}
p[0] = ':';
p[1] = 0;
return p - buffer + 1;
}
static ssize_t sys_dmi_modalias_show(struct device *dev,
struct device_attribute *attr, char *page)
{
ssize_t r;
r = get_modalias(page, PAGE_SIZE-1);
page[r] = '\n';
page[r+1] = 0;
return r+1;
}
DEFINE_DMI_ATTR(modalias, 0444, sys_dmi_modalias_show);
static struct attribute *sys_dmi_attributes[DMI_STRING_MAX+2];
static struct attribute_group sys_dmi_attribute_group = {
.attrs = sys_dmi_attributes,
};
static struct attribute_group* sys_dmi_attribute_groups[] = {
&sys_dmi_attribute_group,
NULL
};
static int dmi_dev_uevent(struct device *dev, char **envp,
int num_envp, char *buffer, int buffer_size)
{
strcpy(buffer, "MODALIAS=");
get_modalias(buffer+9, buffer_size-9);
envp[0] = buffer;
envp[1] = NULL;
return 0;
}
static struct class dmi_class = {
.name = "dmi",
.dev_release = (void(*)(struct device *)) kfree,
.dev_uevent = dmi_dev_uevent,
};
static struct device *dmi_dev;
/* Initialization */
#define ADD_DMI_ATTR(_name, _field) \
if (dmi_get_system_info(_field)) \
sys_dmi_attributes[i++] = & sys_dmi_##_name##_attr.attr;
extern int dmi_available;
static int __init dmi_id_init(void)
{
int ret, i;
if (!dmi_available)
return -ENODEV;
/* Not necessarily all DMI fields are available on all
* systems, hence let's built an attribute table of just
* what's available */
i = 0;
ADD_DMI_ATTR(bios_vendor, DMI_BIOS_VENDOR);
ADD_DMI_ATTR(bios_version, DMI_BIOS_VERSION);
ADD_DMI_ATTR(bios_date, DMI_BIOS_DATE);
ADD_DMI_ATTR(sys_vendor, DMI_SYS_VENDOR);
ADD_DMI_ATTR(product_name, DMI_PRODUCT_NAME);
ADD_DMI_ATTR(product_version, DMI_PRODUCT_VERSION);
ADD_DMI_ATTR(product_serial, DMI_PRODUCT_SERIAL);
ADD_DMI_ATTR(product_uuid, DMI_PRODUCT_UUID);
ADD_DMI_ATTR(board_vendor, DMI_BOARD_VENDOR);
ADD_DMI_ATTR(board_name, DMI_BOARD_NAME);
ADD_DMI_ATTR(board_version, DMI_BOARD_VERSION);
ADD_DMI_ATTR(board_serial, DMI_BOARD_SERIAL);
ADD_DMI_ATTR(board_asset_tag, DMI_BOARD_ASSET_TAG);
ADD_DMI_ATTR(chassis_vendor, DMI_CHASSIS_VENDOR);
ADD_DMI_ATTR(chassis_type, DMI_CHASSIS_TYPE);
ADD_DMI_ATTR(chassis_version, DMI_CHASSIS_VERSION);
ADD_DMI_ATTR(chassis_serial, DMI_CHASSIS_SERIAL);
ADD_DMI_ATTR(chassis_asset_tag, DMI_CHASSIS_ASSET_TAG);
sys_dmi_attributes[i++] = &sys_dmi_modalias_attr.attr;
ret = class_register(&dmi_class);
if (ret)
return ret;
dmi_dev = kzalloc(sizeof(*dmi_dev), GFP_KERNEL);
if (!dmi_dev) {
ret = -ENOMEM;
goto fail_class_unregister;
}
dmi_dev->class = &dmi_class;
strcpy(dmi_dev->bus_id, "id");
dmi_dev->groups = sys_dmi_attribute_groups;
ret = device_register(dmi_dev);
if (ret)
goto fail_class_unregister;
return 0;
fail_class_unregister:
class_unregister(&dmi_class);
return ret;
}
arch_initcall(dmi_id_init);

View file

@ -84,6 +84,7 @@ static int __init dmi_checksum(u8 *buf)
static char *dmi_ident[DMI_STRING_MAX];
static LIST_HEAD(dmi_devices);
int dmi_available;
/*
* Save a DMI string
@ -102,6 +103,51 @@ static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
dmi_ident[slot] = p;
}
static void __init dmi_save_uuid(struct dmi_header *dm, int slot, int index)
{
u8 *d = (u8*) dm + index;
char *s;
int is_ff = 1, is_00 = 1, i;
if (dmi_ident[slot])
return;
for (i = 0; i < 16 && (is_ff || is_00); i++) {
if(d[i] != 0x00) is_ff = 0;
if(d[i] != 0xFF) is_00 = 0;
}
if (is_ff || is_00)
return;
s = dmi_alloc(16*2+4+1);
if (!s)
return;
sprintf(s,
"%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
dmi_ident[slot] = s;
}
static void __init dmi_save_type(struct dmi_header *dm, int slot, int index)
{
u8 *d = (u8*) dm + index;
char *s;
if (dmi_ident[slot])
return;
s = dmi_alloc(4);
if (!s)
return;
sprintf(s, "%u", *d & 0x7F);
dmi_ident[slot] = s;
}
static void __init dmi_save_devices(struct dmi_header *dm)
{
int i, count = (dm->length - sizeof(struct dmi_header)) / 2;
@ -192,11 +238,21 @@ static void __init dmi_decode(struct dmi_header *dm)
dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);
dmi_save_uuid(dm, DMI_PRODUCT_UUID, 8);
break;
case 2: /* Base Board Information */
dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
dmi_save_ident(dm, DMI_BOARD_NAME, 5);
dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
dmi_save_ident(dm, DMI_BOARD_SERIAL, 7);
dmi_save_ident(dm, DMI_BOARD_ASSET_TAG, 8);
break;
case 3: /* Chassis Information */
dmi_save_ident(dm, DMI_CHASSIS_VENDOR, 4);
dmi_save_type(dm, DMI_CHASSIS_TYPE, 5);
dmi_save_ident(dm, DMI_CHASSIS_VERSION, 6);
dmi_save_ident(dm, DMI_CHASSIS_SERIAL, 7);
dmi_save_ident(dm, DMI_CHASSIS_ASSET_TAG, 8);
break;
case 10: /* Onboard Devices Information */
dmi_save_devices(dm);
@ -243,18 +299,20 @@ void __init dmi_scan_machine(void)
if (efi.smbios == EFI_INVALID_TABLE_ADDR)
goto out;
/* This is called as a core_initcall() because it isn't
* needed during early boot. This also means we can
* iounmap the space when we're done with it.
*/
/* This is called as a core_initcall() because it isn't
* needed during early boot. This also means we can
* iounmap the space when we're done with it.
*/
p = dmi_ioremap(efi.smbios, 32);
if (p == NULL)
goto out;
rc = dmi_present(p + 0x10); /* offset of _DMI_ string */
dmi_iounmap(p, 32);
if (!rc)
if (!rc) {
dmi_available = 1;
return;
}
}
else {
/*
@ -268,8 +326,10 @@ void __init dmi_scan_machine(void)
for (q = p; q < p + 0x10000; q += 16) {
rc = dmi_present(q);
if (!rc)
if (!rc) {
dmi_available = 1;
return;
}
}
}
out: printk(KERN_INFO "DMI not present or invalid.\n");
@ -404,3 +464,4 @@ int dmi_get_year(int field)
return year;
}

View file

@ -74,7 +74,7 @@ static struct edd_device *edd_devices[EDD_MBR_SIG_MAX];
#define EDD_DEVICE_ATTR(_name,_mode,_show,_test) \
struct edd_attribute edd_attr_##_name = { \
.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
.attr = {.name = __stringify(_name), .mode = _mode }, \
.show = _show, \
.test = _test, \
};

View file

@ -131,21 +131,21 @@ struct efivar_attribute {
#define EFI_ATTR(_name, _mode, _show, _store) \
struct subsys_attribute efi_attr_##_name = { \
.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
.attr = {.name = __stringify(_name), .mode = _mode}, \
.show = _show, \
.store = _store, \
};
#define EFIVAR_ATTR(_name, _mode, _show, _store) \
struct efivar_attribute efivar_attr_##_name = { \
.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
.attr = {.name = __stringify(_name), .mode = _mode}, \
.show = _show, \
.store = _store, \
};
#define VAR_SUBSYS_ATTR(_name, _mode, _show, _store) \
struct subsys_attribute var_subsys_attr_##_name = { \
.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
.attr = {.name = __stringify(_name), .mode = _mode}, \
.show = _show, \
.store = _store, \
};

View file

@ -112,7 +112,8 @@ exit:
mutex_unlock(&data->update_lock);
}
static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
struct eeprom_data *data = i2c_get_clientdata(client);
@ -145,7 +146,6 @@ static struct bin_attribute eeprom_attr = {
.attr = {
.name = "eeprom",
.mode = S_IRUGO,
.owner = THIS_MODULE,
},
.size = EEPROM_SIZE,
.read = eeprom_read,

View file

@ -126,8 +126,9 @@ exit_up:
mutex_unlock(&data->update_lock);
}
static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off,
size_t count)
static ssize_t max6875_read(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct i2c_client *client = kobj_to_i2c_client(kobj);
struct max6875_data *data = i2c_get_clientdata(client);
@ -153,7 +154,6 @@ static struct bin_attribute user_eeprom_attr = {
.attr = {
.name = "eeprom",
.mode = S_IRUGO,
.owner = THIS_MODULE,
},
.size = USER_EEPROM_SIZE,
.read = max6875_read,

View file

@ -479,7 +479,6 @@ alloc_group_attrs(ssize_t (*show)(struct ib_port *,
element->attr.attr.name = element->name;
element->attr.attr.mode = S_IRUGO;
element->attr.attr.owner = THIS_MODULE;
element->attr.show = show;
element->index = i;

View file

@ -119,7 +119,6 @@ static struct psmouse_attribute psmouse_attr_##_name = { \
.attr = { \
.name = __stringify(_name), \
.mode = _mode, \
.owner = THIS_MODULE, \
}, \
.show = psmouse_attr_show_helper, \
.store = psmouse_attr_set_helper, \

View file

@ -212,7 +212,6 @@ int wf_register_control(struct wf_control *new_ct)
list_add(&new_ct->link, &wf_controls);
new_ct->attr.attr.name = new_ct->name;
new_ct->attr.attr.owner = THIS_MODULE;
new_ct->attr.attr.mode = 0644;
new_ct->attr.show = wf_show_control;
new_ct->attr.store = wf_store_control;
@ -325,7 +324,6 @@ int wf_register_sensor(struct wf_sensor *new_sr)
list_add(&new_sr->link, &wf_sensors);
new_sr->attr.attr.name = new_sr->name;
new_sr->attr.attr.owner = THIS_MODULE;
new_sr->attr.attr.mode = 0444;
new_sr->attr.show = wf_show_sensor;
new_sr->attr.store = NULL;

View file

@ -737,8 +737,7 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
struct device_attribute dev_attr_##_name = { \
.attr = { \
.name = __stringify(_name), \
.mode = 0, \
.owner = THIS_MODULE }, \
.mode = 0 }, \
.show = NULL, \
.store = NULL, \
}

View file

@ -23,6 +23,8 @@
* msi-laptop.c - MSI S270 laptop support. This laptop is sold under
* various brands, including "Cytron/TCM/Medion/Tchibo MD96100".
*
* Driver also supports S271, S420 models.
*
* This driver exports a few files in /sys/devices/platform/msi-laptop-pf/:
*
* lcd_level - Screen brightness: contains a single integer in the
@ -281,25 +283,56 @@ static struct platform_device *msipf_device;
/* Initialization */
static int dmi_check_cb(struct dmi_system_id *id)
{
printk("msi-laptop: Identified laptop model '%s'.\n", id->ident);
return 0;
}
static struct dmi_system_id __initdata msi_dmi_table[] = {
{
.ident = "MSI S270",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD"),
DMI_MATCH(DMI_PRODUCT_NAME, "MS-1013"),
}
DMI_MATCH(DMI_PRODUCT_VERSION, "0131"),
DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT'L CO.,LTD")
},
.callback = dmi_check_cb
},
{
.ident = "MSI S271",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
DMI_MATCH(DMI_PRODUCT_NAME, "MS-1058"),
DMI_MATCH(DMI_PRODUCT_VERSION, "0581"),
DMI_MATCH(DMI_BOARD_NAME, "MS-1058")
},
.callback = dmi_check_cb
},
{
.ident = "MSI S420",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
DMI_MATCH(DMI_PRODUCT_NAME, "MS-1412"),
DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
DMI_MATCH(DMI_BOARD_NAME, "MS-1412")
},
.callback = dmi_check_cb
},
{
.ident = "Medion MD96100",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "NOTEBOOK"),
DMI_MATCH(DMI_PRODUCT_NAME, "SAM2000"),
}
DMI_MATCH(DMI_PRODUCT_VERSION, "0131"),
DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT'L CO.,LTD")
},
.callback = dmi_check_cb
},
{ }
};
static int __init msi_init(void)
{
int ret;
@ -394,3 +427,8 @@ MODULE_AUTHOR("Lennart Poettering");
MODULE_DESCRIPTION("MSI Laptop Support");
MODULE_VERSION(MSI_DRIVER_VERSION);
MODULE_LICENSE("GPL");
MODULE_ALIAS("dmi:*:svnMICRO-STARINT'LCO.,LTD:pnMS-1013:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1058:pvr0581:rvnMSI:rnMS-1058:*:ct10:*");
MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1412:*:rvnMSI:rnMS-1412:*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
MODULE_ALIAS("dmi:*:svnNOTEBOOK:pnSAM2000:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");

View file

@ -1337,7 +1337,7 @@ const char * buf, size_t count)
#define ATTR(_name, _mode) \
struct attribute veth_##_name##_attr = { \
.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE \
.name = __stringify(_name), .mode = _mode, \
};
static ATTR(active, 0644);

View file

@ -121,14 +121,14 @@ struct pdcspath_entry pdcspath_entry_##_name = { \
#define PDCS_ATTR(_name, _mode, _show, _store) \
struct subsys_attribute pdcs_attr_##_name = { \
.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
.attr = {.name = __stringify(_name), .mode = _mode}, \
.show = _show, \
.store = _store, \
};
#define PATHS_ATTR(_name, _mode, _show, _store) \
struct pdcspath_attribute paths_attr_##_name = { \
.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
.attr = {.name = __stringify(_name), .mode = _mode}, \
.show = _show, \
.store = _store, \
};

View file

@ -106,7 +106,8 @@ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status);
static void ibm_handle_events(acpi_handle handle, u32 event, void *context);
static int ibm_get_table_from_acpi(char **bufp);
static ssize_t ibm_read_apci_table(struct kobject *kobj,
char *buffer, loff_t pos, size_t size);
struct bin_attribute *bin_attr,
char *buffer, loff_t pos, size_t size);
static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
u32 lvl, void *context, void **rv);
static int __init ibm_acpiphp_init(void);
@ -117,7 +118,6 @@ static struct notification ibm_note;
static struct bin_attribute ibm_apci_table_attr = {
.attr = {
.name = "apci_table",
.owner = THIS_MODULE,
.mode = S_IRUGO,
},
.read = ibm_read_apci_table,
@ -358,7 +358,8 @@ read_table_done:
* our solution is to only allow reading the table in all at once
**/
static ssize_t ibm_read_apci_table(struct kobject *kobj,
char *buffer, loff_t pos, size_t size)
struct bin_attribute *bin_attr,
char *buffer, loff_t pos, size_t size)
{
int bytes_read = -EINVAL;
char *table = NULL;

View file

@ -213,7 +213,8 @@ struct device_attribute pci_dev_attrs[] = {
};
static ssize_t
pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
pci_read_config(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
unsigned int size = 64;
@ -285,7 +286,8 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
}
static ssize_t
pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
unsigned int size = count;
@ -352,7 +354,8 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
* callback routine (pci_legacy_read).
*/
ssize_t
pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct pci_bus *bus = to_pci_bus(container_of(kobj,
struct class_device,
@ -376,7 +379,8 @@ pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
* callback routine (pci_legacy_write).
*/
ssize_t
pci_write_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct pci_bus *bus = to_pci_bus(container_of(kobj,
struct class_device,
@ -499,7 +503,6 @@ static int pci_create_resource_files(struct pci_dev *pdev)
sprintf(res_attr_name, "resource%d", i);
res_attr->attr.name = res_attr_name;
res_attr->attr.mode = S_IRUSR | S_IWUSR;
res_attr->attr.owner = THIS_MODULE;
res_attr->size = pci_resource_len(pdev, i);
res_attr->mmap = pci_mmap_resource;
res_attr->private = &pdev->resource[i];
@ -529,7 +532,8 @@ static inline void pci_remove_resource_files(struct pci_dev *dev) { return; }
* writing anything except 0 enables it
*/
static ssize_t
pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
pci_write_rom(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
@ -552,7 +556,8 @@ pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
* device corresponding to @kobj.
*/
static ssize_t
pci_read_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
pci_read_rom(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
void __iomem *rom;
@ -582,7 +587,6 @@ static struct bin_attribute pci_config_attr = {
.attr = {
.name = "config",
.mode = S_IRUGO | S_IWUSR,
.owner = THIS_MODULE,
},
.size = 256,
.read = pci_read_config,
@ -593,7 +597,6 @@ static struct bin_attribute pcie_config_attr = {
.attr = {
.name = "config",
.mode = S_IRUGO | S_IWUSR,
.owner = THIS_MODULE,
},
.size = 4096,
.read = pci_read_config,
@ -628,7 +631,6 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
rom_attr->attr.name = "rom";
rom_attr->attr.mode = S_IRUSR;
rom_attr->attr.owner = THIS_MODULE;
rom_attr->read = pci_read_rom;
rom_attr->write = pci_write_rom;
retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr);

View file

@ -39,7 +39,6 @@ static void pci_create_legacy_files(struct pci_bus *b)
b->legacy_io->attr.name = "legacy_io";
b->legacy_io->size = 0xffff;
b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
b->legacy_io->attr.owner = THIS_MODULE;
b->legacy_io->read = pci_read_legacy_io;
b->legacy_io->write = pci_write_legacy_io;
class_device_create_bin_file(&b->class_dev, b->legacy_io);
@ -49,7 +48,6 @@ static void pci_create_legacy_files(struct pci_bus *b)
b->legacy_mem->attr.name = "legacy_mem";
b->legacy_mem->size = 1024*1024;
b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
b->legacy_mem->attr.owner = THIS_MODULE;
b->legacy_mem->mmap = pci_mmap_legacy_mem;
class_device_create_bin_file(&b->class_dev, b->legacy_mem);
}

View file

@ -283,7 +283,9 @@ static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf, loff_t off
return (ret);
}
static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size_t count)
static ssize_t pccard_show_cis(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
unsigned int size = 0x200;
@ -311,7 +313,9 @@ static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size
return (count);
}
static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, size_t count)
static ssize_t pccard_store_cis(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj));
cisdump_t *cis;
@ -366,7 +370,7 @@ static struct device_attribute *pccard_socket_attributes[] = {
};
static struct bin_attribute pccard_cis_attr = {
.attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR, .owner = THIS_MODULE},
.attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR },
.size = 0x200,
.read = pccard_show_cis,
.write = pccard_store_cis,

View file

@ -67,7 +67,8 @@ struct device_attribute rio_dev_attrs[] = {
};
static ssize_t
rio_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
rio_read_config(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct rio_dev *dev =
to_rio_dev(container_of(kobj, struct device, kobj));
@ -137,7 +138,8 @@ rio_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
}
static ssize_t
rio_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
rio_write_config(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct rio_dev *dev =
to_rio_dev(container_of(kobj, struct device, kobj));
@ -197,7 +199,6 @@ static struct bin_attribute rio_config_attr = {
.attr = {
.name = "config",
.mode = S_IRUGO | S_IWUSR,
.owner = THIS_MODULE,
},
.size = 0x200000,
.read = rio_read_config,

View file

@ -258,8 +258,9 @@ static const struct rtc_class_ops ds1553_rtc_ops = {
.ioctl = ds1553_rtc_ioctl,
};
static ssize_t ds1553_nvram_read(struct kobject *kobj, char *buf,
loff_t pos, size_t size)
static ssize_t ds1553_nvram_read(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t pos, size_t size)
{
struct platform_device *pdev =
to_platform_device(container_of(kobj, struct device, kobj));
@ -272,8 +273,9 @@ static ssize_t ds1553_nvram_read(struct kobject *kobj, char *buf,
return count;
}
static ssize_t ds1553_nvram_write(struct kobject *kobj, char *buf,
loff_t pos, size_t size)
static ssize_t ds1553_nvram_write(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t pos, size_t size)
{
struct platform_device *pdev =
to_platform_device(container_of(kobj, struct device, kobj));
@ -290,7 +292,6 @@ static struct bin_attribute ds1553_nvram_attr = {
.attr = {
.name = "nvram",
.mode = S_IRUGO | S_IWUGO,
.owner = THIS_MODULE,
},
.size = RTC_OFFSET,
.read = ds1553_nvram_read,

View file

@ -127,8 +127,9 @@ static const struct rtc_class_ops ds1742_rtc_ops = {
.set_time = ds1742_rtc_set_time,
};
static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf,
loff_t pos, size_t size)
static ssize_t ds1742_nvram_read(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t pos, size_t size)
{
struct platform_device *pdev =
to_platform_device(container_of(kobj, struct device, kobj));
@ -141,8 +142,9 @@ static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf,
return count;
}
static ssize_t ds1742_nvram_write(struct kobject *kobj, char *buf,
loff_t pos, size_t size)
static ssize_t ds1742_nvram_write(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t pos, size_t size)
{
struct platform_device *pdev =
to_platform_device(container_of(kobj, struct device, kobj));
@ -159,7 +161,6 @@ static struct bin_attribute ds1742_nvram_attr = {
.attr = {
.name = "nvram",
.mode = S_IRUGO | S_IWUGO,
.owner = THIS_MODULE,
},
.read = ds1742_nvram_read,
.write = ds1742_nvram_write,

View file

@ -141,8 +141,9 @@ static int s390_vary_chpid(struct chp_id chpid, int on)
/*
* Channel measurement related functions
*/
static ssize_t chp_measurement_chars_read(struct kobject *kobj, char *buf,
loff_t off, size_t count)
static ssize_t chp_measurement_chars_read(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct channel_path *chp;
unsigned int size;
@ -165,7 +166,6 @@ static struct bin_attribute chp_measurement_chars_attr = {
.attr = {
.name = "measurement_chars",
.mode = S_IRUSR,
.owner = THIS_MODULE,
},
.size = sizeof(struct cmg_chars),
.read = chp_measurement_chars_read,
@ -193,8 +193,9 @@ static void chp_measurement_copy_block(struct cmg_entry *buf,
} while (reference_buf.values[0] != buf->values[0]);
}
static ssize_t chp_measurement_read(struct kobject *kobj, char *buf,
loff_t off, size_t count)
static ssize_t chp_measurement_read(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct channel_path *chp;
struct channel_subsystem *css;
@ -217,7 +218,6 @@ static struct bin_attribute chp_measurement_attr = {
.attr = {
.name = "measurement",
.mode = S_IRUSR,
.owner = THIS_MODULE,
},
.size = sizeof(struct cmg_entry),
.read = chp_measurement_read,

View file

@ -991,7 +991,7 @@ static struct attribute_group qeth_osn_device_attr_group = {
#define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store) \
struct device_attribute dev_attr_##_id = { \
.attr = {.name=__stringify(_name), .mode=_mode, .owner=THIS_MODULE },\
.attr = {.name=__stringify(_name), .mode=_mode, },\
.show = _show, \
.store = _store, \
};

View file

@ -59,8 +59,9 @@
struct class_device_attribute *arcmsr_host_attrs[];
static ssize_t
arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off,
size_t count)
arcmsr_sysfs_iop_message_read(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct class_device *cdev = container_of(kobj,struct class_device,kobj);
struct Scsi_Host *host = class_to_shost(cdev);
@ -105,8 +106,9 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off,
}
static ssize_t
arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off,
size_t count)
arcmsr_sysfs_iop_message_write(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct class_device *cdev = container_of(kobj,struct class_device,kobj);
struct Scsi_Host *host = class_to_shost(cdev);
@ -152,8 +154,9 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off,
}
static ssize_t
arcmsr_sysfs_iop_message_clear(struct kobject *kobj, char *buf, loff_t off,
size_t count)
arcmsr_sysfs_iop_message_clear(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct class_device *cdev = container_of(kobj,struct class_device,kobj);
struct Scsi_Host *host = class_to_shost(cdev);
@ -188,7 +191,6 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = {
.attr = {
.name = "mu_read",
.mode = S_IRUSR ,
.owner = THIS_MODULE,
},
.size = 1032,
.read = arcmsr_sysfs_iop_message_read,
@ -198,7 +200,6 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = {
.attr = {
.name = "mu_write",
.mode = S_IWUSR,
.owner = THIS_MODULE,
},
.size = 1032,
.write = arcmsr_sysfs_iop_message_write,
@ -208,7 +209,6 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = {
.attr = {
.name = "mu_clear",
.mode = S_IWUSR,
.owner = THIS_MODULE,
},
.size = 1,
.write = arcmsr_sysfs_iop_message_clear,

View file

@ -2465,6 +2465,7 @@ restart:
/**
* ipr_read_trace - Dump the adapter trace
* @kobj: kobject struct
* @bin_attr: bin_attribute struct
* @buf: buffer
* @off: offset
* @count: buffer size
@ -2472,8 +2473,9 @@ restart:
* Return value:
* number of bytes printed to buffer
**/
static ssize_t ipr_read_trace(struct kobject *kobj, char *buf,
loff_t off, size_t count)
static ssize_t ipr_read_trace(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct class_device *cdev = container_of(kobj,struct class_device,kobj);
struct Scsi_Host *shost = class_to_shost(cdev);
@ -3166,6 +3168,7 @@ static struct class_device_attribute *ipr_ioa_attrs[] = {
/**
* ipr_read_dump - Dump the adapter
* @kobj: kobject struct
* @bin_attr: bin_attribute struct
* @buf: buffer
* @off: offset
* @count: buffer size
@ -3173,8 +3176,9 @@ static struct class_device_attribute *ipr_ioa_attrs[] = {
* Return value:
* number of bytes printed to buffer
**/
static ssize_t ipr_read_dump(struct kobject *kobj, char *buf,
loff_t off, size_t count)
static ssize_t ipr_read_dump(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct class_device *cdev = container_of(kobj,struct class_device,kobj);
struct Scsi_Host *shost = class_to_shost(cdev);
@ -3327,6 +3331,7 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg)
/**
* ipr_write_dump - Setup dump state of adapter
* @kobj: kobject struct
* @bin_attr: bin_attribute struct
* @buf: buffer
* @off: offset
* @count: buffer size
@ -3334,8 +3339,9 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg)
* Return value:
* number of bytes printed to buffer
**/
static ssize_t ipr_write_dump(struct kobject *kobj, char *buf,
loff_t off, size_t count)
static ssize_t ipr_write_dump(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct class_device *cdev = container_of(kobj,struct class_device,kobj);
struct Scsi_Host *shost = class_to_shost(cdev);

View file

@ -38,8 +38,10 @@ static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr);
#if 0
/* FIXME: smp needs to migrate into the sas class */
static ssize_t smp_portal_read(struct kobject *, char *, loff_t, size_t);
static ssize_t smp_portal_write(struct kobject *, char *, loff_t, size_t);
static ssize_t smp_portal_read(struct kobject *, struct bin_attribute *,
char *, loff_t, size_t);
static ssize_t smp_portal_write(struct kobject *, struct bin_attribute *,
char *, loff_t, size_t);
#endif
/* ---------- SMP task management ---------- */
@ -1368,7 +1370,6 @@ static void sas_ex_smp_hook(struct domain_device *dev)
memset(bin_attr, 0, sizeof(*bin_attr));
bin_attr->attr.name = SMP_BIN_ATTR_NAME;
bin_attr->attr.owner = THIS_MODULE;
bin_attr->attr.mode = 0600;
bin_attr->size = 0;
@ -1846,8 +1847,9 @@ out:
#if 0
/* ---------- SMP portal ---------- */
static ssize_t smp_portal_write(struct kobject *kobj, char *buf, loff_t offs,
size_t size)
static ssize_t smp_portal_write(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t offs, size_t size)
{
struct domain_device *dev = to_dom_device(kobj);
struct expander_device *ex = &dev->ex_dev;
@ -1873,8 +1875,9 @@ static ssize_t smp_portal_write(struct kobject *kobj, char *buf, loff_t offs,
return size;
}
static ssize_t smp_portal_read(struct kobject *kobj, char *buf, loff_t offs,
size_t size)
static ssize_t smp_portal_read(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t offs, size_t size)
{
struct domain_device *dev = to_dom_device(kobj);
struct expander_device *ex = &dev->ex_dev;

View file

@ -1133,7 +1133,8 @@ struct class_device_attribute *lpfc_host_attrs[] = {
};
static ssize_t
sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
size_t buf_off;
struct Scsi_Host *host = class_to_shost(container_of(kobj,
@ -1165,7 +1166,8 @@ sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
}
static ssize_t
sysfs_ctlreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
sysfs_ctlreg_read(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
size_t buf_off;
uint32_t * tmp_ptr;
@ -1200,7 +1202,6 @@ static struct bin_attribute sysfs_ctlreg_attr = {
.attr = {
.name = "ctlreg",
.mode = S_IRUSR | S_IWUSR,
.owner = THIS_MODULE,
},
.size = 256,
.read = sysfs_ctlreg_read,
@ -1222,7 +1223,8 @@ sysfs_mbox_idle (struct lpfc_hba * phba)
}
static ssize_t
sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct Scsi_Host * host =
class_to_shost(container_of(kobj, struct class_device, kobj));
@ -1274,7 +1276,8 @@ sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
}
static ssize_t
sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct Scsi_Host *host =
class_to_shost(container_of(kobj, struct class_device,
@ -1422,7 +1425,6 @@ static struct bin_attribute sysfs_mbox_attr = {
.attr = {
.name = "mbox",
.mode = S_IRUSR | S_IWUSR,
.owner = THIS_MODULE,
},
.size = MAILBOX_CMD_SIZE,
.read = sysfs_mbox_read,

View file

@ -11,8 +11,9 @@
/* SYSFS attributes --------------------------------------------------------- */
static ssize_t
qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off,
size_t count)
qla2x00_sysfs_read_fw_dump(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@ -31,8 +32,9 @@ qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off,
}
static ssize_t
qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off,
size_t count)
qla2x00_sysfs_write_fw_dump(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@ -73,7 +75,6 @@ static struct bin_attribute sysfs_fw_dump_attr = {
.attr = {
.name = "fw_dump",
.mode = S_IRUSR | S_IWUSR,
.owner = THIS_MODULE,
},
.size = 0,
.read = qla2x00_sysfs_read_fw_dump,
@ -81,8 +82,9 @@ static struct bin_attribute sysfs_fw_dump_attr = {
};
static ssize_t
qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
size_t count)
qla2x00_sysfs_read_nvram(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@ -101,8 +103,9 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
}
static ssize_t
qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off,
size_t count)
qla2x00_sysfs_write_nvram(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@ -149,7 +152,6 @@ static struct bin_attribute sysfs_nvram_attr = {
.attr = {
.name = "nvram",
.mode = S_IRUSR | S_IWUSR,
.owner = THIS_MODULE,
},
.size = 512,
.read = qla2x00_sysfs_read_nvram,
@ -157,8 +159,9 @@ static struct bin_attribute sysfs_nvram_attr = {
};
static ssize_t
qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off,
size_t count)
qla2x00_sysfs_read_optrom(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@ -176,8 +179,9 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off,
}
static ssize_t
qla2x00_sysfs_write_optrom(struct kobject *kobj, char *buf, loff_t off,
size_t count)
qla2x00_sysfs_write_optrom(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@ -198,7 +202,6 @@ static struct bin_attribute sysfs_optrom_attr = {
.attr = {
.name = "optrom",
.mode = S_IRUSR | S_IWUSR,
.owner = THIS_MODULE,
},
.size = OPTROM_SIZE_24XX,
.read = qla2x00_sysfs_read_optrom,
@ -206,8 +209,9 @@ static struct bin_attribute sysfs_optrom_attr = {
};
static ssize_t
qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off,
size_t count)
qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@ -279,15 +283,15 @@ static struct bin_attribute sysfs_optrom_ctl_attr = {
.attr = {
.name = "optrom_ctl",
.mode = S_IWUSR,
.owner = THIS_MODULE,
},
.size = 0,
.write = qla2x00_sysfs_write_optrom_ctl,
};
static ssize_t
qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off,
size_t count)
qla2x00_sysfs_read_vpd(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@ -305,8 +309,9 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off,
}
static ssize_t
qla2x00_sysfs_write_vpd(struct kobject *kobj, char *buf, loff_t off,
size_t count)
qla2x00_sysfs_write_vpd(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@ -327,7 +332,6 @@ static struct bin_attribute sysfs_vpd_attr = {
.attr = {
.name = "vpd",
.mode = S_IRUSR | S_IWUSR,
.owner = THIS_MODULE,
},
.size = 0,
.read = qla2x00_sysfs_read_vpd,
@ -335,8 +339,9 @@ static struct bin_attribute sysfs_vpd_attr = {
};
static ssize_t
qla2x00_sysfs_read_sfp(struct kobject *kobj, char *buf, loff_t off,
size_t count)
qla2x00_sysfs_read_sfp(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@ -375,7 +380,6 @@ static struct bin_attribute sysfs_sfp_attr = {
.attr = {
.name = "sfp",
.mode = S_IRUSR | S_IWUSR,
.owner = THIS_MODULE,
},
.size = SFP_DEV_SIZE * 2,
.read = qla2x00_sysfs_read_sfp,

View file

@ -111,7 +111,8 @@ at25_ee_read(
}
static ssize_t
at25_bin_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
at25_bin_read(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct device *dev;
struct at25_data *at25;
@ -236,7 +237,8 @@ at25_ee_write(struct at25_data *at25, char *buf, loff_t off, size_t count)
}
static ssize_t
at25_bin_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
at25_bin_write(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct device *dev;
struct at25_data *at25;
@ -314,7 +316,6 @@ static int at25_probe(struct spi_device *spi)
*/
at25->bin.attr.name = "eeprom";
at25->bin.attr.mode = S_IRUSR;
at25->bin.attr.owner = THIS_MODULE;
at25->bin.read = at25_bin_read;
at25->bin.size = at25->chip.byte_len;

View file

@ -1109,11 +1109,6 @@ void usb_root_hub_lost_power(struct usb_device *rhdev)
dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
/* Make sure no potential wakeup events get lost,
* by forcing the root hub to be resumed.
*/
rhdev->dev.power.prev_state.event = PM_EVENT_ON;
spin_lock_irqsave(&device_state_lock, flags);
hub = hdev_to_hub(rhdev);
for (port1 = 1; port1 <= rhdev->maxchild; ++port1) {

View file

@ -2102,7 +2102,9 @@ static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u
}
static ssize_t radeon_show_edid1(struct kobject *kobj, char *buf, loff_t off, size_t count)
static ssize_t radeon_show_edid1(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct pci_dev *pdev = to_pci_dev(dev);
@ -2113,7 +2115,9 @@ static ssize_t radeon_show_edid1(struct kobject *kobj, char *buf, loff_t off, si
}
static ssize_t radeon_show_edid2(struct kobject *kobj, char *buf, loff_t off, size_t count)
static ssize_t radeon_show_edid2(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct pci_dev *pdev = to_pci_dev(dev);
@ -2126,7 +2130,6 @@ static ssize_t radeon_show_edid2(struct kobject *kobj, char *buf, loff_t off, si
static struct bin_attribute edid1_attr = {
.attr = {
.name = "edid1",
.owner = THIS_MODULE,
.mode = 0444,
},
.size = EDID_LENGTH,
@ -2136,7 +2139,6 @@ static struct bin_attribute edid1_attr = {
static struct bin_attribute edid2_attr = {
.attr = {
.name = "edid2",
.owner = THIS_MODULE,
.mode = 0444,
},
.size = EDID_LENGTH,

View file

@ -172,7 +172,7 @@ static struct class backlight_class = {
#define DECLARE_ATTR(_name,_mode,_show,_store) \
{ \
.attr = { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
.attr = { .name = __stringify(_name), .mode = _mode }, \
.show = _show, \
.store = _store, \
}

View file

@ -157,7 +157,7 @@ static struct class lcd_class = {
#define DECLARE_ATTR(_name,_mode,_show,_store) \
{ \
.attr = { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
.attr = { .name = __stringify(_name), .mode = _mode }, \
.show = _show, \
.store = _store, \
}

View file

@ -91,8 +91,9 @@ static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data,
}
#endif /* CONFIG_W1_SLAVE_DS2433_CRC */
static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off,
size_t count)
static ssize_t w1_f23_read_bin(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
#ifdef CONFIG_W1_SLAVE_DS2433_CRC
@ -199,8 +200,9 @@ static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data)
return 0;
}
static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off,
size_t count)
static ssize_t w1_f23_write_bin(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
int addr, len, idx;
@ -252,7 +254,6 @@ static struct bin_attribute w1_f23_bin_attr = {
.attr = {
.name = "eeprom",
.mode = S_IRUGO | S_IWUSR,
.owner = THIS_MODULE,
},
.size = W1_EEPROM_SIZE,
.read = w1_f23_read_bin,

View file

@ -42,13 +42,13 @@ static u8 bad_roms[][9] = {
{}
};
static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t);
static ssize_t w1_therm_read_bin(struct kobject *, struct bin_attribute *,
char *, loff_t, size_t);
static struct bin_attribute w1_therm_bin_attr = {
.attr = {
.name = "w1_slave",
.mode = S_IRUGO,
.owner = THIS_MODULE,
},
.size = W1_SLAVE_DATA_SIZE,
.read = w1_therm_read_bin,
@ -159,7 +159,9 @@ static int w1_therm_check_rom(u8 rom[9])
return 0;
}
static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
static ssize_t w1_therm_read_bin(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
struct w1_master *dev = sl->master;

View file

@ -105,7 +105,9 @@ static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *a
return sprintf(buf, "%s\n", sl->name);
}
static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, size_t count)
static ssize_t w1_slave_read_id(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@ -128,7 +130,6 @@ static struct bin_attribute w1_slave_attr_bin_id = {
.attr = {
.name = "id",
.mode = S_IRUGO,
.owner = THIS_MODULE,
},
.size = 8,
.read = w1_slave_read_id,
@ -136,7 +137,9 @@ static struct bin_attribute w1_slave_attr_bin_id = {
/* Default family */
static ssize_t w1_default_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
static ssize_t w1_default_write(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@ -153,7 +156,9 @@ out_up:
return count;
}
static ssize_t w1_default_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
static ssize_t w1_default_read(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@ -167,7 +172,6 @@ static struct bin_attribute w1_default_attr = {
.attr = {
.name = "rw",
.mode = S_IRUGO | S_IWUSR,
.owner = THIS_MODULE,
},
.size = PAGE_SIZE,
.read = w1_default_read,

View file

@ -49,8 +49,9 @@ static ssize_t zorro_show_resource(struct device *dev, struct device_attribute *
static DEVICE_ATTR(resource, S_IRUGO, zorro_show_resource, NULL);
static ssize_t zorro_read_config(struct kobject *kobj, char *buf, loff_t off,
size_t count)
static ssize_t zorro_read_config(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct zorro_dev *z = to_zorro_dev(container_of(kobj, struct device,
kobj));
@ -78,7 +79,6 @@ static struct bin_attribute zorro_config_attr = {
.attr = {
.name = "config",
.mode = S_IRUGO | S_IWUSR,
.owner = THIS_MODULE
},
.size = sizeof(struct ConfigDev),
.read = zorro_read_config,

View file

@ -368,6 +368,69 @@ void debugfs_remove(struct dentry *dentry)
}
EXPORT_SYMBOL_GPL(debugfs_remove);
/**
* debugfs_rename - rename a file/directory in the debugfs filesystem
* @old_dir: a pointer to the parent dentry for the renamed object. This
* should be a directory dentry.
* @old_dentry: dentry of an object to be renamed.
* @new_dir: a pointer to the parent dentry where the object should be
* moved. This should be a directory dentry.
* @new_name: a pointer to a string containing the target name.
*
* This function renames a file/directory in debugfs. The target must not
* exist for rename to succeed.
*
* This function will return a pointer to old_dentry (which is updated to
* reflect renaming) if it succeeds. If an error occurs, %NULL will be
* returned.
*
* If debugfs is not enabled in the kernel, the value -%ENODEV will be
* returned.
*/
struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
struct dentry *new_dir, const char *new_name)
{
int error;
struct dentry *dentry = NULL, *trap;
const char *old_name;
trap = lock_rename(new_dir, old_dir);
/* Source or destination directories don't exist? */
if (!old_dir->d_inode || !new_dir->d_inode)
goto exit;
/* Source does not exist, cyclic rename, or mountpoint? */
if (!old_dentry->d_inode || old_dentry == trap ||
d_mountpoint(old_dentry))
goto exit;
dentry = lookup_one_len(new_name, new_dir, strlen(new_name));
/* Lookup failed, cyclic rename or target exists? */
if (IS_ERR(dentry) || dentry == trap || dentry->d_inode)
goto exit;
old_name = fsnotify_oldname_init(old_dentry->d_name.name);
error = simple_rename(old_dir->d_inode, old_dentry, new_dir->d_inode,
dentry);
if (error) {
fsnotify_oldname_free(old_name);
goto exit;
}
d_move(old_dentry, dentry);
fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name,
old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode),
NULL, old_dentry->d_inode);
fsnotify_oldname_free(old_name);
unlock_rename(new_dir, old_dir);
dput(dentry);
return old_dentry;
exit:
if (dentry && !IS_ERR(dentry))
dput(dentry);
unlock_rename(new_dir, old_dir);
return NULL;
}
EXPORT_SYMBOL_GPL(debugfs_rename);
static decl_subsys(debug, NULL, NULL);
static int __init debugfs_init(void)

View file

@ -840,8 +840,6 @@ static int __init ecryptfs_init(void)
goto out;
}
kobj_set_kset_s(&ecryptfs_subsys, fs_subsys);
sysfs_attr_version.attr.owner = THIS_MODULE;
sysfs_attr_version_str.attr.owner = THIS_MODULE;
rc = do_sysfs_registration();
if (rc) {
printk(KERN_ERR "sysfs registration failed\n");

View file

@ -74,7 +74,6 @@ struct mlog_attribute {
#define define_mask(_name) { \
.attr = { \
.name = #_name, \
.owner = THIS_MODULE, \
.mode = S_IRUGO | S_IWUSR, \
}, \
.mask = ML_##_name, \

View file

@ -397,7 +397,6 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len,
static struct attribute addpartattr = {
.name = "whole_disk",
.mode = S_IRUSR | S_IRGRP | S_IROTH,
.owner = THIS_MODULE,
};
sysfs_create_file(&p->kobj, &addpartattr);

View file

@ -20,29 +20,41 @@
#include "sysfs.h"
struct bin_buffer {
struct mutex mutex;
void *buffer;
int mmapped;
};
static int
fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
{
struct bin_attribute * attr = to_bin_attr(dentry);
struct kobject * kobj = to_kobj(dentry->d_parent);
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
int rc;
if (!attr->read)
return -EIO;
/* need attr_sd for attr, its parent for kobj */
if (!sysfs_get_active_two(attr_sd))
return -ENODEV;
return attr->read(kobj, buffer, off, count);
rc = -EIO;
if (attr->read)
rc = attr->read(kobj, attr, buffer, off, count);
sysfs_put_active_two(attr_sd);
return rc;
}
static ssize_t
read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
{
char *buffer = file->private_data;
struct bin_buffer *bb = file->private_data;
struct dentry *dentry = file->f_path.dentry;
int size = dentry->d_inode->i_size;
loff_t offs = *off;
int ret;
if (count > PAGE_SIZE)
count = PAGE_SIZE;
int count = min_t(size_t, bytes, PAGE_SIZE);
if (size) {
if (offs > size)
@ -51,43 +63,56 @@ read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
count = size - offs;
}
ret = fill_read(dentry, buffer, offs, count);
if (ret < 0)
return ret;
count = ret;
mutex_lock(&bb->mutex);
if (copy_to_user(userbuf, buffer, count))
return -EFAULT;
count = fill_read(dentry, bb->buffer, offs, count);
if (count < 0)
goto out_unlock;
pr_debug("offs = %lld, *off = %lld, count = %zd\n", offs, *off, count);
if (copy_to_user(userbuf, bb->buffer, count)) {
count = -EFAULT;
goto out_unlock;
}
pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count);
*off = offs + count;
out_unlock:
mutex_unlock(&bb->mutex);
return count;
}
static int
flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
{
struct bin_attribute *attr = to_bin_attr(dentry);
struct kobject *kobj = to_kobj(dentry->d_parent);
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
int rc;
if (!attr->write)
return -EIO;
/* need attr_sd for attr, its parent for kobj */
if (!sysfs_get_active_two(attr_sd))
return -ENODEV;
return attr->write(kobj, buffer, offset, count);
rc = -EIO;
if (attr->write)
rc = attr->write(kobj, attr, buffer, offset, count);
sysfs_put_active_two(attr_sd);
return rc;
}
static ssize_t write(struct file * file, const char __user * userbuf,
size_t count, loff_t * off)
static ssize_t write(struct file *file, const char __user *userbuf,
size_t bytes, loff_t *off)
{
char *buffer = file->private_data;
struct bin_buffer *bb = file->private_data;
struct dentry *dentry = file->f_path.dentry;
int size = dentry->d_inode->i_size;
loff_t offs = *off;
int count = min_t(size_t, bytes, PAGE_SIZE);
if (count > PAGE_SIZE)
count = PAGE_SIZE;
if (size) {
if (offs > size)
return 0;
@ -95,72 +120,100 @@ static ssize_t write(struct file * file, const char __user * userbuf,
count = size - offs;
}
if (copy_from_user(buffer, userbuf, count))
return -EFAULT;
mutex_lock(&bb->mutex);
count = flush_write(dentry, buffer, offs, count);
if (copy_from_user(bb->buffer, userbuf, count)) {
count = -EFAULT;
goto out_unlock;
}
count = flush_write(dentry, bb->buffer, offs, count);
if (count > 0)
*off = offs + count;
out_unlock:
mutex_unlock(&bb->mutex);
return count;
}
static int mmap(struct file *file, struct vm_area_struct *vma)
{
struct dentry *dentry = file->f_path.dentry;
struct bin_attribute *attr = to_bin_attr(dentry);
struct kobject *kobj = to_kobj(dentry->d_parent);
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_elem.bin_attr.bin_attr;
struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
int rc;
if (!attr->mmap)
return -EINVAL;
mutex_lock(&bb->mutex);
return attr->mmap(kobj, attr, vma);
/* need attr_sd for attr, its parent for kobj */
if (!sysfs_get_active_two(attr_sd))
return -ENODEV;
rc = -EINVAL;
if (attr->mmap)
rc = attr->mmap(kobj, attr, vma);
if (rc == 0 && !bb->mmapped)
bb->mmapped = 1;
else
sysfs_put_active_two(attr_sd);
mutex_unlock(&bb->mutex);
return rc;
}
static int open(struct inode * inode, struct file * file)
{
struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
int error = -EINVAL;
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
struct bin_buffer *bb = NULL;
int error;
if (!kobj || !attr)
goto Done;
/* Grab the module reference for this attribute if we have one */
error = -ENODEV;
if (!try_module_get(attr->attr.owner))
goto Done;
/* need attr_sd for attr */
if (!sysfs_get_active(attr_sd))
return -ENODEV;
error = -EACCES;
if ((file->f_mode & FMODE_WRITE) && !(attr->write || attr->mmap))
goto Error;
goto err_out;
if ((file->f_mode & FMODE_READ) && !(attr->read || attr->mmap))
goto Error;
goto err_out;
error = -ENOMEM;
file->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!file->private_data)
goto Error;
bb = kzalloc(sizeof(*bb), GFP_KERNEL);
if (!bb)
goto err_out;
error = 0;
goto Done;
bb->buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!bb->buffer)
goto err_out;
Error:
module_put(attr->attr.owner);
Done:
if (error)
kobject_put(kobj);
mutex_init(&bb->mutex);
file->private_data = bb;
/* open succeeded, put active reference and pin attr_sd */
sysfs_put_active(attr_sd);
sysfs_get(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 kobject * kobj = to_kobj(file->f_path.dentry->d_parent);
struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
u8 * buffer = file->private_data;
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
struct bin_buffer *bb = file->private_data;
kobject_put(kobj);
module_put(attr->attr.owner);
kfree(buffer);
if (bb->mmapped)
sysfs_put_active_two(attr_sd);
sysfs_put(attr_sd);
kfree(bb->buffer);
kfree(bb);
return 0;
}
@ -181,9 +234,9 @@ const struct file_operations bin_fops = {
int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
{
BUG_ON(!kobj || !kobj->dentry || !attr);
BUG_ON(!kobj || !kobj->sd || !attr);
return sysfs_add_file(kobj->dentry, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
return sysfs_add_file(kobj->sd, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
}
@ -195,7 +248,7 @@ int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr)
{
if (sysfs_hash_and_remove(kobj->dentry, attr->attr.name) < 0) {
if (sysfs_hash_and_remove(kobj->sd, attr->attr.name) < 0) {
printk(KERN_ERR "%s: "
"bad dentry or inode or no such file: \"%s\"\n",
__FUNCTION__, attr->attr.name);

File diff suppressed because it is too large Load diff

View file

@ -50,29 +50,15 @@ static struct sysfs_ops subsys_sysfs_ops = {
.store = subsys_attr_store,
};
/**
* add_to_collection - add buffer to a collection
* @buffer: buffer to be added
* @node: inode of set to add to
*/
static inline void
add_to_collection(struct sysfs_buffer *buffer, struct inode *node)
{
struct sysfs_buffer_collection *set = node->i_private;
mutex_lock(&node->i_mutex);
list_add(&buffer->associates, &set->associates);
mutex_unlock(&node->i_mutex);
}
static inline void
remove_from_collection(struct sysfs_buffer *buffer, struct inode *node)
{
mutex_lock(&node->i_mutex);
list_del(&buffer->associates);
mutex_unlock(&node->i_mutex);
}
struct sysfs_buffer {
size_t count;
loff_t pos;
char * page;
struct sysfs_ops * ops;
struct semaphore sem;
int needs_read_fill;
int event;
};
/**
* fill_read_buffer - allocate and fill buffer from object.
@ -87,9 +73,8 @@ remove_from_collection(struct sysfs_buffer *buffer, struct inode *node)
*/
static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
{
struct sysfs_dirent * sd = dentry->d_fsdata;
struct attribute * attr = to_attr(dentry);
struct kobject * kobj = to_kobj(dentry->d_parent);
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
struct sysfs_ops * ops = buffer->ops;
int ret = 0;
ssize_t count;
@ -99,8 +84,15 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
if (!buffer->page)
return -ENOMEM;
buffer->event = atomic_read(&sd->s_event);
count = ops->show(kobj,attr,buffer->page);
/* need attr_sd for attr and ops, its parent for kobj */
if (!sysfs_get_active_two(attr_sd))
return -ENODEV;
buffer->event = atomic_read(&attr_sd->s_event);
count = ops->show(kobj, attr_sd->s_elem.attr.attr, buffer->page);
sysfs_put_active_two(attr_sd);
BUG_ON(count > (ssize_t)PAGE_SIZE);
if (count >= 0) {
buffer->needs_read_fill = 0;
@ -138,10 +130,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
down(&buffer->sem);
if (buffer->needs_read_fill) {
if (buffer->orphaned)
retval = -ENODEV;
else
retval = fill_read_buffer(file->f_path.dentry,buffer);
retval = fill_read_buffer(file->f_path.dentry,buffer);
if (retval)
goto out;
}
@ -196,14 +185,23 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
* passing the buffer that we acquired in fill_write_buffer().
*/
static int
static int
flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count)
{
struct attribute * attr = to_attr(dentry);
struct kobject * kobj = to_kobj(dentry->d_parent);
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
struct sysfs_ops * ops = buffer->ops;
int rc;
return ops->store(kobj,attr,buffer->page,count);
/* need attr_sd for attr and ops, its parent for kobj */
if (!sysfs_get_active_two(attr_sd))
return -ENODEV;
rc = ops->store(kobj, attr_sd->s_elem.attr.attr, buffer->page, count);
sysfs_put_active_two(attr_sd);
return rc;
}
@ -231,37 +229,26 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t
ssize_t len;
down(&buffer->sem);
if (buffer->orphaned) {
len = -ENODEV;
goto out;
}
len = fill_write_buffer(buffer, buf, count);
if (len > 0)
len = flush_write_buffer(file->f_path.dentry, buffer, len);
if (len > 0)
*ppos += len;
out:
up(&buffer->sem);
return len;
}
static int sysfs_open_file(struct inode *inode, struct file *file)
{
struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
struct attribute * attr = to_attr(file->f_path.dentry);
struct sysfs_buffer_collection *set;
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
struct sysfs_buffer * buffer;
struct sysfs_ops * ops = NULL;
int error = 0;
int error;
if (!kobj || !attr)
goto Einval;
/* Grab the module reference for this attribute if we have one */
if (!try_module_get(attr->owner)) {
error = -ENODEV;
goto Done;
}
/* need attr_sd for attr and ops, its parent for kobj */
if (!sysfs_get_active_two(attr_sd))
return -ENODEV;
/* if the kobject has no ktype, then we assume that it is a subsystem
* itself, and use ops for it.
@ -273,33 +260,21 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
else
ops = &subsys_sysfs_ops;
error = -EACCES;
/* No sysfs operations, either from having no subsystem,
* or the subsystem have no operations.
*/
if (!ops)
goto Eaccess;
/* make sure we have a collection to add our buffers to */
mutex_lock(&inode->i_mutex);
if (!(set = inode->i_private)) {
if (!(set = inode->i_private = kmalloc(sizeof(struct sysfs_buffer_collection), GFP_KERNEL))) {
error = -ENOMEM;
goto Done;
} else {
INIT_LIST_HEAD(&set->associates);
}
}
mutex_unlock(&inode->i_mutex);
goto err_out;
/* File needs write support.
* The inode's perms must say it's ok,
* and we must have a store method.
*/
if (file->f_mode & FMODE_WRITE) {
if (!(inode->i_mode & S_IWUGO) || !ops->store)
goto Eaccess;
goto err_out;
}
/* File needs read support.
@ -308,48 +283,38 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
*/
if (file->f_mode & FMODE_READ) {
if (!(inode->i_mode & S_IRUGO) || !ops->show)
goto Eaccess;
goto err_out;
}
/* No error? Great, allocate a buffer for the file, and store it
* it in file->private_data for easy access.
*/
error = -ENOMEM;
buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL);
if (buffer) {
INIT_LIST_HEAD(&buffer->associates);
init_MUTEX(&buffer->sem);
buffer->needs_read_fill = 1;
buffer->ops = ops;
add_to_collection(buffer, inode);
file->private_data = buffer;
} else
error = -ENOMEM;
goto Done;
if (!buffer)
goto err_out;
Einval:
error = -EINVAL;
goto Done;
Eaccess:
error = -EACCES;
module_put(attr->owner);
Done:
if (error)
kobject_put(kobj);
init_MUTEX(&buffer->sem);
buffer->needs_read_fill = 1;
buffer->ops = ops;
file->private_data = buffer;
/* open succeeded, put active references and pin attr_sd */
sysfs_put_active_two(attr_sd);
sysfs_get(attr_sd);
return 0;
err_out:
sysfs_put_active_two(attr_sd);
return error;
}
static int sysfs_release(struct inode * inode, struct file * filp)
{
struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
struct attribute * attr = to_attr(filp->f_path.dentry);
struct module * owner = attr->owner;
struct sysfs_buffer * buffer = filp->private_data;
struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
struct sysfs_buffer *buffer = filp->private_data;
if (buffer)
remove_from_collection(buffer, inode);
kobject_put(kobj);
/* After this point, attr should not be accessed. */
module_put(owner);
sysfs_put(attr_sd);
if (buffer) {
if (buffer->page)
@ -376,57 +341,43 @@ static int sysfs_release(struct inode * inode, struct file * filp)
static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
{
struct sysfs_buffer * buffer = filp->private_data;
struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
struct sysfs_dirent * sd = filp->f_path.dentry->d_fsdata;
int res = 0;
struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
/* need parent for the kobj, grab both */
if (!sysfs_get_active_two(attr_sd))
goto trigger;
poll_wait(filp, &kobj->poll, wait);
if (buffer->event != atomic_read(&sd->s_event)) {
res = POLLERR|POLLPRI;
buffer->needs_read_fill = 1;
}
sysfs_put_active_two(attr_sd);
return res;
if (buffer->event != atomic_read(&attr_sd->s_event))
goto trigger;
return 0;
trigger:
buffer->needs_read_fill = 1;
return POLLERR|POLLPRI;
}
static struct dentry *step_down(struct dentry *dir, const char * name)
void sysfs_notify(struct kobject *k, char *dir, char *attr)
{
struct dentry * de;
struct sysfs_dirent *sd = k->sd;
if (dir == NULL || dir->d_inode == NULL)
return NULL;
mutex_lock(&sysfs_mutex);
mutex_lock(&dir->d_inode->i_mutex);
de = lookup_one_len(name, dir, strlen(name));
mutex_unlock(&dir->d_inode->i_mutex);
dput(dir);
if (IS_ERR(de))
return NULL;
if (de->d_inode == NULL) {
dput(de);
return NULL;
}
return de;
}
void sysfs_notify(struct kobject * k, char *dir, char *attr)
{
struct dentry *de = k->dentry;
if (de)
dget(de);
if (de && dir)
de = step_down(de, dir);
if (de && attr)
de = step_down(de, attr);
if (de) {
struct sysfs_dirent * sd = de->d_fsdata;
if (sd)
atomic_inc(&sd->s_event);
if (sd && dir)
sd = sysfs_find_dirent(sd, dir);
if (sd && attr)
sd = sysfs_find_dirent(sd, attr);
if (sd) {
atomic_inc(&sd->s_event);
wake_up_interruptible(&k->poll);
dput(de);
}
mutex_unlock(&sysfs_mutex);
}
EXPORT_SYMBOL_GPL(sysfs_notify);
@ -440,19 +391,30 @@ const struct file_operations sysfs_file_operations = {
};
int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
int type)
{
struct sysfs_dirent * parent_sd = dir->d_fsdata;
umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
int error = -EEXIST;
struct sysfs_addrm_cxt acxt;
struct sysfs_dirent *sd;
mutex_lock(&dir->d_inode->i_mutex);
if (!sysfs_dirent_exist(parent_sd, attr->name))
error = sysfs_make_dirent(parent_sd, NULL, (void *)attr,
mode, type);
mutex_unlock(&dir->d_inode->i_mutex);
sd = sysfs_new_dirent(attr->name, mode, type);
if (!sd)
return -ENOMEM;
sd->s_elem.attr.attr = (void *)attr;
return error;
sysfs_addrm_start(&acxt, dir_sd);
if (!sysfs_find_dirent(dir_sd, attr->name)) {
sysfs_add_one(&acxt, sd);
sysfs_link_sibling(sd);
}
if (sysfs_addrm_finish(&acxt))
return 0;
sysfs_put(sd);
return -EEXIST;
}
@ -464,9 +426,9 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
{
BUG_ON(!kobj || !kobj->dentry || !attr);
BUG_ON(!kobj || !kobj->sd || !attr);
return sysfs_add_file(kobj->dentry, attr, SYSFS_KOBJ_ATTR);
return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR);
}
@ -480,16 +442,16 @@ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
int sysfs_add_file_to_group(struct kobject *kobj,
const struct attribute *attr, const char *group)
{
struct dentry *dir;
struct sysfs_dirent *dir_sd;
int error;
dir = lookup_one_len(group, kobj->dentry, strlen(group));
if (IS_ERR(dir))
error = PTR_ERR(dir);
else {
error = sysfs_add_file(dir, attr, SYSFS_KOBJ_ATTR);
dput(dir);
}
dir_sd = sysfs_get_dirent(kobj->sd, group);
if (!dir_sd)
return -ENOENT;
error = sysfs_add_file(dir_sd, attr, SYSFS_KOBJ_ATTR);
sysfs_put(dir_sd);
return error;
}
EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
@ -502,30 +464,31 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
*/
int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
{
struct dentry * dir = kobj->dentry;
struct dentry * victim;
int res = -ENOENT;
struct sysfs_dirent *victim_sd = NULL;
struct dentry *victim = NULL;
int rc;
mutex_lock(&dir->d_inode->i_mutex);
victim = lookup_one_len(attr->name, dir, strlen(attr->name));
if (!IS_ERR(victim)) {
/* make sure dentry is really there */
if (victim->d_inode &&
(victim->d_parent->d_inode == dir->d_inode)) {
victim->d_inode->i_mtime = CURRENT_TIME;
fsnotify_modify(victim);
res = 0;
} else
d_drop(victim);
/**
* Drop the reference acquired from lookup_one_len() above.
*/
dput(victim);
rc = -ENOENT;
victim_sd = sysfs_get_dirent(kobj->sd, attr->name);
if (!victim_sd)
goto out;
victim = sysfs_get_dentry(victim_sd);
if (IS_ERR(victim)) {
rc = PTR_ERR(victim);
victim = NULL;
goto out;
}
mutex_unlock(&dir->d_inode->i_mutex);
return res;
mutex_lock(&victim->d_inode->i_mutex);
victim->d_inode->i_mtime = CURRENT_TIME;
fsnotify_modify(victim);
mutex_unlock(&victim->d_inode->i_mutex);
rc = 0;
out:
dput(victim);
sysfs_put(victim_sd);
return rc;
}
@ -538,30 +501,34 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
*/
int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
{
struct dentry *dir = kobj->dentry;
struct dentry *victim;
struct sysfs_dirent *victim_sd = NULL;
struct dentry *victim = NULL;
struct inode * inode;
struct iattr newattrs;
int res = -ENOENT;
int rc;
mutex_lock(&dir->d_inode->i_mutex);
victim = lookup_one_len(attr->name, dir, strlen(attr->name));
if (!IS_ERR(victim)) {
if (victim->d_inode &&
(victim->d_parent->d_inode == dir->d_inode)) {
inode = victim->d_inode;
mutex_lock(&inode->i_mutex);
newattrs.ia_mode = (mode & S_IALLUGO) |
(inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
res = notify_change(victim, &newattrs);
mutex_unlock(&inode->i_mutex);
}
dput(victim);
rc = -ENOENT;
victim_sd = sysfs_get_dirent(kobj->sd, attr->name);
if (!victim_sd)
goto out;
victim = sysfs_get_dentry(victim_sd);
if (IS_ERR(victim)) {
rc = PTR_ERR(victim);
victim = NULL;
goto out;
}
mutex_unlock(&dir->d_inode->i_mutex);
return res;
inode = victim->d_inode;
mutex_lock(&inode->i_mutex);
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
rc = notify_change(victim, &newattrs);
mutex_unlock(&inode->i_mutex);
out:
dput(victim);
sysfs_put(victim_sd);
return rc;
}
EXPORT_SYMBOL_GPL(sysfs_chmod_file);
@ -576,7 +543,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file);
void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
{
sysfs_hash_and_remove(kobj->dentry, attr->name);
sysfs_hash_and_remove(kobj->sd, attr->name);
}
@ -589,12 +556,12 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
void sysfs_remove_file_from_group(struct kobject *kobj,
const struct attribute *attr, const char *group)
{
struct dentry *dir;
struct sysfs_dirent *dir_sd;
dir = lookup_one_len(group, kobj->dentry, strlen(group));
if (!IS_ERR(dir)) {
sysfs_hash_and_remove(dir, attr->name);
dput(dir);
dir_sd = sysfs_get_dirent(kobj->sd, group);
if (dir_sd) {
sysfs_hash_and_remove(dir_sd, attr->name);
sysfs_put(dir_sd);
}
}
EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);

View file

@ -18,26 +18,25 @@
#include "sysfs.h"
static void remove_files(struct dentry * dir,
const struct attribute_group * grp)
static void remove_files(struct sysfs_dirent *dir_sd,
const struct attribute_group *grp)
{
struct attribute *const* attr;
for (attr = grp->attrs; *attr; attr++)
sysfs_hash_and_remove(dir,(*attr)->name);
sysfs_hash_and_remove(dir_sd, (*attr)->name);
}
static int create_files(struct dentry * dir,
const struct attribute_group * grp)
static int create_files(struct sysfs_dirent *dir_sd,
const struct attribute_group *grp)
{
struct attribute *const* attr;
int error = 0;
for (attr = grp->attrs; *attr && !error; attr++) {
error = sysfs_add_file(dir, *attr, SYSFS_KOBJ_ATTR);
}
for (attr = grp->attrs; *attr && !error; attr++)
error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
if (error)
remove_files(dir,grp);
remove_files(dir_sd, grp);
return error;
}
@ -45,44 +44,44 @@ static int create_files(struct dentry * dir,
int sysfs_create_group(struct kobject * kobj,
const struct attribute_group * grp)
{
struct dentry * dir;
struct sysfs_dirent *sd;
int error;
BUG_ON(!kobj || !kobj->dentry);
BUG_ON(!kobj || !kobj->sd);
if (grp->name) {
error = sysfs_create_subdir(kobj,grp->name,&dir);
error = sysfs_create_subdir(kobj, grp->name, &sd);
if (error)
return error;
} else
dir = kobj->dentry;
dir = dget(dir);
if ((error = create_files(dir,grp))) {
sd = kobj->sd;
sysfs_get(sd);
error = create_files(sd, grp);
if (error) {
if (grp->name)
sysfs_remove_subdir(dir);
sysfs_remove_subdir(sd);
}
dput(dir);
sysfs_put(sd);
return error;
}
void sysfs_remove_group(struct kobject * kobj,
const struct attribute_group * grp)
{
struct dentry * dir;
struct sysfs_dirent *dir_sd = kobj->sd;
struct sysfs_dirent *sd;
if (grp->name) {
dir = lookup_one_len_kern(grp->name, kobj->dentry,
strlen(grp->name));
BUG_ON(IS_ERR(dir));
}
else
dir = dget(kobj->dentry);
sd = sysfs_get_dirent(dir_sd, grp->name);
BUG_ON(!sd);
} else
sd = sysfs_get(dir_sd);
remove_files(dir,grp);
remove_files(sd, grp);
if (grp->name)
sysfs_remove_subdir(dir);
/* release the ref. taken in this routine */
dput(dir);
sysfs_remove_subdir(sd);
sysfs_put(sd);
}

View file

@ -133,187 +133,94 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
*/
static struct lock_class_key sysfs_inode_imutex_key;
struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd)
void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
{
struct inode * inode = new_inode(sysfs_sb);
if (inode) {
inode->i_blocks = 0;
inode->i_mapping->a_ops = &sysfs_aops;
inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
inode->i_op = &sysfs_inode_operations;
inode->i_ino = sd->s_ino;
lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
inode->i_blocks = 0;
inode->i_mapping->a_ops = &sysfs_aops;
inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
inode->i_op = &sysfs_inode_operations;
inode->i_ino = sd->s_ino;
lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
if (sd->s_iattr) {
/* sysfs_dirent has non-default attributes
* get them for the new inode from persistent copy
* in sysfs_dirent
*/
set_inode_attr(inode, sd->s_iattr);
} else
set_default_inode_attr(inode, sd->s_mode);
}
/**
* sysfs_get_inode - get inode for sysfs_dirent
* @sd: sysfs_dirent to allocate inode for
*
* Get inode for @sd. If such inode doesn't exist, a new inode
* is allocated and basics are initialized. New inode is
* returned locked.
*
* LOCKING:
* Kernel thread context (may sleep).
*
* RETURNS:
* Pointer to allocated inode on success, NULL on failure.
*/
struct inode * sysfs_get_inode(struct sysfs_dirent *sd)
{
struct inode *inode;
inode = iget_locked(sysfs_sb, sd->s_ino);
if (inode && (inode->i_state & I_NEW))
sysfs_init_inode(sd, inode);
if (sd->s_iattr) {
/* sysfs_dirent has non-default attributes
* get them for the new inode from persistent copy
* in sysfs_dirent
*/
set_inode_attr(inode, sd->s_iattr);
} else
set_default_inode_attr(inode, mode);
}
return inode;
}
int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
{
int error = 0;
struct inode * inode = NULL;
if (dentry) {
if (!dentry->d_inode) {
struct sysfs_dirent * sd = dentry->d_fsdata;
if ((inode = sysfs_new_inode(mode, sd))) {
if (dentry->d_parent && dentry->d_parent->d_inode) {
struct inode *p_inode = dentry->d_parent->d_inode;
p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
}
goto Proceed;
}
else
error = -ENOMEM;
} else
error = -EEXIST;
} else
error = -ENOENT;
goto Done;
Proceed:
if (init)
error = init(inode);
if (!error) {
d_instantiate(dentry, inode);
if (S_ISDIR(mode))
dget(dentry); /* pin only directory dentry in core */
} else
iput(inode);
Done:
return error;
}
/*
* Get the name for corresponding element represented by the given sysfs_dirent
/**
* sysfs_instantiate - instantiate dentry
* @dentry: dentry to be instantiated
* @inode: inode associated with @sd
*
* Unlock @inode if locked and instantiate @dentry with @inode.
*
* LOCKING:
* None.
*/
const unsigned char * sysfs_get_name(struct sysfs_dirent *sd)
void sysfs_instantiate(struct dentry *dentry, struct inode *inode)
{
struct attribute * attr;
struct bin_attribute * bin_attr;
struct sysfs_symlink * sl;
BUG_ON(!dentry || dentry->d_inode);
BUG_ON(!sd || !sd->s_element);
if (inode->i_state & I_NEW)
unlock_new_inode(inode);
switch (sd->s_type) {
case SYSFS_DIR:
/* Always have a dentry so use that */
return sd->s_dentry->d_name.name;
case SYSFS_KOBJ_ATTR:
attr = sd->s_element;
return attr->name;
case SYSFS_KOBJ_BIN_ATTR:
bin_attr = sd->s_element;
return bin_attr->attr.name;
case SYSFS_KOBJ_LINK:
sl = sd->s_element;
return sl->link_name;
}
return NULL;
d_instantiate(dentry, inode);
}
static inline void orphan_all_buffers(struct inode *node)
int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name)
{
struct sysfs_buffer_collection *set;
struct sysfs_buffer *buf;
struct sysfs_addrm_cxt acxt;
struct sysfs_dirent **pos, *sd;
mutex_lock_nested(&node->i_mutex, I_MUTEX_CHILD);
set = node->i_private;
if (set) {
list_for_each_entry(buf, &set->associates, associates) {
down(&buf->sem);
buf->orphaned = 1;
up(&buf->sem);
}
}
mutex_unlock(&node->i_mutex);
}
/*
* Unhashes the dentry corresponding to given sysfs_dirent
* Called with parent inode's i_mutex held.
*/
void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent)
{
struct dentry *dentry = NULL;
struct inode *inode;
/* We're not holding a reference to ->s_dentry dentry but the
* field will stay valid as long as sysfs_lock is held.
*/
spin_lock(&sysfs_lock);
spin_lock(&dcache_lock);
/* dget dentry if it's still alive */
if (sd->s_dentry && sd->s_dentry->d_inode)
dentry = dget_locked(sd->s_dentry);
spin_unlock(&dcache_lock);
spin_unlock(&sysfs_lock);
/* drop dentry */
if (dentry) {
spin_lock(&dcache_lock);
spin_lock(&dentry->d_lock);
if (!d_unhashed(dentry) && dentry->d_inode) {
inode = dentry->d_inode;
spin_lock(&inode->i_lock);
__iget(inode);
spin_unlock(&inode->i_lock);
dget_locked(dentry);
__d_drop(dentry);
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
simple_unlink(parent->d_inode, dentry);
orphan_all_buffers(inode);
iput(inode);
} else {
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
}
dput(dentry);
}
}
int sysfs_hash_and_remove(struct dentry * dir, const char * name)
{
struct sysfs_dirent * sd;
struct sysfs_dirent * parent_sd;
int found = 0;
if (!dir)
if (!dir_sd)
return -ENOENT;
if (dir->d_inode == NULL)
/* no inode means this hasn't been made visible yet */
return -ENOENT;
sysfs_addrm_start(&acxt, dir_sd);
parent_sd = dir->d_fsdata;
mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
if (!sd->s_element)
for (pos = &dir_sd->s_children; *pos; pos = &(*pos)->s_sibling) {
sd = *pos;
if (!sysfs_type(sd))
continue;
if (!strcmp(sysfs_get_name(sd), name)) {
list_del_init(&sd->s_sibling);
sysfs_drop_dentry(sd, dir);
sysfs_put(sd);
found = 1;
if (!strcmp(sd->s_name, name)) {
*pos = sd->s_sibling;
sd->s_sibling = NULL;
sysfs_remove_one(&acxt, sd);
break;
}
}
mutex_unlock(&dir->d_inode->i_mutex);
return found ? 0 : -ENOENT;
if (sysfs_addrm_finish(&acxt))
return 0;
return -ENOENT;
}

View file

@ -19,28 +19,18 @@ struct vfsmount *sysfs_mount;
struct super_block * sysfs_sb = NULL;
struct kmem_cache *sysfs_dir_cachep;
static void sysfs_clear_inode(struct inode *inode);
static const struct super_operations sysfs_ops = {
.statfs = simple_statfs,
.drop_inode = sysfs_delete_inode,
.clear_inode = sysfs_clear_inode,
};
static struct sysfs_dirent sysfs_root = {
.s_sibling = LIST_HEAD_INIT(sysfs_root.s_sibling),
.s_children = LIST_HEAD_INIT(sysfs_root.s_children),
.s_element = NULL,
.s_type = SYSFS_ROOT,
.s_iattr = NULL,
struct sysfs_dirent sysfs_root = {
.s_count = ATOMIC_INIT(1),
.s_flags = SYSFS_ROOT,
.s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
.s_ino = 1,
};
static void sysfs_clear_inode(struct inode *inode)
{
kfree(inode->i_private);
}
static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
{
struct inode *inode;
@ -53,24 +43,26 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_time_gran = 1;
sysfs_sb = sb;
inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
&sysfs_root);
if (inode) {
inode->i_op = &sysfs_dir_inode_operations;
inode->i_fop = &sysfs_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
inc_nlink(inode);
} else {
inode = new_inode(sysfs_sb);
if (!inode) {
pr_debug("sysfs: could not get root inode\n");
return -ENOMEM;
}
sysfs_init_inode(&sysfs_root, inode);
inode->i_op = &sysfs_dir_inode_operations;
inode->i_fop = &sysfs_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
inc_nlink(inode);
root = d_alloc_root(inode);
if (!root) {
pr_debug("%s: could not get root dentry!\n",__FUNCTION__);
iput(inode);
return -ENOMEM;
}
sysfs_root.s_dentry = root;
root->d_fsdata = &sysfs_root;
sb->s_root = root;
return 0;

View file

@ -11,71 +11,39 @@
#include "sysfs.h"
static int object_depth(struct kobject * kobj)
static int object_depth(struct sysfs_dirent *sd)
{
struct kobject * p = kobj;
int depth = 0;
do { depth++; } while ((p = p->parent));
for (; sd->s_parent; sd = sd->s_parent)
depth++;
return depth;
}
static int object_path_length(struct kobject * kobj)
static int object_path_length(struct sysfs_dirent * sd)
{
struct kobject * p = kobj;
int length = 1;
do {
length += strlen(kobject_name(p)) + 1;
p = p->parent;
} while (p);
for (; sd->s_parent; sd = sd->s_parent)
length += strlen(sd->s_name) + 1;
return length;
}
static void fill_object_path(struct kobject * kobj, char * buffer, int length)
static void fill_object_path(struct sysfs_dirent *sd, char *buffer, int length)
{
struct kobject * p;
--length;
for (p = kobj; p; p = p->parent) {
int cur = strlen(kobject_name(p));
for (; sd->s_parent; sd = sd->s_parent) {
int cur = strlen(sd->s_name);
/* back up enough to print this bus id with '/' */
length -= cur;
strncpy(buffer + length,kobject_name(p),cur);
strncpy(buffer + length, sd->s_name, cur);
*(buffer + --length) = '/';
}
}
static int sysfs_add_link(struct dentry * parent, const char * name, struct kobject * target)
{
struct sysfs_dirent * parent_sd = parent->d_fsdata;
struct sysfs_symlink * sl;
int error = 0;
error = -ENOMEM;
sl = kmalloc(sizeof(*sl), GFP_KERNEL);
if (!sl)
goto exit1;
sl->link_name = kmalloc(strlen(name) + 1, GFP_KERNEL);
if (!sl->link_name)
goto exit2;
strcpy(sl->link_name, name);
sl->target_kobj = kobject_get(target);
error = sysfs_make_dirent(parent_sd, NULL, sl, S_IFLNK|S_IRWXUGO,
SYSFS_KOBJ_LINK);
if (!error)
return 0;
kobject_put(target);
kfree(sl->link_name);
exit2:
kfree(sl);
exit1:
return error;
}
/**
* sysfs_create_link - create symlink between two objects.
* @kobj: object whose directory we're creating the link in.
@ -84,24 +52,57 @@ exit1:
*/
int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name)
{
struct dentry *dentry = NULL;
int error = -EEXIST;
struct sysfs_dirent *parent_sd = NULL;
struct sysfs_dirent *target_sd = NULL;
struct sysfs_dirent *sd = NULL;
struct sysfs_addrm_cxt acxt;
int error;
BUG_ON(!name);
if (!kobj) {
if (sysfs_mount && sysfs_mount->mnt_sb)
dentry = sysfs_mount->mnt_sb->s_root;
parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata;
} else
dentry = kobj->dentry;
parent_sd = kobj->sd;
if (!dentry)
return -EFAULT;
error = -EFAULT;
if (!parent_sd)
goto out_put;
mutex_lock(&dentry->d_inode->i_mutex);
if (!sysfs_dirent_exist(dentry->d_fsdata, name))
error = sysfs_add_link(dentry, name, target);
mutex_unlock(&dentry->d_inode->i_mutex);
/* target->sd can go away beneath us but is protected with
* sysfs_assoc_lock. Fetch target_sd from it.
*/
spin_lock(&sysfs_assoc_lock);
if (target->sd)
target_sd = sysfs_get(target->sd);
spin_unlock(&sysfs_assoc_lock);
error = -ENOENT;
if (!target_sd)
goto out_put;
error = -ENOMEM;
sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK);
if (!sd)
goto out_put;
sd->s_elem.symlink.target_sd = target_sd;
sysfs_addrm_start(&acxt, parent_sd);
if (!sysfs_find_dirent(parent_sd, name)) {
sysfs_add_one(&acxt, sd);
sysfs_link_sibling(sd);
}
if (sysfs_addrm_finish(&acxt))
return 0;
error = -EEXIST;
/* fall through */
out_put:
sysfs_put(target_sd);
sysfs_put(sd);
return error;
}
@ -114,17 +115,17 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
void sysfs_remove_link(struct kobject * kobj, const char * name)
{
sysfs_hash_and_remove(kobj->dentry,name);
sysfs_hash_and_remove(kobj->sd, name);
}
static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target,
char *path)
static int sysfs_get_target_path(struct sysfs_dirent * parent_sd,
struct sysfs_dirent * target_sd, char *path)
{
char * s;
int depth, size;
depth = object_depth(kobj);
size = object_path_length(target) + depth * 3 - 1;
depth = object_depth(parent_sd);
size = object_path_length(target_sd) + depth * 3 - 1;
if (size > PATH_MAX)
return -ENAMETOOLONG;
@ -133,7 +134,7 @@ static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target,
for (s = path; depth--; s += 3)
strcpy(s,"../");
fill_object_path(target, path, size);
fill_object_path(target_sd, path, size);
pr_debug("%s: path = '%s'\n", __FUNCTION__, path);
return 0;
@ -141,27 +142,16 @@ static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target,
static int sysfs_getlink(struct dentry *dentry, char * path)
{
struct kobject *kobj, *target_kobj;
int error = 0;
struct sysfs_dirent *sd = dentry->d_fsdata;
struct sysfs_dirent *parent_sd = sd->s_parent;
struct sysfs_dirent *target_sd = sd->s_elem.symlink.target_sd;
int error;
kobj = sysfs_get_kobject(dentry->d_parent);
if (!kobj)
return -EINVAL;
mutex_lock(&sysfs_mutex);
error = sysfs_get_target_path(parent_sd, target_sd, path);
mutex_unlock(&sysfs_mutex);
target_kobj = sysfs_get_kobject(dentry);
if (!target_kobj) {
kobject_put(kobj);
return -EINVAL;
}
down_read(&sysfs_rename_sem);
error = sysfs_get_target_path(kobj, target_kobj, path);
up_read(&sysfs_rename_sem);
kobject_put(kobj);
kobject_put(target_kobj);
return error;
}
static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)

View file

@ -1,9 +1,40 @@
struct sysfs_elem_dir {
struct kobject * kobj;
};
struct sysfs_elem_symlink {
struct sysfs_dirent * target_sd;
};
struct sysfs_elem_attr {
struct attribute * attr;
};
struct sysfs_elem_bin_attr {
struct bin_attribute * bin_attr;
};
/*
* As long as s_count reference is held, the sysfs_dirent itself is
* accessible. Dereferencing s_elem or any other outer entity
* requires s_active reference.
*/
struct sysfs_dirent {
atomic_t s_count;
struct list_head s_sibling;
struct list_head s_children;
void * s_element;
int s_type;
atomic_t s_active;
struct sysfs_dirent * s_parent;
struct sysfs_dirent * s_sibling;
struct sysfs_dirent * s_children;
const char * s_name;
union {
struct sysfs_elem_dir dir;
struct sysfs_elem_symlink symlink;
struct sysfs_elem_attr attr;
struct sysfs_elem_bin_attr bin_attr;
} s_elem;
unsigned int s_flags;
umode_t s_mode;
ino_t s_ino;
struct dentry * s_dentry;
@ -11,30 +42,60 @@ struct sysfs_dirent {
atomic_t s_event;
};
#define SD_DEACTIVATED_BIAS INT_MIN
struct sysfs_addrm_cxt {
struct sysfs_dirent *parent_sd;
struct inode *parent_inode;
struct sysfs_dirent *removed;
int cnt;
};
extern struct vfsmount * sysfs_mount;
extern struct sysfs_dirent sysfs_root;
extern struct kmem_cache *sysfs_dir_cachep;
extern struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd);
extern void sysfs_link_sibling(struct sysfs_dirent *sd);
extern void sysfs_unlink_sibling(struct sysfs_dirent *sd);
extern struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd);
extern void sysfs_put_active(struct sysfs_dirent *sd);
extern struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd);
extern void sysfs_put_active_two(struct sysfs_dirent *sd);
extern void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
struct sysfs_dirent *parent_sd);
extern void sysfs_add_one(struct sysfs_addrm_cxt *acxt,
struct sysfs_dirent *sd);
extern void sysfs_remove_one(struct sysfs_addrm_cxt *acxt,
struct sysfs_dirent *sd);
extern int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
extern void sysfs_delete_inode(struct inode *inode);
extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
extern void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode);
extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd);
extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode);
extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *);
extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
umode_t, int);
extern void release_sysfs_dirent(struct sysfs_dirent * sd);
extern struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
const unsigned char *name);
extern struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
const unsigned char *name);
extern struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode,
int type);
extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
extern int sysfs_hash_and_remove(struct dentry * dir, const char * name);
extern int sysfs_add_file(struct sysfs_dirent *dir_sd,
const struct attribute *attr, int type);
extern int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name);
extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **);
extern void sysfs_remove_subdir(struct dentry *);
extern int sysfs_create_subdir(struct kobject *kobj, const char *name,
struct sysfs_dirent **p_sd);
extern void sysfs_remove_subdir(struct sysfs_dirent *sd);
extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd);
extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent);
extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
extern spinlock_t sysfs_lock;
extern struct rw_semaphore sysfs_rename_sem;
extern spinlock_t sysfs_assoc_lock;
extern struct mutex sysfs_mutex;
extern struct super_block * sysfs_sb;
extern const struct file_operations sysfs_dir_operations;
extern const struct file_operations sysfs_file_operations;
@ -42,73 +103,9 @@ extern const struct file_operations bin_fops;
extern const struct inode_operations sysfs_dir_inode_operations;
extern const struct inode_operations sysfs_symlink_inode_operations;
struct sysfs_symlink {
char * link_name;
struct kobject * target_kobj;
};
struct sysfs_buffer {
struct list_head associates;
size_t count;
loff_t pos;
char * page;
struct sysfs_ops * ops;
struct semaphore sem;
int orphaned;
int needs_read_fill;
int event;
};
struct sysfs_buffer_collection {
struct list_head associates;
};
static inline struct kobject * to_kobj(struct dentry * dentry)
static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
{
struct sysfs_dirent * sd = dentry->d_fsdata;
return ((struct kobject *) sd->s_element);
}
static inline struct attribute * to_attr(struct dentry * dentry)
{
struct sysfs_dirent * sd = dentry->d_fsdata;
return ((struct attribute *) sd->s_element);
}
static inline struct bin_attribute * to_bin_attr(struct dentry * dentry)
{
struct sysfs_dirent * sd = dentry->d_fsdata;
return ((struct bin_attribute *) sd->s_element);
}
static inline struct kobject *sysfs_get_kobject(struct dentry *dentry)
{
struct kobject * kobj = NULL;
spin_lock(&dcache_lock);
if (!d_unhashed(dentry)) {
struct sysfs_dirent * sd = dentry->d_fsdata;
if (sd->s_type & SYSFS_KOBJ_LINK) {
struct sysfs_symlink * sl = sd->s_element;
kobj = kobject_get(sl->target_kobj);
} else
kobj = kobject_get(sd->s_element);
}
spin_unlock(&dcache_lock);
return kobj;
}
static inline void release_sysfs_dirent(struct sysfs_dirent * sd)
{
if (sd->s_type & SYSFS_KOBJ_LINK) {
struct sysfs_symlink * sl = sd->s_element;
kfree(sl->link_name);
kobject_put(sl->target_kobj);
kfree(sl);
}
kfree(sd->s_iattr);
kmem_cache_free(sysfs_dir_cachep, sd);
return sd->s_flags & SYSFS_TYPE_MASK;
}
static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd)
@ -122,7 +119,7 @@ static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd)
static inline void sysfs_put(struct sysfs_dirent * sd)
{
if (atomic_dec_and_test(&sd->s_count))
if (sd && atomic_dec_and_test(&sd->s_count))
release_sysfs_dirent(sd);
}

View file

@ -38,6 +38,9 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
void debugfs_remove(struct dentry *dentry);
struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
struct dentry *new_dir, const char *new_name);
struct dentry *debugfs_create_u8(const char *name, mode_t mode,
struct dentry *parent, u8 *value);
struct dentry *debugfs_create_u16(const char *name, mode_t mode,
@ -85,6 +88,12 @@ static inline struct dentry *debugfs_create_symlink(const char *name,
static inline void debugfs_remove(struct dentry *dentry)
{ }
static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
struct dentry *new_dir, char *new_name)
{
return ERR_PTR(-ENODEV);
}
static inline struct dentry *debugfs_create_u8(const char *name, mode_t mode,
struct dentry *parent,
u8 *value)

View file

@ -238,7 +238,6 @@ extern int __must_check class_device_create_file(struct class_device *,
* @devt: for internal use by the driver core only.
* @node: for internal use by the driver core only.
* @kobj: for internal use by the driver core only.
* @devt_attr: for internal use by the driver core only.
* @groups: optional additional groups to be created
* @dev: if set, a symlink to the struct device is created in the sysfs
* directory for this struct class device.
@ -263,8 +262,6 @@ struct class_device {
struct kobject kobj;
struct class * class; /* required */
dev_t devt; /* dev_t, creates the sysfs "dev" */
struct class_device_attribute *devt_attr;
struct class_device_attribute uevent_attr;
struct device * dev; /* not necessary, but nice to have */
void * class_data; /* class-specific data */
struct class_device *parent; /* parent of this child device, if there is one */
@ -419,8 +416,6 @@ struct device {
struct device_type *type;
unsigned is_registered:1;
unsigned uevent_suppress:1;
struct device_attribute uevent_attr;
struct device_attribute *devt_attr;
struct semaphore sem; /* semaphore to synchronize calls to
* its driver.

View file

@ -12,9 +12,17 @@ enum dmi_field {
DMI_PRODUCT_NAME,
DMI_PRODUCT_VERSION,
DMI_PRODUCT_SERIAL,
DMI_PRODUCT_UUID,
DMI_BOARD_VENDOR,
DMI_BOARD_NAME,
DMI_BOARD_VERSION,
DMI_BOARD_SERIAL,
DMI_BOARD_ASSET_TAG,
DMI_CHASSIS_VENDOR,
DMI_CHASSIS_TYPE,
DMI_CHASSIS_VERSION,
DMI_CHASSIS_SERIAL,
DMI_CHASSIS_ASSET_TAG,
DMI_STRING_MAX,
};

View file

@ -83,4 +83,33 @@ void idr_remove(struct idr *idp, int id);
void idr_destroy(struct idr *idp);
void idr_init(struct idr *idp);
/*
* IDA - IDR based id allocator, use when translation from id to
* pointer isn't necessary.
*/
#define IDA_CHUNK_SIZE 128 /* 128 bytes per chunk */
#define IDA_BITMAP_LONGS (128 / sizeof(long) - 1)
#define IDA_BITMAP_BITS (IDA_BITMAP_LONGS * sizeof(long) * 8)
struct ida_bitmap {
long nr_busy;
unsigned long bitmap[IDA_BITMAP_LONGS];
};
struct ida {
struct idr idr;
struct ida_bitmap *free_bitmap;
};
#define IDA_INIT(name) { .idr = IDR_INIT(name), .free_bitmap = NULL, }
#define DEFINE_IDA(name) struct ida name = IDA_INIT(name)
int ida_pre_get(struct ida *ida, gfp_t gfp_mask);
int ida_get_new_above(struct ida *ida, int starting_id, int *p_id);
int ida_get_new(struct ida *ida, int *p_id);
void ida_remove(struct ida *ida, int id);
void ida_destroy(struct ida *ida);
void ida_init(struct ida *ida);
#endif /* __IDR_H__ */

View file

@ -55,7 +55,7 @@ struct kobject {
struct kobject * parent;
struct kset * kset;
struct kobj_type * ktype;
struct dentry * dentry;
struct sysfs_dirent * sd;
wait_queue_head_t poll;
};
@ -71,13 +71,14 @@ extern void kobject_init(struct kobject *);
extern void kobject_cleanup(struct kobject *);
extern int __must_check kobject_add(struct kobject *);
extern int __must_check kobject_shadow_add(struct kobject *, struct dentry *);
extern int __must_check kobject_shadow_add(struct kobject *kobj,
struct sysfs_dirent *shadow_parent);
extern void kobject_del(struct kobject *);
extern int __must_check kobject_rename(struct kobject *, const char *new_name);
extern int __must_check kobject_shadow_rename(struct kobject *kobj,
struct dentry *new_parent,
const char *new_name);
struct sysfs_dirent *new_parent,
const char *new_name);
extern int __must_check kobject_move(struct kobject *, struct kobject *);
extern int __must_check kobject_register(struct kobject *);

View file

@ -267,15 +267,10 @@ struct dev_pm_info {
unsigned can_wakeup:1;
#ifdef CONFIG_PM
unsigned should_wakeup:1;
pm_message_t prev_state;
void * saved_state;
struct device * pm_parent;
struct list_head entry;
#endif
};
extern void device_pm_set_parent(struct device * dev, struct device * parent);
extern int device_power_down(pm_message_t state);
extern void device_power_up(void);
extern void device_resume(void);

View file

@ -101,8 +101,7 @@ struct sysdev_attribute {
#define _SYSDEV_ATTR(_name,_mode,_show,_store) \
{ \
.attr = { .name = __stringify(_name), .mode = _mode, \
.owner = THIS_MODULE }, \
.attr = { .name = __stringify(_name), .mode = _mode }, \
.show = _show, \
.store = _store, \
}

View file

@ -19,10 +19,15 @@ struct kobject;
struct module;
struct nameidata;
struct dentry;
struct sysfs_dirent;
/* FIXME
* The *owner field is no longer used, but leave around
* until the tree gets cleaned up fully.
*/
struct attribute {
const char * name;
struct module * owner;
struct module * owner;
mode_t mode;
};
@ -39,14 +44,14 @@ struct attribute_group {
*/
#define __ATTR(_name,_mode,_show,_store) { \
.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
.attr = {.name = __stringify(_name), .mode = _mode }, \
.show = _show, \
.store = _store, \
}
#define __ATTR_RO(_name) { \
.attr = { .name = __stringify(_name), .mode = 0444, .owner = THIS_MODULE }, \
.show = _name##_show, \
.attr = { .name = __stringify(_name), .mode = 0444 }, \
.show = _name##_show, \
}
#define __ATTR_NULL { .attr = { .name = NULL } }
@ -59,8 +64,10 @@ struct bin_attribute {
struct attribute attr;
size_t size;
void *private;
ssize_t (*read)(struct kobject *, char *, loff_t, size_t);
ssize_t (*write)(struct kobject *, char *, loff_t, size_t);
ssize_t (*read)(struct kobject *, struct bin_attribute *,
char *, loff_t, size_t);
ssize_t (*write)(struct kobject *, struct bin_attribute *,
char *, loff_t, size_t);
int (*mmap)(struct kobject *, struct bin_attribute *attr,
struct vm_area_struct *vma);
};
@ -70,12 +77,16 @@ struct sysfs_ops {
ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
};
#define SYSFS_TYPE_MASK 0x00ff
#define SYSFS_ROOT 0x0001
#define SYSFS_DIR 0x0002
#define SYSFS_KOBJ_ATTR 0x0004
#define SYSFS_KOBJ_BIN_ATTR 0x0008
#define SYSFS_KOBJ_LINK 0x0020
#define SYSFS_NOT_PINNED (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | SYSFS_KOBJ_LINK)
#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK)
#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK
#define SYSFS_FLAG_REMOVED 0x0100
#ifdef CONFIG_SYSFS
@ -83,13 +94,14 @@ extern int sysfs_schedule_callback(struct kobject *kobj,
void (*func)(void *), void *data, struct module *owner);
extern int __must_check
sysfs_create_dir(struct kobject *, struct dentry *);
sysfs_create_dir(struct kobject *kobj, struct sysfs_dirent *shadow_parent_sd);
extern void
sysfs_remove_dir(struct kobject *);
extern int __must_check
sysfs_rename_dir(struct kobject *, struct dentry *, const char *new_name);
sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd,
const char *new_name);
extern int __must_check
sysfs_move_dir(struct kobject *, struct kobject *);
@ -129,8 +141,8 @@ void sysfs_notify(struct kobject * k, char *dir, char *attr);
extern int sysfs_make_shadowed_dir(struct kobject *kobj,
void * (*follow_link)(struct dentry *, struct nameidata *));
extern struct dentry *sysfs_create_shadow_dir(struct kobject *kobj);
extern void sysfs_remove_shadow_dir(struct dentry *dir);
extern struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj);
extern void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd);
extern int __must_check sysfs_init(void);
@ -142,7 +154,8 @@ static inline int sysfs_schedule_callback(struct kobject *kobj,
return -ENOSYS;
}
static inline int sysfs_create_dir(struct kobject * k, struct dentry *shadow)
static inline int sysfs_create_dir(struct kobject *kobj,
struct sysfs_dirent *shadow_parent_sd)
{
return 0;
}
@ -152,9 +165,9 @@ static inline void sysfs_remove_dir(struct kobject * k)
;
}
static inline int sysfs_rename_dir(struct kobject * k,
struct dentry *new_parent,
const char *new_name)
static inline int sysfs_rename_dir(struct kobject *kobj,
struct sysfs_dirent *new_parent_sd,
const char *new_name)
{
return 0;
}

View file

@ -488,8 +488,7 @@ static void free_modinfo_##field(struct module *mod) \
mod->field = NULL; \
} \
static struct module_attribute modinfo_##field = { \
.attr = { .name = __stringify(field), .mode = 0444, \
.owner = THIS_MODULE }, \
.attr = { .name = __stringify(field), .mode = 0444 }, \
.show = show_modinfo_##field, \
.setup = setup_modinfo_##field, \
.test = modinfo_##field##_exists, \
@ -793,7 +792,7 @@ static ssize_t show_refcnt(struct module_attribute *mattr,
}
static struct module_attribute refcnt = {
.attr = { .name = "refcnt", .mode = 0444, .owner = THIS_MODULE },
.attr = { .name = "refcnt", .mode = 0444 },
.show = show_refcnt,
};
@ -851,7 +850,7 @@ static ssize_t show_initstate(struct module_attribute *mattr,
}
static struct module_attribute initstate = {
.attr = { .name = "initstate", .mode = 0444, .owner = THIS_MODULE },
.attr = { .name = "initstate", .mode = 0444 },
.show = show_initstate,
};
@ -1032,7 +1031,6 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect,
sattr->mattr.show = module_sect_show;
sattr->mattr.store = NULL;
sattr->mattr.attr.name = sattr->name;
sattr->mattr.attr.owner = mod;
sattr->mattr.attr.mode = S_IRUGO;
*(gattr++) = &(sattr++)->mattr.attr;
}
@ -1090,7 +1088,6 @@ int module_add_modinfo_attrs(struct module *mod)
if (!attr->test ||
(attr->test && attr->test(mod))) {
memcpy(temp_attr, attr, sizeof(*temp_attr));
temp_attr->attr.owner = mod;
error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr);
++temp_attr;
}

View file

@ -491,7 +491,6 @@ param_sysfs_setup(struct module_kobject *mk,
pattr->mattr.show = param_attr_show;
pattr->mattr.store = param_attr_store;
pattr->mattr.attr.name = (char *)&kp->name[name_skip];
pattr->mattr.attr.owner = mk->mod;
pattr->mattr.attr.mode = kp->perm;
*(gattr++) = &(pattr++)->mattr.attr;
}

332
lib/idr.c
View file

@ -70,6 +70,26 @@ static void free_layer(struct idr *idp, struct idr_layer *p)
spin_unlock_irqrestore(&idp->lock, flags);
}
static void idr_mark_full(struct idr_layer **pa, int id)
{
struct idr_layer *p = pa[0];
int l = 0;
__set_bit(id & IDR_MASK, &p->bitmap);
/*
* If this layer is full mark the bit in the layer above to
* show that this part of the radix tree is full. This may
* complete the layer above and require walking up the radix
* tree.
*/
while (p->bitmap == IDR_FULL) {
if (!(p = pa[++l]))
break;
id = id >> IDR_BITS;
__set_bit((id & IDR_MASK), &p->bitmap);
}
}
/**
* idr_pre_get - reserver resources for idr allocation
* @idp: idr handle
@ -95,15 +115,15 @@ int idr_pre_get(struct idr *idp, gfp_t gfp_mask)
}
EXPORT_SYMBOL(idr_pre_get);
static int sub_alloc(struct idr *idp, void *ptr, int *starting_id)
static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)
{
int n, m, sh;
struct idr_layer *p, *new;
struct idr_layer *pa[MAX_LEVEL];
int l, id;
int l, id, oid;
long bm;
id = *starting_id;
restart:
p = idp->top;
l = idp->layers;
pa[l--] = NULL;
@ -117,12 +137,23 @@ static int sub_alloc(struct idr *idp, void *ptr, int *starting_id)
if (m == IDR_SIZE) {
/* no space available go back to previous layer. */
l++;
oid = id;
id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1;
/* if already at the top layer, we need to grow */
if (!(p = pa[l])) {
*starting_id = id;
return -2;
}
continue;
/* If we need to go up one layer, continue the
* loop; otherwise, restart from the top.
*/
sh = IDR_BITS * (l + 1);
if (oid >> sh == id >> sh)
continue;
else
goto restart;
}
if (m != n) {
sh = IDR_BITS*l;
@ -144,30 +175,13 @@ static int sub_alloc(struct idr *idp, void *ptr, int *starting_id)
pa[l--] = p;
p = p->ary[m];
}
/*
* We have reached the leaf node, plant the
* users pointer and return the raw id.
*/
p->ary[m] = (struct idr_layer *)ptr;
__set_bit(m, &p->bitmap);
p->count++;
/*
* If this layer is full mark the bit in the layer above
* to show that this part of the radix tree is full.
* This may complete the layer above and require walking
* up the radix tree.
*/
n = id;
while (p->bitmap == IDR_FULL) {
if (!(p = pa[++l]))
break;
n = n >> IDR_BITS;
__set_bit((n & IDR_MASK), &p->bitmap);
}
return(id);
pa[l] = p;
return id;
}
static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
static int idr_get_empty_slot(struct idr *idp, int starting_id,
struct idr_layer **pa)
{
struct idr_layer *p, *new;
int layers, v, id;
@ -213,12 +227,31 @@ build_up:
}
idp->top = p;
idp->layers = layers;
v = sub_alloc(idp, ptr, &id);
v = sub_alloc(idp, &id, pa);
if (v == -2)
goto build_up;
return(v);
}
static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
{
struct idr_layer *pa[MAX_LEVEL];
int id;
id = idr_get_empty_slot(idp, starting_id, pa);
if (id >= 0) {
/*
* Successfully found an empty slot. Install the user
* pointer and mark the slot full.
*/
pa[0]->ary[id & IDR_MASK] = (struct idr_layer *)ptr;
pa[0]->count++;
idr_mark_full(pa, id);
}
return id;
}
/**
* idr_get_new_above - allocate new idr entry above or equal to a start id
* @idp: idr handle
@ -473,3 +506,248 @@ void idr_init(struct idr *idp)
spin_lock_init(&idp->lock);
}
EXPORT_SYMBOL(idr_init);
/*
* IDA - IDR based ID allocator
*
* this is id allocator without id -> pointer translation. Memory
* usage is much lower than full blown idr because each id only
* occupies a bit. ida uses a custom leaf node which contains
* IDA_BITMAP_BITS slots.
*
* 2007-04-25 written by Tejun Heo <htejun@gmail.com>
*/
static void free_bitmap(struct ida *ida, struct ida_bitmap *bitmap)
{
unsigned long flags;
if (!ida->free_bitmap) {
spin_lock_irqsave(&ida->idr.lock, flags);
if (!ida->free_bitmap) {
ida->free_bitmap = bitmap;
bitmap = NULL;
}
spin_unlock_irqrestore(&ida->idr.lock, flags);
}
kfree(bitmap);
}
/**
* ida_pre_get - reserve resources for ida allocation
* @ida: ida handle
* @gfp_mask: memory allocation flag
*
* This function should be called prior to locking and calling the
* following function. It preallocates enough memory to satisfy the
* worst possible allocation.
*
* If the system is REALLY out of memory this function returns 0,
* otherwise 1.
*/
int ida_pre_get(struct ida *ida, gfp_t gfp_mask)
{
/* allocate idr_layers */
if (!idr_pre_get(&ida->idr, gfp_mask))
return 0;
/* allocate free_bitmap */
if (!ida->free_bitmap) {
struct ida_bitmap *bitmap;
bitmap = kmalloc(sizeof(struct ida_bitmap), gfp_mask);
if (!bitmap)
return 0;
free_bitmap(ida, bitmap);
}
return 1;
}
EXPORT_SYMBOL(ida_pre_get);
/**
* ida_get_new_above - allocate new ID above or equal to a start id
* @ida: ida handle
* @staring_id: id to start search at
* @p_id: pointer to the allocated handle
*
* Allocate new ID above or equal to @ida. It should be called with
* any required locks.
*
* If memory is required, it will return -EAGAIN, you should unlock
* and go back to the ida_pre_get() call. If the ida is full, it will
* return -ENOSPC.
*
* @p_id returns a value in the range 0 ... 0x7fffffff.
*/
int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
{
struct idr_layer *pa[MAX_LEVEL];
struct ida_bitmap *bitmap;
unsigned long flags;
int idr_id = starting_id / IDA_BITMAP_BITS;
int offset = starting_id % IDA_BITMAP_BITS;
int t, id;
restart:
/* get vacant slot */
t = idr_get_empty_slot(&ida->idr, idr_id, pa);
if (t < 0) {
if (t == -1)
return -EAGAIN;
else /* will be -3 */
return -ENOSPC;
}
if (t * IDA_BITMAP_BITS >= MAX_ID_BIT)
return -ENOSPC;
if (t != idr_id)
offset = 0;
idr_id = t;
/* if bitmap isn't there, create a new one */
bitmap = (void *)pa[0]->ary[idr_id & IDR_MASK];
if (!bitmap) {
spin_lock_irqsave(&ida->idr.lock, flags);
bitmap = ida->free_bitmap;
ida->free_bitmap = NULL;
spin_unlock_irqrestore(&ida->idr.lock, flags);
if (!bitmap)
return -EAGAIN;
memset(bitmap, 0, sizeof(struct ida_bitmap));
pa[0]->ary[idr_id & IDR_MASK] = (void *)bitmap;
pa[0]->count++;
}
/* lookup for empty slot */
t = find_next_zero_bit(bitmap->bitmap, IDA_BITMAP_BITS, offset);
if (t == IDA_BITMAP_BITS) {
/* no empty slot after offset, continue to the next chunk */
idr_id++;
offset = 0;
goto restart;
}
id = idr_id * IDA_BITMAP_BITS + t;
if (id >= MAX_ID_BIT)
return -ENOSPC;
__set_bit(t, bitmap->bitmap);
if (++bitmap->nr_busy == IDA_BITMAP_BITS)
idr_mark_full(pa, idr_id);
*p_id = id;
/* Each leaf node can handle nearly a thousand slots and the
* whole idea of ida is to have small memory foot print.
* Throw away extra resources one by one after each successful
* allocation.
*/
if (ida->idr.id_free_cnt || ida->free_bitmap) {
struct idr_layer *p = alloc_layer(&ida->idr);
if (p)
kmem_cache_free(idr_layer_cache, p);
}
return 0;
}
EXPORT_SYMBOL(ida_get_new_above);
/**
* ida_get_new - allocate new ID
* @ida: idr handle
* @p_id: pointer to the allocated handle
*
* Allocate new ID. It should be called with any required locks.
*
* If memory is required, it will return -EAGAIN, you should unlock
* and go back to the idr_pre_get() call. If the idr is full, it will
* return -ENOSPC.
*
* @id returns a value in the range 0 ... 0x7fffffff.
*/
int ida_get_new(struct ida *ida, int *p_id)
{
return ida_get_new_above(ida, 0, p_id);
}
EXPORT_SYMBOL(ida_get_new);
/**
* ida_remove - remove the given ID
* @ida: ida handle
* @id: ID to free
*/
void ida_remove(struct ida *ida, int id)
{
struct idr_layer *p = ida->idr.top;
int shift = (ida->idr.layers - 1) * IDR_BITS;
int idr_id = id / IDA_BITMAP_BITS;
int offset = id % IDA_BITMAP_BITS;
int n;
struct ida_bitmap *bitmap;
/* clear full bits while looking up the leaf idr_layer */
while ((shift > 0) && p) {
n = (idr_id >> shift) & IDR_MASK;
__clear_bit(n, &p->bitmap);
p = p->ary[n];
shift -= IDR_BITS;
}
if (p == NULL)
goto err;
n = idr_id & IDR_MASK;
__clear_bit(n, &p->bitmap);
bitmap = (void *)p->ary[n];
if (!test_bit(offset, bitmap->bitmap))
goto err;
/* update bitmap and remove it if empty */
__clear_bit(offset, bitmap->bitmap);
if (--bitmap->nr_busy == 0) {
__set_bit(n, &p->bitmap); /* to please idr_remove() */
idr_remove(&ida->idr, idr_id);
free_bitmap(ida, bitmap);
}
return;
err:
printk(KERN_WARNING
"ida_remove called for id=%d which is not allocated.\n", id);
}
EXPORT_SYMBOL(ida_remove);
/**
* ida_destroy - release all cached layers within an ida tree
* ida: ida handle
*/
void ida_destroy(struct ida *ida)
{
idr_destroy(&ida->idr);
kfree(ida->free_bitmap);
}
EXPORT_SYMBOL(ida_destroy);
/**
* ida_init - initialize ida handle
* @ida: ida handle
*
* This function is use to set up the handle (@ida) that you will pass
* to the rest of the functions.
*/
void ida_init(struct ida *ida)
{
memset(ida, 0, sizeof(struct ida));
idr_init(&ida->idr);
}
EXPORT_SYMBOL(ida_init);

View file

@ -44,7 +44,7 @@ static int populate_dir(struct kobject * kobj)
return error;
}
static int create_dir(struct kobject * kobj, struct dentry *shadow_parent)
static int create_dir(struct kobject *kobj, struct sysfs_dirent *shadow_parent)
{
int error = 0;
if (kobject_name(kobj)) {
@ -162,7 +162,7 @@ static void unlink(struct kobject * kobj)
* @shadow_parent: sysfs directory to add to.
*/
int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent)
{
int error = 0;
struct kobject * parent;
@ -338,7 +338,7 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
/* Note : if we want to send the new name alone, not the full path,
* we could probably use kobject_name(kobj); */
error = sysfs_rename_dir(kobj, kobj->parent->dentry, new_name);
error = sysfs_rename_dir(kobj, kobj->parent->sd, new_name);
/* This function is mostly/only used for network interface.
* Some hotplug package track interfaces by their name and
@ -361,8 +361,8 @@ out:
* @new_name: object's new name
*/
int kobject_shadow_rename(struct kobject * kobj, struct dentry *new_parent,
const char *new_name)
int kobject_shadow_rename(struct kobject *kobj,
struct sysfs_dirent *new_parent, const char *new_name)
{
int error = 0;
@ -597,10 +597,17 @@ int kset_add(struct kset * k)
int kset_register(struct kset * k)
{
int err;
if (!k)
return -EINVAL;
kset_init(k);
return kset_add(k);
err = kset_add(k);
if (err)
return err;
kobject_uevent(&k->kobj, KOBJ_ADD);
return 0;
}

View file

@ -360,8 +360,9 @@ static struct attribute_group bridge_group = {
*
* Returns the number of bytes read.
*/
static ssize_t brforward_read(struct kobject *kobj, char *buf,
loff_t off, size_t count)
static ssize_t brforward_read(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct device *dev = to_dev(kobj);
struct net_bridge *br = to_bridge(dev);
@ -383,8 +384,7 @@ static ssize_t brforward_read(struct kobject *kobj, char *buf,
static struct bin_attribute bridge_forward = {
.attr = { .name = SYSFS_BRIDGE_FDB,
.mode = S_IRUGO,
.owner = THIS_MODULE, },
.mode = S_IRUGO, },
.read = brforward_read,
};

View file

@ -29,8 +29,7 @@ struct brport_attribute {
#define BRPORT_ATTR(_name,_mode,_show,_store) \
struct brport_attribute brport_attr_##_name = { \
.attr = {.name = __stringify(_name), \
.mode = _mode, \
.owner = THIS_MODULE, }, \
.mode = _mode }, \
.show = _show, \
.store = _store, \
};