Merge "asoc: msm_common: use logical CPU cores for qos request"
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

commit
ccb952555b
@@ -9,6 +9,7 @@
|
|||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/arch_topology.h>
|
||||||
#include <sound/control.h>
|
#include <sound/control.h>
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/soc.h>
|
#include <sound/soc.h>
|
||||||
@@ -23,6 +24,10 @@
|
|||||||
|
|
||||||
#include "msm_common.h"
|
#include "msm_common.h"
|
||||||
|
|
||||||
|
#ifndef topology_cluster_id
|
||||||
|
#define topology_cluster_id(cpu) topology_physical_package_id(cpu)
|
||||||
|
#endif
|
||||||
|
|
||||||
struct snd_card_pdata {
|
struct snd_card_pdata {
|
||||||
struct kobject snd_card_kobj;
|
struct kobject snd_card_kobj;
|
||||||
int card_status;
|
int card_status;
|
||||||
@@ -86,7 +91,7 @@ static const struct snd_pcm_hardware dummy_dma_hardware = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_USR_INPUT 10
|
#define MAX_USR_INPUT 10
|
||||||
#define MAX_AUDIO_CPU_CORE_NUM 2
|
#define MAX_CPU_CLUSTER 4 /* Silver, Gold, T, Prime */
|
||||||
|
|
||||||
static int qos_vote_status;
|
static int qos_vote_status;
|
||||||
static bool lpi_pcm_logging_enable;
|
static bool lpi_pcm_logging_enable;
|
||||||
@@ -95,9 +100,7 @@ static unsigned int vote_against_sleep_cnt;
|
|||||||
|
|
||||||
static struct dev_pm_qos_request latency_pm_qos_req; /* pm_qos request */
|
static struct dev_pm_qos_request latency_pm_qos_req; /* pm_qos request */
|
||||||
static unsigned int qos_client_active_cnt;
|
static unsigned int qos_client_active_cnt;
|
||||||
static uint32_t *audio_core_list = NULL;
|
static int cluster_first_cpu[MAX_CPU_CLUSTER] = {-1, };
|
||||||
static uint32_t audio_core_num = MAX_AUDIO_CPU_CORE_NUM;
|
|
||||||
static cpumask_t audio_cpu_map = CPU_MASK_NONE;
|
|
||||||
static struct dev_pm_qos_request *msm_audio_req = NULL;
|
static struct dev_pm_qos_request *msm_audio_req = NULL;
|
||||||
static bool kregister_pm_qos_latency_controls = false;
|
static bool kregister_pm_qos_latency_controls = false;
|
||||||
#define MSM_LL_QOS_VALUE 300 /* time in us to ensure LPM doesn't go in C3/C4 */
|
#define MSM_LL_QOS_VALUE 300 /* time in us to ensure LPM doesn't go in C3/C4 */
|
||||||
@@ -617,24 +620,30 @@ void msm_common_snd_shutdown(struct snd_pcm_substream *substream)
|
|||||||
|
|
||||||
static void msm_audio_add_qos_request(void)
|
static void msm_audio_add_qos_request(void)
|
||||||
{
|
{
|
||||||
int i;
|
int num_req = 0;
|
||||||
int cpu = 0;
|
int cpu = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
int cid, prev_cid = -1;
|
||||||
|
int cluster_num = 0;
|
||||||
|
cpumask_t *cluster_cpu_mask = NULL;
|
||||||
|
|
||||||
msm_audio_req = kcalloc(num_possible_cpus(),
|
msm_audio_req = kcalloc(num_possible_cpus(),
|
||||||
sizeof(struct dev_pm_qos_request), GFP_KERNEL);
|
sizeof(struct dev_pm_qos_request), GFP_KERNEL);
|
||||||
if (!msm_audio_req)
|
if (!msm_audio_req)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < audio_core_num; i++) {
|
for_each_cpu(cpu, cpu_possible_mask) {
|
||||||
if (audio_core_list[i] >= num_possible_cpus())
|
cid = topology_cluster_id(cpu);
|
||||||
pr_err("%s incorrect cpu id: %d specified.\n",
|
if (cid != prev_cid) {
|
||||||
__func__, audio_core_list[i]);
|
cluster_first_cpu[cluster_num++] = cpu;
|
||||||
else
|
prev_cid = cid;
|
||||||
cpumask_set_cpu(audio_core_list[i], &audio_cpu_map);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_cpu(cpu, &audio_cpu_map) {
|
/* Pick the first cluster as it represents the Silver cluster. */
|
||||||
|
cluster_cpu_mask = topology_core_cpumask(cluster_first_cpu[0]);
|
||||||
|
|
||||||
|
for_each_cpu(cpu, cluster_cpu_mask) {
|
||||||
ret = dev_pm_qos_add_request(get_cpu_device(cpu),
|
ret = dev_pm_qos_add_request(get_cpu_device(cpu),
|
||||||
&msm_audio_req[cpu],
|
&msm_audio_req[cpu],
|
||||||
DEV_PM_QOS_RESUME_LATENCY,
|
DEV_PM_QOS_RESUME_LATENCY,
|
||||||
@@ -642,7 +651,11 @@ static void msm_audio_add_qos_request(void)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
pr_err("%s error (%d) adding resume latency to cpu %d.\n",
|
pr_err("%s error (%d) adding resume latency to cpu %d.\n",
|
||||||
__func__, ret, cpu);
|
__func__, ret, cpu);
|
||||||
pr_debug("%s set cpu affinity to core %d.\n", __func__, cpu);
|
pr_debug("%s set cpu affinity to logical core %d.\n", __func__, cpu);
|
||||||
|
|
||||||
|
/* Limit the request to 2 silver cpu cores. */
|
||||||
|
if (++num_req == 2)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -650,9 +663,12 @@ static void msm_audio_remove_qos_request(void)
|
|||||||
{
|
{
|
||||||
int cpu = 0;
|
int cpu = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
cpumask_t *cluster_cpu_mask = NULL;
|
||||||
|
|
||||||
|
cluster_cpu_mask = topology_core_cpumask(cluster_first_cpu[0]);
|
||||||
|
|
||||||
if (msm_audio_req) {
|
if (msm_audio_req) {
|
||||||
for_each_cpu(cpu, &audio_cpu_map) {
|
for_each_cpu(cpu, cluster_cpu_mask) {
|
||||||
ret = dev_pm_qos_remove_request(
|
ret = dev_pm_qos_remove_request(
|
||||||
&msm_audio_req[cpu]);
|
&msm_audio_req[cpu]);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@@ -670,7 +686,6 @@ int msm_common_snd_init(struct platform_device *pdev, struct snd_soc_card *card)
|
|||||||
int count, ret = 0;
|
int count, ret = 0;
|
||||||
uint32_t val_array[MI2S_TDM_AUXPCM_MAX] = {0};
|
uint32_t val_array[MI2S_TDM_AUXPCM_MAX] = {0};
|
||||||
struct clk *lpass_audio_hw_vote = NULL;
|
struct clk *lpass_audio_hw_vote = NULL;
|
||||||
uint32_t *core_val_array = NULL;
|
|
||||||
common_pdata = kcalloc(1, sizeof(struct msm_common_pdata), GFP_KERNEL);
|
common_pdata = kcalloc(1, sizeof(struct msm_common_pdata), GFP_KERNEL);
|
||||||
if (!common_pdata)
|
if (!common_pdata)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@@ -774,48 +789,8 @@ int msm_common_snd_init(struct platform_device *pdev, struct snd_soc_card *card)
|
|||||||
msm_common_set_pdata(card, common_pdata);
|
msm_common_set_pdata(card, common_pdata);
|
||||||
|
|
||||||
/* Add QoS request for audio tasks */
|
/* Add QoS request for audio tasks */
|
||||||
core_val_array = devm_kcalloc(&pdev->dev, num_possible_cpus(), sizeof(uint32_t), GFP_KERNEL);
|
|
||||||
if (!core_val_array) {
|
|
||||||
dev_info(&pdev->dev, "%s: core val array is nullptr\n", __func__);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
ret = of_property_read_variable_u32_array(pdev->dev.of_node, "qcom,audio-core-list",
|
|
||||||
core_val_array, 0, num_possible_cpus());
|
|
||||||
dev_info(&pdev->dev, "%s: getting the core list size:%d, num_possible_cpus:%d \n",
|
|
||||||
__func__, ret, num_possible_cpus());
|
|
||||||
if (ret > 0 && (ret <= num_possible_cpus())) {
|
|
||||||
audio_core_num = ret;
|
|
||||||
audio_core_list = devm_kcalloc(&pdev->dev, audio_core_num, sizeof(uint32_t), GFP_KERNEL);
|
|
||||||
if (!audio_core_list) {
|
|
||||||
dev_info(&pdev->dev, "%s: calloc failed for audio core list\n", __func__);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
for (count = 0; count < audio_core_num; count++) {
|
|
||||||
audio_core_list[count] = core_val_array[count];
|
|
||||||
dev_info(&pdev->dev, "%s: update core %d\n", __func__, core_val_array[count]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dev_info(&pdev->dev, "%s: keep default core\n", __func__);
|
|
||||||
audio_core_list = devm_kcalloc(&pdev->dev, audio_core_num, sizeof(uint32_t), GFP_KERNEL);
|
|
||||||
/* set audio task affinity to core 1 & 2 as default*/
|
|
||||||
if (!audio_core_list) {
|
|
||||||
dev_info(&pdev->dev, "%s: calloc failed for audio core list\n", __func__);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
audio_core_list[0] = 1;
|
|
||||||
audio_core_list[1] = 2;
|
|
||||||
}
|
|
||||||
msm_audio_add_qos_request();
|
msm_audio_add_qos_request();
|
||||||
|
|
||||||
exit:
|
|
||||||
if (audio_core_list) {
|
|
||||||
devm_kfree(&pdev->dev, audio_core_list);
|
|
||||||
audio_core_list = NULL;
|
|
||||||
}
|
|
||||||
if (core_val_array) {
|
|
||||||
devm_kfree(&pdev->dev, core_val_array);
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_init(&vote_against_sleep_lock);
|
mutex_init(&vote_against_sleep_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -983,9 +958,13 @@ static void msm_audio_update_qos_request(u32 latency)
|
|||||||
{
|
{
|
||||||
int cpu = 0;
|
int cpu = 0;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
int num_req = 0;
|
||||||
|
cpumask_t *cluster_cpu_mask = NULL;
|
||||||
|
|
||||||
|
cluster_cpu_mask = topology_core_cpumask(cluster_first_cpu[0]);
|
||||||
|
|
||||||
if (msm_audio_req) {
|
if (msm_audio_req) {
|
||||||
for_each_cpu(cpu, &audio_cpu_map) {
|
for_each_cpu(cpu, cluster_cpu_mask) {
|
||||||
ret = dev_pm_qos_update_request(
|
ret = dev_pm_qos_update_request(
|
||||||
&msm_audio_req[cpu], latency);
|
&msm_audio_req[cpu], latency);
|
||||||
if (1 == ret ) {
|
if (1 == ret ) {
|
||||||
@@ -998,6 +977,9 @@ static void msm_audio_update_qos_request(u32 latency)
|
|||||||
pr_err("%s: failed to update latency of core %d, error %d \n",
|
pr_err("%s: failed to update latency of core %d, error %d \n",
|
||||||
__func__, cpu, ret);
|
__func__, cpu, ret);
|
||||||
}
|
}
|
||||||
|
/* Limit the request to 2 Silver CPU cores. */
|
||||||
|
if (++num_req == 2)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1024,8 +1006,10 @@ static int msm_qos_ctl_put(struct snd_kcontrol *kcontrol,
|
|||||||
struct snd_ctl_elem_value *ucontrol)
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
{
|
{
|
||||||
cpumask_t expected_cpu_map = CPU_MASK_NONE;
|
cpumask_t expected_cpu_map = CPU_MASK_NONE;
|
||||||
|
cpumask_t *cluster_cpu_mask = NULL;
|
||||||
qos_vote_status = ucontrol->value.enumerated.item[0];
|
qos_vote_status = ucontrol->value.enumerated.item[0];
|
||||||
|
|
||||||
|
cluster_cpu_mask = topology_core_cpumask(cluster_first_cpu[0]);
|
||||||
pr_debug("%s: qos_vote_status = %d, qos_client_active_cnt = %d.\n",
|
pr_debug("%s: qos_vote_status = %d, qos_client_active_cnt = %d.\n",
|
||||||
__func__, qos_vote_status, qos_client_active_cnt);
|
__func__, qos_vote_status, qos_client_active_cnt);
|
||||||
if (qos_vote_status) {
|
if (qos_vote_status) {
|
||||||
@@ -1036,14 +1020,14 @@ static int msm_qos_ctl_put(struct snd_kcontrol *kcontrol,
|
|||||||
if (qos_client_active_cnt == 1) {
|
if (qos_client_active_cnt == 1) {
|
||||||
msm_audio_update_qos_request(MSM_LL_QOS_VALUE);
|
msm_audio_update_qos_request(MSM_LL_QOS_VALUE);
|
||||||
|
|
||||||
expected_cpu_map = audio_cpu_map;
|
expected_cpu_map = *cluster_cpu_mask;
|
||||||
if (msm_get_and_print_cpu_map_taken(&expected_cpu_map)) {
|
if (msm_get_and_print_cpu_map_taken(&expected_cpu_map)) {
|
||||||
pr_debug("%s: already expected, don't need to set it.\n",
|
pr_debug("%s: already expected, don't need to set it.\n",
|
||||||
__func__);
|
__func__);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
walt_set_cpus_taken(&audio_cpu_map);
|
walt_set_cpus_taken(cluster_cpu_mask);
|
||||||
pr_debug("%s: set cpus taken to walt for audio RT tasks.\n",
|
pr_debug("%s: set cpus taken to walt for audio RT tasks.\n",
|
||||||
__func__);
|
__func__);
|
||||||
|
|
||||||
@@ -1064,7 +1048,7 @@ static int msm_qos_ctl_put(struct snd_kcontrol *kcontrol,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
walt_unset_cpus_taken(&audio_cpu_map);
|
walt_unset_cpus_taken(cluster_cpu_mask);
|
||||||
pr_debug("%s: unset cpus taken to walt for audio RT tasks.\n",
|
pr_debug("%s: unset cpus taken to walt for audio RT tasks.\n",
|
||||||
__func__);
|
__func__);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user