Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 079d364b authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'pm-domains'

* pm-domains:
  PM / Domains: Fix compilation warning related to genpd_start_dev_no_timing()
  PM / Domains: Operations related to cpuidle using domain names
  PM / Domains: Document cpuidle-related functions and change their names
  PM / Domains: Add power-on function using names to identify domains
  PM / Domains: Make it possible to use names when adding subdomains
  PM / Domains: Make it possible to use domain names when adding devices
parents 8592013b b3d3b9fb
Loading
Loading
Loading
Loading
+117 −9
Original line number Diff line number Diff line
@@ -53,6 +53,24 @@
static LIST_HEAD(gpd_list);
static DEFINE_MUTEX(gpd_list_lock);

static struct generic_pm_domain *pm_genpd_lookup_name(const char *domain_name)
{
	struct generic_pm_domain *genpd = NULL, *gpd;

	if (IS_ERR_OR_NULL(domain_name))
		return NULL;

	mutex_lock(&gpd_list_lock);
	list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
		if (!strcmp(gpd->name, domain_name)) {
			genpd = gpd;
			break;
		}
	}
	mutex_unlock(&gpd_list_lock);
	return genpd;
}

#ifdef CONFIG_PM

struct generic_pm_domain *dev_to_genpd(struct device *dev)
@@ -75,12 +93,6 @@ static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev)
					start_latency_ns, "start");
}

static int genpd_start_dev_no_timing(struct generic_pm_domain *genpd,
				     struct device *dev)
{
	return GENPD_DEV_CALLBACK(genpd, int, start, dev);
}

static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd)
{
	bool ret = false;
@@ -262,10 +274,28 @@ int pm_genpd_poweron(struct generic_pm_domain *genpd)
	return ret;
}

/**
 * pm_genpd_name_poweron - Restore power to a given PM domain and its masters.
 * @domain_name: Name of the PM domain to power up.
 */
int pm_genpd_name_poweron(const char *domain_name)
{
	struct generic_pm_domain *genpd;

	genpd = pm_genpd_lookup_name(domain_name);
	return genpd ? pm_genpd_poweron(genpd) : -EINVAL;
}

#endif /* CONFIG_PM */

#ifdef CONFIG_PM_RUNTIME

static int genpd_start_dev_no_timing(struct generic_pm_domain *genpd,
				     struct device *dev)
{
	return GENPD_DEV_CALLBACK(genpd, int, start, dev);
}

static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev)
{
	return GENPD_DEV_TIMED_CALLBACK(genpd, int, save_state, dev,
@@ -1465,6 +1495,19 @@ int __pm_genpd_of_add_device(struct device_node *genpd_node, struct device *dev,
	return __pm_genpd_add_device(genpd, dev, td);
}


/**
 * __pm_genpd_name_add_device - Find I/O PM domain and add a device to it.
 * @domain_name: Name of the PM domain to add the device to.
 * @dev: Device to be added.
 * @td: Set of PM QoS timing parameters to attach to the device.
 */
int __pm_genpd_name_add_device(const char *domain_name, struct device *dev,
			       struct gpd_timing_data *td)
{
	return __pm_genpd_add_device(pm_genpd_lookup_name(domain_name), dev, td);
}

/**
 * pm_genpd_remove_device - Remove a device from an I/O PM domain.
 * @genpd: PM domain to remove the device from.
@@ -1557,7 +1600,8 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
	struct gpd_link *link;
	int ret = 0;

	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain)
	    || genpd == subdomain)
		return -EINVAL;

 start:
@@ -1603,6 +1647,35 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
	return ret;
}

/**
 * pm_genpd_add_subdomain_names - Add a subdomain to an I/O PM domain.
 * @master_name: Name of the master PM domain to add the subdomain to.
 * @subdomain_name: Name of the subdomain to be added.
 */
int pm_genpd_add_subdomain_names(const char *master_name,
				 const char *subdomain_name)
{
	struct generic_pm_domain *master = NULL, *subdomain = NULL, *gpd;

	if (IS_ERR_OR_NULL(master_name) || IS_ERR_OR_NULL(subdomain_name))
		return -EINVAL;

	mutex_lock(&gpd_list_lock);
	list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
		if (!master && !strcmp(gpd->name, master_name))
			master = gpd;

		if (!subdomain && !strcmp(gpd->name, subdomain_name))
			subdomain = gpd;

		if (master && subdomain)
			break;
	}
	mutex_unlock(&gpd_list_lock);

	return pm_genpd_add_subdomain(master, subdomain);
}

/**
 * pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain.
 * @genpd: Master PM domain to remove the subdomain from.
@@ -1756,7 +1829,16 @@ int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td)
}
EXPORT_SYMBOL_GPL(__pm_genpd_remove_callbacks);

int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
/**
 * pm_genpd_attach_cpuidle - Connect the given PM domain with cpuidle.
 * @genpd: PM domain to be connected with cpuidle.
 * @state: cpuidle state this domain can disable/enable.
 *
 * Make a PM domain behave as though it contained a CPU core, that is, instead
 * of calling its power down routine it will enable the given cpuidle state so
 * that the cpuidle subsystem can power it down (if possible and desirable).
 */
int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
{
	struct cpuidle_driver *cpuidle_drv;
	struct gpd_cpu_data *cpu_data;
@@ -1805,7 +1887,24 @@ int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
	goto out;
}

int genpd_detach_cpuidle(struct generic_pm_domain *genpd)
/**
 * pm_genpd_name_attach_cpuidle - Find PM domain and connect cpuidle to it.
 * @name: Name of the domain to connect to cpuidle.
 * @state: cpuidle state this domain can manipulate.
 */
int pm_genpd_name_attach_cpuidle(const char *name, int state)
{
	return pm_genpd_attach_cpuidle(pm_genpd_lookup_name(name), state);
}

/**
 * pm_genpd_detach_cpuidle - Remove the cpuidle connection from a PM domain.
 * @genpd: PM domain to remove the cpuidle connection from.
 *
 * Remove the cpuidle connection set up by pm_genpd_attach_cpuidle() from the
 * given PM domain.
 */
int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd)
{
	struct gpd_cpu_data *cpu_data;
	struct cpuidle_state *idle_state;
@@ -1836,6 +1935,15 @@ int genpd_detach_cpuidle(struct generic_pm_domain *genpd)
	return ret;
}

/**
 * pm_genpd_name_detach_cpuidle - Find PM domain and disconnect cpuidle from it.
 * @name: Name of the domain to disconnect cpuidle from.
 */
int pm_genpd_name_detach_cpuidle(const char *name)
{
	return pm_genpd_detach_cpuidle(pm_genpd_lookup_name(name));
}

/* Default device callbacks for generic PM domains. */

/**
+56 −17
Original line number Diff line number Diff line
@@ -138,35 +138,32 @@ extern int __pm_genpd_of_add_device(struct device_node *genpd_node,
				    struct device *dev,
				    struct gpd_timing_data *td);

static inline int pm_genpd_add_device(struct generic_pm_domain *genpd,
				      struct device *dev)
{
	return __pm_genpd_add_device(genpd, dev, NULL);
}

static inline int pm_genpd_of_add_device(struct device_node *genpd_node,
					 struct device *dev)
{
	return __pm_genpd_of_add_device(genpd_node, dev, NULL);
}
extern int __pm_genpd_name_add_device(const char *domain_name,
				      struct device *dev,
				      struct gpd_timing_data *td);

extern int pm_genpd_remove_device(struct generic_pm_domain *genpd,
				  struct device *dev);
extern void pm_genpd_dev_need_restore(struct device *dev, bool val);
extern int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
				  struct generic_pm_domain *new_subdomain);
extern int pm_genpd_add_subdomain_names(const char *master_name,
					const char *subdomain_name);
extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
				     struct generic_pm_domain *target);
extern int pm_genpd_add_callbacks(struct device *dev,
				  struct gpd_dev_ops *ops,
				  struct gpd_timing_data *td);
extern int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td);
extern int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state);
extern int genpd_detach_cpuidle(struct generic_pm_domain *genpd);
extern int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state);
extern int pm_genpd_name_attach_cpuidle(const char *name, int state);
extern int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd);
extern int pm_genpd_name_detach_cpuidle(const char *name);
extern void pm_genpd_init(struct generic_pm_domain *genpd,
			  struct dev_power_governor *gov, bool is_off);

extern int pm_genpd_poweron(struct generic_pm_domain *genpd);
extern int pm_genpd_name_poweron(const char *domain_name);

extern bool default_stop_ok(struct device *dev);

@@ -187,8 +184,15 @@ static inline int __pm_genpd_add_device(struct generic_pm_domain *genpd,
{
	return -ENOSYS;
}
static inline int pm_genpd_add_device(struct generic_pm_domain *genpd,
				      struct device *dev)
static inline int __pm_genpd_of_add_device(struct device_node *genpd_node,
					   struct device *dev,
					   struct gpd_timing_data *td)
{
	return -ENOSYS;
}
static inline int __pm_genpd_name_add_device(const char *domain_name,
					     struct device *dev,
					     struct gpd_timing_data *td)
{
	return -ENOSYS;
}
@@ -203,6 +207,11 @@ static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
{
	return -ENOSYS;
}
static inline int pm_genpd_add_subdomain_names(const char *master_name,
					       const char *subdomain_name)
{
	return -ENOSYS;
}
static inline int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
					    struct generic_pm_domain *target)
{
@@ -218,11 +227,19 @@ static inline int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td)
{
	return -ENOSYS;
}
static inline int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int st)
static inline int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int st)
{
	return -ENOSYS;
}
static inline int genpd_detach_cpuidle(struct generic_pm_domain *genpd)
static inline int pm_genpd_name_attach_cpuidle(const char *name, int state)
{
	return -ENOSYS;
}
static inline int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd)
{
	return -ENOSYS;
}
static inline int pm_genpd_name_detach_cpuidle(const char *name)
{
	return -ENOSYS;
}
@@ -234,6 +251,10 @@ static inline int pm_genpd_poweron(struct generic_pm_domain *genpd)
{
	return -ENOSYS;
}
static inline int pm_genpd_name_poweron(const char *domain_name)
{
	return -ENOSYS;
}
static inline bool default_stop_ok(struct device *dev)
{
	return false;
@@ -242,6 +263,24 @@ static inline bool default_stop_ok(struct device *dev)
#define pm_domain_always_on_gov NULL
#endif

static inline int pm_genpd_add_device(struct generic_pm_domain *genpd,
				      struct device *dev)
{
	return __pm_genpd_add_device(genpd, dev, NULL);
}

static inline int pm_genpd_of_add_device(struct device_node *genpd_node,
					 struct device *dev)
{
	return __pm_genpd_of_add_device(genpd_node, dev, NULL);
}

static inline int pm_genpd_name_add_device(const char *domain_name,
					   struct device *dev)
{
	return __pm_genpd_name_add_device(domain_name, dev, NULL);
}

static inline int pm_genpd_remove_callbacks(struct device *dev)
{
	return __pm_genpd_remove_callbacks(dev, true);