diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-04-14 20:07:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-04-14 20:07:57 -0400 |
commit | 754a264c42178b85125a071299bb900b615c853b (patch) | |
tree | 8cfc6d85e6725f90672b75314064ead9fd62e3c6 | |
parent | f9814802dfec8feaf51ba873d7eac1a05ee65842 (diff) | |
parent | 4f705ae3e94ffaafe8d35f71ff4d5c499bb06814 (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/Makefile | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/Makefile | 3 | ||||
-rw-r--r-- | arch/x86_64/kernel/Makefile | 4 | ||||
-rw-r--r-- | drivers/base/bus.c | 5 | ||||
-rw-r--r-- | drivers/base/class.c | 13 | ||||
-rw-r--r-- | drivers/base/dd.c | 2 | ||||
-rw-r--r-- | drivers/base/power/suspend.c | 12 | ||||
-rw-r--r-- | drivers/firmware/Makefile | 3 | ||||
-rw-r--r-- | drivers/firmware/dmi_scan.c (renamed from arch/i386/kernel/dmi_scan.c) | 12 | ||||
-rw-r--r-- | drivers/md/md.c | 1 | ||||
-rw-r--r-- | drivers/pci/pci-driver.c | 6 | ||||
-rw-r--r-- | drivers/pci/pci.c | 6 | ||||
-rw-r--r-- | drivers/usb/core/hcd-pci.c | 7 | ||||
-rw-r--r-- | fs/partitions/check.c | 38 | ||||
-rw-r--r-- | fs/sysfs/dir.c | 1 | ||||
-rw-r--r-- | fs/sysfs/file.c | 76 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 1 | ||||
-rw-r--r-- | include/linux/genhd.h | 1 | ||||
-rw-r--r-- | include/linux/kobject.h | 2 | ||||
-rw-r--r-- | include/linux/pm.h | 8 | ||||
-rw-r--r-- | include/linux/sysfs.h | 6 | ||||
-rw-r--r-- | lib/kobject.c | 1 |
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 | ||
7 | obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ | 7 | obj-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 | ||
12 | obj-y += cpu/ | 12 | obj-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 | |||
7 | obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \ | 7 | obj-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 | ||
12 | obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o | 12 | obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o |
13 | obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o | 13 | obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o |
@@ -30,7 +30,6 @@ obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o | |||
30 | obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o | 30 | obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o |
31 | obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o | 31 | obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o |
32 | mca_recovery-y += mca_drv.o mca_drv_asm.o | 32 | mca_recovery-y += mca_drv.o mca_drv_asm.o |
33 | dmi_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. |
36 | targets += gate.so gate-syms.o | 35 | targets += 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 | ||
13 | obj-$(CONFIG_X86_MCE) += mce.o | 13 | obj-$(CONFIG_X86_MCE) += mce.o |
14 | obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o | 14 | obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o |
@@ -49,5 +49,3 @@ intel_cacheinfo-y += ../../i386/kernel/cpu/intel_cacheinfo.o | |||
49 | quirks-y += ../../i386/kernel/quirks.o | 49 | quirks-y += ../../i386/kernel/quirks.o |
50 | i8237-y += ../../i386/kernel/i8237.o | 50 | i8237-y += ../../i386/kernel/i8237.o |
51 | msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o | 51 | msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o |
52 | dmi_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 | ||
170 | EXPORT_SYMBOL_GPL(device_power_down); | 173 | EXPORT_SYMBOL_GPL(device_power_down); |
171 | 174 | ||
175 | void __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 | } | ||
183 | EXPORT_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 | # |
4 | obj-$(CONFIG_EDD) += edd.o | 4 | obj-$(CONFIG_DMI) += dmi_scan.o |
5 | obj-$(CONFIG_EDD) += edd.o | ||
5 | obj-$(CONFIG_EFI_VARS) += efivars.o | 6 | obj-$(CONFIG_EFI_VARS) += efivars.o |
6 | obj-$(CONFIG_EFI_PCDP) += pcdp.o | 7 | obj-$(CONFIG_EFI_PCDP) += pcdp.o |
7 | obj-$(CONFIG_DELL_RBU) += dell_rbu.o | 8 | obj-$(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 | } |
167 | EXPORT_SYMBOL_GPL(md_new_event); | 168 | EXPORT_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 | ||
337 | void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len) | 339 | 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 | 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 | |||
444 | exit: | ||
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 | ||
435 | int rescan_partitions(struct gendisk *disk, struct block_device *bdev) | 457 | int 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 | */ |
73 | static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) | 75 | static 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 | */ | ||
369 | static 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 | |||
387 | static 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 | |||
407 | void 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 | } | ||
424 | EXPORT_SYMBOL_GPL(sysfs_notify); | ||
425 | |||
351 | const struct file_operations sysfs_file_operations = { | 426 | const 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 | ||
12 | extern int sysfs_add_file(struct dentry *, const struct attribute *, int); | 12 | extern int sysfs_add_file(struct dentry *, const struct attribute *, int); |
13 | extern void sysfs_hash_and_remove(struct dentry * dir, const char * name); | 13 | extern void sysfs_hash_and_remove(struct dentry * dir, const char * name); |
14 | extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name); | ||
14 | 15 | ||
15 | extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **); | 16 | extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **); |
16 | extern void sysfs_remove_subdir(struct dentry *); | 17 | extern 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 | ||
61 | extern int kobject_set_name(struct kobject *, const char *, ...) | 63 | extern 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 | ||
200 | extern int dpm_runtime_suspend(struct device *, pm_message_t); | 200 | extern int dpm_runtime_suspend(struct device *, pm_message_t); |
201 | extern void dpm_runtime_resume(struct device *); | 201 | extern void dpm_runtime_resume(struct device *); |
202 | extern 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 | ||
118 | int sysfs_create_group(struct kobject *, const struct attribute_group *); | 119 | int sysfs_create_group(struct kobject *, const struct attribute_group *); |
119 | void sysfs_remove_group(struct kobject *, const struct attribute_group *); | 120 | void sysfs_remove_group(struct kobject *, const struct attribute_group *); |
121 | void 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 | ||
190 | static 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 | ||