summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeela Chithirala <chithiralan@google.com>2022-03-14 05:24:14 +0000
committerNeela Chithirala <chithiralan@google.com>2022-03-14 05:24:14 +0000
commit8f54b9374e56fd08f990fe2fe4dc8b3bde1c00d2 (patch)
tree241cb59b01b6985fba593e162c85bc14050ed1b1
parent6d71338807ebff13916d2285d67ce59f261eab3e (diff)
downloadgs201-8f54b9374e56fd08f990fe2fe4dc8b3bde1c00d2.tar.gz
Merge branch 'gs201-release' to android13-gs-pixel-5.10
* gs201-release: gxp: ignore AUR_OFF in power voting Bug: 223286553 gxp: change memory power state asynchronously Bug: 221187219 gxp: cancel the vote when the client is destroyed Bug: 201600514 gxp: refactor pm interface Bug: 201600514 gxp: Make a power state vote for debugfs wakelocks Bug: 223286553 gxp: Return error if gxp_vd_allocate() fails Signed-off-by: Neela Chithirala <chithiralan@google.com> Change-Id: Ibb879ffffa83e787409debec4e5e55bfe8858808
-rw-r--r--gxp-client.c8
-rw-r--r--gxp-debugfs.c29
-rw-r--r--gxp-platform.c5
-rw-r--r--gxp-pm.c62
-rw-r--r--gxp-pm.h10
5 files changed, 78 insertions, 36 deletions
diff --git a/gxp-client.c b/gxp-client.c
index 2ff0a7c..73aafc1 100644
--- a/gxp-client.c
+++ b/gxp-client.c
@@ -52,8 +52,14 @@ void gxp_client_destroy(struct gxp_client *client)
up_write(&gxp->vd_semaphore);
- if (client->has_block_wakelock)
+ if (client->has_block_wakelock) {
gxp_wakelock_release(client->gxp);
+ gxp_pm_update_requested_power_state(
+ gxp, client->requested_power_state, AUR_OFF);
+ gxp_pm_update_requested_memory_power_state(
+ gxp, client->requested_memory_power_state,
+ AUR_MEM_UNDEFINED);
+ }
gxp_vd_release(client->vd);
diff --git a/gxp-debugfs.c b/gxp-debugfs.c
index 0576c9a..480dca2 100644
--- a/gxp-debugfs.c
+++ b/gxp-debugfs.c
@@ -148,15 +148,16 @@ static int gxp_firmware_run_set(void *data, u64 val)
if (IS_ERR(gxp->debugfs_client->vd)) {
dev_err(gxp->dev, "Failed to allocate VD\n");
ret = PTR_ERR(gxp->debugfs_client->vd);
- goto err_start;
+ goto err_wakelock;
}
ret = gxp_wakelock_acquire(gxp);
if (ret) {
dev_err(gxp->dev, "Failed to acquire BLOCK wakelock\n");
- goto err_start;
+ goto err_wakelock;
}
gxp->debugfs_client->has_block_wakelock = true;
+ gxp_pm_update_requested_power_state(gxp, AUR_OFF, AUR_UUD);
down_write(&gxp->vd_semaphore);
ret = gxp_vd_start(gxp->debugfs_client->vd);
@@ -179,6 +180,7 @@ static int gxp_firmware_run_set(void *data, u64 val)
*/
gxp_client_destroy(gxp->debugfs_client);
gxp->debugfs_client = NULL;
+ gxp_pm_update_requested_power_state(gxp, AUR_UUD, AUR_OFF);
}
out:
@@ -187,6 +189,9 @@ out:
return ret;
err_start:
+ gxp_wakelock_release(gxp);
+ gxp_pm_update_requested_power_state(gxp, AUR_UUD, AUR_OFF);
+err_wakelock:
/* Destroying a client cleans up any VDss or wakelocks it held. */
gxp_client_destroy(gxp->debugfs_client);
gxp->debugfs_client = NULL;
@@ -210,32 +215,42 @@ static int gxp_wakelock_set(void *data, u64 val)
struct gxp_dev *gxp = (struct gxp_dev *)data;
int ret = 0;
+ mutex_lock(&gxp->debugfs_client_lock);
+
if (val > 0) {
/* Wakelock Acquire */
if (gxp->debugfs_wakelock_held) {
dev_warn(gxp->dev,
"Debugfs wakelock is already held.\n");
- return -EBUSY;
+ ret = -EBUSY;
+ goto out;
}
ret = gxp_wakelock_acquire(gxp);
- if (ret)
+ if (ret) {
dev_err(gxp->dev,
"Failed to acquire debugfs wakelock ret=%d\n",
ret);
- else
- gxp->debugfs_wakelock_held = true;
+ goto out;
+ }
+ gxp->debugfs_wakelock_held = true;
+ gxp_pm_update_requested_power_state(gxp, AUR_OFF, AUR_UUD);
} else {
/* Wakelock Release */
if (!gxp->debugfs_wakelock_held) {
dev_warn(gxp->dev, "Debugfs wakelock not held.\n");
- return -EIO;
+ ret = -EIO;
+ goto out;
}
gxp_wakelock_release(gxp);
gxp->debugfs_wakelock_held = false;
+ gxp_pm_update_requested_power_state(gxp, AUR_UUD, AUR_OFF);
}
+out:
+ mutex_unlock(&gxp->debugfs_client_lock);
+
return ret;
}
diff --git a/gxp-platform.c b/gxp-platform.c
index 3061935..ba2093e 100644
--- a/gxp-platform.c
+++ b/gxp-platform.c
@@ -536,9 +536,10 @@ static int gxp_allocate_vd(struct gxp_client *client,
vd = gxp_vd_allocate(gxp, ibuf.core_count);
if (IS_ERR(vd)) {
+ ret = PTR_ERR(vd);
dev_err(gxp->dev,
- "Failed to allocate virtual device for client (%ld)\n",
- PTR_ERR(vd));
+ "Failed to allocate virtual device for client (%d)\n",
+ ret);
goto out;
}
diff --git a/gxp-pm.c b/gxp-pm.c
index 87da768..7ca23a5 100644
--- a/gxp-pm.c
+++ b/gxp-pm.c
@@ -242,7 +242,7 @@ static int gxp_pm_req_state_locked(struct gxp_dev *gxp, enum aur_power_state sta
if (state != gxp->power_mgr->curr_state) {
gxp->power_mgr->curr_state = state;
if (state == AUR_OFF) {
- gxp_pm_blk_off(gxp);
+ dev_warn(gxp->dev, "It is not supported to request AUR_OFF\n");
} else {
gxp->power_mgr->set_acpm_rate_work.gxp = gxp;
gxp->power_mgr->set_acpm_rate_work.state = state;
@@ -265,24 +265,23 @@ int gxp_pm_req_state(struct gxp_dev *gxp, enum aur_power_state state)
}
/* Caller must hold pm_lock */
-static int gxp_pm_revoke_power_state_vote(struct gxp_dev *gxp,
- enum aur_power_state revoked_state)
+static void gxp_pm_revoke_power_state_vote(struct gxp_dev *gxp,
+ enum aur_power_state revoked_state)
{
unsigned int i;
if (revoked_state == AUR_OFF)
- return 0;
+ return;
for (i = 0; i < AUR_NUM_POWER_STATE; i++) {
if (aur_state_array[i] == revoked_state) {
- if (gxp->power_mgr->pwr_state_req_count[i] <= 0) {
+ if (gxp->power_mgr->pwr_state_req_count[i] == 0)
dev_err(gxp->dev, "Invalid state %d\n",
revoked_state);
- return -EINVAL;
- }
- gxp->power_mgr->pwr_state_req_count[i]--;
+ else
+ gxp->power_mgr->pwr_state_req_count[i]--;
+ return;
}
}
- return 0;
}
/* Caller must hold pm_lock */
@@ -293,9 +292,12 @@ static void gxp_pm_vote_power_state(struct gxp_dev *gxp,
if (state == AUR_OFF)
return;
- for (i = 0; i < AUR_NUM_POWER_STATE; i++)
- if (aur_state_array[i] == state)
+ for (i = 0; i < AUR_NUM_POWER_STATE; i++) {
+ if (aur_state_array[i] == state) {
gxp->power_mgr->pwr_state_req_count[i]++;
+ return;
+ }
+ }
}
/* Caller must hold pm_lock */
@@ -321,13 +323,10 @@ int gxp_pm_update_requested_power_state(struct gxp_dev *gxp,
unsigned long max_state;
mutex_lock(&gxp->power_mgr->pm_lock);
- ret = gxp_pm_revoke_power_state_vote(gxp, origin_state);
- if (ret < 0)
- goto out;
+ gxp_pm_revoke_power_state_vote(gxp, origin_state);
gxp_pm_vote_power_state(gxp, requested_state);
max_state = gxp_pm_get_max_voted_power_state(gxp);
ret = gxp_pm_req_state_locked(gxp, max_state);
-out:
mutex_unlock(&gxp->power_mgr->pm_lock);
return ret;
}
@@ -339,6 +338,17 @@ static int gxp_pm_req_pm_qos(struct gxp_dev *gxp, s32 int_val, s32 mif_val)
return 0;
}
+static void gxp_pm_req_pm_qos_async(struct work_struct *work)
+{
+ struct gxp_req_pm_qos_work *req_pm_qos_work =
+ container_of(work, struct gxp_req_pm_qos_work, work);
+
+ mutex_lock(&req_pm_qos_work->gxp->power_mgr->pm_lock);
+ gxp_pm_req_pm_qos(req_pm_qos_work->gxp, req_pm_qos_work->int_val,
+ req_pm_qos_work->mif_val);
+ mutex_unlock(&req_pm_qos_work->gxp->power_mgr->pm_lock);
+}
+
static int gxp_pm_req_memory_state_locked(struct gxp_dev *gxp, enum aur_memory_power_state state)
{
s32 int_val = 0, mif_val = 0;
@@ -351,20 +361,25 @@ static int gxp_pm_req_memory_state_locked(struct gxp_dev *gxp, enum aur_memory_p
gxp->power_mgr->curr_memory_state = state;
int_val = aur_memory_state2int_table[state];
mif_val = aur_memory_state2mif_table[state];
- gxp_pm_req_pm_qos(gxp, int_val, mif_val);
+ gxp->power_mgr->req_pm_qos_work.gxp = gxp;
+ gxp->power_mgr->req_pm_qos_work.int_val = int_val;
+ gxp->power_mgr->req_pm_qos_work.mif_val = mif_val;
+ queue_work(gxp->power_mgr->wq,
+ &gxp->power_mgr->req_pm_qos_work.work);
}
return 0;
}
/* Caller must hold pm_lock */
-static int gxp_pm_revoke_memory_power_state_vote(struct gxp_dev *gxp,
- enum aur_memory_power_state revoked_state)
+static void
+gxp_pm_revoke_memory_power_state_vote(struct gxp_dev *gxp,
+ enum aur_memory_power_state revoked_state)
{
unsigned int i;
if (revoked_state == AUR_MEM_UNDEFINED)
- return 0;
+ return;
for (i = 0; i < AUR_NUM_MEMORY_POWER_STATE; i++) {
if (aur_memory_state_array[i] == revoked_state) {
if (gxp->power_mgr->mem_pwr_state_req_count[i] == 0)
@@ -374,10 +389,9 @@ static int gxp_pm_revoke_memory_power_state_vote(struct gxp_dev *gxp,
revoked_state);
else
gxp->power_mgr->mem_pwr_state_req_count[i]--;
- return 0;
+ return;
}
}
- return 0;
}
/* Caller must hold pm_lock */
@@ -419,13 +433,10 @@ int gxp_pm_update_requested_memory_power_state(
unsigned long max_state;
mutex_lock(&gxp->power_mgr->pm_lock);
- ret = gxp_pm_revoke_memory_power_state_vote(gxp, origin_state);
- if (ret < 0)
- goto out;
+ gxp_pm_revoke_memory_power_state_vote(gxp, origin_state);
gxp_pm_vote_memory_power_state(gxp, requested_state);
max_state = gxp_pm_get_max_voted_memory_power_state(gxp);
ret = gxp_pm_req_memory_state_locked(gxp, max_state);
-out:
mutex_unlock(&gxp->power_mgr->pm_lock);
return ret;
}
@@ -471,6 +482,7 @@ int gxp_pm_init(struct gxp_dev *gxp)
mgr->ops = &gxp_aur_ops;
gxp->power_mgr = mgr;
INIT_WORK(&mgr->set_acpm_rate_work.work, gxp_pm_blk_set_state_acpm_async);
+ INIT_WORK(&mgr->req_pm_qos_work.work, gxp_pm_req_pm_qos_async);
gxp->power_mgr->wq =
create_singlethread_workqueue("gxp_power_work_queue");
diff --git a/gxp-pm.h b/gxp-pm.h
index 73273f7..e5bbdad 100644
--- a/gxp-pm.h
+++ b/gxp-pm.h
@@ -52,16 +52,24 @@ struct gxp_set_acpm_state_work {
unsigned long state;
};
+struct gxp_req_pm_qos_work {
+ struct work_struct work;
+ struct gxp_dev *gxp;
+ s32 int_val;
+ s32 mif_val;
+};
+
struct gxp_power_manager {
struct gxp_dev *gxp;
struct mutex pm_lock;
- int pwr_state_req_count[AUR_NUM_POWER_STATE];
+ uint pwr_state_req_count[AUR_NUM_POWER_STATE];
uint mem_pwr_state_req_count[AUR_NUM_MEMORY_POWER_STATE];
int curr_state;
int curr_memory_state;
refcount_t blk_wake_ref;
struct gxp_pm_device_ops *ops;
struct gxp_set_acpm_state_work set_acpm_rate_work;
+ struct gxp_req_pm_qos_work req_pm_qos_work;
struct workqueue_struct *wq;
/* INT/MIF requests for memory bandwidth */
struct exynos_pm_qos_request int_min;