in qcom/bcm-voter.c [246:333]
int qcom_icc_bcm_voter_commit(struct bcm_voter *voter)
{
struct qcom_icc_bcm *bcm;
struct qcom_icc_bcm *bcm_tmp;
int commit_idx[MAX_VCD + 1];
struct tcs_cmd cmds[MAX_BCMS];
int ret = 0;
if (!voter)
return 0;
mutex_lock(&voter->lock);
list_for_each_entry(bcm, &voter->commit_list, list)
bcm_aggregate(bcm);
/*
* Pre sort the BCMs based on VCD for ease of generating a command list
* that groups the BCMs with the same VCD together. VCDs are numbered
* with lowest being the most expensive time wise, ensuring that
* those commands are being sent the earliest in the queue. This needs
* to be sorted every commit since we can't guarantee the order in which
* the BCMs are added to the list.
*/
list_sort(NULL, &voter->commit_list, cmp_vcd);
/*
* Construct the command list based on a pre ordered list of BCMs
* based on VCD.
*/
tcs_list_gen(voter, QCOM_ICC_BUCKET_AMC, cmds, commit_idx);
if (!commit_idx[0])
goto out;
rpmh_invalidate(voter->dev);
ret = rpmh_write_batch(voter->dev, RPMH_ACTIVE_ONLY_STATE,
cmds, commit_idx);
if (ret) {
pr_err("Error sending AMC RPMH requests (%d)\n", ret);
goto out;
}
list_for_each_entry_safe(bcm, bcm_tmp, &voter->commit_list, list)
list_del_init(&bcm->list);
list_for_each_entry_safe(bcm, bcm_tmp, &voter->ws_list, ws_list) {
/*
* Only generate WAKE and SLEEP commands if a resource's
* requirements change as the execution environment transitions
* between different power states.
*/
if (bcm->vote_x[QCOM_ICC_BUCKET_WAKE] !=
bcm->vote_x[QCOM_ICC_BUCKET_SLEEP] ||
bcm->vote_y[QCOM_ICC_BUCKET_WAKE] !=
bcm->vote_y[QCOM_ICC_BUCKET_SLEEP])
list_add_tail(&bcm->list, &voter->commit_list);
else
list_del_init(&bcm->ws_list);
}
if (list_empty(&voter->commit_list))
goto out;
list_sort(NULL, &voter->commit_list, cmp_vcd);
tcs_list_gen(voter, QCOM_ICC_BUCKET_WAKE, cmds, commit_idx);
ret = rpmh_write_batch(voter->dev, RPMH_WAKE_ONLY_STATE, cmds, commit_idx);
if (ret) {
pr_err("Error sending WAKE RPMH requests (%d)\n", ret);
goto out;
}
tcs_list_gen(voter, QCOM_ICC_BUCKET_SLEEP, cmds, commit_idx);
ret = rpmh_write_batch(voter->dev, RPMH_SLEEP_STATE, cmds, commit_idx);
if (ret) {
pr_err("Error sending SLEEP RPMH requests (%d)\n", ret);
goto out;
}
out:
list_for_each_entry_safe(bcm, bcm_tmp, &voter->commit_list, list)
list_del_init(&bcm->list);
mutex_unlock(&voter->lock);
return ret;
}