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 | ||
