Merge tag 'module-builtin_driver-v4.1-rc8' of git://git.kernel.org/pub/scm/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 2 Jul 2015 17:42:13 +0000 (10:42 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 2 Jul 2015 17:42:13 +0000 (10:42 -0700)
Pull module_platform_driver replacement from Paul Gortmaker:
 "Replace module_platform_driver with builtin_platform driver in non
  modules.

  We see an increasing number of non-modular drivers using
  modular_driver() type register functions.  There are several downsides
  to letting this continue unchecked:

   - The code can appear modular to a reader of the code, and they won't
     know if the code really is modular without checking the Makefile
     and Kconfig to see if compilation is governed by a bool or
     tristate.

   - Coders of drivers may be tempted to code up an __exit function that
     is never used, just in order to satisfy the required three args of
     the modular registration function.

   - Non-modular code ends up including the <module.h> which increases
     CPP overhead that they don't need.

   - It hinders us from performing better separation of the module init
     code and the generic init code.

  So here we introduce similar macros for builtin drivers.  Then we
  convert builtin drivers (controlled by a bool Kconfig) by making the
  following type of mapping:

    module_platform_driver()       --->  builtin_platform_driver()
    module_platform_driver_probe() --->  builtin_platform_driver_probe().

  The set of drivers that are converted here are just the ones that
  showed up as relying on an implicit include of <module.h> during a
  pending header cleanup.  So we convert them here vs adding an include
  of <module.h> to non-modular code to avoid compile fails.  Additonal
  conversions can be done asynchronously at any time.

  Once again, an unused module_exit function that is removed here
  appears in the diffstat as an outlier wrt all the other changes"

* tag 'module-builtin_driver-v4.1-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/paulg/linux:
  drivers/clk: convert sunxi/clk-mod0.c to use builtin_platform_driver
  drivers/power: Convert non-modular syscon-reboot to use builtin_platform_driver
  drivers/soc: Convert non-modular soc-realview to use builtin_platform_driver
  drivers/soc: Convert non-modular tegra/pmc to use builtin_platform_driver
  drivers/cpufreq: Convert non-modular s5pv210-cpufreq.c to use builtin_platform_driver
  drivers/cpuidle: Convert non-modular drivers to use builtin_platform_driver
  drivers/platform: Convert non-modular pdev_bus to use builtin_platform_driver
  platform_device: better support builtin boilerplate avoidance

1  2 
drivers/soc/tegra/pmc.c
include/linux/device.h

diff --combined drivers/soc/tegra/pmc.c
@@@ -377,10 -377,13 +377,10 @@@ int tegra_pmc_cpu_remove_clamping(int c
  }
  #endif /* CONFIG_SMP */
  
 -/**
 - * tegra_pmc_restart() - reboot the system
 - * @mode: which mode to reboot in
 - * @cmd: reboot command
 - */
 -void tegra_pmc_restart(enum reboot_mode mode, const char *cmd)
 +static int tegra_pmc_restart_notify(struct notifier_block *this,
 +                                  unsigned long action, void *data)
  {
 +      const char *cmd = data;
        u32 value;
  
        value = tegra_pmc_readl(PMC_SCRATCH0);
        value = tegra_pmc_readl(0);
        value |= 0x10;
        tegra_pmc_writel(value, 0);
 +
 +      return NOTIFY_DONE;
  }
  
 +static struct notifier_block tegra_pmc_restart_handler = {
 +      .notifier_call = tegra_pmc_restart_notify,
 +      .priority = 128,
 +};
 +
  static int powergate_show(struct seq_file *s, void *data)
  {
        unsigned int i;
@@@ -839,13 -835,6 +839,13 @@@ static int tegra_pmc_probe(struct platf
                err = tegra_powergate_debugfs_init();
                if (err < 0)
                        return err;
 +      }
 +
 +      err = register_restart_handler(&tegra_pmc_restart_handler);
 +      if (err) {
 +              dev_err(&pdev->dev, "unable to register restart handler, %d\n",
 +                      err);
 +              return err;
        }
  
        return 0;
@@@ -1021,7 -1010,7 +1021,7 @@@ static struct platform_driver tegra_pmc
        },
        .probe = tegra_pmc_probe,
  };
module_platform_driver(tegra_pmc_driver);
builtin_platform_driver(tegra_pmc_driver);
  
  /*
   * Early initialization to allow access to registers in the very early boot
diff --combined include/linux/device.h
@@@ -196,41 -196,12 +196,41 @@@ extern struct kset *bus_get_kset(struc
  extern struct klist *bus_get_device_klist(struct bus_type *bus);
  
  /**
 + * enum probe_type - device driver probe type to try
 + *    Device drivers may opt in for special handling of their
 + *    respective probe routines. This tells the core what to
 + *    expect and prefer.
 + *
 + * @PROBE_DEFAULT_STRATEGY: Used by drivers that work equally well
 + *    whether probed synchronously or asynchronously.
 + * @PROBE_PREFER_ASYNCHRONOUS: Drivers for "slow" devices which
 + *    probing order is not essential for booting the system may
 + *    opt into executing their probes asynchronously.
 + * @PROBE_FORCE_SYNCHRONOUS: Use this to annotate drivers that need
 + *    their probe routines to run synchronously with driver and
 + *    device registration (with the exception of -EPROBE_DEFER
 + *    handling - re-probing always ends up being done asynchronously).
 + *
 + * Note that the end goal is to switch the kernel to use asynchronous
 + * probing by default, so annotating drivers with
 + * %PROBE_PREFER_ASYNCHRONOUS is a temporary measure that allows us
 + * to speed up boot process while we are validating the rest of the
 + * drivers.
 + */
 +enum probe_type {
 +      PROBE_DEFAULT_STRATEGY,
 +      PROBE_PREFER_ASYNCHRONOUS,
 +      PROBE_FORCE_SYNCHRONOUS,
 +};
 +
 +/**
   * struct device_driver - The basic device driver structure
   * @name:     Name of the device driver.
   * @bus:      The bus which the device of this driver belongs to.
   * @owner:    The module owner.
   * @mod_name: Used for built-in modules.
   * @suppress_bind_attrs: Disables bind/unbind via sysfs.
 + * @probe_type:       Type of the probe (synchronous or asynchronous) to use.
   * @of_match_table: The open firmware table.
   * @acpi_match_table: The ACPI match table.
   * @probe:    Called to query the existence of a specific device,
@@@ -264,7 -235,6 +264,7 @@@ struct device_driver 
        const char              *mod_name;      /* used for built-in modules */
  
        bool suppress_bind_attrs;       /* disables bind/unbind via sysfs */
 +      enum probe_type probe_type;
  
        const struct of_device_id       *of_match_table;
        const struct acpi_device_id     *acpi_match_table;
@@@ -1005,7 -975,6 +1005,7 @@@ extern int __must_check device_bind_dri
  extern void device_release_driver(struct device *dev);
  extern int  __must_check device_attach(struct device *dev);
  extern int __must_check driver_attach(struct device_driver *drv);
 +extern void device_initial_probe(struct device *dev);
  extern int __must_check device_reprobe(struct device *dev);
  
  /*
@@@ -1300,4 -1269,26 +1300,26 @@@ static void __exit __driver##_exit(void
  } \
  module_exit(__driver##_exit);
  
+ /**
+  * builtin_driver() - Helper macro for drivers that don't do anything
+  * special in init and have no exit. This eliminates some boilerplate.
+  * Each driver may only use this macro once, and calling it replaces
+  * device_initcall (or in some cases, the legacy __initcall).  This is
+  * meant to be a direct parallel of module_driver() above but without
+  * the __exit stuff that is not used for builtin cases.
+  *
+  * @__driver: driver name
+  * @__register: register function for this driver type
+  * @...: Additional arguments to be passed to __register
+  *
+  * Use this macro to construct bus specific macros for registering
+  * drivers, and do not use it on its own.
+  */
+ #define builtin_driver(__driver, __register, ...) \
+ static int __init __driver##_init(void) \
+ { \
+       return __register(&(__driver) , ##__VA_ARGS__); \
+ } \
+ device_initcall(__driver##_init);
  #endif /* _DEVICE_H_ */