Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6
Linus Torvalds [Thu, 16 Oct 2008 19:40:26 +0000 (12:40 -0700)]
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (46 commits)
  UIO: Fix mapping of logical and virtual memory
  UIO: add automata sercos3 pci card support
  UIO: Change driver name of uio_pdrv
  UIO: Add alignment warnings for uio-mem
  Driver core: add bus_sort_breadthfirst() function
  NET: convert the phy_device file to use bus_find_device_by_name
  kobject: Cleanup kobject_rename and !CONFIG_SYSFS
  kobject: Fix kobject_rename and !CONFIG_SYSFS
  sysfs: Make dir and name args to sysfs_notify() const
  platform: add new device registration helper
  sysfs: use ilookup5() instead of ilookup5_nowait()
  PNP: create device attributes via default device attributes
  Driver core: make bus_find_device_by_name() more robust
  usb: turn dev_warn+WARN_ON combos into dev_WARN
  debug: use dev_WARN() rather than WARN_ON() in device_pm_add()
  debug: Introduce a dev_WARN() function
  sysfs: fix deadlock
  device model: Do a quickcheck for driver binding before doing an expensive check
  Driver core: Fix cleanup in device_create_vargs().
  Driver core: Clarify device cleanup.
  ...

1  2 
Documentation/kernel-parameters.txt
drivers/base/platform.c
drivers/base/power/main.c
drivers/net/ppp_generic.c
drivers/pnp/base.h
drivers/pnp/core.c
drivers/video/console/fbcon.c
drivers/video/fbmem.c
include/linux/kernel.h
kernel/module.c

@@@ -796,7 -796,6 +796,7 @@@ and is between 256 and 4096 characters
                        Defaults to the default architecture's huge page size
                        if not specified.
  
 +      i8042.debug     [HW] Toggle i8042 debug mode
        i8042.direct    [HW] Put keyboard port into non-translated mode
        i8042.dumbkbd   [HW] Pretend that controller can only read data from
                             keyboard and cannot control its state
                        autoconfiguration.
                        Ranges are in pairs (memory base and size).
  
+       dynamic_printk
+                       Enables pr_debug()/dev_dbg() calls if
+                       CONFIG_DYNAMIC_PRINTK_DEBUG has been enabled. These can also
+                       be switched on/off via <debugfs>/dynamic_printk/modules
        print-fatal-signals=
                        [KNL] debug: print fatal signals
                        print-fatal-signals=1: print segfault info to
diff --combined drivers/base/platform.c
@@@ -42,8 -42,10 +42,8 @@@ struct resource *platform_get_resource(
        for (i = 0; i < dev->num_resources; i++) {
                struct resource *r = &dev->resource[i];
  
 -              if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM|
 -                               IORESOURCE_IRQ|IORESOURCE_DMA)) == type)
 -                      if (num-- == 0)
 -                              return r;
 +              if (type == resource_type(r) && num-- == 0)
 +                      return r;
        }
        return NULL;
  }
@@@ -76,8 -78,10 +76,8 @@@ struct resource *platform_get_resource_
        for (i = 0; i < dev->num_resources; i++) {
                struct resource *r = &dev->resource[i];
  
 -              if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM|
 -                               IORESOURCE_IRQ|IORESOURCE_DMA)) == type)
 -                      if (!strcmp(r->name, name))
 -                              return r;
 +              if (type == resource_type(r) && !strcmp(r->name, name))
 +                      return r;
        }
        return NULL;
  }
@@@ -255,9 -259,9 +255,9 @@@ int platform_device_add(struct platform
  
                p = r->parent;
                if (!p) {
 -                      if (r->flags & IORESOURCE_MEM)
 +                      if (resource_type(r) == IORESOURCE_MEM)
                                p = &iomem_resource;
 -                      else if (r->flags & IORESOURCE_IO)
 +                      else if (resource_type(r) == IORESOURCE_IO)
                                p = &ioport_resource;
                }
  
                return ret;
  
   failed:
 -      while (--i >= 0)
 -              if (pdev->resource[i].flags & (IORESOURCE_MEM|IORESOURCE_IO))
 -                      release_resource(&pdev->resource[i]);
 +      while (--i >= 0) {
 +              struct resource *r = &pdev->resource[i];
 +              unsigned long type = resource_type(r);
 +
 +              if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
 +                      release_resource(r);
 +      }
 +
        return ret;
  }
  EXPORT_SYMBOL_GPL(platform_device_add);
@@@ -307,9 -306,7 +307,9 @@@ void platform_device_del(struct platfor
  
                for (i = 0; i < pdev->num_resources; i++) {
                        struct resource *r = &pdev->resource[i];
 -                      if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO))
 +                      unsigned long type = resource_type(r);
 +
 +                      if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
                                release_resource(r);
                }
        }
@@@ -394,6 -391,53 +394,53 @@@ error
  }
  EXPORT_SYMBOL_GPL(platform_device_register_simple);
  
+ /**
+  * platform_device_register_data
+  * @parent: parent device for the device we're adding
+  * @name: base name of the device we're adding
+  * @id: instance id
+  * @data: platform specific data for this platform device
+  * @size: size of platform specific data
+  *
+  * This function creates a simple platform device that requires minimal
+  * resource and memory management. Canned release function freeing memory
+  * allocated for the device allows drivers using such devices to be
+  * unloaded without waiting for the last reference to the device to be
+  * dropped.
+  */
+ struct platform_device *platform_device_register_data(
+               struct device *parent,
+               const char *name, int id,
+               const void *data, size_t size)
+ {
+       struct platform_device *pdev;
+       int retval;
+       pdev = platform_device_alloc(name, id);
+       if (!pdev) {
+               retval = -ENOMEM;
+               goto error;
+       }
+       pdev->dev.parent = parent;
+       if (size) {
+               retval = platform_device_add_data(pdev, data, size);
+               if (retval)
+                       goto error;
+       }
+       retval = platform_device_add(pdev);
+       if (retval)
+               goto error;
+       return pdev;
+ error:
+       platform_device_put(pdev);
+       return ERR_PTR(retval);
+ }
  static int platform_drv_probe(struct device *_dev)
  {
        struct platform_driver *drv = to_platform_driver(_dev->driver);
@@@ -865,7 -909,7 +912,7 @@@ static int platform_pm_restore_noirq(st
  
  #endif /* !CONFIG_HIBERNATION */
  
- struct pm_ext_ops platform_pm_ops = {
+ static struct pm_ext_ops platform_pm_ops = {
        .base = {
                .prepare = platform_pm_prepare,
                .complete = platform_pm_complete,
@@@ -83,7 -83,7 +83,7 @@@ void device_pm_add(struct device *dev
                 * transition is in progress in order to avoid leaving them
                 * unhandled down the road
                 */
-               WARN_ON(true);
+               dev_WARN(dev, "Parentless device registered during a PM transaction\n");
        }
  
        list_add_tail(&dev->power.entry, &dpm_list);
@@@ -778,7 -778,10 +778,7 @@@ EXPORT_SYMBOL_GPL(device_suspend)
  
  void __suspend_report_result(const char *function, void *fn, int ret)
  {
 -      if (ret) {
 -              printk(KERN_ERR "%s(): ", function);
 -              print_fn_descriptor_symbol("%s returns ", fn);
 -              printk("%d\n", ret);
 -      }
 +      if (ret)
 +              printk(KERN_ERR "%s(): %pF returns %d\n", function, fn, ret);
  }
  EXPORT_SYMBOL_GPL(__suspend_report_result);
@@@ -866,8 -866,8 +866,8 @@@ static int __init ppp_init(void
                        err = PTR_ERR(ppp_class);
                        goto out_chrdev;
                }
-               device_create_drvdata(ppp_class, NULL, MKDEV(PPP_MAJOR, 0),
-                                     NULL, "ppp");
+               device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL,
+                             "ppp");
        }
  
  out:
@@@ -2127,9 -2127,13 +2127,9 @@@ ppp_set_compress(struct ppp *ppp, unsig
            || ccp_option[1] < 2 || ccp_option[1] > data.length)
                goto out;
  
 -      cp = find_compressor(ccp_option[0]);
 -#ifdef CONFIG_KMOD
 -      if (!cp) {
 -              request_module("ppp-compress-%d", ccp_option[0]);
 -              cp = find_compressor(ccp_option[0]);
 -      }
 -#endif /* CONFIG_KMOD */
 +      cp = try_then_request_module(
 +              find_compressor(ccp_option[0]),
 +              "ppp-compress-%d", ccp_option[0]);
        if (!cp)
                goto out;
  
diff --combined drivers/pnp/base.h
@@@ -4,6 -4,7 +4,7 @@@
   */
  
  extern spinlock_t pnp_lock;
+ extern struct device_attribute pnp_interface_attrs[];
  void *pnp_alloc(long size);
  
  int pnp_register_protocol(struct pnp_protocol *protocol);
@@@ -16,7 -17,6 +17,6 @@@ struct pnp_card *pnp_alloc_card(struct 
  
  int pnp_add_device(struct pnp_dev *dev);
  struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id);
- int pnp_interface_attach_device(struct pnp_dev *dev);
  
  int pnp_add_card(struct pnp_card *card);
  void pnp_remove_card(struct pnp_card *card);
@@@ -147,7 -147,7 +147,7 @@@ char *pnp_resource_type_name(struct res
  void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc);
  
  void pnp_free_resources(struct pnp_dev *dev);
 -int pnp_resource_type(struct resource *res);
 +unsigned long pnp_resource_type(struct resource *res);
  
  struct pnp_resource {
        struct list_head list;
diff --combined drivers/pnp/core.c
@@@ -159,21 -159,13 +159,13 @@@ struct pnp_dev *pnp_alloc_dev(struct pn
  
  int __pnp_add_device(struct pnp_dev *dev)
  {
-       int ret;
        pnp_fixup_device(dev);
        dev->status = PNP_READY;
        spin_lock(&pnp_lock);
        list_add_tail(&dev->global_list, &pnp_global);
        list_add_tail(&dev->protocol_list, &dev->protocol->devices);
        spin_unlock(&pnp_lock);
-       ret = device_register(&dev->dev);
-       if (ret)
-               return ret;
-       pnp_interface_attach_device(dev);
-       return 0;
+       return device_register(&dev->dev);
  }
  
  /*
@@@ -218,6 -210,7 +210,6 @@@ void __pnp_remove_device(struct pnp_de
  
  static int __init pnp_init(void)
  {
 -      printk(KERN_INFO "Linux Plug and Play Support v0.97 (c) Adam Belay\n");
        return bus_register(&pnp_bus_type);
  }
  
@@@ -2977,8 -2977,8 +2977,8 @@@ static void fbcon_set_all_vcs(struct fb
                p = &fb_display[vc->vc_num];
                set_blitting_type(vc, info);
                var_to_display(p, &info->var, info);
 -              cols = FBCON_SWAP(p->rotate, info->var.xres, info->var.yres);
 -              rows = FBCON_SWAP(p->rotate, info->var.yres, info->var.xres);
 +              cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
 +              rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
                cols /= vc->vc_font.width;
                rows /= vc->vc_font.height;
                vc_resize(vc, cols, rows);
@@@ -3573,8 -3573,8 +3573,8 @@@ static int __init fb_console_init(void
  
        acquire_console_sem();
        fb_register_client(&fbcon_event_notifier);
-       fbcon_device = device_create_drvdata(fb_class, NULL, MKDEV(0, 0),
-                                            NULL, "fbcon");
+       fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), NULL,
+                                    "fbcon");
  
        if (IS_ERR(fbcon_device)) {
                printk(KERN_WARNING "Unable to create device "
diff --combined drivers/video/fbmem.c
@@@ -28,7 -28,9 +28,7 @@@
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
  #include <linux/console.h>
 -#ifdef CONFIG_KMOD
  #include <linux/kmod.h>
 -#endif
  #include <linux/err.h>
  #include <linux/device.h>
  #include <linux/efi.h>
@@@ -835,6 -837,13 +835,6 @@@ fb_write(struct file *file, const char 
        return (cnt) ? cnt : err;
  }
  
 -#ifdef CONFIG_KMOD
 -static void try_to_load(int fb)
 -{
 -      request_module("fb%d", fb);
 -}
 -#endif /* CONFIG_KMOD */
 -
  int
  fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
  {
@@@ -1077,8 -1086,10 +1077,8 @@@ fb_ioctl(struct inode *inode, struct fi
                    return -EINVAL;
                if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
                    return -EINVAL;
 -#ifdef CONFIG_KMOD
                if (!registered_fb[con2fb.framebuffer])
 -                  try_to_load(con2fb.framebuffer);
 -#endif /* CONFIG_KMOD */
 +                  request_module("fb%d", con2fb.framebuffer);
                if (!registered_fb[con2fb.framebuffer])
                    return -EINVAL;
                event.info = info;
@@@ -1316,8 -1327,10 +1316,8 @@@ fb_open(struct inode *inode, struct fil
        if (fbidx >= FB_MAX)
                return -ENODEV;
        lock_kernel();
 -#ifdef CONFIG_KMOD
        if (!(info = registered_fb[fbidx]))
 -              try_to_load(fbidx);
 -#endif /* CONFIG_KMOD */
 +              request_module("fb%d", fbidx);
        if (!(info = registered_fb[fbidx])) {
                res = -ENODEV;
                goto out;
@@@ -1430,9 -1443,8 +1430,8 @@@ register_framebuffer(struct fb_info *fb
                        break;
        fb_info->node = i;
  
-       fb_info->dev = device_create_drvdata(fb_class, fb_info->device,
-                                            MKDEV(FB_MAJOR, i), NULL,
-                                            "fb%d", i);
+       fb_info->dev = device_create(fb_class, fb_info->device,
+                                    MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
        if (IS_ERR(fb_info->dev)) {
                /* Not fatal */
                printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
diff --combined include/linux/kernel.h
@@@ -16,6 -16,7 +16,7 @@@
  #include <linux/log2.h>
  #include <linux/typecheck.h>
  #include <linux/ratelimit.h>
+ #include <linux/dynamic_printk.h>
  #include <asm/byteorder.h>
  #include <asm/bug.h>
  
@@@ -235,10 -236,9 +236,10 @@@ extern int oops_in_progress;             /* If set
  extern int panic_timeout;
  extern int panic_on_oops;
  extern int panic_on_unrecovered_nmi;
 -extern int tainted;
  extern const char *print_tainted(void);
 -extern void add_taint(unsigned);
 +extern void add_taint(unsigned flag);
 +extern int test_taint(unsigned flag);
 +extern unsigned long get_taint(void);
  extern int root_mountflags;
  
  /* Values used for system_state */
@@@ -251,16 -251,16 +252,16 @@@ extern enum system_states 
        SYSTEM_SUSPEND_DISK,
  } system_state;
  
 -#define TAINT_PROPRIETARY_MODULE      (1<<0)
 -#define TAINT_FORCED_MODULE           (1<<1)
 -#define TAINT_UNSAFE_SMP              (1<<2)
 -#define TAINT_FORCED_RMMOD            (1<<3)
 -#define TAINT_MACHINE_CHECK           (1<<4)
 -#define TAINT_BAD_PAGE                        (1<<5)
 -#define TAINT_USER                    (1<<6)
 -#define TAINT_DIE                     (1<<7)
 -#define TAINT_OVERRIDDEN_ACPI_TABLE   (1<<8)
 -#define TAINT_WARN                    (1<<9)
 +#define TAINT_PROPRIETARY_MODULE      0
 +#define TAINT_FORCED_MODULE           1
 +#define TAINT_UNSAFE_SMP              2
 +#define TAINT_FORCED_RMMOD            3
 +#define TAINT_MACHINE_CHECK           4
 +#define TAINT_BAD_PAGE                        5
 +#define TAINT_USER                    6
 +#define TAINT_DIE                     7
 +#define TAINT_OVERRIDDEN_ACPI_TABLE   8
 +#define TAINT_WARN                    9
  
  extern void dump_stack(void) __cold;
  
@@@ -304,8 -304,12 +305,12 @@@ static inline char *pack_hex_byte(char 
  #define pr_info(fmt, arg...) \
        printk(KERN_INFO fmt, ##arg)
  
- #ifdef DEBUG
  /* If you are writing a driver, please use dev_dbg instead */
+ #if defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
+ #define pr_debug(fmt, ...) do { \
+       dynamic_pr_debug(fmt, ##__VA_ARGS__); \
+       } while (0)
+ #elif defined(DEBUG)
  #define pr_debug(fmt, arg...) \
        printk(KERN_DEBUG fmt, ##arg)
  #else
diff --combined kernel/module.c
@@@ -100,7 -100,7 +100,7 @@@ static inline int strong_try_module_get
  static inline void add_taint_module(struct module *mod, unsigned flag)
  {
        add_taint(flag);
 -      mod->taints |= flag;
 +      mod->taints |= (1U << flag);
  }
  
  /*
@@@ -784,6 -784,7 +784,7 @@@ sys_delete_module(const char __user *na
        mutex_lock(&module_mutex);
        /* Store the name of the last unloaded module for diagnostic purposes */
        strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
+       unregister_dynamic_debug_module(mod->name);
        free_module(mod);
  
   out:
@@@ -923,7 -924,7 +924,7 @@@ static const char vermagic[] = VERMAGIC
  static int try_to_force_load(struct module *mod, const char *symname)
  {
  #ifdef CONFIG_MODULE_FORCE_LOAD
 -      if (!(tainted & TAINT_FORCED_MODULE))
 +      if (!test_taint(TAINT_FORCED_MODULE))
                printk("%s: no version for \"%s\" found: kernel tainted.\n",
                       mod->name, symname);
        add_taint_module(mod, TAINT_FORCED_MODULE);
@@@ -1033,7 -1034,7 +1034,7 @@@ static unsigned long resolve_symbol(Elf
        const unsigned long *crc;
  
        ret = find_symbol(name, &owner, &crc,
 -                        !(mod->taints & TAINT_PROPRIETARY_MODULE), true);
 +                        !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true);
        if (!IS_ERR_VALUE(ret)) {
                /* use_module can fail due to OOM,
                   or module initialization or unloading */
@@@ -1173,7 -1174,7 +1174,7 @@@ static void free_notes_attrs(struct mod
                while (i-- > 0)
                        sysfs_remove_bin_file(notes_attrs->dir,
                                              &notes_attrs->attrs[i]);
-               kobject_del(notes_attrs->dir);
+               kobject_put(notes_attrs->dir);
        }
        kfree(notes_attrs);
  }
@@@ -1634,7 -1635,7 +1635,7 @@@ static void set_license(struct module *
                license = "unspecified";
  
        if (!license_is_gpl_compatible(license)) {
 -              if (!(tainted & TAINT_PROPRIETARY_MODULE))
 +              if (!test_taint(TAINT_PROPRIETARY_MODULE))
                        printk(KERN_WARNING "%s: module license '%s' taints "
                                "kernel.\n", mod->name, license);
                add_taint_module(mod, TAINT_PROPRIETARY_MODULE);
@@@ -1783,6 -1784,33 +1784,33 @@@ static inline void add_kallsyms(struct 
  }
  #endif /* CONFIG_KALLSYMS */
  
+ #ifdef CONFIG_DYNAMIC_PRINTK_DEBUG
+ static void dynamic_printk_setup(Elf_Shdr *sechdrs, unsigned int verboseindex)
+ {
+       struct mod_debug *debug_info;
+       unsigned long pos, end;
+       unsigned int num_verbose;
+       pos = sechdrs[verboseindex].sh_addr;
+       num_verbose = sechdrs[verboseindex].sh_size /
+                               sizeof(struct mod_debug);
+       end = pos + (num_verbose * sizeof(struct mod_debug));
+       for (; pos < end; pos += sizeof(struct mod_debug)) {
+               debug_info = (struct mod_debug *)pos;
+               register_dynamic_debug_module(debug_info->modname,
+                       debug_info->type, debug_info->logical_modname,
+                       debug_info->flag_names, debug_info->hash,
+                       debug_info->hash2);
+       }
+ }
+ #else
+ static inline void dynamic_printk_setup(Elf_Shdr *sechdrs,
+                                       unsigned int verboseindex)
+ {
+ }
+ #endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */
  static void *module_alloc_update_bounds(unsigned long size)
  {
        void *ret = module_alloc(size);
@@@ -1831,6 -1859,7 +1859,7 @@@ static noinline struct module *load_mod
  #endif
        unsigned int markersindex;
        unsigned int markersstringsindex;
+       unsigned int verboseindex;
        struct module *mod;
        long err = 0;
        void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
        markersindex = find_sec(hdr, sechdrs, secstrings, "__markers");
        markersstringsindex = find_sec(hdr, sechdrs, secstrings,
                                        "__markers_strings");
+       verboseindex = find_sec(hdr, sechdrs, secstrings, "__verbose");
  
        /* Now do relocations. */
        for (i = 1; i < hdr->e_shnum; i++) {
                marker_update_probe_range(mod->markers,
                        mod->markers + mod->num_markers);
  #endif
+       dynamic_printk_setup(sechdrs, verboseindex);
        err = module_finalize(hdr, sechdrs, mod);
        if (err < 0)
                goto cleanup;
@@@ -2552,9 -2583,9 +2583,9 @@@ static char *module_flags(struct modul
            mod->state == MODULE_STATE_GOING ||
            mod->state == MODULE_STATE_COMING) {
                buf[bx++] = '(';
 -              if (mod->taints & TAINT_PROPRIETARY_MODULE)
 +              if (mod->taints & (1 << TAINT_PROPRIETARY_MODULE))
                        buf[bx++] = 'P';
 -              if (mod->taints & TAINT_FORCED_MODULE)
 +              if (mod->taints & (1 << TAINT_FORCED_MODULE))
                        buf[bx++] = 'F';
                /*
                 * TAINT_FORCED_RMMOD: could be added.