Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 23 Oct 2010 02:36:42 +0000 (19:36 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 23 Oct 2010 02:36:42 +0000 (19:36 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (31 commits)
  driver core: Display error codes when class suspend fails
  Driver core: Add section count to memory_block struct
  Driver core: Add mutex for adding/removing memory blocks
  Driver core: Move find_memory_block routine
  hpilo: Despecificate driver from iLO generation
  driver core: Convert link_mem_sections to use find_memory_block_hinted.
  driver core: Introduce find_memory_block_hinted which utilizes kset_find_obj_hinted.
  kobject: Introduce kset_find_obj_hinted.
  driver core: fix build for CONFIG_BLOCK not enabled
  driver-core: base: change to new flag variable
  sysfs: only access bin file vm_ops with the active lock
  sysfs: Fail bin file mmap if vma close is implemented.
  FW_LOADER: fix kconfig dependency warning on HOTPLUG
  uio: Statically allocate uio_class and use class .dev_attrs.
  uio: Support 2^MINOR_BITS minors
  uio: Cleanup irq handling.
  uio: Don't clear driver data
  uio: Fix lack of locking in init_uio_class
  SYSFS: Allow boot time switching between deprecated and modern sysfs layout
  driver core: remove CONFIG_SYSFS_DEPRECATED_V2 but keep it for block devices
  ...

34 files changed:
Documentation/ABI/testing/sysfs-module [new file with mode: 0644]
Documentation/dynamic-debug-howto.txt
Documentation/kernel-parameters.txt
MAINTAINERS
block/genhd.c
drivers/base/Kconfig
drivers/base/Makefile
drivers/base/bus.c
drivers/base/class.c
drivers/base/core.c
drivers/base/memory.c
drivers/base/node.c
drivers/base/platform.c
drivers/base/sys.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/hpilo.c
drivers/misc/pch_phub.c [new file with mode: 0644]
drivers/scsi/hosts.c
drivers/scsi/scsi_scan.c
drivers/uio/uio.c
drivers/uio/uio_pci_generic.c
fs/partitions/check.c
fs/sysfs/bin.c
include/linux/device.h
include/linux/kobject.h
include/linux/memory.h
include/linux/platform_device.h
include/linux/uio_driver.h
include/sound/core.h
init/Kconfig
lib/dynamic_debug.c
lib/kobject.c
sound/core/init.c

diff --git a/Documentation/ABI/testing/sysfs-module b/Documentation/ABI/testing/sysfs-module
new file mode 100644 (file)
index 0000000..cfcec3b
--- /dev/null
@@ -0,0 +1,12 @@
+What:          /sys/module/pch_phub/drivers/.../pch_mac
+Date:          August 2010
+KernelVersion: 2.6.35
+Contact:       masa-korg@dsn.okisemi.com
+Description:   Write/read GbE MAC address.
+
+What:          /sys/module/pch_phub/drivers/.../pch_firmware
+Date:          August 2010
+KernelVersion: 2.6.35
+Contact:       masa-korg@dsn.okisemi.com
+Description:   Write/read Option ROM data.
+
index 674c566..58ea64a 100644 (file)
@@ -24,7 +24,7 @@ Dynamic debug has even more useful features:
    read to display the complete list of known debug statements, to help guide you
 
 Controlling dynamic debug Behaviour
-===============================
+===================================
 
 The behaviour of pr_debug()/dev_debug()s are controlled via writing to a
 control file in the 'debugfs' filesystem. Thus, you must first mount the debugfs
@@ -212,6 +212,26 @@ Note the regexp ^[-+=][scp]+$ matches a flags specification.
 Note also that there is no convenient syntax to remove all
 the flags at once, you need to use "-psc".
 
+
+Debug messages during boot process
+==================================
+
+To be able to activate debug messages during the boot process,
+even before userspace and debugfs exists, use the boot parameter:
+ddebug_query="QUERY"
+
+QUERY follows the syntax described above, but must not exceed 1023
+characters. The enablement of debug messages is done as an arch_initcall.
+Thus you can enable debug messages in all code processed after this
+arch_initcall via this boot parameter.
+On an x86 system for example ACPI enablement is a subsys_initcall and
+ddebug_query="file ec.c +p"
+will show early Embedded Controller transactions during ACPI setup if
+your machine (typically a laptop) has an Embedded Controller.
+PCI (or other devices) initialization also is a hot candidate for using
+this boot parameter for debugging purposes.
+
+
 Examples
 ========
 
index 02f21d9..4cd8b86 100644 (file)
@@ -43,10 +43,11 @@ parameter is applicable:
        AVR32   AVR32 architecture is enabled.
        AX25    Appropriate AX.25 support is enabled.
        BLACKFIN Blackfin architecture is enabled.
-       DRM     Direct Rendering Management support is enabled.
        EDD     BIOS Enhanced Disk Drive Services (EDD) is enabled
        EFI     EFI Partitioning (GPT) is enabled
        EIDE    EIDE/ATAPI support is enabled.
+       DRM     Direct Rendering Management support is enabled.
+       DYNAMIC_DEBUG Build in debug messages and enable them at runtime
        FB      The frame buffer device is enabled.
        GCOV    GCOV profiling is enabled.
        HW      Appropriate hardware is enabled.
@@ -570,6 +571,10 @@ and is between 256 and 4096 characters. It is defined in the file
                        Format: <port#>,<type>
                        See also Documentation/input/joystick-parport.txt
 
+       ddebug_query=   [KNL,DYNAMIC_DEBUG] Enable debug messages at early boot
+                       time. See Documentation/dynamic-debug-howto.txt for
+                       details.
+
        debug           [KNL] Enable kernel debugging (events log level).
 
        debug_locks_verbose=
@@ -2370,6 +2375,15 @@ and is between 256 and 4096 characters. It is defined in the file
 
        switches=       [HW,M68k]
 
+       sysfs.deprecated=0|1 [KNL]
+                       Enable/disable old style sysfs layout for old udev
+                       on older distributions. When this option is enabled
+                       very new udev will not work anymore. When this option
+                       is disabled (or CONFIG_SYSFS_DEPRECATED not compiled)
+                       in older udev will not work anymore.
+                       Default depends on CONFIG_SYSFS_DEPRECATED_V2 set in
+                       the kernel configuration.
+
        sysrq_always_enabled
                        [KNL]
                        Ignore sysrq setting - this boot parameter will
index b618b1e..fd19b54 100644 (file)
@@ -2064,14 +2064,16 @@ F:      drivers/block/drbd/
 F:     lib/lru_cache.c
 F:     Documentation/blockdev/drbd/
 
-DRIVER CORE, KOBJECTS, AND SYSFS
+DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS
 M:     Greg Kroah-Hartman <gregkh@suse.de>
 T:     quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
 S:     Supported
 F:     Documentation/kobject.txt
 F:     drivers/base/
 F:     fs/sysfs/
+F:     fs/debugfs/
 F:     include/linux/kobj*
+F:     include/linux/debugfs.h
 F:     lib/kobj*
 
 DRM DRIVERS
index 8313834..a8adf96 100644 (file)
@@ -22,9 +22,7 @@
 #include "blk.h"
 
 static DEFINE_MUTEX(block_class_lock);
-#ifndef CONFIG_SYSFS_DEPRECATED
 struct kobject *block_depr;
-#endif
 
 /* for extended dynamic devt allocation, currently only one major is used */
 #define MAX_EXT_DEVT           (1 << MINORBITS)
@@ -810,10 +808,9 @@ static int __init genhd_device_init(void)
 
        register_blkdev(BLOCK_EXT_MAJOR, "blkext");
 
-#ifndef CONFIG_SYSFS_DEPRECATED
        /* create top-level block dir */
-       block_depr = kobject_create_and_add("block", NULL);
-#endif
+       if (!sysfs_deprecated)
+               block_depr = kobject_create_and_add("block", NULL);
        return 0;
 }
 
index ef38aff..fd96345 100644 (file)
@@ -71,7 +71,6 @@ config PREVENT_FIRMWARE_BUILD
 
 config FW_LOADER
        tristate "Userspace firmware loading support" if EMBEDDED
-       depends on HOTPLUG
        default y
        ---help---
          This option is provided for the case where no in-kernel-tree modules
index c12c7f2..5f51c3b 100644 (file)
@@ -19,7 +19,5 @@ obj-$(CONFIG_MODULES) += module.o
 endif
 obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
 
-ifeq ($(CONFIG_DEBUG_DRIVER),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
 
index eb1b7fa..33c270a 100644 (file)
@@ -440,22 +440,6 @@ static void device_remove_attrs(struct bus_type *bus, struct device *dev)
        }
 }
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-static int make_deprecated_bus_links(struct device *dev)
-{
-       return sysfs_create_link(&dev->kobj,
-                                &dev->bus->p->subsys.kobj, "bus");
-}
-
-static void remove_deprecated_bus_links(struct device *dev)
-{
-       sysfs_remove_link(&dev->kobj, "bus");
-}
-#else
-static inline int make_deprecated_bus_links(struct device *dev) { return 0; }
-static inline void remove_deprecated_bus_links(struct device *dev) { }
-#endif
-
 /**
  * bus_add_device - add device to bus
  * @dev: device being added
@@ -482,15 +466,10 @@ int bus_add_device(struct device *dev)
                                &dev->bus->p->subsys.kobj, "subsystem");
                if (error)
                        goto out_subsys;
-               error = make_deprecated_bus_links(dev);
-               if (error)
-                       goto out_deprecated;
                klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);
        }
        return 0;
 
-out_deprecated:
-       sysfs_remove_link(&dev->kobj, "subsystem");
 out_subsys:
        sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev));
 out_id:
@@ -530,7 +509,6 @@ void bus_remove_device(struct device *dev)
 {
        if (dev->bus) {
                sysfs_remove_link(&dev->kobj, "subsystem");
-               remove_deprecated_bus_links(dev);
                sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
                                  dev_name(dev));
                device_remove_attrs(dev->bus, dev);
index 8e231d0..9c63a56 100644 (file)
@@ -184,9 +184,9 @@ int __class_register(struct class *cls, struct lock_class_key *key)
        if (!cls->dev_kobj)
                cls->dev_kobj = sysfs_dev_char_kobj;
 
-#if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK)
+#if defined(CONFIG_BLOCK)
        /* let the block class directory show up in the root of sysfs */
-       if (cls != &block_class)
+       if (!sysfs_deprecated || cls != &block_class)
                cp->class_subsys.kobj.kset = class_kset;
 #else
        cp->class_subsys.kobj.kset = class_kset;
@@ -276,25 +276,6 @@ void class_destroy(struct class *cls)
        class_unregister(cls);
 }
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-char *make_class_name(const char *name, struct kobject *kobj)
-{
-       char *class_name;
-       int size;
-
-       size = strlen(name) + strlen(kobject_name(kobj)) + 2;
-
-       class_name = kmalloc(size, GFP_KERNEL);
-       if (!class_name)
-               return NULL;
-
-       strcpy(class_name, name);
-       strcat(class_name, ":");
-       strcat(class_name, kobject_name(kobj));
-       return class_name;
-}
-#endif
-
 /**
  * class_dev_iter_init - initialize class device iterator
  * @iter: class iterator to initialize
index d1b2c9a..2cb49a9 100644 (file)
 #include "base.h"
 #include "power/power.h"
 
+#ifdef CONFIG_SYSFS_DEPRECATED
+#ifdef CONFIG_SYSFS_DEPRECATED_V2
+long sysfs_deprecated = 1;
+#else
+long sysfs_deprecated = 0;
+#endif
+static __init int sysfs_deprecated_setup(char *arg)
+{
+       return strict_strtol(arg, 10, &sysfs_deprecated);
+}
+early_param("sysfs.deprecated", sysfs_deprecated_setup);
+#endif
+
 int (*platform_notify)(struct device *dev) = NULL;
 int (*platform_notify_remove)(struct device *dev) = NULL;
 static struct kobject *dev_kobj;
@@ -203,37 +216,6 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
        if (dev->driver)
                add_uevent_var(env, "DRIVER=%s", dev->driver->name);
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-       if (dev->class) {
-               struct device *parent = dev->parent;
-
-               /* find first bus device in parent chain */
-               while (parent && !parent->bus)
-                       parent = parent->parent;
-               if (parent && parent->bus) {
-                       const char *path;
-
-                       path = kobject_get_path(&parent->kobj, GFP_KERNEL);
-                       if (path) {
-                               add_uevent_var(env, "PHYSDEVPATH=%s", path);
-                               kfree(path);
-                       }
-
-                       add_uevent_var(env, "PHYSDEVBUS=%s", parent->bus->name);
-
-                       if (parent->driver)
-                               add_uevent_var(env, "PHYSDEVDRIVER=%s",
-                                              parent->driver->name);
-               }
-       } else if (dev->bus) {
-               add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
-
-               if (dev->driver)
-                       add_uevent_var(env, "PHYSDEVDRIVER=%s",
-                                      dev->driver->name);
-       }
-#endif
-
        /* have the bus specific function add its stuff */
        if (dev->bus && dev->bus->uevent) {
                retval = dev->bus->uevent(dev, env);
@@ -578,24 +560,6 @@ void device_initialize(struct device *dev)
        set_dev_node(dev, -1);
 }
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-static struct kobject *get_device_parent(struct device *dev,
-                                        struct device *parent)
-{
-       /* class devices without a parent live in /sys/class/<classname>/ */
-       if (dev->class && (!parent || parent->class != dev->class))
-               return &dev->class->p->class_subsys.kobj;
-       /* all other devices keep their parent */
-       else if (parent)
-               return &parent->kobj;
-
-       return NULL;
-}
-
-static inline void cleanup_device_parent(struct device *dev) {}
-static inline void cleanup_glue_dir(struct device *dev,
-                                   struct kobject *glue_dir) {}
-#else
 static struct kobject *virtual_device_parent(struct device *dev)
 {
        static struct kobject *virtual_dir = NULL;
@@ -666,6 +630,15 @@ static struct kobject *get_device_parent(struct device *dev,
                struct kobject *parent_kobj;
                struct kobject *k;
 
+#ifdef CONFIG_BLOCK
+               /* block disks show up in /sys/block */
+               if (sysfs_deprecated && dev->class == &block_class) {
+                       if (parent && parent->class == &block_class)
+                               return &parent->kobj;
+                       return &block_class.p->class_subsys.kobj;
+               }
+#endif
+
                /*
                 * If we have no parent, we live in "virtual".
                 * Class-devices with a non class-device as parent, live
@@ -719,7 +692,6 @@ static void cleanup_device_parent(struct device *dev)
 {
        cleanup_glue_dir(dev, dev->kobj.parent);
 }
-#endif
 
 static void setup_parent(struct device *dev, struct device *parent)
 {
@@ -742,70 +714,29 @@ static int device_add_class_symlinks(struct device *dev)
        if (error)
                goto out;
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-       /* stacked class devices need a symlink in the class directory */
-       if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
-           device_is_not_partition(dev)) {
-               error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
-                                         &dev->kobj, dev_name(dev));
-               if (error)
-                       goto out_subsys;
-       }
-
        if (dev->parent && device_is_not_partition(dev)) {
-               struct device *parent = dev->parent;
-               char *class_name;
-
-               /*
-                * stacked class devices have the 'device' link
-                * pointing to the bus device instead of the parent
-                */
-               while (parent->class && !parent->bus && parent->parent)
-                       parent = parent->parent;
-
-               error = sysfs_create_link(&dev->kobj,
-                                         &parent->kobj,
+               error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
                                          "device");
                if (error)
-                       goto out_busid;
-
-               class_name = make_class_name(dev->class->name,
-                                               &dev->kobj);
-               if (class_name)
-                       error = sysfs_create_link(&dev->parent->kobj,
-                                               &dev->kobj, class_name);
-               kfree(class_name);
-               if (error)
-                       goto out_device;
+                       goto out_subsys;
        }
-       return 0;
 
-out_device:
-       if (dev->parent && device_is_not_partition(dev))
-               sysfs_remove_link(&dev->kobj, "device");
-out_busid:
-       if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
-           device_is_not_partition(dev))
-               sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj,
-                                 dev_name(dev));
-#else
+#ifdef CONFIG_BLOCK
+       /* /sys/block has directories and does not need symlinks */
+       if (sysfs_deprecated && dev->class == &block_class)
+               return 0;
+#endif
+
        /* link in the class directory pointing to the device */
        error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
                                  &dev->kobj, dev_name(dev));
        if (error)
-               goto out_subsys;
+               goto out_device;
 
-       if (dev->parent && device_is_not_partition(dev)) {
-               error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
-                                         "device");
-               if (error)
-                       goto out_busid;
-       }
        return 0;
 
-out_busid:
-       sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev));
-#endif
+out_device:
+       sysfs_remove_link(&dev->kobj, "device");
 
 out_subsys:
        sysfs_remove_link(&dev->kobj, "subsystem");
@@ -818,30 +749,14 @@ static void device_remove_class_symlinks(struct device *dev)
        if (!dev->class)
                return;
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-       if (dev->parent && device_is_not_partition(dev)) {
-               char *class_name;
-
-               class_name = make_class_name(dev->class->name, &dev->kobj);
-               if (class_name) {
-                       sysfs_remove_link(&dev->parent->kobj, class_name);
-                       kfree(class_name);
-               }
-               sysfs_remove_link(&dev->kobj, "device");
-       }
-
-       if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
-           device_is_not_partition(dev))
-               sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj,
-                                 dev_name(dev));
-#else
        if (dev->parent && device_is_not_partition(dev))
                sysfs_remove_link(&dev->kobj, "device");
-
-       sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev));
-#endif
-
        sysfs_remove_link(&dev->kobj, "subsystem");
+#ifdef CONFIG_BLOCK
+       if (sysfs_deprecated && dev->class == &block_class)
+               return;
+#endif
+       sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev));
 }
 
 /**
@@ -1613,41 +1528,23 @@ int device_rename(struct device *dev, const char *new_name)
        pr_debug("device: '%s': %s: renaming to '%s'\n", dev_name(dev),
                 __func__, new_name);
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-       if ((dev->class) && (dev->parent))
-               old_class_name = make_class_name(dev->class->name, &dev->kobj);
-#endif
-
        old_device_name = kstrdup(dev_name(dev), GFP_KERNEL);
        if (!old_device_name) {
                error = -ENOMEM;
                goto out;
        }
 
-#ifndef CONFIG_SYSFS_DEPRECATED
        if (dev->class) {
                error = sysfs_rename_link(&dev->class->p->class_subsys.kobj,
                        &dev->kobj, old_device_name, new_name);
                if (error)
                        goto out;
        }
-#endif
+
        error = kobject_rename(&dev->kobj, new_name);
        if (error)
                goto out;
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-       if (old_class_name) {
-               new_class_name = make_class_name(dev->class->name, &dev->kobj);
-               if (new_class_name) {
-                       error = sysfs_rename_link(&dev->parent->kobj,
-                                                 &dev->kobj,
-                                                 old_class_name,
-                                                 new_class_name);
-               }
-       }
-#endif
-
 out:
        put_device(dev);
 
@@ -1664,40 +1561,13 @@ static int device_move_class_links(struct device *dev,
                                   struct device *new_parent)
 {
        int error = 0;
-#ifdef CONFIG_SYSFS_DEPRECATED
-       char *class_name;
 
-       class_name = make_class_name(dev->class->name, &dev->kobj);
-       if (!class_name) {
-               error = -ENOMEM;
-               goto out;
-       }
-       if (old_parent) {
-               sysfs_remove_link(&dev->kobj, "device");
-               sysfs_remove_link(&old_parent->kobj, class_name);
-       }
-       if (new_parent) {
-               error = sysfs_create_link(&dev->kobj, &new_parent->kobj,
-                                         "device");
-               if (error)
-                       goto out;
-               error = sysfs_create_link(&new_parent->kobj, &dev->kobj,
-                                         class_name);
-               if (error)
-                       sysfs_remove_link(&dev->kobj, "device");
-       } else
-               error = 0;
-out:
-       kfree(class_name);
-       return error;
-#else
        if (old_parent)
                sysfs_remove_link(&dev->kobj, "device");
        if (new_parent)
                error = sysfs_create_link(&dev->kobj, &new_parent->kobj,
                                          "device");
        return error;
-#endif
 }
 
 /**
index 933442f..cafeaaf 100644 (file)
@@ -27,6 +27,8 @@
 #include <asm/atomic.h>
 #include <asm/uaccess.h>
 
+static DEFINE_MUTEX(mem_sysfs_mutex);
+
 #define MEMORY_CLASS_NAME      "memory"
 
 static struct sysdev_class memory_sysdev_class = {
@@ -435,6 +437,45 @@ int __weak arch_get_memory_phys_device(unsigned long start_pfn)
        return 0;
 }
 
+struct memory_block *find_memory_block_hinted(struct mem_section *section,
+                                             struct memory_block *hint)
+{
+       struct kobject *kobj;
+       struct sys_device *sysdev;
+       struct memory_block *mem;
+       char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
+
+       kobj = hint ? &hint->sysdev.kobj : NULL;
+
+       /*
+        * This only works because we know that section == sysdev->id
+        * slightly redundant with sysdev_register()
+        */
+       sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section));
+
+       kobj = kset_find_obj_hinted(&memory_sysdev_class.kset, name, kobj);
+       if (!kobj)
+               return NULL;
+
+       sysdev = container_of(kobj, struct sys_device, kobj);
+       mem = container_of(sysdev, struct memory_block, sysdev);
+
+       return mem;
+}
+
+/*
+ * For now, we have a linear search to go find the appropriate
+ * memory_block corresponding to a particular phys_index. If
+ * this gets to be a real problem, we can always use a radix
+ * tree or something here.
+ *
+ * This could be made generic for all sysdev classes.
+ */
+struct memory_block *find_memory_block(struct mem_section *section)
+{
+       return find_memory_block_hinted(section, NULL);
+}
+
 static int add_memory_block(int nid, struct mem_section *section,
                        unsigned long state, enum mem_add_context context)
 {
@@ -445,8 +486,11 @@ static int add_memory_block(int nid, struct mem_section *section,
        if (!mem)
                return -ENOMEM;
 
+       mutex_lock(&mem_sysfs_mutex);
+
        mem->phys_index = __section_nr(section);
        mem->state = state;
+       mem->section_count++;
        mutex_init(&mem->state_mutex);
        start_pfn = section_nr_to_pfn(mem->phys_index);
        mem->phys_device = arch_get_memory_phys_device(start_pfn);
@@ -465,53 +509,29 @@ static int add_memory_block(int nid, struct mem_section *section,
                        ret = register_mem_sect_under_node(mem, nid);
        }
 
+       mutex_unlock(&mem_sysfs_mutex);
        return ret;
 }
 
-/*
- * For now, we have a linear search to go find the appropriate
- * memory_block corresponding to a particular phys_index. If
- * this gets to be a real problem, we can always use a radix
- * tree or something here.
- *
- * This could be made generic for all sysdev classes.
- */
-struct memory_block *find_memory_block(struct mem_section *section)
-{
-       struct kobject *kobj;
-       struct sys_device *sysdev;
-       struct memory_block *mem;
-       char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
-
-       /*
-        * This only works because we know that section == sysdev->id
-        * slightly redundant with sysdev_register()
-        */
-       sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section));
-
-       kobj = kset_find_obj(&memory_sysdev_class.kset, name);
-       if (!kobj)
-               return NULL;
-
-       sysdev = container_of(kobj, struct sys_device, kobj);
-       mem = container_of(sysdev, struct memory_block, sysdev);
-
-       return mem;
-}
-
 int remove_memory_block(unsigned long node_id, struct mem_section *section,
                int phys_device)
 {
        struct memory_block *mem;
 
+       mutex_lock(&mem_sysfs_mutex);
        mem = find_memory_block(section);
-       unregister_mem_sect_under_nodes(mem);
-       mem_remove_simple_file(mem, phys_index);
-       mem_remove_simple_file(mem, state);
-       mem_remove_simple_file(mem, phys_device);
-       mem_remove_simple_file(mem, removable);
-       unregister_memory(mem, section);
 
+       mem->section_count--;
+       if (mem->section_count == 0) {
+               unregister_mem_sect_under_nodes(mem);
+               mem_remove_simple_file(mem, phys_index);
+               mem_remove_simple_file(mem, state);
+               mem_remove_simple_file(mem, phys_device);
+               mem_remove_simple_file(mem, removable);
+               unregister_memory(mem, section);
+       }
+
+       mutex_unlock(&mem_sysfs_mutex);
        return 0;
 }
 
index 2872e86..ee53558 100644 (file)
@@ -409,25 +409,27 @@ static int link_mem_sections(int nid)
        unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn;
        unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_spanned_pages;
        unsigned long pfn;
+       struct memory_block *mem_blk = NULL;
        int err = 0;
 
        for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
                unsigned long section_nr = pfn_to_section_nr(pfn);
                struct mem_section *mem_sect;
-               struct memory_block *mem_blk;
                int ret;
 
                if (!present_section_nr(section_nr))
                        continue;
                mem_sect = __nr_to_section(section_nr);
-               mem_blk = find_memory_block(mem_sect);
+               mem_blk = find_memory_block_hinted(mem_sect, mem_blk);
                ret = register_mem_sect_under_node(mem_blk, nid);
                if (!err)
                        err = ret;
 
                /* discard ref obtained in find_memory_block() */
-               kobject_put(&mem_blk->sysdev.kobj);
        }
+
+       if (mem_blk)
+               kobject_put(&mem_blk->sysdev.kobj);
        return err;
 }
 
index c6c933f..3966e62 100644 (file)
@@ -192,6 +192,9 @@ int platform_device_add_resources(struct platform_device *pdev,
 {
        struct resource *r;
 
+       if (!res)
+               return 0;
+
        r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL);
        if (r) {
                pdev->resource = r;
@@ -215,8 +218,12 @@ EXPORT_SYMBOL_GPL(platform_device_add_resources);
 int platform_device_add_data(struct platform_device *pdev, const void *data,
                             size_t size)
 {
-       void *d = kmemdup(data, size, GFP_KERNEL);
+       void *d;
+
+       if (!data)
+               return 0;
 
+       d = kmemdup(data, size, GFP_KERNEL);
        if (d) {
                pdev->dev.platform_data = d;
                return 0;
@@ -373,17 +380,13 @@ struct platform_device *__init_or_module platform_device_register_resndata(
 
        pdev->dev.parent = parent;
 
-       if (res) {
-               ret = platform_device_add_resources(pdev, res, num);
-               if (ret)
-                       goto err;
-       }
+       ret = platform_device_add_resources(pdev, res, num);
+       if (ret)
+               goto err;
 
-       if (data) {
-               ret = platform_device_add_data(pdev, data, size);
-               if (ret)
-                       goto err;
-       }
+       ret = platform_device_add_data(pdev, data, size);
+       if (ret)
+               goto err;
 
        ret = platform_device_add(pdev);
        if (ret) {
@@ -488,12 +491,12 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv,
         * if the probe was successful, and make sure any forced probes of
         * new devices fail.
         */
-       spin_lock(&platform_bus_type.p->klist_drivers.k_lock);
+       spin_lock(&drv->driver.bus->p->klist_drivers.k_lock);
        drv->probe = NULL;
        if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list))
                retval = -ENODEV;
        drv->driver.probe = platform_drv_probe_fail;
-       spin_unlock(&platform_bus_type.p->klist_drivers.k_lock);
+       spin_unlock(&drv->driver.bus->p->klist_drivers.k_lock);
 
        if (code != retval)
                platform_driver_unregister(drv);
@@ -530,17 +533,13 @@ struct platform_device * __init_or_module platform_create_bundle(
                goto err_out;
        }
 
-       if (res) {
-               error = platform_device_add_resources(pdev, res, n_res);
-               if (error)
-                       goto err_pdev_put;
-       }
+       error = platform_device_add_resources(pdev, res, n_res);
+       if (error)
+               goto err_pdev_put;
 
-       if (data) {
-               error = platform_device_add_data(pdev, data, size);
-               if (error)
-                       goto err_pdev_put;
-       }
+       error = platform_device_add_data(pdev, data, size);
+       if (error)
+               goto err_pdev_put;
 
        error = platform_device_add(pdev);
        if (error)
@@ -976,6 +975,41 @@ struct bus_type platform_bus_type = {
 };
 EXPORT_SYMBOL_GPL(platform_bus_type);
 
+/**
+ * platform_bus_get_pm_ops() - return pointer to busses dev_pm_ops
+ *
+ * This function can be used by platform code to get the current
+ * set of dev_pm_ops functions used by the platform_bus_type.
+ */
+const struct dev_pm_ops * __init platform_bus_get_pm_ops(void)
+{
+       return platform_bus_type.pm;
+}
+
+/**
+ * platform_bus_set_pm_ops() - update dev_pm_ops for the platform_bus_type
+ *
+ * @pm: pointer to new dev_pm_ops struct to be used for platform_bus_type
+ *
+ * Platform code can override the dev_pm_ops methods of
+ * platform_bus_type by using this function.  It is expected that
+ * platform code will first do a platform_bus_get_pm_ops(), then
+ * kmemdup it, then customize selected methods and pass a pointer to
+ * the new struct dev_pm_ops to this function.
+ *
+ * Since platform-specific code is customizing methods for *all*
+ * devices (not just platform-specific devices) it is expected that
+ * any custom overrides of these functions will keep existing behavior
+ * and simply extend it.  For example, any customization of the
+ * runtime PM methods should continue to call the pm_generic_*
+ * functions as the default ones do in addition to the
+ * platform-specific behavior.
+ */
+void __init platform_bus_set_pm_ops(const struct dev_pm_ops *pm)
+{
+       platform_bus_type.pm = pm;
+}
+
 int __init platform_bus_init(void)
 {
        int error;
index 9354dc1..1667aaf 100644 (file)
@@ -432,13 +432,13 @@ int sysdev_suspend(pm_message_t state)
        /* resume current sysdev */
 cls_driver:
        drv = NULL;
-       printk(KERN_ERR "Class suspend failed for %s\n",
-               kobject_name(&sysdev->kobj));
+       printk(KERN_ERR "Class suspend failed for %s: %d\n",
+               kobject_name(&sysdev->kobj), ret);
 
 aux_driver:
        if (drv)
-               printk(KERN_ERR "Class driver suspend failed for %s\n",
-                               kobject_name(&sysdev->kobj));
+               printk(KERN_ERR "Class driver suspend failed for %s: %d\n",
+                               kobject_name(&sysdev->kobj), ret);
        list_for_each_entry(err_drv, &cls->drivers, entry) {
                if (err_drv == drv)
                        break;
index b743312..db2fbe2 100644 (file)
@@ -248,15 +248,15 @@ config CS5535_CLOCK_EVENT_SRC
          generic PIT, and are suitable for use as high-res timers.
 
 config HP_ILO
-       tristate "Channel interface driver for HP iLO/iLO2 processor"
+       tristate "Channel interface driver for the HP iLO processor"
        depends on PCI
        default n
        help
          The channel interface driver allows applications to communicate
-         with iLO/iLO2 management processors present on HP ProLiant
-         servers.  Upon loading, the driver creates /dev/hpilo/dXccbN files,
-         which can be used to gather data from the management processor,
-         via read and write system calls.
+         with iLO management processors present on HP ProLiant servers.
+         Upon loading, the driver creates /dev/hpilo/dXccbN files, which
+         can be used to gather data from the management processor, via
+         read and write system calls.
 
          To compile this driver as a module, choose M here: the
          module will be called hpilo.
@@ -390,6 +390,18 @@ config BMP085
          To compile this driver as a module, choose M here: the
          module will be called bmp085.
 
+config PCH_PHUB
+       tristate "PCH Packet Hub of Intel Topcliff"
+       depends on PCI
+       help
+         This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of
+         Intel Topcliff which is an IOH(Input/Output Hub) for x86 embedded
+         processor. The Topcliff has MAC address and Option ROM data in SROM.
+         This driver can access MAC address and Option ROM data in SROM.
+
+         To compile this driver as a module, choose M here: the module will
+         be called pch_phub.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
index 42eab95..9f2986b 100644 (file)
@@ -35,3 +35,4 @@ obj-y                         += eeprom/
 obj-y                          += cb710/
 obj-$(CONFIG_VMWARE_BALLOON)   += vmw_balloon.o
 obj-$(CONFIG_ARM_CHARLCD)      += arm-charlcd.o
+obj-$(CONFIG_PCH_PHUB)         += pch_phub.o
index 69c1f2f..fffc227 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Driver for HP iLO/iLO2 management processor.
+ * Driver for the HP iLO management processor.
  *
  * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
  *     David Altobelli <david.altobelli@hp.com>
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c
new file mode 100644 (file)
index 0000000..744b804
--- /dev/null
@@ -0,0 +1,717 @@
+/*
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/if_ether.h>
+#include <linux/ctype.h>
+
+#define PHUB_STATUS 0x00               /* Status Register offset */
+#define PHUB_CONTROL 0x04              /* Control Register offset */
+#define PHUB_TIMEOUT 0x05              /* Time out value for Status Register */
+#define PCH_PHUB_ROM_WRITE_ENABLE 0x01 /* Enabling for writing ROM */
+#define PCH_PHUB_ROM_WRITE_DISABLE 0x00        /* Disabling for writing ROM */
+#define PCH_PHUB_ROM_START_ADDR 0x14   /* ROM data area start address offset */
+
+/* MAX number of INT_REDUCE_CONTROL registers */
+#define MAX_NUM_INT_REDUCE_CONTROL_REG 128
+#define PCI_DEVICE_ID_PCH1_PHUB 0x8801
+#define PCH_MINOR_NOS 1
+#define CLKCFG_CAN_50MHZ 0x12000000
+#define CLKCFG_CANCLK_MASK 0xFF000000
+
+/* SROM ACCESS Macro */
+#define PCH_WORD_ADDR_MASK (~((1 << 2) - 1))
+
+/* Registers address offset */
+#define PCH_PHUB_ID_REG                                0x0000
+#define PCH_PHUB_QUEUE_PRI_VAL_REG             0x0004
+#define PCH_PHUB_RC_QUEUE_MAXSIZE_REG          0x0008
+#define PCH_PHUB_BRI_QUEUE_MAXSIZE_REG         0x000C
+#define PCH_PHUB_COMP_RESP_TIMEOUT_REG         0x0010
+#define PCH_PHUB_BUS_SLAVE_CONTROL_REG         0x0014
+#define PCH_PHUB_DEADLOCK_AVOID_TYPE_REG       0x0018
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG0       0x0020
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG1       0x0024
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG2       0x0028
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG3       0x002C
+#define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE   0x0040
+#define CLKCFG_REG_OFFSET                      0x500
+
+#define PCH_PHUB_OROM_SIZE 15360
+
+/**
+ * struct pch_phub_reg - PHUB register structure
+ * @phub_id_reg:                       PHUB_ID register val
+ * @q_pri_val_reg:                     QUEUE_PRI_VAL register val
+ * @rc_q_maxsize_reg:                  RC_QUEUE_MAXSIZE register val
+ * @bri_q_maxsize_reg:                 BRI_QUEUE_MAXSIZE register val
+ * @comp_resp_timeout_reg:             COMP_RESP_TIMEOUT register val
+ * @bus_slave_control_reg:             BUS_SLAVE_CONTROL_REG register val
+ * @deadlock_avoid_type_reg:           DEADLOCK_AVOID_TYPE register val
+ * @intpin_reg_wpermit_reg0:           INTPIN_REG_WPERMIT register 0 val
+ * @intpin_reg_wpermit_reg1:           INTPIN_REG_WPERMIT register 1 val
+ * @intpin_reg_wpermit_reg2:           INTPIN_REG_WPERMIT register 2 val
+ * @intpin_reg_wpermit_reg3:           INTPIN_REG_WPERMIT register 3 val
+ * @int_reduce_control_reg:            INT_REDUCE_CONTROL registers val
+ * @clkcfg_reg:                                CLK CFG register val
+ * @pch_phub_base_address:             Register base address
+ * @pch_phub_extrom_base_address:      external rom base address
+ */
+struct pch_phub_reg {
+       u32 phub_id_reg;
+       u32 q_pri_val_reg;
+       u32 rc_q_maxsize_reg;
+       u32 bri_q_maxsize_reg;
+       u32 comp_resp_timeout_reg;
+       u32 bus_slave_control_reg;
+       u32 deadlock_avoid_type_reg;
+       u32 intpin_reg_wpermit_reg0;
+       u32 intpin_reg_wpermit_reg1;
+       u32 intpin_reg_wpermit_reg2;
+       u32 intpin_reg_wpermit_reg3;
+       u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
+       u32 clkcfg_reg;
+       void __iomem *pch_phub_base_address;
+       void __iomem *pch_phub_extrom_base_address;
+};
+
+/* SROM SPEC for MAC address assignment offset */
+static const int pch_phub_mac_offset[ETH_ALEN] = {0x3, 0x2, 0x1, 0x0, 0xb, 0xa};
+
+static DEFINE_MUTEX(pch_phub_mutex);
+
+/**
+ * pch_phub_read_modify_write_reg() - Reading modifying and writing register
+ * @reg_addr_offset:   Register offset address value.
+ * @data:              Writing value.
+ * @mask:              Mask value.
+ */
+static void pch_phub_read_modify_write_reg(struct pch_phub_reg *chip,
+                                          unsigned int reg_addr_offset,
+                                          unsigned int data, unsigned int mask)
+{
+       void __iomem *reg_addr = chip->pch_phub_base_address + reg_addr_offset;
+       iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr);
+}
+
+/* pch_phub_save_reg_conf - saves register configuration */
+static void pch_phub_save_reg_conf(struct pci_dev *pdev)
+{
+       unsigned int i;
+       struct pch_phub_reg *chip = pci_get_drvdata(pdev);
+
+       void __iomem *p = chip->pch_phub_base_address;
+
+       chip->phub_id_reg = ioread32(p + PCH_PHUB_ID_REG);
+       chip->q_pri_val_reg = ioread32(p + PCH_PHUB_QUEUE_PRI_VAL_REG);
+       chip->rc_q_maxsize_reg = ioread32(p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+       chip->bri_q_maxsize_reg = ioread32(p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+       chip->comp_resp_timeout_reg =
+                               ioread32(p + PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+       chip->bus_slave_control_reg =
+                               ioread32(p + PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+       chip->deadlock_avoid_type_reg =
+                               ioread32(p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+       chip->intpin_reg_wpermit_reg0 =
+                               ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+       chip->intpin_reg_wpermit_reg1 =
+                               ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+       chip->intpin_reg_wpermit_reg2 =
+                               ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+       chip->intpin_reg_wpermit_reg3 =
+                               ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+       dev_dbg(&pdev->dev, "%s : "
+               "chip->phub_id_reg=%x, "
+               "chip->q_pri_val_reg=%x, "
+               "chip->rc_q_maxsize_reg=%x, "
+               "chip->bri_q_maxsize_reg=%x, "
+               "chip->comp_resp_timeout_reg=%x, "
+               "chip->bus_slave_control_reg=%x, "
+               "chip->deadlock_avoid_type_reg=%x, "
+               "chip->intpin_reg_wpermit_reg0=%x, "
+               "chip->intpin_reg_wpermit_reg1=%x, "
+               "chip->intpin_reg_wpermit_reg2=%x, "
+               "chip->intpin_reg_wpermit_reg3=%x\n", __func__,
+               chip->phub_id_reg,
+               chip->q_pri_val_reg,
+               chip->rc_q_maxsize_reg,
+               chip->bri_q_maxsize_reg,
+               chip->comp_resp_timeout_reg,
+               chip->bus_slave_control_reg,
+               chip->deadlock_avoid_type_reg,
+               chip->intpin_reg_wpermit_reg0,
+               chip->intpin_reg_wpermit_reg1,
+               chip->intpin_reg_wpermit_reg2,
+               chip->intpin_reg_wpermit_reg3);
+       for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+               chip->int_reduce_control_reg[i] =
+                   ioread32(p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+               dev_dbg(&pdev->dev, "%s : "
+                       "chip->int_reduce_control_reg[%d]=%x\n",
+                       __func__, i, chip->int_reduce_control_reg[i]);
+       }
+       chip->clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET);
+}
+
+/* pch_phub_restore_reg_conf - restore register configuration */
+static void pch_phub_restore_reg_conf(struct pci_dev *pdev)
+{
+       unsigned int i;
+       struct pch_phub_reg *chip = pci_get_drvdata(pdev);
+       void __iomem *p;
+       p = chip->pch_phub_base_address;
+
+       iowrite32(chip->phub_id_reg, p + PCH_PHUB_ID_REG);
+       iowrite32(chip->q_pri_val_reg, p + PCH_PHUB_QUEUE_PRI_VAL_REG);
+       iowrite32(chip->rc_q_maxsize_reg, p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+       iowrite32(chip->bri_q_maxsize_reg, p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+       iowrite32(chip->comp_resp_timeout_reg,
+                                       p + PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+       iowrite32(chip->bus_slave_control_reg,
+                                       p + PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+       iowrite32(chip->deadlock_avoid_type_reg,
+                                       p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+       iowrite32(chip->intpin_reg_wpermit_reg0,
+                                       p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+       iowrite32(chip->intpin_reg_wpermit_reg1,
+                                       p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+       iowrite32(chip->intpin_reg_wpermit_reg2,
+                                       p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+       iowrite32(chip->intpin_reg_wpermit_reg3,
+                                       p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+       dev_dbg(&pdev->dev, "%s : "
+               "chip->phub_id_reg=%x, "
+               "chip->q_pri_val_reg=%x, "
+               "chip->rc_q_maxsize_reg=%x, "
+               "chip->bri_q_maxsize_reg=%x, "
+               "chip->comp_resp_timeout_reg=%x, "
+               "chip->bus_slave_control_reg=%x, "
+               "chip->deadlock_avoid_type_reg=%x, "
+               "chip->intpin_reg_wpermit_reg0=%x, "
+               "chip->intpin_reg_wpermit_reg1=%x, "
+               "chip->intpin_reg_wpermit_reg2=%x, "
+               "chip->intpin_reg_wpermit_reg3=%x\n", __func__,
+               chip->phub_id_reg,
+               chip->q_pri_val_reg,
+               chip->rc_q_maxsize_reg,
+               chip->bri_q_maxsize_reg,
+               chip->comp_resp_timeout_reg,
+               chip->bus_slave_control_reg,
+               chip->deadlock_avoid_type_reg,
+               chip->intpin_reg_wpermit_reg0,
+               chip->intpin_reg_wpermit_reg1,
+               chip->intpin_reg_wpermit_reg2,
+               chip->intpin_reg_wpermit_reg3);
+       for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+               iowrite32(chip->int_reduce_control_reg[i],
+                       p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+               dev_dbg(&pdev->dev, "%s : "
+                       "chip->int_reduce_control_reg[%d]=%x\n",
+                       __func__, i, chip->int_reduce_control_reg[i]);
+       }
+
+       iowrite32(chip->clkcfg_reg, p + CLKCFG_REG_OFFSET);
+}
+
+/**
+ * pch_phub_read_serial_rom() - Reading Serial ROM
+ * @offset_address:    Serial ROM offset address to read.
+ * @data:              Read buffer for specified Serial ROM value.
+ */
+static void pch_phub_read_serial_rom(struct pch_phub_reg *chip,
+                                    unsigned int offset_address, u8 *data)
+{
+       void __iomem *mem_addr = chip->pch_phub_extrom_base_address +
+                                                               offset_address;
+
+       *data = ioread8(mem_addr);
+}
+
+/**
+ * pch_phub_write_serial_rom() - Writing Serial ROM
+ * @offset_address:    Serial ROM offset address.
+ * @data:              Serial ROM value to write.
+ */
+static int pch_phub_write_serial_rom(struct pch_phub_reg *chip,
+                                    unsigned int offset_address, u8 data)
+{
+       void __iomem *mem_addr = chip->pch_phub_extrom_base_address +
+                                       (offset_address & PCH_WORD_ADDR_MASK);
+       int i;
+       unsigned int word_data;
+       unsigned int pos;
+       unsigned int mask;
+       pos = (offset_address % 4) * 8;
+       mask = ~(0xFF << pos);
+
+       iowrite32(PCH_PHUB_ROM_WRITE_ENABLE,
+                       chip->pch_phub_extrom_base_address + PHUB_CONTROL);
+
+       word_data = ioread32(mem_addr);
+       iowrite32((word_data & mask) | (u32)data << pos, mem_addr);
+
+       i = 0;
+       while (ioread8(chip->pch_phub_extrom_base_address +
+                                               PHUB_STATUS) != 0x00) {
+               msleep(1);
+               if (i == PHUB_TIMEOUT)
+                       return -ETIMEDOUT;
+               i++;
+       }
+
+       iowrite32(PCH_PHUB_ROM_WRITE_DISABLE,
+                       chip->pch_phub_extrom_base_address + PHUB_CONTROL);
+
+       return 0;
+}
+
+/**
+ * pch_phub_read_serial_rom_val() - Read Serial ROM value
+ * @offset_address:    Serial ROM address offset value.
+ * @data:              Serial ROM value to read.
+ */
+static void pch_phub_read_serial_rom_val(struct pch_phub_reg *chip,
+                                        unsigned int offset_address, u8 *data)
+{
+       unsigned int mem_addr;
+
+       mem_addr = PCH_PHUB_ROM_START_ADDR +
+                       pch_phub_mac_offset[offset_address];
+
+       pch_phub_read_serial_rom(chip, mem_addr, data);
+}
+
+/**
+ * pch_phub_write_serial_rom_val() - writing Serial ROM value
+ * @offset_address:    Serial ROM address offset value.
+ * @data:              Serial ROM value.
+ */
+static int pch_phub_write_serial_rom_val(struct pch_phub_reg *chip,
+                                        unsigned int offset_address, u8 data)
+{
+       int retval;
+       unsigned int mem_addr;
+
+       mem_addr = PCH_PHUB_ROM_START_ADDR +
+                       pch_phub_mac_offset[offset_address];
+
+       retval = pch_phub_write_serial_rom(chip, mem_addr, data);
+
+       return retval;
+}
+
+/* pch_phub_gbe_serial_rom_conf - makes Serial ROM header format configuration
+ * for Gigabit Ethernet MAC address
+ */
+static int pch_phub_gbe_serial_rom_conf(struct pch_phub_reg *chip)
+{
+       int retval;
+
+       retval = pch_phub_write_serial_rom(chip, 0x0b, 0xbc);
+       retval |= pch_phub_write_serial_rom(chip, 0x0a, 0x10);
+       retval |= pch_phub_write_serial_rom(chip, 0x09, 0x01);
+       retval |= pch_phub_write_serial_rom(chip, 0x08, 0x02);
+
+       retval |= pch_phub_write_serial_rom(chip, 0x0f, 0x00);
+       retval |= pch_phub_write_serial_rom(chip, 0x0e, 0x00);
+       retval |= pch_phub_write_serial_rom(chip, 0x0d, 0x00);
+       retval |= pch_phub_write_serial_rom(chip, 0x0c, 0x80);
+
+       retval |= pch_phub_write_serial_rom(chip, 0x13, 0xbc);
+       retval |= pch_phub_write_serial_rom(chip, 0x12, 0x10);
+       retval |= pch_phub_write_serial_rom(chip, 0x11, 0x01);
+       retval |= pch_phub_write_serial_rom(chip, 0x10, 0x18);
+
+       retval |= pch_phub_write_serial_rom(chip, 0x1b, 0xbc);
+       retval |= pch_phub_write_serial_rom(chip, 0x1a, 0x10);
+       retval |= pch_phub_write_serial_rom(chip, 0x19, 0x01);
+       retval |= pch_phub_write_serial_rom(chip, 0x18, 0x19);
+
+       retval |= pch_phub_write_serial_rom(chip, 0x23, 0xbc);
+       retval |= pch_phub_write_serial_rom(chip, 0x22, 0x10);
+       retval |= pch_phub_write_serial_rom(chip, 0x21, 0x01);
+       retval |= pch_phub_write_serial_rom(chip, 0x20, 0x3a);
+
+       retval |= pch_phub_write_serial_rom(chip, 0x27, 0x01);
+       retval |= pch_phub_write_serial_rom(chip, 0x26, 0x00);
+       retval |= pch_phub_write_serial_rom(chip, 0x25, 0x00);
+       retval |= pch_phub_write_serial_rom(chip, 0x24, 0x00);
+
+       return retval;
+}
+
+/**
+ * pch_phub_read_gbe_mac_addr() - Read Gigabit Ethernet MAC address
+ * @offset_address:    Gigabit Ethernet MAC address offset value.
+ * @data:              Buffer of the Gigabit Ethernet MAC address value.
+ */
+static void pch_phub_read_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data)
+{
+       int i;
+       for (i = 0; i < ETH_ALEN; i++)
+               pch_phub_read_serial_rom_val(chip, i, &data[i]);
+}
+
+/**
+ * pch_phub_write_gbe_mac_addr() - Write MAC address
+ * @offset_address:    Gigabit Ethernet MAC address offset value.
+ * @data:              Gigabit Ethernet MAC address value.
+ */
+static int pch_phub_write_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data)
+{
+       int retval;
+       int i;
+
+       retval = pch_phub_gbe_serial_rom_conf(chip);
+       if (retval)
+               return retval;
+
+       for (i = 0; i < ETH_ALEN; i++) {
+               retval = pch_phub_write_serial_rom_val(chip, i, data[i]);
+               if (retval)
+                       return retval;
+       }
+
+       return retval;
+}
+
+static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
+                                struct bin_attribute *attr, char *buf,
+                                loff_t off, size_t count)
+{
+       unsigned int rom_signature;
+       unsigned char rom_length;
+       unsigned int tmp;
+       unsigned int addr_offset;
+       unsigned int orom_size;
+       int ret;
+       int err;
+
+       struct pch_phub_reg *chip =
+               dev_get_drvdata(container_of(kobj, struct device, kobj));
+
+       ret = mutex_lock_interruptible(&pch_phub_mutex);
+       if (ret) {
+               err = -ERESTARTSYS;
+               goto return_err_nomutex;
+       }
+
+       /* Get Rom signature */
+       pch_phub_read_serial_rom(chip, 0x80, (unsigned char *)&rom_signature);
+       rom_signature &= 0xff;
+       pch_phub_read_serial_rom(chip, 0x81, (unsigned char *)&tmp);
+       rom_signature |= (tmp & 0xff) << 8;
+       if (rom_signature == 0xAA55) {
+               pch_phub_read_serial_rom(chip, 0x82, &rom_length);
+               orom_size = rom_length * 512;
+               if (orom_size < off) {
+                       addr_offset = 0;
+                       goto return_ok;
+               }
+               if (orom_size < count) {
+                       addr_offset = 0;
+                       goto return_ok;
+               }
+
+               for (addr_offset = 0; addr_offset < count; addr_offset++) {
+                       pch_phub_read_serial_rom(chip, 0x80 + addr_offset + off,
+                                                        &buf[addr_offset]);
+               }
+       } else {
+               err = -ENODATA;
+               goto return_err;
+       }
+return_ok:
+       mutex_unlock(&pch_phub_mutex);
+       return addr_offset;
+
+return_err:
+       mutex_unlock(&pch_phub_mutex);
+return_err_nomutex:
+       return err;
+}
+
+static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,
+                                 struct bin_attribute *attr,
+                                 char *buf, loff_t off, size_t count)
+{
+       int err;
+       unsigned int addr_offset;
+       int ret;
+       struct pch_phub_reg *chip =
+               dev_get_drvdata(container_of(kobj, struct device, kobj));
+
+       ret = mutex_lock_interruptible(&pch_phub_mutex);
+       if (ret)
+               return -ERESTARTSYS;
+
+       if (off > PCH_PHUB_OROM_SIZE) {
+               addr_offset = 0;
+               goto return_ok;
+       }
+       if (count > PCH_PHUB_OROM_SIZE) {
+               addr_offset = 0;
+               goto return_ok;
+       }
+
+       for (addr_offset = 0; addr_offset < count; addr_offset++) {
+               if (PCH_PHUB_OROM_SIZE < off + addr_offset)
+                       goto return_ok;
+
+               ret = pch_phub_write_serial_rom(chip, 0x80 + addr_offset + off,
+                                                      buf[addr_offset]);
+               if (ret) {
+                       err = ret;
+                       goto return_err;
+               }
+       }
+
+return_ok:
+       mutex_unlock(&pch_phub_mutex);
+       return addr_offset;
+
+return_err:
+       mutex_unlock(&pch_phub_mutex);
+       return err;
+}
+
+static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       u8 mac[8];
+       struct pch_phub_reg *chip = dev_get_drvdata(dev);
+
+       pch_phub_read_gbe_mac_addr(chip, mac);
+
+       return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
+                               mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+}
+
+static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,
+                            const char *buf, size_t count)
+{
+       u8 mac[6];
+       struct pch_phub_reg *chip = dev_get_drvdata(dev);
+
+       if (count != 18)
+               return -EINVAL;
+
+       sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
+               (u32 *)&mac[0], (u32 *)&mac[1], (u32 *)&mac[2], (u32 *)&mac[3],
+               (u32 *)&mac[4], (u32 *)&mac[5]);
+
+       pch_phub_write_gbe_mac_addr(chip, mac);
+
+       return count;
+}
+
+static DEVICE_ATTR(pch_mac, S_IRUGO | S_IWUSR, show_pch_mac, store_pch_mac);
+
+static struct bin_attribute pch_bin_attr = {
+       .attr = {
+               .name = "pch_firmware",
+               .mode = S_IRUGO | S_IWUSR,
+       },
+       .size = PCH_PHUB_OROM_SIZE + 1,
+       .read = pch_phub_bin_read,
+       .write = pch_phub_bin_write,
+};
+
+static int __devinit pch_phub_probe(struct pci_dev *pdev,
+                                   const struct pci_device_id *id)
+{
+       int retval;
+
+       int ret;
+       ssize_t rom_size;
+       struct pch_phub_reg *chip;
+
+       chip = kzalloc(sizeof(struct pch_phub_reg), GFP_KERNEL);
+       if (chip == NULL)
+               return -ENOMEM;
+
+       ret = pci_enable_device(pdev);
+       if (ret) {
+               dev_err(&pdev->dev,
+               "%s : pci_enable_device FAILED(ret=%d)", __func__, ret);
+               goto err_pci_enable_dev;
+       }
+       dev_dbg(&pdev->dev, "%s : pci_enable_device returns %d\n", __func__,
+               ret);
+
+       ret = pci_request_regions(pdev, KBUILD_MODNAME);
+       if (ret) {
+               dev_err(&pdev->dev,
+               "%s : pci_request_regions FAILED(ret=%d)", __func__, ret);
+               goto err_req_regions;
+       }
+       dev_dbg(&pdev->dev, "%s : "
+               "pci_request_regions returns %d\n", __func__, ret);
+
+       chip->pch_phub_base_address = pci_iomap(pdev, 1, 0);
+
+
+       if (chip->pch_phub_base_address == 0) {
+               dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
+               ret = -ENOMEM;
+               goto err_pci_iomap;
+       }
+       dev_dbg(&pdev->dev, "%s : pci_iomap SUCCESS and value "
+               "in pch_phub_base_address variable is %p\n", __func__,
+               chip->pch_phub_base_address);
+       chip->pch_phub_extrom_base_address = pci_map_rom(pdev, &rom_size);
+
+       if (chip->pch_phub_extrom_base_address == 0) {
+               dev_err(&pdev->dev, "%s : pci_map_rom FAILED", __func__);
+               ret = -ENOMEM;
+               goto err_pci_map;
+       }
+       dev_dbg(&pdev->dev, "%s : "
+               "pci_map_rom SUCCESS and value in "
+               "pch_phub_extrom_base_address variable is %p\n", __func__,
+               chip->pch_phub_extrom_base_address);
+
+       pci_set_drvdata(pdev, chip);
+
+       retval = sysfs_create_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
+       if (retval)
+               goto err_sysfs_create;
+
+       retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
+       if (retval)
+               goto exit_bin_attr;
+
+       pch_phub_read_modify_write_reg(chip, (unsigned int)CLKCFG_REG_OFFSET,
+                                       CLKCFG_CAN_50MHZ, CLKCFG_CANCLK_MASK);
+
+       /* set the prefech value */
+       iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14);
+       /* set the interrupt delay value */
+       iowrite32(0x25, chip->pch_phub_base_address + 0x44);
+
+       return 0;
+exit_bin_attr:
+       sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
+
+err_sysfs_create:
+       pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
+err_pci_map:
+       pci_iounmap(pdev, chip->pch_phub_base_address);
+err_pci_iomap:
+       pci_release_regions(pdev);
+err_req_regions:
+       pci_disable_device(pdev);
+err_pci_enable_dev:
+       kfree(chip);
+       dev_err(&pdev->dev, "%s returns %d\n", __func__, ret);
+       return ret;
+}
+
+static void __devexit pch_phub_remove(struct pci_dev *pdev)
+{
+       struct pch_phub_reg *chip = pci_get_drvdata(pdev);
+
+       sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
+       sysfs_remove_bin_file(&pdev->dev.kobj, &pch_bin_attr);
+       pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
+       pci_iounmap(pdev, chip->pch_phub_base_address);
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+       kfree(chip);
+}
+
+#ifdef CONFIG_PM
+
+static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       int ret;
+
+       pch_phub_save_reg_conf(pdev);
+       ret = pci_save_state(pdev);
+       if (ret) {
+               dev_err(&pdev->dev,
+                       " %s -pci_save_state returns %d\n", __func__, ret);
+               return ret;
+       }
+       pci_enable_wake(pdev, PCI_D3hot, 0);
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+       return 0;
+}
+
+static int pch_phub_resume(struct pci_dev *pdev)
+{
+       int ret;
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       ret = pci_enable_device(pdev);
+       if (ret) {
+               dev_err(&pdev->dev,
+               "%s-pci_enable_device failed(ret=%d) ", __func__, ret);
+               return ret;
+       }
+
+       pci_enable_wake(pdev, PCI_D3hot, 0);
+       pch_phub_restore_reg_conf(pdev);
+
+       return 0;
+}
+#else
+#define pch_phub_suspend NULL
+#define pch_phub_resume NULL
+#endif /* CONFIG_PM */
+
+static struct pci_device_id pch_phub_pcidev_id[] = {
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)},
+       {0,}
+};
+
+static struct pci_driver pch_phub_driver = {
+       .name = "pch_phub",
+       .id_table = pch_phub_pcidev_id,
+       .probe = pch_phub_probe,
+       .remove = __devexit_p(pch_phub_remove),
+       .suspend = pch_phub_suspend,
+       .resume = pch_phub_resume
+};
+
+static int __init pch_phub_pci_init(void)
+{
+       return pci_register_driver(&pch_phub_driver);
+}
+
+static void __exit pch_phub_pci_exit(void)
+{
+       pci_unregister_driver(&pch_phub_driver);
+}
+
+module_init(pch_phub_pci_init);
+module_exit(pch_phub_pci_exit);
+
+MODULE_DESCRIPTION("PCH Packet Hub PCI Driver");
+MODULE_LICENSE("GPL");
index 1047815..4f7a582 100644 (file)
@@ -412,9 +412,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
 
        device_initialize(&shost->shost_gendev);
        dev_set_name(&shost->shost_gendev, "host%d", shost->host_no);
-#ifndef CONFIG_SYSFS_DEPRECATED
        shost->shost_gendev.bus = &scsi_bus_type;
-#endif
        shost->shost_gendev.type = &scsi_host_type;
 
        device_initialize(&shost->shost_dev);
index 3d0a1e6..087821f 100644 (file)
@@ -417,9 +417,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
        starget->reap_ref = 1;
        dev->parent = get_device(parent);
        dev_set_name(dev, "target%d:%d:%d", shost->host_no, channel, id);
-#ifndef CONFIG_SYSFS_DEPRECATED
        dev->bus = &scsi_bus_type;
-#endif
        dev->type = &scsi_target_type;
        starget->id = id;
        starget->channel = channel;
index 4d3a6fd..a858d2b 100644 (file)
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/kobject.h>
+#include <linux/cdev.h>
 #include <linux/uio_driver.h>
 
-#define UIO_MAX_DEVICES 255
+#define UIO_MAX_DEVICES                (1U << MINORBITS)
 
 struct uio_device {
        struct module           *owner;
@@ -41,15 +42,10 @@ struct uio_device {
 };
 
 static int uio_major;
+static struct cdev *uio_cdev;
 static DEFINE_IDR(uio_idr);
 static const struct file_operations uio_fops;
 
-/* UIO class infrastructure */
-static struct uio_class {
-       struct kref kref;
-       struct class *class;
-} *uio_class;
-
 /* Protect idr accesses */
 static DEFINE_MUTEX(minor_lock);
 
@@ -232,45 +228,34 @@ static ssize_t show_name(struct device *dev,
                         struct device_attribute *attr, char *buf)
 {
        struct uio_device *idev = dev_get_drvdata(dev);
-       if (idev)
-               return sprintf(buf, "%s\n", idev->info->name);
-       else
-               return -ENODEV;
+       return sprintf(buf, "%s\n", idev->info->name);
 }
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
 static ssize_t show_version(struct device *dev,
                            struct device_attribute *attr, char *buf)
 {
        struct uio_device *idev = dev_get_drvdata(dev);
-       if (idev)
-               return sprintf(buf, "%s\n", idev->info->version);
-       else
-               return -ENODEV;
+       return sprintf(buf, "%s\n", idev->info->version);
 }
-static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
 
 static ssize_t show_event(struct device *dev,
                          struct device_attribute *attr, char *buf)
 {
        struct uio_device *idev = dev_get_drvdata(dev);
-       if (idev)
-               return sprintf(buf, "%u\n",
-                               (unsigned int)atomic_read(&idev->event));
-       else
-               return -ENODEV;
+       return sprintf(buf, "%u\n", (unsigned int)atomic_read(&idev->event));
 }
-static DEVICE_ATTR(event, S_IRUGO, show_event, NULL);
 
-static struct attribute *uio_attrs[] = {
-       &dev_attr_name.attr,
-       &dev_attr_version.attr,
-       &dev_attr_event.attr,
-       NULL,
+static struct device_attribute uio_class_attributes[] = {
+       __ATTR(name, S_IRUGO, show_name, NULL),
+       __ATTR(version, S_IRUGO, show_version, NULL),
+       __ATTR(event, S_IRUGO, show_event, NULL),
+       {}
 };
 
-static struct attribute_group uio_attr_grp = {
-       .attrs = uio_attrs,
+/* UIO class infrastructure */
+static struct class uio_class = {
+       .name = "uio",
+       .dev_attrs = uio_class_attributes,
 };
 
 /*
@@ -287,10 +272,6 @@ static int uio_dev_add_attributes(struct uio_device *idev)
        struct uio_port *port;
        struct uio_portio *portio;
 
-       ret = sysfs_create_group(&idev->dev->kobj, &uio_attr_grp);
-       if (ret)
-               goto err_group;
-
        for (mi = 0; mi < MAX_UIO_MAPS; mi++) {
                mem = &idev->info->mem[mi];
                if (mem->size == 0)
@@ -358,8 +339,6 @@ err_map:
                kobject_put(&map->kobj);
        }
        kobject_put(idev->map_dir);
-       sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
-err_group:
        dev_err(idev->dev, "error creating sysfs files (%d)\n", ret);
        return ret;
 }
@@ -385,8 +364,6 @@ static void uio_dev_del_attributes(struct uio_device *idev)
                kobject_put(&port->portio->kobj);
        }
        kobject_put(idev->portio_dir);
-
-       sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
 }
 
 static int uio_get_minor(struct uio_device *idev)
@@ -525,7 +502,7 @@ static unsigned int uio_poll(struct file *filep, poll_table *wait)
        struct uio_listener *listener = filep->private_data;
        struct uio_device *idev = listener->dev;
 
-       if (idev->info->irq == UIO_IRQ_NONE)
+       if (!idev->info->irq)
                return -EIO;
 
        poll_wait(filep, &idev->wait, wait);
@@ -543,7 +520,7 @@ static ssize_t uio_read(struct file *filep, char __user *buf,
        ssize_t retval;
        s32 event_count;
 
-       if (idev->info->irq == UIO_IRQ_NONE)
+       if (!idev->info->irq)
                return -EIO;
 
        if (count != sizeof(s32))
@@ -591,7 +568,7 @@ static ssize_t uio_write(struct file *filep, const char __user *buf,
        ssize_t retval;
        s32 irq_on;
 
-       if (idev->info->irq == UIO_IRQ_NONE)
+       if (!idev->info->irq)
                return -EIO;
 
        if (count != sizeof(s32))
@@ -745,68 +722,72 @@ static const struct file_operations uio_fops = {
 
 static int uio_major_init(void)
 {
-       uio_major = register_chrdev(0, "uio", &uio_fops);
-       if (uio_major < 0)
-               return uio_major;
-       return 0;
+       static const char name[] = "uio";
+       struct cdev *cdev = NULL;
+       dev_t uio_dev = 0;
+       int result;
+
+       result = alloc_chrdev_region(&uio_dev, 0, UIO_MAX_DEVICES, name);
+       if (result)
+               goto out;
+
+       result = -ENOMEM;
+       cdev = cdev_alloc();
+       if (!cdev)
+               goto out_unregister;
+
+       cdev->owner = THIS_MODULE;
+       cdev->ops = &uio_fops;
+       kobject_set_name(&cdev->kobj, "%s", name);
+
+       result = cdev_add(cdev, uio_dev, UIO_MAX_DEVICES);
+       if (result)
+               goto out_put;
+
+       uio_major = MAJOR(uio_dev);
+       uio_cdev = cdev;
+       result = 0;
+out:
+       return result;
+out_put:
+       kobject_put(&cdev->kobj);
+out_unregister:
+       unregister_chrdev_region(uio_dev, UIO_MAX_DEVICES);
+       goto out;
 }
 
 static void uio_major_cleanup(void)
 {
-       unregister_chrdev(uio_major, "uio");
+       unregister_chrdev_region(MKDEV(uio_major, 0), UIO_MAX_DEVICES);
+       cdev_del(uio_cdev);
 }
 
 static int init_uio_class(void)
 {
-       int ret = 0;
-
-       if (uio_class != NULL) {
-               kref_get(&uio_class->kref);
-               goto exit;
-       }
+       int ret;
 
        /* This is the first time in here, set everything up properly */
        ret = uio_major_init();
        if (ret)
                goto exit;
 
-       uio_class = kzalloc(sizeof(*uio_class), GFP_KERNEL);
-       if (!uio_class) {
-               ret = -ENOMEM;
-               goto err_kzalloc;
-       }
-
-       kref_init(&uio_class->kref);
-       uio_class->class = class_create(THIS_MODULE, "uio");
-       if (IS_ERR(uio_class->class)) {
-               ret = IS_ERR(uio_class->class);
-               printk(KERN_ERR "class_create failed for uio\n");
-               goto err_class_create;
+       ret = class_register(&uio_class);
+       if (ret) {
+               printk(KERN_ERR "class_register failed for uio\n");
+               goto err_class_register;
        }
        return 0;
 
-err_class_create:
-       kfree(uio_class);
-       uio_class = NULL;
-err_kzalloc:
+err_class_register:
        uio_major_cleanup();
 exit:
        return ret;
 }
 
-static void release_uio_class(struct kref *kref)
+static void release_uio_class(void)
 {
-       /* Ok, we cheat as we know we only have one uio_class */
-       class_destroy(uio_class->class);
-       kfree(uio_class);
+       class_unregister(&uio_class);
        uio_major_cleanup();
-       uio_class = NULL;
-}
-
-static void uio_class_destroy(void)
-{
-       if (uio_class)
-               kref_put(&uio_class->kref, release_uio_class);
 }
 
 /**
@@ -829,10 +810,6 @@ int __uio_register_device(struct module *owner,
 
        info->uio_dev = NULL;
 
-       ret = init_uio_class();
-       if (ret)
-               return ret;
-
        idev = kzalloc(sizeof(*idev), GFP_KERNEL);
        if (!idev) {
                ret = -ENOMEM;
@@ -848,7 +825,7 @@ int __uio_register_device(struct module *owner,
        if (ret)
                goto err_get_minor;
 
-       idev->dev = device_create(uio_class->class, parent,
+       idev->dev = device_create(&uio_class, parent,
                                  MKDEV(uio_major, idev->minor), idev,
                                  "uio%d", idev->minor);
        if (IS_ERR(idev->dev)) {
@@ -863,9 +840,9 @@ int __uio_register_device(struct module *owner,
 
        info->uio_dev = idev;
 
-       if (idev->info->irq >= 0) {
-               ret = request_irq(idev->info->irq, uio_interrupt,
-                                 idev->info->irq_flags, idev->info->name, idev);
+       if (info->irq && (info->irq != UIO_IRQ_CUSTOM)) {
+               ret = request_irq(info->irq, uio_interrupt,
+                                 info->irq_flags, info->name, idev);
                if (ret)
                        goto err_request_irq;
        }
@@ -875,13 +852,12 @@ int __uio_register_device(struct module *owner,
 err_request_irq:
        uio_dev_del_attributes(idev);
 err_uio_dev_add_attributes:
-       device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));
+       device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
 err_device_create:
        uio_free_minor(idev);
 err_get_minor:
        kfree(idev);
 err_kzalloc:
-       uio_class_destroy();
        return ret;
 }
 EXPORT_SYMBOL_GPL(__uio_register_device);
@@ -902,15 +878,13 @@ void uio_unregister_device(struct uio_info *info)
 
        uio_free_minor(idev);
 
-       if (info->irq >= 0)
+       if (info->irq && (info->irq != UIO_IRQ_CUSTOM))
                free_irq(info->irq, idev);
 
        uio_dev_del_attributes(idev);
 
-       dev_set_drvdata(idev->dev, NULL);
-       device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));
+       device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
        kfree(idev);
-       uio_class_destroy();
 
        return;
 }
@@ -918,11 +892,12 @@ EXPORT_SYMBOL_GPL(uio_unregister_device);
 
 static int __init uio_init(void)
 {
-       return 0;
+       return init_uio_class();
 }
 
 static void __exit uio_exit(void)
 {
+       release_uio_class();
 }
 
 module_init(uio_init)
index 85c9884..fc22e1e 100644 (file)
@@ -128,12 +128,6 @@ static int __devinit probe(struct pci_dev *pdev,
        struct uio_pci_generic_dev *gdev;
        int err;
 
-       if (!pdev->irq) {
-               dev_warn(&pdev->dev, "No IRQ assigned to device: "
-                        "no support for interrupts?\n");
-               return -ENODEV;
-       }
-
        err = pci_enable_device(pdev);
        if (err) {
                dev_err(&pdev->dev, "%s: pci_enable_device failed: %d\n",
@@ -141,6 +135,13 @@ static int __devinit probe(struct pci_dev *pdev,
                return err;
        }
 
+       if (!pdev->irq) {
+               dev_warn(&pdev->dev, "No IRQ assigned to device: "
+                        "no support for interrupts?\n");
+               pci_disable_device(pdev);
+               return -ENODEV;
+       }
+
        err = verify_pci_2_3(pdev);
        if (err)
                goto err_verify;
index 30f46c2..b81bfc0 100644 (file)
@@ -537,14 +537,14 @@ void register_disk(struct gendisk *disk)
 
        if (device_add(ddev))
                return;
-#ifndef CONFIG_SYSFS_DEPRECATED
-       err = sysfs_create_link(block_depr, &ddev->kobj,
-                               kobject_name(&ddev->kobj));
-       if (err) {
-               device_del(ddev);
-               return;
+       if (!sysfs_deprecated) {
+               err = sysfs_create_link(block_depr, &ddev->kobj,
+                                       kobject_name(&ddev->kobj));
+               if (err) {
+                       device_del(ddev);
+                       return;
+               }
        }
-#endif
        disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj);
        disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj);
 
@@ -766,8 +766,7 @@ void del_gendisk(struct gendisk *disk)
        kobject_put(disk->part0.holder_dir);
        kobject_put(disk->slave_dir);
        disk->driverfs_dev = NULL;
-#ifndef CONFIG_SYSFS_DEPRECATED
-       sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
-#endif
+       if (!sysfs_deprecated)
+               sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
        device_del(disk_to_dev(disk));
 }
index 4e321f7..a475983 100644 (file)
@@ -179,30 +179,14 @@ static void bin_vma_open(struct vm_area_struct *vma)
        struct bin_buffer *bb = file->private_data;
        struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
 
-       if (!bb->vm_ops || !bb->vm_ops->open)
-               return;
-
-       if (!sysfs_get_active(attr_sd))
-               return;
-
-       bb->vm_ops->open(vma);
-
-       sysfs_put_active(attr_sd);
-}
-
-static void bin_vma_close(struct vm_area_struct *vma)
-{
-       struct file *file = vma->vm_file;
-       struct bin_buffer *bb = file->private_data;
-       struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-
-       if (!bb->vm_ops || !bb->vm_ops->close)
+       if (!bb->vm_ops)
                return;
 
        if (!sysfs_get_active(attr_sd))
                return;
 
-       bb->vm_ops->close(vma);
+       if (bb->vm_ops->open)
+               bb->vm_ops->open(vma);
 
        sysfs_put_active(attr_sd);
 }
@@ -214,13 +198,15 @@ static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
        int ret;
 
-       if (!bb->vm_ops || !bb->vm_ops->fault)
+       if (!bb->vm_ops)
                return VM_FAULT_SIGBUS;
 
        if (!sysfs_get_active(attr_sd))
                return VM_FAULT_SIGBUS;
 
-       ret = bb->vm_ops->fault(vma, vmf);
+       ret = VM_FAULT_SIGBUS;
+       if (bb->vm_ops->fault)
+               ret = bb->vm_ops->fault(vma, vmf);
 
        sysfs_put_active(attr_sd);
        return ret;
@@ -236,13 +222,12 @@ static int bin_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        if (!bb->vm_ops)
                return VM_FAULT_SIGBUS;
 
-       if (!bb->vm_ops->page_mkwrite)
-               return 0;
-
        if (!sysfs_get_active(attr_sd))
                return VM_FAULT_SIGBUS;
 
-       ret = bb->vm_ops->page_mkwrite(vma, vmf);
+       ret = 0;
+       if (bb->vm_ops->page_mkwrite)
+               ret = bb->vm_ops->page_mkwrite(vma, vmf);
 
        sysfs_put_active(attr_sd);
        return ret;
@@ -256,13 +241,15 @@ static int bin_access(struct vm_area_struct *vma, unsigned long addr,
        struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
        int ret;
 
-       if (!bb->vm_ops || !bb->vm_ops->access)
+       if (!bb->vm_ops)
                return -EINVAL;
 
        if (!sysfs_get_active(attr_sd))
                return -EINVAL;
 
-       ret = bb->vm_ops->access(vma, addr, buf, len, write);
+       ret = -EINVAL;
+       if (bb->vm_ops->access)
+               ret = bb->vm_ops->access(vma, addr, buf, len, write);
 
        sysfs_put_active(attr_sd);
        return ret;
@@ -276,13 +263,15 @@ static int bin_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
        struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
        int ret;
 
-       if (!bb->vm_ops || !bb->vm_ops->set_policy)
+       if (!bb->vm_ops)
                return 0;
 
        if (!sysfs_get_active(attr_sd))
                return -EINVAL;
 
-       ret = bb->vm_ops->set_policy(vma, new);
+       ret = 0;
+       if (bb->vm_ops->set_policy)
+               ret = bb->vm_ops->set_policy(vma, new);
 
        sysfs_put_active(attr_sd);
        return ret;
@@ -296,13 +285,15 @@ static struct mempolicy *bin_get_policy(struct vm_area_struct *vma,
        struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
        struct mempolicy *pol;
 
-       if (!bb->vm_ops || !bb->vm_ops->get_policy)
+       if (!bb->vm_ops)
                return vma->vm_policy;
 
        if (!sysfs_get_active(attr_sd))
                return vma->vm_policy;
 
-       pol = bb->vm_ops->get_policy(vma, addr);
+       pol = vma->vm_policy;
+       if (bb->vm_ops->get_policy)
+               pol = bb->vm_ops->get_policy(vma, addr);
 
        sysfs_put_active(attr_sd);
        return pol;
@@ -316,13 +307,15 @@ static int bin_migrate(struct vm_area_struct *vma, const nodemask_t *from,
        struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
        int ret;
 
-       if (!bb->vm_ops || !bb->vm_ops->migrate)
+       if (!bb->vm_ops)
                return 0;
 
        if (!sysfs_get_active(attr_sd))
                return 0;
 
-       ret = bb->vm_ops->migrate(vma, from, to, flags);
+       ret = 0;
+       if (bb->vm_ops->migrate)
+               ret = bb->vm_ops->migrate(vma, from, to, flags);
 
        sysfs_put_active(attr_sd);
        return ret;
@@ -331,7 +324,6 @@ static int bin_migrate(struct vm_area_struct *vma, const nodemask_t *from,
 
 static const struct vm_operations_struct bin_vm_ops = {
        .open           = bin_vma_open,
-       .close          = bin_vma_close,
        .fault          = bin_fault,
        .page_mkwrite   = bin_page_mkwrite,
        .access         = bin_access,
@@ -377,6 +369,14 @@ static int mmap(struct file *file, struct vm_area_struct *vma)
        if (bb->mmapped && bb->vm_ops != vma->vm_ops)
                goto out_put;
 
+       /*
+        * It is not possible to successfully wrap close.
+        * So error if someone is trying to use close.
+        */
+       rc = -EINVAL;
+       if (vma->vm_ops && vma->vm_ops->close)
+               goto out_put;
+
        rc = 0;
        bb->mmapped = 1;
        bb->vm_ops = vma->vm_ops;
index 516feca..dd48953 100644 (file)
@@ -751,4 +751,11 @@ do {                                                    \
        MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor))
 #define MODULE_ALIAS_CHARDEV_MAJOR(major) \
        MODULE_ALIAS("char-major-" __stringify(major) "-*")
+
+#ifdef CONFIG_SYSFS_DEPRECATED
+extern long sysfs_deprecated;
+#else
+#define sysfs_deprecated 0
+#endif
+
 #endif /* _DEVICE_H_ */
index 7950a37..8f6d121 100644 (file)
@@ -191,6 +191,8 @@ static inline struct kobj_type *get_ktype(struct kobject *kobj)
 }
 
 extern struct kobject *kset_find_obj(struct kset *, const char *);
+extern struct kobject *kset_find_obj_hinted(struct kset *, const char *,
+                                               struct kobject *);
 
 /* The global /sys/kernel/ kobject for people to chain off of */
 extern struct kobject *kernel_kobj;
index 85582e1..06c1fa0 100644 (file)
@@ -23,6 +23,8 @@
 struct memory_block {
        unsigned long phys_index;
        unsigned long state;
+       int section_count;
+
        /*
         * This serializes all state change requests.  It isn't
         * held during creation because the control files are
@@ -113,6 +115,8 @@ extern int memory_dev_init(void);
 extern int remove_memory_block(unsigned long, struct mem_section *, int);
 extern int memory_notify(unsigned long val, void *v);
 extern int memory_isolate_notify(unsigned long val, void *v);
+extern struct memory_block *find_memory_block_hinted(struct mem_section *,
+                                                       struct memory_block *);
 extern struct memory_block *find_memory_block(struct mem_section *);
 #define CONFIG_MEM_BLOCK_SIZE  (PAGES_PER_SECTION<<PAGE_SHIFT)
 enum mem_add_context { BOOT, HOTPLUG };
index d7ecad0..2e700ec 100644 (file)
@@ -138,6 +138,9 @@ extern struct platform_device *platform_create_bundle(struct platform_driver *dr
                                        struct resource *res, unsigned int n_res,
                                        const void *data, size_t size);
 
+extern const struct dev_pm_ops * platform_bus_get_pm_ops(void);
+extern void platform_bus_set_pm_ops(const struct dev_pm_ops *pm);
+
 /* early platform driver interface */
 struct early_platform_driver {
        const char *class_str;
index 5dcc9ff..d6188e5 100644 (file)
@@ -108,7 +108,7 @@ extern void uio_event_notify(struct uio_info *info);
 
 /* defines for uio_info->irq */
 #define UIO_IRQ_CUSTOM -1
-#define UIO_IRQ_NONE   -2
+#define UIO_IRQ_NONE   0
 
 /* defines for uio_mem->memtype */
 #define UIO_MEM_NONE   0
index 89e0ac1..df26ebb 100644 (file)
@@ -133,9 +133,7 @@ struct snd_card {
        int free_on_last_close;         /* free in context of file_release */
        wait_queue_head_t shutdown_sleep;
        struct device *dev;             /* device assigned to this card */
-#ifndef CONFIG_SYSFS_DEPRECATED
        struct device *card_dev;        /* cardX object for sysfs */
-#endif
 
 #ifdef CONFIG_PM
        unsigned int power_state;       /* power state */
@@ -196,11 +194,7 @@ struct snd_minor {
 /* return a device pointer linked to each sound device as a parent */
 static inline struct device *snd_card_get_device_link(struct snd_card *card)
 {
-#ifdef CONFIG_SYSFS_DEPRECATED
-       return card ? card->dev : NULL;
-#else
        return card ? card->card_dev : NULL;
-#endif
 }
 
 /* sound.c */
index bd125a7..fdfd97e 100644 (file)
@@ -686,40 +686,42 @@ config MM_OWNER
        bool
 
 config SYSFS_DEPRECATED
-       bool
-
-config SYSFS_DEPRECATED_V2
        bool "enable deprecated sysfs features to support old userspace tools"
        depends on SYSFS
        default n
-       select SYSFS_DEPRECATED
-       help
-         This option switches the layout of sysfs to the deprecated
-         version. Do not use it on recent distributions.
-
-         The current sysfs layout features a unified device tree at
-         /sys/devices/, which is able to express a hierarchy between
-         class devices. If the deprecated option is set to Y, the
-         unified device tree is split into a bus device tree at
-         /sys/devices/ and several individual class device trees at
-         /sys/class/. The class and bus devices will be connected by
-         "<subsystem>:<name>" and the "device" links. The "block"
-         class devices, will not show up in /sys/class/block/. Some
-         subsystems will suppress the creation of some devices which
-         depend on the unified device tree.
-
-         This option is not a pure compatibility option that can
-         be safely enabled on newer distributions. It will change the
-         layout of sysfs to the non-extensible deprecated version,
-         and disable some features, which can not be exported without
-         confusing older userspace tools. Since 2007/2008 all major
-         distributions do not enable this option, and ship no tools which
-         depend on the deprecated layout or this option.
-
-         If you are using a new kernel on an older distribution, or use
-         older userspace tools, you might need to say Y here. Do not say Y,
-         if the original kernel, that came with your distribution, has
-         this option set to N.
+       help
+         This option adds code that switches the layout of the "block" class
+         devices, to not show up in /sys/class/block/, but only in
+         /sys/block/.
+
+         This switch is only active when the sysfs.deprecated=1 boot option is
+         passed or the SYSFS_DEPRECATED_V2 option is set.
+
+         This option allows new kernels to run on old distributions and tools,
+         which might get confused by /sys/class/block/. Since 2007/2008 all
+         major distributions and tools handle this just fine.
+
+         Recent distributions and userspace tools after 2009/2010 depend on
+         the existence of /sys/class/block/, and will not work with this
+         option enabled.
+
+         Only if you are using a new kernel on an old distribution, you might
+         need to say Y here.
+
+config SYSFS_DEPRECATED_V2
+       bool "enabled deprecated sysfs features by default"
+       default n
+       depends on SYSFS
+       depends on SYSFS_DEPRECATED
+       help
+         Enable deprecated sysfs by default.
+
+         See the CONFIG_SYSFS_DEPRECATED option for more details about this
+         option.
+
+         Only if you are using a new kernel on an old distribution, you might
+         need to say Y here. Even then, odds are you would not need it
+         enabled, you can always pass the boot option if absolutely necessary.
 
 config RELAY
        bool "Kernel->user space relay support (formerly relayfs)"
index 7bd6df7..3094318 100644 (file)
@@ -393,6 +393,40 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
        return 0;
 }
 
+static int ddebug_exec_query(char *query_string)
+{
+       unsigned int flags = 0, mask = 0;
+       struct ddebug_query query;
+#define MAXWORDS 9
+       int nwords;
+       char *words[MAXWORDS];
+
+       nwords = ddebug_tokenize(query_string, words, MAXWORDS);
+       if (nwords <= 0)
+               return -EINVAL;
+       if (ddebug_parse_query(words, nwords-1, &query))
+               return -EINVAL;
+       if (ddebug_parse_flags(words[nwords-1], &flags, &mask))
+               return -EINVAL;
+
+       /* actually go and implement the change */
+       ddebug_change(&query, flags, mask);
+       return 0;
+}
+
+static __initdata char ddebug_setup_string[1024];
+static __init int ddebug_setup_query(char *str)
+{
+       if (strlen(str) >= 1024) {
+               pr_warning("ddebug boot param string too large\n");
+               return 0;
+       }
+       strcpy(ddebug_setup_string, str);
+       return 1;
+}
+
+__setup("ddebug_query=", ddebug_setup_query);
+
 /*
  * File_ops->write method for <debugfs>/dynamic_debug/conrol.  Gathers the
  * command text from userspace, parses and executes it.
@@ -400,12 +434,8 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
 static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf,
                                  size_t len, loff_t *offp)
 {
-       unsigned int flags = 0, mask = 0;
-       struct ddebug_query query;
-#define MAXWORDS 9
-       int nwords;
-       char *words[MAXWORDS];
        char tmpbuf[256];
+       int ret;
 
        if (len == 0)
                return 0;
@@ -419,16 +449,9 @@ static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf,
                printk(KERN_INFO "%s: read %d bytes from userspace\n",
                        __func__, (int)len);
 
-       nwords = ddebug_tokenize(tmpbuf, words, MAXWORDS);
-       if (nwords <= 0)
-               return -EINVAL;
-       if (ddebug_parse_query(words, nwords-1, &query))
-               return -EINVAL;
-       if (ddebug_parse_flags(words[nwords-1], &flags, &mask))
-               return -EINVAL;
-
-       /* actually go and implement the change */
-       ddebug_change(&query, flags, mask);
+       ret = ddebug_exec_query(tmpbuf);
+       if (ret)
+               return ret;
 
        *offp += len;
        return len;
@@ -689,13 +712,14 @@ static void ddebug_remove_all_tables(void)
        mutex_unlock(&ddebug_lock);
 }
 
-static int __init dynamic_debug_init(void)
+static __initdata int ddebug_init_success;
+
+static int __init dynamic_debug_init_debugfs(void)
 {
        struct dentry *dir, *file;
-       struct _ddebug *iter, *iter_start;
-       const char *modname = NULL;
-       int ret = 0;
-       int n = 0;
+
+       if (!ddebug_init_success)
+               return -ENODEV;
 
        dir = debugfs_create_dir("dynamic_debug", NULL);
        if (!dir)
@@ -706,6 +730,16 @@ static int __init dynamic_debug_init(void)
                debugfs_remove(dir);
                return -ENOMEM;
        }
+       return 0;
+}
+
+static int __init dynamic_debug_init(void)
+{
+       struct _ddebug *iter, *iter_start;
+       const char *modname = NULL;
+       int ret = 0;
+       int n = 0;
+
        if (__start___verbose != __stop___verbose) {
                iter = __start___verbose;
                modname = iter->modname;
@@ -723,12 +757,26 @@ static int __init dynamic_debug_init(void)
                }
                ret = ddebug_add_module(iter_start, n, modname);
        }
+
+       /* ddebug_query boot param got passed -> set it up */
+       if (ddebug_setup_string[0] != '\0') {
+               ret = ddebug_exec_query(ddebug_setup_string);
+               if (ret)
+                       pr_warning("Invalid ddebug boot param %s",
+                                  ddebug_setup_string);
+               else
+                       pr_info("ddebug initialized with string %s",
+                               ddebug_setup_string);
+       }
+
 out_free:
-       if (ret) {
+       if (ret)
                ddebug_remove_all_tables();
-               debugfs_remove(dir);
-               debugfs_remove(file);
-       }
+       else
+               ddebug_init_success = 1;
        return 0;
 }
-module_init(dynamic_debug_init);
+/* Allow early initialization for boot messages via boot param */
+arch_initcall(dynamic_debug_init);
+/* Debugfs setup must be done later */
+module_init(dynamic_debug_init_debugfs);
index f07c572..82dc34c 100644 (file)
@@ -745,18 +745,57 @@ void kset_unregister(struct kset *k)
  * take a reference and return the object.
  */
 struct kobject *kset_find_obj(struct kset *kset, const char *name)
+{
+       return kset_find_obj_hinted(kset, name, NULL);
+}
+
+/**
+ * kset_find_obj_hinted - search for object in kset given a predecessor hint.
+ * @kset: kset we're looking in.
+ * @name: object's name.
+ * @hint: hint to possible object's predecessor.
+ *
+ * Check the hint's next object and if it is a match return it directly,
+ * otherwise, fall back to the behavior of kset_find_obj().  Either way
+ * a reference for the returned object is held and the reference on the
+ * hinted object is released.
+ */
+struct kobject *kset_find_obj_hinted(struct kset *kset, const char *name,
+                                    struct kobject *hint)
 {
        struct kobject *k;
        struct kobject *ret = NULL;
 
        spin_lock(&kset->list_lock);
+
+       if (!hint)
+               goto slow_search;
+
+       /* end of list detection */
+       if (hint->entry.next == kset->list.next)
+               goto slow_search;
+
+       k = container_of(hint->entry.next, struct kobject, entry);
+       if (!kobject_name(k) || strcmp(kobject_name(k), name))
+               goto slow_search;
+
+       ret = kobject_get(k);
+       goto unlock_exit;
+
+slow_search:
        list_for_each_entry(k, &kset->list, entry) {
                if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
                        ret = kobject_get(k);
                        break;
                }
        }
+
+unlock_exit:
        spin_unlock(&kset->list_lock);
+
+       if (hint)
+               kobject_put(hint);
+
        return ret;
 }
 
index ec4a50c..f7c3df8 100644 (file)
@@ -395,12 +395,10 @@ int snd_card_disconnect(struct snd_card *card)
                snd_printk(KERN_ERR "not all devices for card %i can be disconnected\n", card->number);
 
        snd_info_card_disconnect(card);
-#ifndef CONFIG_SYSFS_DEPRECATED
        if (card->card_dev) {
                device_unregister(card->card_dev);
                card->card_dev = NULL;
        }
-#endif
 #ifdef CONFIG_PM
        wake_up(&card->power_sleep);
 #endif
@@ -573,7 +571,6 @@ void snd_card_set_id(struct snd_card *card, const char *nid)
 }
 EXPORT_SYMBOL(snd_card_set_id);
 
-#ifndef CONFIG_SYSFS_DEPRECATED
 static ssize_t
 card_id_show_attr(struct device *dev,
                  struct device_attribute *attr, char *buf)
@@ -630,7 +627,6 @@ card_number_show_attr(struct device *dev,
 
 static struct device_attribute card_number_attrs =
        __ATTR(number, S_IRUGO, card_number_show_attr, NULL);
-#endif /* CONFIG_SYSFS_DEPRECATED */
 
 /**
  *  snd_card_register - register the soundcard
@@ -649,7 +645,7 @@ int snd_card_register(struct snd_card *card)
 
        if (snd_BUG_ON(!card))
                return -EINVAL;
-#ifndef CONFIG_SYSFS_DEPRECATED
+
        if (!card->card_dev) {
                card->card_dev = device_create(sound_class, card->dev,
                                               MKDEV(0, 0), card,
@@ -657,7 +653,7 @@ int snd_card_register(struct snd_card *card)
                if (IS_ERR(card->card_dev))
                        card->card_dev = NULL;
        }
-#endif
+
        if ((err = snd_device_register_all(card)) < 0)
                return err;
        mutex_lock(&snd_card_mutex);
@@ -674,7 +670,6 @@ int snd_card_register(struct snd_card *card)
        if (snd_mixer_oss_notify_callback)
                snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER);
 #endif
-#ifndef CONFIG_SYSFS_DEPRECATED
        if (card->card_dev) {
                err = device_create_file(card->card_dev, &card_id_attrs);
                if (err < 0)
@@ -683,7 +678,7 @@ int snd_card_register(struct snd_card *card)
                if (err < 0)
                        return err;
        }
-#endif
+
        return 0;
 }