diff --git a/asoc/msm_common.c b/asoc/msm_common.c index 7107e44e87..ace536303b 100644 --- a/asoc/msm_common.c +++ b/asoc/msm_common.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,10 @@ #include "msm_common.h" +#ifndef topology_cluster_id +#define topology_cluster_id(cpu) topology_physical_package_id(cpu) +#endif + struct snd_card_pdata { struct kobject snd_card_kobj; int card_status; @@ -86,7 +91,7 @@ static const struct snd_pcm_hardware dummy_dma_hardware = { }; #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 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 unsigned int qos_client_active_cnt; -static uint32_t *audio_core_list = NULL; -static uint32_t audio_core_num = MAX_AUDIO_CPU_CORE_NUM; -static cpumask_t audio_cpu_map = CPU_MASK_NONE; +static int cluster_first_cpu[MAX_CPU_CLUSTER] = {-1, }; static struct dev_pm_qos_request *msm_audio_req = NULL; 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 */ @@ -617,24 +620,30 @@ void msm_common_snd_shutdown(struct snd_pcm_substream *substream) static void msm_audio_add_qos_request(void) { - int i; + int num_req = 0; int cpu = 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(), sizeof(struct dev_pm_qos_request), GFP_KERNEL); if (!msm_audio_req) return; - for (i = 0; i < audio_core_num; i++) { - if (audio_core_list[i] >= num_possible_cpus()) - pr_err("%s incorrect cpu id: %d specified.\n", - __func__, audio_core_list[i]); - else - cpumask_set_cpu(audio_core_list[i], &audio_cpu_map); + for_each_cpu(cpu, cpu_possible_mask) { + cid = topology_cluster_id(cpu); + if (cid != prev_cid) { + cluster_first_cpu[cluster_num++] = cpu; + prev_cid = cid; + } } - 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), &msm_audio_req[cpu], DEV_PM_QOS_RESUME_LATENCY, @@ -642,7 +651,11 @@ static void msm_audio_add_qos_request(void) if (ret < 0) pr_err("%s error (%d) adding resume latency to cpu %d.\n", __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 ret = 0; + cpumask_t *cluster_cpu_mask = NULL; + + cluster_cpu_mask = topology_core_cpumask(cluster_first_cpu[0]); if (msm_audio_req) { - for_each_cpu(cpu, &audio_cpu_map) { + for_each_cpu(cpu, cluster_cpu_mask) { ret = dev_pm_qos_remove_request( &msm_audio_req[cpu]); 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; uint32_t val_array[MI2S_TDM_AUXPCM_MAX] = {0}; struct clk *lpass_audio_hw_vote = NULL; - uint32_t *core_val_array = NULL; common_pdata = kcalloc(1, sizeof(struct msm_common_pdata), GFP_KERNEL); if (!common_pdata) 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); /* 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(); -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); return 0; @@ -983,9 +958,13 @@ static void msm_audio_update_qos_request(u32 latency) { int cpu = 0; 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) { - for_each_cpu(cpu, &audio_cpu_map) { + for_each_cpu(cpu, cluster_cpu_mask) { ret = dev_pm_qos_update_request( &msm_audio_req[cpu], latency); 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", __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) { cpumask_t expected_cpu_map = CPU_MASK_NONE; + cpumask_t *cluster_cpu_mask = NULL; 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", __func__, qos_vote_status, qos_client_active_cnt); if (qos_vote_status) { @@ -1036,14 +1020,14 @@ static int msm_qos_ctl_put(struct snd_kcontrol *kcontrol, if (qos_client_active_cnt == 1) { 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)) { pr_debug("%s: already expected, don't need to set it.\n", __func__); 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", __func__); @@ -1064,7 +1048,7 @@ static int msm_qos_ctl_put(struct snd_kcontrol *kcontrol, 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", __func__);