Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
31f18230
Commit
31f18230
authored
Nov 08, 2017
by
Rafael J. Wysocki
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'pm-domains' into pm-qos
parents
20f97caf
704d2ce6
Changes
6
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
223 additions
and
121 deletions
+223
-121
arch/arm/mach-shmobile/pm-rmobile.c
arch/arm/mach-shmobile/pm-rmobile.c
+1
-7
drivers/base/power/domain.c
drivers/base/power/domain.c
+153
-64
drivers/base/power/domain_governor.c
drivers/base/power/domain_governor.c
+49
-22
drivers/soc/mediatek/mtk-scpsys.c
drivers/soc/mediatek/mtk-scpsys.c
+2
-12
drivers/soc/rockchip/pm_domains.c
drivers/soc/rockchip/pm_domains.c
+2
-12
include/linux/pm_domain.h
include/linux/pm_domain.h
+16
-4
No files found.
arch/arm/mach-shmobile/pm-rmobile.c
View file @
31f18230
...
@@ -120,18 +120,12 @@ static int rmobile_pd_power_up(struct generic_pm_domain *genpd)
...
@@ -120,18 +120,12 @@ static int rmobile_pd_power_up(struct generic_pm_domain *genpd)
return
__rmobile_pd_power_up
(
to_rmobile_pd
(
genpd
),
true
);
return
__rmobile_pd_power_up
(
to_rmobile_pd
(
genpd
),
true
);
}
}
static
bool
rmobile_pd_active_wakeup
(
struct
device
*
dev
)
{
return
true
;
}
static
void
rmobile_init_pm_domain
(
struct
rmobile_pm_domain
*
rmobile_pd
)
static
void
rmobile_init_pm_domain
(
struct
rmobile_pm_domain
*
rmobile_pd
)
{
{
struct
generic_pm_domain
*
genpd
=
&
rmobile_pd
->
genpd
;
struct
generic_pm_domain
*
genpd
=
&
rmobile_pd
->
genpd
;
struct
dev_power_governor
*
gov
=
rmobile_pd
->
gov
;
struct
dev_power_governor
*
gov
=
rmobile_pd
->
gov
;
genpd
->
flags
|=
GENPD_FLAG_PM_CLK
;
genpd
->
flags
|=
GENPD_FLAG_PM_CLK
|
GENPD_FLAG_ACTIVE_WAKEUP
;
genpd
->
dev_ops
.
active_wakeup
=
rmobile_pd_active_wakeup
;
genpd
->
power_off
=
rmobile_pd_power_down
;
genpd
->
power_off
=
rmobile_pd_power_down
;
genpd
->
power_on
=
rmobile_pd_power_up
;
genpd
->
power_on
=
rmobile_pd_power_up
;
genpd
->
attach_dev
=
cpg_mstp_attach_dev
;
genpd
->
attach_dev
=
cpg_mstp_attach_dev
;
...
...
drivers/base/power/domain.c
View file @
31f18230
This diff is collapsed.
Click to expand it.
drivers/base/power/domain_governor.c
View file @
31f18230
...
@@ -14,22 +14,33 @@
...
@@ -14,22 +14,33 @@
static
int
dev_update_qos_constraint
(
struct
device
*
dev
,
void
*
data
)
static
int
dev_update_qos_constraint
(
struct
device
*
dev
,
void
*
data
)
{
{
s64
*
constraint_ns_p
=
data
;
s64
*
constraint_ns_p
=
data
;
s
32
constraint_ns
=
-
1
;
s
64
constraint_ns
;
if
(
dev
->
power
.
subsys_data
&&
dev
->
power
.
subsys_data
->
domain_data
)
if
(
dev
->
power
.
subsys_data
&&
dev
->
power
.
subsys_data
->
domain_data
)
{
/*
* Only take suspend-time QoS constraints of devices into
* account, because constraints updated after the device has
* been suspended are not guaranteed to be taken into account
* anyway. In order for them to take effect, the device has to
* be resumed and suspended again.
*/
constraint_ns
=
dev_gpd_data
(
dev
)
->
td
.
effective_constraint_ns
;
constraint_ns
=
dev_gpd_data
(
dev
)
->
td
.
effective_constraint_ns
;
}
else
{
if
(
constraint_ns
<
0
)
{
/*
* The child is not in a domain and there's no info on its
* suspend/resume latencies, so assume them to be negligible and
* take its current PM QoS constraint (that's the only thing
* known at this point anyway).
*/
constraint_ns
=
dev_pm_qos_read_value
(
dev
);
constraint_ns
=
dev_pm_qos_read_value
(
dev
);
if
(
constraint_ns
>
0
)
constraint_ns
*=
NSEC_PER_USEC
;
constraint_ns
*=
NSEC_PER_USEC
;
}
}
/* 0 means "no constraint" */
if
(
constraint_ns
==
0
)
if
(
constraint_ns
==
0
)
return
0
;
return
0
;
/*
* constraint_ns cannot be negative here, because the device has been
* suspended.
*/
if
(
constraint_ns
<
*
constraint_ns_p
||
*
constraint_ns_p
==
0
)
if
(
constraint_ns
<
*
constraint_ns_p
||
*
constraint_ns_p
==
0
)
*
constraint_ns_p
=
constraint_ns
;
*
constraint_ns_p
=
constraint_ns
;
...
@@ -76,14 +87,32 @@ static bool default_suspend_ok(struct device *dev)
...
@@ -76,14 +87,32 @@ static bool default_suspend_ok(struct device *dev)
device_for_each_child
(
dev
,
&
constraint_ns
,
device_for_each_child
(
dev
,
&
constraint_ns
,
dev_update_qos_constraint
);
dev_update_qos_constraint
);
if
(
constraint_ns
>
0
)
{
if
(
constraint_ns
==
0
)
{
/* "No restriction", so the device is allowed to suspend. */
td
->
effective_constraint_ns
=
0
;
td
->
cached_suspend_ok
=
true
;
}
else
if
(
constraint_ns
<
0
)
{
/*
* This triggers if one of the children that don't belong to a
* domain has a negative PM QoS constraint and it's better not
* to suspend then. effective_constraint_ns is negative already
* and cached_suspend_ok is false, so bail out.
*/
return
false
;
}
else
{
constraint_ns
-=
td
->
suspend_latency_ns
+
constraint_ns
-=
td
->
suspend_latency_ns
+
td
->
resume_latency_ns
;
td
->
resume_latency_ns
;
if
(
constraint_ns
==
0
)
/*
* effective_constraint_ns is negative already and
* cached_suspend_ok is false, so if the computed value is not
* positive, return right away.
*/
if
(
constraint_ns
<=
0
)
return
false
;
return
false
;
}
td
->
effective_constraint_ns
=
constraint_ns
;
td
->
effective_constraint_ns
=
constraint_ns
;
td
->
cached_suspend_ok
=
constraint_ns
>=
0
;
td
->
cached_suspend_ok
=
true
;
}
/*
/*
* The children have been suspended already, so we don't need to take
* The children have been suspended already, so we don't need to take
...
@@ -144,18 +173,16 @@ static bool __default_power_down_ok(struct dev_pm_domain *pd,
...
@@ -144,18 +173,16 @@ static bool __default_power_down_ok(struct dev_pm_domain *pd,
*/
*/
td
=
&
to_gpd_data
(
pdd
)
->
td
;
td
=
&
to_gpd_data
(
pdd
)
->
td
;
constraint_ns
=
td
->
effective_constraint_ns
;
constraint_ns
=
td
->
effective_constraint_ns
;
/* default_suspend_ok() need not be called before us. */
/*
if
(
constraint_ns
<
0
)
{
* Negative values mean "no suspend at all" and this runs only
constraint_ns
=
dev_pm_qos_read_value
(
pdd
->
dev
);
* when all devices in the domain are suspended, so it must be
constraint_ns
*=
NSEC_PER_USEC
;
* 0 at least.
}
*
* 0 means "no constraint"
*/
if
(
constraint_ns
==
0
)
if
(
constraint_ns
==
0
)
continue
;
continue
;
/*
* constraint_ns cannot be negative here, because the device has
* been suspended.
*/
if
(
constraint_ns
<=
off_on_time_ns
)
if
(
constraint_ns
<=
off_on_time_ns
)
return
false
;
return
false
;
...
...
drivers/soc/mediatek/mtk-scpsys.c
View file @
31f18230
...
@@ -361,17 +361,6 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
...
@@ -361,17 +361,6 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
return
ret
;
return
ret
;
}
}
static
bool
scpsys_active_wakeup
(
struct
device
*
dev
)
{
struct
generic_pm_domain
*
genpd
;
struct
scp_domain
*
scpd
;
genpd
=
pd_to_genpd
(
dev
->
pm_domain
);
scpd
=
container_of
(
genpd
,
struct
scp_domain
,
genpd
);
return
scpd
->
data
->
active_wakeup
;
}
static
void
init_clks
(
struct
platform_device
*
pdev
,
struct
clk
**
clk
)
static
void
init_clks
(
struct
platform_device
*
pdev
,
struct
clk
**
clk
)
{
{
int
i
;
int
i
;
...
@@ -466,7 +455,8 @@ static struct scp *init_scp(struct platform_device *pdev,
...
@@ -466,7 +455,8 @@ static struct scp *init_scp(struct platform_device *pdev,
genpd
->
name
=
data
->
name
;
genpd
->
name
=
data
->
name
;
genpd
->
power_off
=
scpsys_power_off
;
genpd
->
power_off
=
scpsys_power_off
;
genpd
->
power_on
=
scpsys_power_on
;
genpd
->
power_on
=
scpsys_power_on
;
genpd
->
dev_ops
.
active_wakeup
=
scpsys_active_wakeup
;
if
(
scpd
->
data
->
active_wakeup
)
genpd
->
flags
|=
GENPD_FLAG_ACTIVE_WAKEUP
;
}
}
return
scp
;
return
scp
;
...
...
drivers/soc/rockchip/pm_domains.c
View file @
31f18230
...
@@ -358,17 +358,6 @@ static void rockchip_pd_detach_dev(struct generic_pm_domain *genpd,
...
@@ -358,17 +358,6 @@ static void rockchip_pd_detach_dev(struct generic_pm_domain *genpd,
pm_clk_destroy
(
dev
);
pm_clk_destroy
(
dev
);
}
}
static
bool
rockchip_active_wakeup
(
struct
device
*
dev
)
{
struct
generic_pm_domain
*
genpd
;
struct
rockchip_pm_domain
*
pd
;
genpd
=
pd_to_genpd
(
dev
->
pm_domain
);
pd
=
container_of
(
genpd
,
struct
rockchip_pm_domain
,
genpd
);
return
pd
->
info
->
active_wakeup
;
}
static
int
rockchip_pm_add_one_domain
(
struct
rockchip_pmu
*
pmu
,
static
int
rockchip_pm_add_one_domain
(
struct
rockchip_pmu
*
pmu
,
struct
device_node
*
node
)
struct
device_node
*
node
)
{
{
...
@@ -489,8 +478,9 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
...
@@ -489,8 +478,9 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
pd
->
genpd
.
power_on
=
rockchip_pd_power_on
;
pd
->
genpd
.
power_on
=
rockchip_pd_power_on
;
pd
->
genpd
.
attach_dev
=
rockchip_pd_attach_dev
;
pd
->
genpd
.
attach_dev
=
rockchip_pd_attach_dev
;
pd
->
genpd
.
detach_dev
=
rockchip_pd_detach_dev
;
pd
->
genpd
.
detach_dev
=
rockchip_pd_detach_dev
;
pd
->
genpd
.
dev_ops
.
active_wakeup
=
rockchip_active_wakeup
;
pd
->
genpd
.
flags
=
GENPD_FLAG_PM_CLK
;
pd
->
genpd
.
flags
=
GENPD_FLAG_PM_CLK
;
if
(
pd_info
->
active_wakeup
)
pd
->
genpd
.
flags
|=
GENPD_FLAG_ACTIVE_WAKEUP
;
pm_genpd_init
(
&
pd
->
genpd
,
NULL
,
false
);
pm_genpd_init
(
&
pd
->
genpd
,
NULL
,
false
);
pmu
->
genpd_data
.
domains
[
id
]
=
&
pd
->
genpd
;
pmu
->
genpd_data
.
domains
[
id
]
=
&
pd
->
genpd
;
...
...
include/linux/pm_domain.h
View file @
31f18230
...
@@ -21,6 +21,7 @@
...
@@ -21,6 +21,7 @@
#define GENPD_FLAG_PM_CLK (1U << 0)
/* PM domain uses PM clk */
#define GENPD_FLAG_PM_CLK (1U << 0)
/* PM domain uses PM clk */
#define GENPD_FLAG_IRQ_SAFE (1U << 1)
/* PM domain operates in atomic */
#define GENPD_FLAG_IRQ_SAFE (1U << 1)
/* PM domain operates in atomic */
#define GENPD_FLAG_ALWAYS_ON (1U << 2)
/* PM domain is always powered on */
#define GENPD_FLAG_ALWAYS_ON (1U << 2)
/* PM domain is always powered on */
#define GENPD_FLAG_ACTIVE_WAKEUP (1U << 3)
/* Keep devices active if wakeup */
enum
gpd_status
{
enum
gpd_status
{
GPD_STATE_ACTIVE
=
0
,
/* PM domain is active */
GPD_STATE_ACTIVE
=
0
,
/* PM domain is active */
...
@@ -35,7 +36,6 @@ struct dev_power_governor {
...
@@ -35,7 +36,6 @@ struct dev_power_governor {
struct
gpd_dev_ops
{
struct
gpd_dev_ops
{
int
(
*
start
)(
struct
device
*
dev
);
int
(
*
start
)(
struct
device
*
dev
);
int
(
*
stop
)(
struct
device
*
dev
);
int
(
*
stop
)(
struct
device
*
dev
);
bool
(
*
active_wakeup
)(
struct
device
*
dev
);
};
};
struct
genpd_power_state
{
struct
genpd_power_state
{
...
@@ -64,8 +64,11 @@ struct generic_pm_domain {
...
@@ -64,8 +64,11 @@ struct generic_pm_domain {
unsigned
int
device_count
;
/* Number of devices */
unsigned
int
device_count
;
/* Number of devices */
unsigned
int
suspended_count
;
/* System suspend device counter */
unsigned
int
suspended_count
;
/* System suspend device counter */
unsigned
int
prepared_count
;
/* Suspend counter of prepared devices */
unsigned
int
prepared_count
;
/* Suspend counter of prepared devices */
unsigned
int
performance_state
;
/* Aggregated max performance state */
int
(
*
power_off
)(
struct
generic_pm_domain
*
domain
);
int
(
*
power_off
)(
struct
generic_pm_domain
*
domain
);
int
(
*
power_on
)(
struct
generic_pm_domain
*
domain
);
int
(
*
power_on
)(
struct
generic_pm_domain
*
domain
);
int
(
*
set_performance_state
)(
struct
generic_pm_domain
*
genpd
,
unsigned
int
state
);
struct
gpd_dev_ops
dev_ops
;
struct
gpd_dev_ops
dev_ops
;
s64
max_off_time_ns
;
/* Maximum allowed "suspended" time. */
s64
max_off_time_ns
;
/* Maximum allowed "suspended" time. */
bool
max_off_time_changed
;
bool
max_off_time_changed
;
...
@@ -121,6 +124,7 @@ struct generic_pm_domain_data {
...
@@ -121,6 +124,7 @@ struct generic_pm_domain_data {
struct
pm_domain_data
base
;
struct
pm_domain_data
base
;
struct
gpd_timing_data
td
;
struct
gpd_timing_data
td
;
struct
notifier_block
nb
;
struct
notifier_block
nb
;
unsigned
int
performance_state
;
void
*
data
;
void
*
data
;
};
};
...
@@ -148,6 +152,8 @@ extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
...
@@ -148,6 +152,8 @@ extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
extern
int
pm_genpd_init
(
struct
generic_pm_domain
*
genpd
,
extern
int
pm_genpd_init
(
struct
generic_pm_domain
*
genpd
,
struct
dev_power_governor
*
gov
,
bool
is_off
);
struct
dev_power_governor
*
gov
,
bool
is_off
);
extern
int
pm_genpd_remove
(
struct
generic_pm_domain
*
genpd
);
extern
int
pm_genpd_remove
(
struct
generic_pm_domain
*
genpd
);
extern
int
dev_pm_genpd_set_performance_state
(
struct
device
*
dev
,
unsigned
int
state
);
extern
struct
dev_power_governor
simple_qos_governor
;
extern
struct
dev_power_governor
simple_qos_governor
;
extern
struct
dev_power_governor
pm_domain_always_on_gov
;
extern
struct
dev_power_governor
pm_domain_always_on_gov
;
...
@@ -188,6 +194,12 @@ static inline int pm_genpd_remove(struct generic_pm_domain *genpd)
...
@@ -188,6 +194,12 @@ static inline int pm_genpd_remove(struct generic_pm_domain *genpd)
return
-
ENOTSUPP
;
return
-
ENOTSUPP
;
}
}
static
inline
int
dev_pm_genpd_set_performance_state
(
struct
device
*
dev
,
unsigned
int
state
)
{
return
-
ENOTSUPP
;
}
#define simple_qos_governor (*(struct dev_power_governor *)(NULL))
#define simple_qos_governor (*(struct dev_power_governor *)(NULL))
#define pm_domain_always_on_gov (*(struct dev_power_governor *)(NULL))
#define pm_domain_always_on_gov (*(struct dev_power_governor *)(NULL))
#endif
#endif
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment