Commit 754a264c authored by Linus Torvalds's avatar Linus Torvalds

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: (158 commits)
  commit 4f705ae3
  Author: Bjorn Helgaas <bjorn.helgaas@hp.com>
  Date:   Mon Apr 3 17:09:22 2006 -0700
  
      [PATCH] DMI: move dmi_scan.c from arch/i386 to drivers/firmware/
      
      dmi_scan.c is arch-independent and is used by i386, x86_64, and ia64.
      Currently all three arches compile it from arch/i386, which means that ia64
      and x86_64 depend on things in arch/i386 that they wouldn't otherwise care
      about.
      
      This is simply "mv arch/i386/kernel/dmi_scan.c drivers/firmware/" (removing
      trailing whitespace) and the associated Makefile changes.  All three
      architectures already set CONFIG_DMI in their top-level Kconfig files.
Signed-off-by: default avatarBjorn Helgaas <bjorn.helgaas@hp.com>
      Cc: Andi Kleen <ak@muc.de>
      Cc: "Luck, Tony" <tony.luck@intel.com>
      Cc: Andrey Panin <pazke@orbita1.ru>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
  ...
parents f9814802 4f705ae3
...@@ -6,7 +6,7 @@ extra-y := head.o init_task.o vmlinux.lds ...@@ -6,7 +6,7 @@ extra-y := head.o init_task.o vmlinux.lds
obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \
ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \ ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \
pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \ pci-dma.o i386_ksyms.o i387.o bootflag.o \
quirks.o i8237.o topology.o alternative.o quirks.o i8237.o topology.o alternative.o
obj-y += cpu/ obj-y += cpu/
......
...@@ -7,7 +7,7 @@ extra-y := head.o init_task.o vmlinux.lds ...@@ -7,7 +7,7 @@ extra-y := head.o init_task.o vmlinux.lds
obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \ obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \
irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o \ irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o \
salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \ salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \
unwind.o mca.o mca_asm.o topology.o dmi_scan.o unwind.o mca.o mca_asm.o topology.o
obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o
obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o
...@@ -30,7 +30,6 @@ obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o ...@@ -30,7 +30,6 @@ obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
mca_recovery-y += mca_drv.o mca_drv_asm.o mca_recovery-y += mca_drv.o mca_drv_asm.o
dmi_scan-y += ../../i386/kernel/dmi_scan.o
# The gate DSO image is built using a special linker script. # The gate DSO image is built using a special linker script.
targets += gate.so gate-syms.o targets += gate.so gate-syms.o
......
...@@ -8,7 +8,7 @@ obj-y := process.o signal.o entry.o traps.o irq.o \ ...@@ -8,7 +8,7 @@ obj-y := process.o signal.o entry.o traps.o irq.o \
ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \ ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \
x8664_ksyms.o i387.o syscall.o vsyscall.o \ x8664_ksyms.o i387.o syscall.o vsyscall.o \
setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \ setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \
dmi_scan.o pci-dma.o pci-nommu.o pci-dma.o pci-nommu.o
obj-$(CONFIG_X86_MCE) += mce.o obj-$(CONFIG_X86_MCE) += mce.o
obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o
...@@ -49,5 +49,3 @@ intel_cacheinfo-y += ../../i386/kernel/cpu/intel_cacheinfo.o ...@@ -49,5 +49,3 @@ intel_cacheinfo-y += ../../i386/kernel/cpu/intel_cacheinfo.o
quirks-y += ../../i386/kernel/quirks.o quirks-y += ../../i386/kernel/quirks.o
i8237-y += ../../i386/kernel/i8237.o i8237-y += ../../i386/kernel/i8237.o
msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o
dmi_scan-y += ../../i386/kernel/dmi_scan.o
...@@ -188,6 +188,11 @@ static ssize_t driver_bind(struct device_driver *drv, ...@@ -188,6 +188,11 @@ static ssize_t driver_bind(struct device_driver *drv,
up(&dev->sem); up(&dev->sem);
if (dev->parent) if (dev->parent)
up(&dev->parent->sem); up(&dev->parent->sem);
if (err > 0) /* success */
err = count;
else if (err == 0) /* driver didn't accept device */
err = -ENODEV;
} }
put_device(dev); put_device(dev);
put_bus(bus); put_bus(bus);
......
...@@ -562,14 +562,13 @@ int class_device_add(struct class_device *class_dev) ...@@ -562,14 +562,13 @@ int class_device_add(struct class_device *class_dev)
kobject_uevent(&class_dev->kobj, KOBJ_ADD); kobject_uevent(&class_dev->kobj, KOBJ_ADD);
/* notify any interfaces this device is now here */ /* notify any interfaces this device is now here */
if (parent_class) { down(&parent_class->sem);
down(&parent_class->sem); list_add_tail(&class_dev->node, &parent_class->children);
list_add_tail(&class_dev->node, &parent_class->children); list_for_each_entry(class_intf, &parent_class->interfaces, node) {
list_for_each_entry(class_intf, &parent_class->interfaces, node) if (class_intf->add)
if (class_intf->add) class_intf->add(class_dev, class_intf);
class_intf->add(class_dev, class_intf);
up(&parent_class->sem);
} }
up(&parent_class->sem);
register_done: register_done:
if (error) { if (error) {
......
...@@ -209,7 +209,7 @@ static void __device_release_driver(struct device * dev) ...@@ -209,7 +209,7 @@ static void __device_release_driver(struct device * dev)
sysfs_remove_link(&dev->kobj, "driver"); sysfs_remove_link(&dev->kobj, "driver");
klist_remove(&dev->knode_driver); klist_remove(&dev->knode_driver);
if (dev->bus->remove) if (dev->bus && dev->bus->remove)
dev->bus->remove(dev); dev->bus->remove(dev);
else if (drv->remove) else if (drv->remove)
drv->remove(dev); drv->remove(dev);
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include <linux/vt_kern.h> #include <linux/vt_kern.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/kallsyms.h>
#include <linux/pm.h>
#include "../base.h" #include "../base.h"
#include "power.h" #include "power.h"
...@@ -58,6 +60,7 @@ int suspend_device(struct device * dev, pm_message_t state) ...@@ -58,6 +60,7 @@ int suspend_device(struct device * dev, pm_message_t state)
if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) { if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
dev_dbg(dev, "suspending\n"); dev_dbg(dev, "suspending\n");
error = dev->bus->suspend(dev, state); error = dev->bus->suspend(dev, state);
suspend_report_result(dev->bus->suspend, error);
} }
up(&dev->sem); up(&dev->sem);
return error; return error;
...@@ -169,3 +172,12 @@ int device_power_down(pm_message_t state) ...@@ -169,3 +172,12 @@ int device_power_down(pm_message_t state)
EXPORT_SYMBOL_GPL(device_power_down); EXPORT_SYMBOL_GPL(device_power_down);
void __suspend_report_result(const char *function, void *fn, int ret)
{
if (ret) {
printk(KERN_ERR "%s(): ", function);
print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn);
printk("%d\n", ret);
}
}
EXPORT_SYMBOL_GPL(__suspend_report_result);
# #
# Makefile for the linux kernel. # Makefile for the linux kernel.
# #
obj-$(CONFIG_EDD) += edd.o obj-$(CONFIG_DMI) += dmi_scan.o
obj-$(CONFIG_EDD) += edd.o
obj-$(CONFIG_EFI_VARS) += efivars.o obj-$(CONFIG_EFI_VARS) += efivars.o
obj-$(CONFIG_EFI_PCDP) += pcdp.o obj-$(CONFIG_EFI_PCDP) += pcdp.o
obj-$(CONFIG_DELL_RBU) += dell_rbu.o obj-$(CONFIG_DELL_RBU) += dell_rbu.o
......
...@@ -27,7 +27,7 @@ static char * __init dmi_string(struct dmi_header *dm, u8 s) ...@@ -27,7 +27,7 @@ static char * __init dmi_string(struct dmi_header *dm, u8 s)
else else
printk(KERN_ERR "dmi_string: out of memory.\n"); printk(KERN_ERR "dmi_string: out of memory.\n");
} }
} }
return str; return str;
} }
...@@ -41,7 +41,7 @@ static int __init dmi_table(u32 base, int len, int num, ...@@ -41,7 +41,7 @@ static int __init dmi_table(u32 base, int len, int num,
{ {
u8 *buf, *data; u8 *buf, *data;
int i = 0; int i = 0;
buf = dmi_ioremap(base, len); buf = dmi_ioremap(base, len);
if (buf == NULL) if (buf == NULL)
return -1; return -1;
...@@ -49,9 +49,9 @@ static int __init dmi_table(u32 base, int len, int num, ...@@ -49,9 +49,9 @@ static int __init dmi_table(u32 base, int len, int num,
data = buf; data = buf;
/* /*
* Stop when we see all the items the table claimed to have * Stop when we see all the items the table claimed to have
* OR we run off the end of the table (also happens) * OR we run off the end of the table (also happens)
*/ */
while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) { while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) {
struct dmi_header *dm = (struct dmi_header *)data; struct dmi_header *dm = (struct dmi_header *)data;
/* /*
...@@ -75,7 +75,7 @@ static int __init dmi_checksum(u8 *buf) ...@@ -75,7 +75,7 @@ static int __init dmi_checksum(u8 *buf)
{ {
u8 sum = 0; u8 sum = 0;
int a; int a;
for (a = 0; a < 15; a++) for (a = 0; a < 15; a++)
sum += buf[a]; sum += buf[a];
......
...@@ -163,6 +163,7 @@ void md_new_event(mddev_t *mddev) ...@@ -163,6 +163,7 @@ void md_new_event(mddev_t *mddev)
{ {
atomic_inc(&md_event_count); atomic_inc(&md_event_count);
wake_up(&md_event_waiters); wake_up(&md_event_waiters);
sysfs_notify(&mddev->kobj, NULL, "sync_action");
} }
EXPORT_SYMBOL_GPL(md_new_event); EXPORT_SYMBOL_GPL(md_new_event);
......
...@@ -271,10 +271,12 @@ static int pci_device_suspend(struct device * dev, pm_message_t state) ...@@ -271,10 +271,12 @@ static int pci_device_suspend(struct device * dev, pm_message_t state)
struct pci_driver * drv = pci_dev->driver; struct pci_driver * drv = pci_dev->driver;
int i = 0; int i = 0;
if (drv && drv->suspend) if (drv && drv->suspend) {
i = drv->suspend(pci_dev, state); i = drv->suspend(pci_dev, state);
else suspend_report_result(drv->suspend, i);
} else {
pci_save_state(pci_dev); pci_save_state(pci_dev);
}
return i; return i;
} }
......
...@@ -307,9 +307,11 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) ...@@ -307,9 +307,11 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
* Can enter D0 from any state, but if we can only go deeper * Can enter D0 from any state, but if we can only go deeper
* to sleep if we're already in a low power state * to sleep if we're already in a low power state
*/ */
if (state != PCI_D0 && dev->current_state > state) if (state != PCI_D0 && dev->current_state > state) {
printk(KERN_ERR "%s(): %s: state=%d, current state=%d\n",
__FUNCTION__, pci_name(dev), state, dev->current_state);
return -EINVAL; return -EINVAL;
else if (dev->current_state == state) } else if (dev->current_state == state)
return 0; /* we're already there */ return 0; /* we're already there */
/* find PCI PM capability in list */ /* find PCI PM capability in list */
......
...@@ -213,11 +213,9 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) ...@@ -213,11 +213,9 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
if (hcd->driver->suspend) { if (hcd->driver->suspend) {
retval = hcd->driver->suspend(hcd, message); retval = hcd->driver->suspend(hcd, message);
if (retval) { suspend_report_result(hcd->driver->suspend, retval);
dev_dbg (&dev->dev, "PCI pre-suspend fail, %d\n", if (retval)
retval);
goto done; goto done;
}
} }
synchronize_irq(dev->irq); synchronize_irq(dev->irq);
...@@ -263,6 +261,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) ...@@ -263,6 +261,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
* some device state (e.g. as part of clock reinit). * some device state (e.g. as part of clock reinit).
*/ */
retval = pci_set_power_state (dev, PCI_D3hot); retval = pci_set_power_state (dev, PCI_D3hot);
suspend_report_result(pci_set_power_state, retval);
if (retval == 0) { if (retval == 0) {
int wake = device_can_wakeup(&hcd->self.root_hub->dev); int wake = device_can_wakeup(&hcd->self.root_hub->dev);
......
...@@ -331,7 +331,9 @@ void delete_partition(struct gendisk *disk, int part) ...@@ -331,7 +331,9 @@ void delete_partition(struct gendisk *disk, int part)
devfs_remove("%s/part%d", disk->devfs_name, part); devfs_remove("%s/part%d", disk->devfs_name, part);
if (p->holder_dir) if (p->holder_dir)
kobject_unregister(p->holder_dir); kobject_unregister(p->holder_dir);
kobject_unregister(&p->kobj); kobject_uevent(&p->kobj, KOBJ_REMOVE);
kobject_del(&p->kobj);
kobject_put(&p->kobj);
} }
void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len) void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
...@@ -357,7 +359,10 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len) ...@@ -357,7 +359,10 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
snprintf(p->kobj.name,KOBJ_NAME_LEN,"%s%d",disk->kobj.name,part); snprintf(p->kobj.name,KOBJ_NAME_LEN,"%s%d",disk->kobj.name,part);
p->kobj.parent = &disk->kobj; p->kobj.parent = &disk->kobj;
p->kobj.ktype = &ktype_part; p->kobj.ktype = &ktype_part;
kobject_register(&p->kobj); kobject_init(&p->kobj);
kobject_add(&p->kobj);
if (!disk->part_uevent_suppress)
kobject_uevent(&p->kobj, KOBJ_ADD);
partition_sysfs_add_subdir(p); partition_sysfs_add_subdir(p);
disk->part[part-1] = p; disk->part[part-1] = p;
} }
...@@ -395,6 +400,8 @@ void register_disk(struct gendisk *disk) ...@@ -395,6 +400,8 @@ void register_disk(struct gendisk *disk)
{ {
struct block_device *bdev; struct block_device *bdev;
char *s; char *s;
int i;
struct hd_struct *p;
int err; int err;
strlcpy(disk->kobj.name,disk->disk_name,KOBJ_NAME_LEN); strlcpy(disk->kobj.name,disk->disk_name,KOBJ_NAME_LEN);
...@@ -406,13 +413,12 @@ void register_disk(struct gendisk *disk) ...@@ -406,13 +413,12 @@ void register_disk(struct gendisk *disk)
return; return;
disk_sysfs_symlinks(disk); disk_sysfs_symlinks(disk);
disk_sysfs_add_subdirs(disk); disk_sysfs_add_subdirs(disk);
kobject_uevent(&disk->kobj, KOBJ_ADD);
/* No minors to use for partitions */ /* No minors to use for partitions */
if (disk->minors == 1) { if (disk->minors == 1) {
if (disk->devfs_name[0] != '\0') if (disk->devfs_name[0] != '\0')
devfs_add_disk(disk); devfs_add_disk(disk);
return; goto exit;
} }
/* always add handle for the whole disk */ /* always add handle for the whole disk */
...@@ -420,16 +426,32 @@ void register_disk(struct gendisk *disk) ...@@ -420,16 +426,32 @@ void register_disk(struct gendisk *disk)
/* No such device (e.g., media were just removed) */ /* No such device (e.g., media were just removed) */
if (!get_capacity(disk)) if (!get_capacity(disk))
return; goto exit;
bdev = bdget_disk(disk, 0); bdev = bdget_disk(disk, 0);
if (!bdev) if (!bdev)
return; goto exit;
/* scan partition table, but suppress uevents */
bdev->bd_invalidated = 1; bdev->bd_invalidated = 1;
if (blkdev_get(bdev, FMODE_READ, 0) < 0) disk->part_uevent_suppress = 1;
return; err = blkdev_get(bdev, FMODE_READ, 0);
disk->part_uevent_suppress = 0;
if (err < 0)
goto exit;
blkdev_put(bdev); blkdev_put(bdev);
exit:
/* announce disk after possible partitions are already created */
kobject_uevent(&disk->kobj, KOBJ_ADD);
/* announce possible partitions */
for (i = 1; i < disk->minors; i++) {
p = disk->part[i-1];
if (!p || !p->nr_sects)
continue;
kobject_uevent(&p->kobj, KOBJ_ADD);
}
} }
int rescan_partitions(struct gendisk *disk, struct block_device *bdev) int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
......
...@@ -43,6 +43,7 @@ static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * parent_sd, ...@@ -43,6 +43,7 @@ static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * parent_sd,
memset(sd, 0, sizeof(*sd)); memset(sd, 0, sizeof(*sd));
atomic_set(&sd->s_count, 1); atomic_set(&sd->s_count, 1);
atomic_set(&sd->s_event, 0);
INIT_LIST_HEAD(&sd->s_children); INIT_LIST_HEAD(&sd->s_children);
list_add(&sd->s_sibling, &parent_sd->s_children); list_add(&sd->s_sibling, &parent_sd->s_children);
sd->s_element = element; sd->s_element = element;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <linux/fsnotify.h> #include <linux/fsnotify.h>
#include <linux/kobject.h> #include <linux/kobject.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/poll.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
...@@ -57,6 +58,7 @@ struct sysfs_buffer { ...@@ -57,6 +58,7 @@ struct sysfs_buffer {
struct sysfs_ops * ops; struct sysfs_ops * ops;
struct semaphore sem; struct semaphore sem;
int needs_read_fill; int needs_read_fill;
int event;
}; };
...@@ -72,6 +74,7 @@ struct sysfs_buffer { ...@@ -72,6 +74,7 @@ struct sysfs_buffer {
*/ */
static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) 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 attribute * attr = to_attr(dentry);
struct kobject * kobj = to_kobj(dentry->d_parent); struct kobject * kobj = to_kobj(dentry->d_parent);
struct sysfs_ops * ops = buffer->ops; struct sysfs_ops * ops = buffer->ops;
...@@ -83,6 +86,7 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer ...@@ -83,6 +86,7 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
if (!buffer->page) if (!buffer->page)
return -ENOMEM; return -ENOMEM;
buffer->event = atomic_read(&sd->s_event);
count = ops->show(kobj,attr,buffer->page); count = ops->show(kobj,attr,buffer->page);
buffer->needs_read_fill = 0; buffer->needs_read_fill = 0;
BUG_ON(count > (ssize_t)PAGE_SIZE); BUG_ON(count > (ssize_t)PAGE_SIZE);
...@@ -348,12 +352,84 @@ static int sysfs_release(struct inode * inode, struct file * filp) ...@@ -348,12 +352,84 @@ static int sysfs_release(struct inode * inode, struct file * filp)
return 0; return 0;
} }
/* Sysfs attribute files are pollable. The idea is that you read
* the content and then you use 'poll' or 'select' to wait for
* the content to change. When the content changes (assuming the
* manager for the kobject supports notification), poll will
* return POLLERR|POLLPRI, and select will return the fd whether
* it is waiting for read, write, or exceptions.
* Once poll/select indicates that the value has changed, you
* need to close and re-open the file, as simply seeking and reading
* again will not get new data, or reset the state of 'poll'.
* Reminder: this only works for attributes which actively support
* it, and it is not possible to test an attribute from userspace
* to see if it supports poll (Nether 'poll' or 'select' return
* an appropriate error code). When in doubt, set a suitable timeout value.
*/
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_dentry->d_parent);
struct sysfs_dirent * sd = filp->f_dentry->d_fsdata;
int res = 0;
poll_wait(filp, &kobj->poll, wait);
if (buffer->event != atomic_read(&sd->s_event)) {
res = POLLERR|POLLPRI;
buffer->needs_read_fill = 1;
}
return res;
}
static struct dentry *step_down(struct dentry *dir, const char * name)
{
struct dentry * de;
if (dir == NULL || dir->d_inode == NULL)
return NULL;
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);
wake_up_interruptible(&k->poll);
dput(de);
}
}
EXPORT_SYMBOL_GPL(sysfs_notify);
const struct file_operations sysfs_file_operations = { const struct file_operations sysfs_file_operations = {
.read = sysfs_read_file, .read = sysfs_read_file,
.write = sysfs_write_file, .write = sysfs_write_file,
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
.open = sysfs_open_file, .open = sysfs_open_file,
.release = sysfs_release, .release = sysfs_release,
.poll = sysfs_poll,
}; };
......
...@@ -11,6 +11,7 @@ extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *, ...@@ -11,6 +11,7 @@ extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
extern int sysfs_add_file(struct dentry *, const struct attribute *, int); extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
extern void sysfs_hash_and_remove(struct dentry * dir, const char * name); extern void sysfs_hash_and_remove(struct dentry * dir, 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 int sysfs_create_subdir(struct kobject *, const char *, struct dentry **);
extern void sysfs_remove_subdir(struct dentry *); extern void sysfs_remove_subdir(struct dentry *);
......
...@@ -105,6 +105,7 @@ struct gendisk { ...@@ -105,6 +105,7 @@ struct gendisk {
* disks that can't be partitioned. */ * disks that can't be partitioned. */
char disk_name[32]; /* name of major driver */ char disk_name[32]; /* name of major driver */
struct hd_struct **part; /* [indexed by minor] */ struct hd_struct **part; /* [indexed by minor] */
int part_uevent_suppress;
struct block_device_operations *fops; struct block_device_operations *fops;
struct request_queue *queue; struct request_queue *queue;
void *private_data; void *private_data;
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/rwsem.h> #include <linux/rwsem.h>
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/wait.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#define KOBJ_NAME_LEN 20 #define KOBJ_NAME_LEN 20
...@@ -56,6 +57,7 @@ struct kobject { ...@@ -56,6 +57,7 @@ struct kobject {
struct kset * kset; struct kset * kset;
struct kobj_type * ktype; struct kobj_type * ktype;
struct dentry * dentry; struct dentry * dentry;
wait_queue_head_t poll;
}; };
extern int kobject_set_name(struct kobject *, const char *, ...) extern int kobject_set_name(struct kobject *, const char *, ...)
......
...@@ -199,6 +199,12 @@ extern int device_suspend(pm_message_t state); ...@@ -199,6 +199,12 @@ extern int device_suspend(pm_message_t state);
extern int dpm_runtime_suspend(struct device *, pm_message_t); extern int dpm_runtime_suspend(struct device *, pm_message_t);
extern void dpm_runtime_resume(struct device *); extern void dpm_runtime_resume(struct device *);
extern void __suspend_report_result(const char *function, void *fn, int ret);
#define suspend_report_result(fn, ret) \
do { \
__suspend_report_result(__FUNCTION__, fn, ret); \
} while (0)
#else /* !CONFIG_PM */ #else /* !CONFIG_PM */
...@@ -219,6 +225,8 @@ static inline void dpm_runtime_resume(struct device * dev) ...@@ -219,6 +225,8 @@ static inline void dpm_runtime_resume(struct device * dev)
{ {
} }
#define suspend_report_result(fn, ret) do { } while (0)
#endif #endif
/* changes to device_may_wakeup take effect on the next pm state change. /* changes to device_may_wakeup take effect on the next pm state change.
......
...@@ -74,6 +74,7 @@ struct sysfs_dirent { ...@@ -74,6 +74,7 @@ struct sysfs_dirent {
umode_t s_mode; umode_t s_mode;
struct dentry * s_dentry; struct dentry * s_dentry;
struct iattr * s_iattr; struct iattr * s_iattr;
atomic_t s_event;
}; };
#define SYSFS_ROOT 0x0001 #define SYSFS_ROOT 0x0001
...@@ -117,6 +118,7 @@ int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr); ...@@ -117,6 +118,7 @@ int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr);
int sysfs_create_group(struct kobject *, const struct attribute_group *); int sysfs_create_group(struct kobject *, const struct attribute_group *);
void sysfs_remove_group(struct kobject *, const struct attribute_group *); void sysfs_remove_group(struct kobject *, const struct attribute_group *);
void sysfs_notify(struct kobject * k, char *dir, char *attr);
#else /* CONFIG_SYSFS */ #else /* CONFIG_SYSFS */
...@@ -185,6 +187,10 @@ static inline void sysfs_remove_group(struct kobject * k, const struct attribute ...@@ -185,6 +187,10 @@ static inline void sysfs_remove_group(struct kobject * k, const struct attribute
; ;
} }
static inline void sysfs_notify(struct kobject * k, char *dir, char *attr)
{
}
#endif /* CONFIG_SYSFS */ #endif /* CONFIG_SYSFS */
#endif /* _SYSFS_H_ */ #endif /* _SYSFS_H_ */
...@@ -128,6 +128,7 @@ void kobject_init(struct kobject * kobj) ...@@ -128,6 +128,7 @@ void kobject_init(struct kobject * kobj)
{ {
kref_init(&kobj->kref); kref_init(&kobj->kref);
INIT_LIST_HEAD(&kobj->entry); INIT_LIST_HEAD(&kobj->entry);
init_waitqueue_head(&kobj->poll);
kobj->kset = kset_get(kobj->kset); kobj->kset = kset_get(kobj->kset);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment