Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux...
[sfrench/cifs-2.6.git] / include / linux / device.h
index e396de656f2072617293dffadb8a128d62cae9dc..e226030c1df3c3f1c333f2acba8955a116921cf6 100644 (file)
@@ -80,6 +80,13 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
  *             that generate uevents to add the environment variables.
  * @probe:     Called when a new device or driver add to this bus, and callback
  *             the specific driver's probe to initial the matched device.
+ * @sync_state:        Called to sync device state to software state after all the
+ *             state tracking consumers linked to this device (present at
+ *             the time of late_initcall) have successfully bound to a
+ *             driver. If the device has no consumers, this function will
+ *             be called at late_initcall_sync level. If the device has
+ *             consumers that are never bound to a driver, this function
+ *             will never get called until they do.
  * @remove:    Called when a device removed from this bus.
  * @shutdown:  Called at shut-down time to quiesce the device.
  *
@@ -123,6 +130,7 @@ struct bus_type {
        int (*match)(struct device *dev, struct device_driver *drv);
        int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
        int (*probe)(struct device *dev);
+       void (*sync_state)(struct device *dev);
        int (*remove)(struct device *dev);
        void (*shutdown)(struct device *dev);
 
@@ -340,6 +348,13 @@ enum probe_type {
  * @probe:     Called to query the existence of a specific device,
  *             whether this driver can work with it, and bind the driver
  *             to a specific device.
+ * @sync_state:        Called to sync device state to software state after all the
+ *             state tracking consumers linked to this device (present at
+ *             the time of late_initcall) have successfully bound to a
+ *             driver. If the device has no consumers, this function will
+ *             be called at late_initcall_sync level. If the device has
+ *             consumers that are never bound to a driver, this function
+ *             will never get called until they do.
  * @remove:    Called when the device is removed from the system to
  *             unbind a device from this driver.
  * @shutdown:  Called at shut-down time to quiesce the device.
@@ -379,6 +394,7 @@ struct device_driver {
        const struct acpi_device_id     *acpi_match_table;
 
        int (*probe) (struct device *dev);
+       void (*sync_state)(struct device *dev);
        int (*remove) (struct device *dev);
        void (*shutdown) (struct device *dev);
        int (*suspend) (struct device *dev, pm_message_t state);
@@ -946,6 +962,8 @@ extern void devm_free_pages(struct device *dev, unsigned long addr);
 
 void __iomem *devm_ioremap_resource(struct device *dev,
                                    const struct resource *res);
+void __iomem *devm_ioremap_resource_wc(struct device *dev,
+                                      const struct resource *res);
 
 void __iomem *devm_of_iomap(struct device *dev,
                            struct device_node *node, int index,
@@ -1080,6 +1098,7 @@ enum device_link_state {
  * AUTOREMOVE_SUPPLIER: Remove the link automatically on supplier driver unbind.
  * AUTOPROBE_CONSUMER: Probe consumer driver automatically after supplier binds.
  * MANAGED: The core tracks presence of supplier/consumer drivers (internal).
+ * SYNC_STATE_ONLY: Link only affects sync_state() behavior.
  */
 #define DL_FLAG_STATELESS              BIT(0)
 #define DL_FLAG_AUTOREMOVE_CONSUMER    BIT(1)
@@ -1088,6 +1107,7 @@ enum device_link_state {
 #define DL_FLAG_AUTOREMOVE_SUPPLIER    BIT(4)
 #define DL_FLAG_AUTOPROBE_CONSUMER     BIT(5)
 #define DL_FLAG_MANAGED                        BIT(6)
+#define DL_FLAG_SYNC_STATE_ONLY                BIT(7)
 
 /**
  * struct device_link - Device link representation.
@@ -1135,11 +1155,18 @@ enum dl_dev_state {
  * struct dev_links_info - Device data related to device links.
  * @suppliers: List of links to supplier devices.
  * @consumers: List of links to consumer devices.
+ * @needs_suppliers: Hook to global list of devices waiting for suppliers.
+ * @defer_sync: Hook to global list of devices that have deferred sync_state.
+ * @need_for_probe: If needs_suppliers is on a list, this indicates if the
+ *                 suppliers are needed for probe or not.
  * @status: Driver status information.
  */
 struct dev_links_info {
        struct list_head suppliers;
        struct list_head consumers;
+       struct list_head needs_suppliers;
+       struct list_head defer_sync;
+       bool need_for_probe;
        enum dl_dev_state status;
 };
 
@@ -1215,6 +1242,9 @@ struct dev_links_info {
  * @offline:   Set after successful invocation of bus type's .offline().
  * @of_node_reused: Set if the device-tree node is shared with an ancestor
  *              device.
+ * @state_synced: The hardware state of this device has been synced to match
+ *               the software state of this device by calling the driver/bus
+ *               sync_state() callback.
  * @dma_coherent: this particular device is dma coherent, even if the
  *             architecture supports non-coherent devices.
  *
@@ -1311,6 +1341,7 @@ struct device {
        bool                    offline_disabled:1;
        bool                    offline:1;
        bool                    of_node_reused:1;
+       bool                    state_synced:1;
 #if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \
     defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) || \
     defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL)
@@ -1653,6 +1684,8 @@ struct device_link *device_link_add(struct device *consumer,
                                    struct device *supplier, u32 flags);
 void device_link_del(struct device_link *link);
 void device_link_remove(void *consumer, struct device *supplier);
+void device_links_supplier_sync_state_pause(void);
+void device_links_supplier_sync_state_resume(void);
 
 #ifndef dev_fmt
 #define dev_fmt(fmt) fmt