aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-04-14 20:07:57 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-14 20:07:57 -0400
commit754a264c42178b85125a071299bb900b615c853b (patch)
tree8cfc6d85e6725f90672b75314064ead9fd62e3c6
parentf9814802dfec8feaf51ba873d7eac1a05ee65842 (diff)
parent4f705ae3e94ffaafe8d35f71ff4d5c499bb06814 (diff)
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 4f705ae3e94ffaafe8d35f71ff4d5c499bb06814 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: Bjorn 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: Andrew Morton <akpm@osdl.org> ...
-rw-r--r--arch/i386/kernel/Makefile2
-rw-r--r--arch/ia64/kernel/Makefile3
-rw-r--r--arch/x86_64/kernel/Makefile4
-rw-r--r--drivers/base/bus.c5
-rw-r--r--drivers/base/class.c13
-rw-r--r--drivers/base/dd.c2
-rw-r--r--drivers/base/power/suspend.c12
-rw-r--r--drivers/firmware/Makefile3
-rw-r--r--drivers/firmware/dmi_scan.c (renamed from arch/i386/kernel/dmi_scan.c)12
-rw-r--r--drivers/md/md.c1
-rw-r--r--drivers/pci/pci-driver.c6
-rw-r--r--drivers/pci/pci.c6
-rw-r--r--drivers/usb/core/hcd-pci.c7
-rw-r--r--fs/partitions/check.c38
-rw-r--r--fs/sysfs/dir.c1
-rw-r--r--fs/sysfs/file.c76
-rw-r--r--fs/sysfs/sysfs.h1
-rw-r--r--include/linux/genhd.h1
-rw-r--r--include/linux/kobject.h2
-rw-r--r--include/linux/pm.h8
-rw-r--r--include/linux/sysfs.h6
-rw-r--r--lib/kobject.c1
22 files changed, 173 insertions, 37 deletions
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 5b9ed21216cf..96fb8a020af2 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -6,7 +6,7 @@ extra-y := head.o init_task.o vmlinux.lds
6 6
7obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ 7obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \
8 ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \ 8 ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \
9 pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \ 9 pci-dma.o i386_ksyms.o i387.o bootflag.o \
10 quirks.o i8237.o topology.o alternative.o 10 quirks.o i8237.o topology.o alternative.o
11 11
12obj-y += cpu/ 12obj-y += cpu/
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 59e871dae742..09a0dbc17fb6 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -7,7 +7,7 @@ extra-y := head.o init_task.o vmlinux.lds
7obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \ 7obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \
8 irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o \ 8 irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o \
9 salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \ 9 salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \
10 unwind.o mca.o mca_asm.o topology.o dmi_scan.o 10 unwind.o mca.o mca_asm.o topology.o
11 11
12obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o 12obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o
13obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o 13obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o
@@ -30,7 +30,6 @@ obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
30obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o 30obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
31obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o 31obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
32mca_recovery-y += mca_drv.o mca_drv_asm.o 32mca_recovery-y += mca_drv.o mca_drv_asm.o
33dmi_scan-y += ../../i386/kernel/dmi_scan.o
34 33
35# The gate DSO image is built using a special linker script. 34# The gate DSO image is built using a special linker script.
36targets += gate.so gate-syms.o 35targets += gate.so gate-syms.o
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index a098a11e7755..059c88313f4e 100644
--- a/arch/x86_64/kernel/Makefile
+++ b/arch/x86_64/kernel/Makefile
@@ -8,7 +8,7 @@ obj-y := process.o signal.o entry.o traps.o irq.o \
8 ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \ 8 ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \
9 x8664_ksyms.o i387.o syscall.o vsyscall.o \ 9 x8664_ksyms.o i387.o syscall.o vsyscall.o \
10 setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \ 10 setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \
11 dmi_scan.o pci-dma.o pci-nommu.o 11 pci-dma.o pci-nommu.o
12 12
13obj-$(CONFIG_X86_MCE) += mce.o 13obj-$(CONFIG_X86_MCE) += mce.o
14obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o 14obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o
@@ -49,5 +49,3 @@ intel_cacheinfo-y += ../../i386/kernel/cpu/intel_cacheinfo.o
49quirks-y += ../../i386/kernel/quirks.o 49quirks-y += ../../i386/kernel/quirks.o
50i8237-y += ../../i386/kernel/i8237.o 50i8237-y += ../../i386/kernel/i8237.o
51msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o 51msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o
52dmi_scan-y += ../../i386/kernel/dmi_scan.o
53
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 48718b7f4fa0..76656acd00d4 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -188,6 +188,11 @@ static ssize_t driver_bind(struct device_driver *drv,
188 up(&dev->sem); 188 up(&dev->sem);
189 if (dev->parent) 189 if (dev->parent)
190 up(&dev->parent->sem); 190 up(&dev->parent->sem);
191
192 if (err > 0) /* success */
193 err = count;
194 else if (err == 0) /* driver didn't accept device */
195 err = -ENODEV;
191 } 196 }
192 put_device(dev); 197 put_device(dev);
193 put_bus(bus); 198 put_bus(bus);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index df7fdabd0730..0e71dff327cd 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -562,14 +562,13 @@ int class_device_add(struct class_device *class_dev)
562 kobject_uevent(&class_dev->kobj, KOBJ_ADD); 562 kobject_uevent(&class_dev->kobj, KOBJ_ADD);
563 563
564 /* notify any interfaces this device is now here */ 564 /* notify any interfaces this device is now here */
565 if (parent_class) { 565 down(&parent_class->sem);
566 down(&parent_class->sem); 566 list_add_tail(&class_dev->node, &parent_class->children);
567 list_add_tail(&class_dev->node, &parent_class->children); 567 list_for_each_entry(class_intf, &parent_class->interfaces, node) {
568 list_for_each_entry(class_intf, &parent_class->interfaces, node) 568 if (class_intf->add)
569 if (class_intf->add) 569 class_intf->add(class_dev, class_intf);
570 class_intf->add(class_dev, class_intf);
571 up(&parent_class->sem);
572 } 570 }
571 up(&parent_class->sem);
573 572
574 register_done: 573 register_done:
575 if (error) { 574 if (error) {
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 730a9ce0a14a..889c71111239 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -209,7 +209,7 @@ static void __device_release_driver(struct device * dev)
209 sysfs_remove_link(&dev->kobj, "driver"); 209 sysfs_remove_link(&dev->kobj, "driver");
210 klist_remove(&dev->knode_driver); 210 klist_remove(&dev->knode_driver);
211 211
212 if (dev->bus->remove) 212 if (dev->bus && dev->bus->remove)
213 dev->bus->remove(dev); 213 dev->bus->remove(dev);
214 else if (drv->remove) 214 else if (drv->remove)
215 drv->remove(dev); 215 drv->remove(dev);
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index bdb60663f2ef..662209d3f42d 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -10,6 +10,8 @@
10 10
11#include <linux/vt_kern.h> 11#include <linux/vt_kern.h>
12#include <linux/device.h> 12#include <linux/device.h>
13#include <linux/kallsyms.h>
14#include <linux/pm.h>
13#include "../base.h" 15#include "../base.h"
14#include "power.h" 16#include "power.h"
15 17
@@ -58,6 +60,7 @@ int suspend_device(struct device * dev, pm_message_t state)
58 if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) { 60 if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
59 dev_dbg(dev, "suspending\n"); 61 dev_dbg(dev, "suspending\n");
60 error = dev->bus->suspend(dev, state); 62 error = dev->bus->suspend(dev, state);
63 suspend_report_result(dev->bus->suspend, error);
61 } 64 }
62 up(&dev->sem); 65 up(&dev->sem);
63 return error; 66 return error;
@@ -169,3 +172,12 @@ int device_power_down(pm_message_t state)
169 172
170EXPORT_SYMBOL_GPL(device_power_down); 173EXPORT_SYMBOL_GPL(device_power_down);
171 174
175void __suspend_report_result(const char *function, void *fn, int ret)
176{
177 if (ret) {
178 printk(KERN_ERR "%s(): ", function);
179 print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn);
180 printk("%d\n", ret);
181 }
182}
183EXPORT_SYMBOL_GPL(__suspend_report_result);
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 85429979d0db..98e395f4bb29 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -1,7 +1,8 @@
1# 1#
2# Makefile for the linux kernel. 2# Makefile for the linux kernel.
3# 3#
4obj-$(CONFIG_EDD) += edd.o 4obj-$(CONFIG_DMI) += dmi_scan.o
5obj-$(CONFIG_EDD) += edd.o
5obj-$(CONFIG_EFI_VARS) += efivars.o 6obj-$(CONFIG_EFI_VARS) += efivars.o
6obj-$(CONFIG_EFI_PCDP) += pcdp.o 7obj-$(CONFIG_EFI_PCDP) += pcdp.o
7obj-$(CONFIG_DELL_RBU) += dell_rbu.o 8obj-$(CONFIG_DELL_RBU) += dell_rbu.o
diff --git a/arch/i386/kernel/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 5efceebc48dc..948bd7e1445a 100644
--- a/arch/i386/kernel/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -27,7 +27,7 @@ static char * __init dmi_string(struct dmi_header *dm, u8 s)
27 else 27 else
28 printk(KERN_ERR "dmi_string: out of memory.\n"); 28 printk(KERN_ERR "dmi_string: out of memory.\n");
29 } 29 }
30 } 30 }
31 31
32 return str; 32 return str;
33} 33}
@@ -41,7 +41,7 @@ static int __init dmi_table(u32 base, int len, int num,
41{ 41{
42 u8 *buf, *data; 42 u8 *buf, *data;
43 int i = 0; 43 int i = 0;
44 44
45 buf = dmi_ioremap(base, len); 45 buf = dmi_ioremap(base, len);
46 if (buf == NULL) 46 if (buf == NULL)
47 return -1; 47 return -1;
@@ -49,9 +49,9 @@ static int __init dmi_table(u32 base, int len, int num,
49 data = buf; 49 data = buf;
50 50
51 /* 51 /*
52 * Stop when we see all the items the table claimed to have 52 * Stop when we see all the items the table claimed to have
53 * OR we run off the end of the table (also happens) 53 * OR we run off the end of the table (also happens)
54 */ 54 */
55 while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) { 55 while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) {
56 struct dmi_header *dm = (struct dmi_header *)data; 56 struct dmi_header *dm = (struct dmi_header *)data;
57 /* 57 /*
@@ -75,7 +75,7 @@ static int __init dmi_checksum(u8 *buf)
75{ 75{
76 u8 sum = 0; 76 u8 sum = 0;
77 int a; 77 int a;
78 78
79 for (a = 0; a < 15; a++) 79 for (a = 0; a < 15; a++)
80 sum += buf[a]; 80 sum += buf[a];
81 81
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 1ed5152db450..434ca39d19c1 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -163,6 +163,7 @@ void md_new_event(mddev_t *mddev)
163{ 163{
164 atomic_inc(&md_event_count); 164 atomic_inc(&md_event_count);
165 wake_up(&md_event_waiters); 165 wake_up(&md_event_waiters);
166 sysfs_notify(&mddev->kobj, NULL, "sync_action");
166} 167}
167EXPORT_SYMBOL_GPL(md_new_event); 168EXPORT_SYMBOL_GPL(md_new_event);
168 169
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index f22f69ac6445..1456759936c5 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -271,10 +271,12 @@ static int pci_device_suspend(struct device * dev, pm_message_t state)
271 struct pci_driver * drv = pci_dev->driver; 271 struct pci_driver * drv = pci_dev->driver;
272 int i = 0; 272 int i = 0;
273 273
274 if (drv && drv->suspend) 274 if (drv && drv->suspend) {
275 i = drv->suspend(pci_dev, state); 275 i = drv->suspend(pci_dev, state);
276 else 276 suspend_report_result(drv->suspend, i);
277 } else {
277 pci_save_state(pci_dev); 278 pci_save_state(pci_dev);
279 }
278 return i; 280 return i;
279} 281}
280 282
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index bea1ad1ad5ba..042fa5265cf6 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -307,9 +307,11 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
307 * Can enter D0 from any state, but if we can only go deeper 307 * Can enter D0 from any state, but if we can only go deeper
308 * to sleep if we're already in a low power state 308 * to sleep if we're already in a low power state
309 */ 309 */
310 if (state != PCI_D0 && dev->current_state > state) 310 if (state != PCI_D0 && dev->current_state > state) {
311 printk(KERN_ERR "%s(): %s: state=%d, current state=%d\n",
312 __FUNCTION__, pci_name(dev), state, dev->current_state);
311 return -EINVAL; 313 return -EINVAL;
312 else if (dev->current_state == state) 314 } else if (dev->current_state == state)
313 return 0; /* we're already there */ 315 return 0; /* we're already there */
314 316
315 /* find PCI PM capability in list */ 317 /* find PCI PM capability in list */
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 0d2193b69235..66b78404ab34 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -213,11 +213,9 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
213 213
214 if (hcd->driver->suspend) { 214 if (hcd->driver->suspend) {
215 retval = hcd->driver->suspend(hcd, message); 215 retval = hcd->driver->suspend(hcd, message);
216 if (retval) { 216 suspend_report_result(hcd->driver->suspend, retval);
217 dev_dbg (&dev->dev, "PCI pre-suspend fail, %d\n", 217 if (retval)
218 retval);
219 goto done; 218 goto done;
220 }
221 } 219 }
222 synchronize_irq(dev->irq); 220 synchronize_irq(dev->irq);
223 221
@@ -263,6 +261,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
263 * some device state (e.g. as part of clock reinit). 261 * some device state (e.g. as part of clock reinit).
264 */ 262 */
265 retval = pci_set_power_state (dev, PCI_D3hot); 263 retval = pci_set_power_state (dev, PCI_D3hot);
264 suspend_report_result(pci_set_power_state, retval);
266 if (retval == 0) { 265 if (retval == 0) {
267 int wake = device_can_wakeup(&hcd->self.root_hub->dev); 266 int wake = device_can_wakeup(&hcd->self.root_hub->dev);
268 267
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index af0cb4b9e784..f3b6af071722 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -331,7 +331,9 @@ void delete_partition(struct gendisk *disk, int part)
331 devfs_remove("%s/part%d", disk->devfs_name, part); 331 devfs_remove("%s/part%d", disk->devfs_name, part);
332 if (p->holder_dir) 332 if (p->holder_dir)
333 kobject_unregister(p->holder_dir); 333 kobject_unregister(p->holder_dir);
334 kobject_unregister(&p->kobj); 334 kobject_uevent(&p->kobj, KOBJ_REMOVE);
335 kobject_del(&p->kobj);
336 kobject_put(&p->kobj);
335} 337}
336 338
337void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len) 339void 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 snprintf(p->kobj.name,KOBJ_NAME_LEN,"%s%d",disk->kobj.name,part); 359 snprintf(p->kobj.name,KOBJ_NAME_LEN,"%s%d",disk->kobj.name,part);
358 p->kobj.parent = &disk->kobj; 360 p->kobj.parent = &disk->kobj;
359 p->kobj.ktype = &ktype_part; 361 p->kobj.ktype = &ktype_part;
360 kobject_register(&p->kobj); 362 kobject_init(&p->kobj);
363 kobject_add(&p->kobj);
364 if (!disk->part_uevent_suppress)
365 kobject_uevent(&p->kobj, KOBJ_ADD);
361 partition_sysfs_add_subdir(p); 366 partition_sysfs_add_subdir(p);
362 disk->part[part-1] = p; 367 disk->part[part-1] = p;
363} 368}
@@ -395,6 +400,8 @@ void register_disk(struct gendisk *disk)
395{ 400{
396 struct block_device *bdev; 401 struct block_device *bdev;
397 char *s; 402 char *s;
403 int i;
404 struct hd_struct *p;
398 int err; 405 int err;
399 406
400 strlcpy(disk->kobj.name,disk->disk_name,KOBJ_NAME_LEN); 407 strlcpy(disk->kobj.name,disk->disk_name,KOBJ_NAME_LEN);
@@ -406,13 +413,12 @@ void register_disk(struct gendisk *disk)
406 return; 413 return;
407 disk_sysfs_symlinks(disk); 414 disk_sysfs_symlinks(disk);
408 disk_sysfs_add_subdirs(disk); 415 disk_sysfs_add_subdirs(disk);
409 kobject_uevent(&disk->kobj, KOBJ_ADD);
410 416
411 /* No minors to use for partitions */ 417 /* No minors to use for partitions */
412 if (disk->minors == 1) { 418 if (disk->minors == 1) {
413 if (disk->devfs_name[0] != '\0') 419 if (disk->devfs_name[0] != '\0')
414 devfs_add_disk(disk); 420 devfs_add_disk(disk);
415 return; 421 goto exit;
416 } 422 }
417 423
418 /* always add handle for the whole disk */ 424 /* always add handle for the whole disk */
@@ -420,16 +426,32 @@ void register_disk(struct gendisk *disk)
420 426
421 /* No such device (e.g., media were just removed) */ 427 /* No such device (e.g., media were just removed) */
422 if (!get_capacity(disk)) 428 if (!get_capacity(disk))
423 return; 429 goto exit;
424 430
425 bdev = bdget_disk(disk, 0); 431 bdev = bdget_disk(disk, 0);
426 if (!bdev) 432 if (!bdev)
427 return; 433 goto exit;
428 434
435 /* scan partition table, but suppress uevents */
429 bdev->bd_invalidated = 1; 436 bdev->bd_invalidated = 1;
430 if (blkdev_get(bdev, FMODE_READ, 0) < 0) 437 disk->part_uevent_suppress = 1;
431 return; 438 err = blkdev_get(bdev, FMODE_READ, 0);
439 disk->part_uevent_suppress = 0;
440 if (err < 0)
441 goto exit;
432 blkdev_put(bdev); 442 blkdev_put(bdev);
443
444exit:
445 /* announce disk after possible partitions are already created */
446 kobject_uevent(&disk->kobj, KOBJ_ADD);
447
448 /* announce possible partitions */
449 for (i = 1; i < disk->minors; i++) {
450 p = disk->part[i-1];
451 if (!p || !p->nr_sects)
452 continue;
453 kobject_uevent(&p->kobj, KOBJ_ADD);
454 }
433} 455}
434 456
435int rescan_partitions(struct gendisk *disk, struct block_device *bdev) 457int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 6cfdc9a87772..610b5bdbe75b 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -43,6 +43,7 @@ static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * parent_sd,
43 43
44 memset(sd, 0, sizeof(*sd)); 44 memset(sd, 0, sizeof(*sd));
45 atomic_set(&sd->s_count, 1); 45 atomic_set(&sd->s_count, 1);
46 atomic_set(&sd->s_event, 0);
46 INIT_LIST_HEAD(&sd->s_children); 47 INIT_LIST_HEAD(&sd->s_children);
47 list_add(&sd->s_sibling, &parent_sd->s_children); 48 list_add(&sd->s_sibling, &parent_sd->s_children);
48 sd->s_element = element; 49 sd->s_element = element;
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index f1cb1ddde511..cf3786625bfa 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -6,6 +6,7 @@
6#include <linux/fsnotify.h> 6#include <linux/fsnotify.h>
7#include <linux/kobject.h> 7#include <linux/kobject.h>
8#include <linux/namei.h> 8#include <linux/namei.h>
9#include <linux/poll.h>
9#include <asm/uaccess.h> 10#include <asm/uaccess.h>
10#include <asm/semaphore.h> 11#include <asm/semaphore.h>
11 12
@@ -57,6 +58,7 @@ struct sysfs_buffer {
57 struct sysfs_ops * ops; 58 struct sysfs_ops * ops;
58 struct semaphore sem; 59 struct semaphore sem;
59 int needs_read_fill; 60 int needs_read_fill;
61 int event;
60}; 62};
61 63
62 64
@@ -72,6 +74,7 @@ struct sysfs_buffer {
72 */ 74 */
73static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) 75static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
74{ 76{
77 struct sysfs_dirent * sd = dentry->d_fsdata;
75 struct attribute * attr = to_attr(dentry); 78 struct attribute * attr = to_attr(dentry);
76 struct kobject * kobj = to_kobj(dentry->d_parent); 79 struct kobject * kobj = to_kobj(dentry->d_parent);
77 struct sysfs_ops * ops = buffer->ops; 80 struct sysfs_ops * ops = buffer->ops;
@@ -83,6 +86,7 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
83 if (!buffer->page) 86 if (!buffer->page)
84 return -ENOMEM; 87 return -ENOMEM;
85 88
89 buffer->event = atomic_read(&sd->s_event);
86 count = ops->show(kobj,attr,buffer->page); 90 count = ops->show(kobj,attr,buffer->page);
87 buffer->needs_read_fill = 0; 91 buffer->needs_read_fill = 0;
88 BUG_ON(count > (ssize_t)PAGE_SIZE); 92 BUG_ON(count > (ssize_t)PAGE_SIZE);
@@ -348,12 +352,84 @@ static int sysfs_release(struct inode * inode, struct file * filp)
348 return 0; 352 return 0;
349} 353}
350 354
355/* Sysfs attribute files are pollable. The idea is that you read
356 * the content and then you use 'poll' or 'select' to wait for
357 * the content to change. When the content changes (assuming the
358 * manager for the kobject supports notification), poll will
359 * return POLLERR|POLLPRI, and select will return the fd whether
360 * it is waiting for read, write, or exceptions.
361 * Once poll/select indicates that the value has changed, you
362 * need to close and re-open the file, as simply seeking and reading
363 * again will not get new data, or reset the state of 'poll'.
364 * Reminder: this only works for attributes which actively support
365 * it, and it is not possible to test an attribute from userspace
366 * to see if it supports poll (Nether 'poll' or 'select' return
367 * an appropriate error code). When in doubt, set a suitable timeout value.
368 */
369static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
370{
371 struct sysfs_buffer * buffer = filp->private_data;
372 struct kobject * kobj = to_kobj(filp->f_dentry->d_parent);
373 struct sysfs_dirent * sd = filp->f_dentry->d_fsdata;
374 int res = 0;
375
376 poll_wait(filp, &kobj->poll, wait);
377
378 if (buffer->event != atomic_read(&sd->s_event)) {
379 res = POLLERR|POLLPRI;
380 buffer->needs_read_fill = 1;
381 }
382
383 return res;
384}
385
386
387static struct dentry *step_down(struct dentry *dir, const char * name)
388{
389 struct dentry * de;
390
391 if (dir == NULL || dir->d_inode == NULL)
392 return NULL;
393
394 mutex_lock(&dir->d_inode->i_mutex);
395 de = lookup_one_len(name, dir, strlen(name));
396 mutex_unlock(&dir->d_inode->i_mutex);
397 dput(dir);
398 if (IS_ERR(de))
399 return NULL;
400 if (de->d_inode == NULL) {
401 dput(de);
402 return NULL;
403 }
404 return de;
405}
406
407void sysfs_notify(struct kobject * k, char *dir, char *attr)
408{
409 struct dentry *de = k->dentry;
410 if (de)
411 dget(de);
412 if (de && dir)
413 de = step_down(de, dir);
414 if (de && attr)
415 de = step_down(de, attr);
416 if (de) {
417 struct sysfs_dirent * sd = de->d_fsdata;
418 if (sd)
419 atomic_inc(&sd->s_event);
420 wake_up_interruptible(&k->poll);
421 dput(de);
422 }
423}
424EXPORT_SYMBOL_GPL(sysfs_notify);
425
351const struct file_operations sysfs_file_operations = { 426const struct file_operations sysfs_file_operations = {
352 .read = sysfs_read_file, 427 .read = sysfs_read_file,
353 .write = sysfs_write_file, 428 .write = sysfs_write_file,
354 .llseek = generic_file_llseek, 429 .llseek = generic_file_llseek,
355 .open = sysfs_open_file, 430 .open = sysfs_open_file,
356 .release = sysfs_release, 431 .release = sysfs_release,
432 .poll = sysfs_poll,
357}; 433};
358 434
359 435
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 32958a7c50e9..3651ffb5ec09 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -11,6 +11,7 @@ extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
11 11
12extern int sysfs_add_file(struct dentry *, const struct attribute *, int); 12extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
13extern void sysfs_hash_and_remove(struct dentry * dir, const char * name); 13extern void sysfs_hash_and_remove(struct dentry * dir, const char * name);
14extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name);
14 15
15extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **); 16extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **);
16extern void sysfs_remove_subdir(struct dentry *); 17extern void sysfs_remove_subdir(struct dentry *);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 10a27f29d692..2ef845b35175 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -105,6 +105,7 @@ struct gendisk {
105 * disks that can't be partitioned. */ 105 * disks that can't be partitioned. */
106 char disk_name[32]; /* name of major driver */ 106 char disk_name[32]; /* name of major driver */
107 struct hd_struct **part; /* [indexed by minor] */ 107 struct hd_struct **part; /* [indexed by minor] */
108 int part_uevent_suppress;
108 struct block_device_operations *fops; 109 struct block_device_operations *fops;
109 struct request_queue *queue; 110 struct request_queue *queue;
110 void *private_data; 111 void *private_data;
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 4cb1214ec290..dcd0623be892 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -24,6 +24,7 @@
24#include <linux/rwsem.h> 24#include <linux/rwsem.h>
25#include <linux/kref.h> 25#include <linux/kref.h>
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/wait.h>
27#include <asm/atomic.h> 28#include <asm/atomic.h>
28 29
29#define KOBJ_NAME_LEN 20 30#define KOBJ_NAME_LEN 20
@@ -56,6 +57,7 @@ struct kobject {
56 struct kset * kset; 57 struct kset * kset;
57 struct kobj_type * ktype; 58 struct kobj_type * ktype;
58 struct dentry * dentry; 59 struct dentry * dentry;
60 wait_queue_head_t poll;
59}; 61};
60 62
61extern int kobject_set_name(struct kobject *, const char *, ...) 63extern int kobject_set_name(struct kobject *, const char *, ...)
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 6df2585c0169..66be58902b17 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -199,6 +199,12 @@ extern int device_suspend(pm_message_t state);
199 199
200extern int dpm_runtime_suspend(struct device *, pm_message_t); 200extern int dpm_runtime_suspend(struct device *, pm_message_t);
201extern void dpm_runtime_resume(struct device *); 201extern void dpm_runtime_resume(struct device *);
202extern void __suspend_report_result(const char *function, void *fn, int ret);
203
204#define suspend_report_result(fn, ret) \
205 do { \
206 __suspend_report_result(__FUNCTION__, fn, ret); \
207 } while (0)
202 208
203#else /* !CONFIG_PM */ 209#else /* !CONFIG_PM */
204 210
@@ -219,6 +225,8 @@ static inline void dpm_runtime_resume(struct device * dev)
219{ 225{
220} 226}
221 227
228#define suspend_report_result(fn, ret) do { } while (0)
229
222#endif 230#endif
223 231
224/* changes to device_may_wakeup take effect on the next pm state change. 232/* changes to device_may_wakeup take effect on the next pm state change.
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 392da5a6dacb..1ea5d3cda6ae 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -74,6 +74,7 @@ struct sysfs_dirent {
74 umode_t s_mode; 74 umode_t s_mode;
75 struct dentry * s_dentry; 75 struct dentry * s_dentry;
76 struct iattr * s_iattr; 76 struct iattr * s_iattr;
77 atomic_t s_event;
77}; 78};
78 79
79#define SYSFS_ROOT 0x0001 80#define SYSFS_ROOT 0x0001
@@ -117,6 +118,7 @@ int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr);
117 118
118int sysfs_create_group(struct kobject *, const struct attribute_group *); 119int sysfs_create_group(struct kobject *, const struct attribute_group *);
119void sysfs_remove_group(struct kobject *, const struct attribute_group *); 120void sysfs_remove_group(struct kobject *, const struct attribute_group *);
121void sysfs_notify(struct kobject * k, char *dir, char *attr);
120 122
121#else /* CONFIG_SYSFS */ 123#else /* CONFIG_SYSFS */
122 124
@@ -185,6 +187,10 @@ static inline void sysfs_remove_group(struct kobject * k, const struct attribute
185 ; 187 ;
186} 188}
187 189
190static inline void sysfs_notify(struct kobject * k, char *dir, char *attr)
191{
192}
193
188#endif /* CONFIG_SYSFS */ 194#endif /* CONFIG_SYSFS */
189 195
190#endif /* _SYSFS_H_ */ 196#endif /* _SYSFS_H_ */
diff --git a/lib/kobject.c b/lib/kobject.c
index 25204a41a9b0..01d957513940 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -128,6 +128,7 @@ void kobject_init(struct kobject * kobj)
128{ 128{
129 kref_init(&kobj->kref); 129 kref_init(&kobj->kref);
130 INIT_LIST_HEAD(&kobj->entry); 130 INIT_LIST_HEAD(&kobj->entry);
131 init_waitqueue_head(&kobj->poll);
131 kobj->kset = kset_get(kobj->kset); 132 kobj->kset = kset_get(kobj->kset);
132} 133}
133 134