From 18ae38826c9314cb571f2a21ee49d808e76df6ac Mon Sep 17 00:00:00 2001 From: Lior David Date: Sun, 22 Jan 2017 12:31:22 +0200 Subject: [PATCH] msm_11ad: basic support for CPU boost Added basic support for CPU boost: when driver calls ops_bus_request with a high bandwidth requirement, enable the big CPU cluster and adjust the affinity of the wil6210 interrupt to run on the first big core. The first big core is selected because WLAN driver uses the other cores. Change-Id: Ia752b9a8ca343b56e2839a30a4fdb59231f9a634 CRs-Fixed: 1114406 Signed-off-by: Lior David --- drivers/platform/msm/msm_11ad/msm_11ad.c | 102 ++++++++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/msm_11ad/msm_11ad.c b/drivers/platform/msm/msm_11ad/msm_11ad.c index b7fc68a6efdd..7f97d7c6bab7 100644 --- a/drivers/platform/msm/msm_11ad/msm_11ad.c +++ b/drivers/platform/msm/msm_11ad/msm_11ad.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -26,6 +26,10 @@ #include #include #include +#include +#include +#include +#include #include "wil_platform.h" #include "msm_11ad.h" @@ -54,6 +58,8 @@ #define DISABLE_PCIE_L1_MASK 0xFFFFFFFD #define PCIE20_CAP_LINKCTRLSTATUS 0x80 +#define WIGIG_MIN_CPU_BOOST_KBPS 150000 + struct device; static const char * const gpio_en_name = "qcom,wigig-en"; @@ -113,6 +119,11 @@ struct msm11ad_ctx { struct msm11ad_vreg vddio; struct msm11ad_clk rf_clk3; struct msm11ad_clk rf_clk3_pin; + + /* cpu boost support */ + bool use_cpu_boost; + bool is_cpu_boosted; + struct cpumask boost_cpu; }; static LIST_HEAD(dev_list); @@ -823,6 +834,36 @@ out_rc: return rc; } +static void msm_11ad_init_cpu_boost(struct msm11ad_ctx *ctx) +{ + unsigned int minfreq = 0, maxfreq = 0, freq; + int i, boost_cpu; + + for_each_possible_cpu(i) { + freq = cpufreq_quick_get_max(i); + if (freq > maxfreq) { + maxfreq = freq; + boost_cpu = i; + } + if (!minfreq || freq < minfreq) + minfreq = freq; + } + + if (minfreq != maxfreq) { + /* + * use first big core for boost, to be compatible with WLAN + * which assigns big cores from the last index + */ + ctx->use_cpu_boost = true; + cpumask_clear(&ctx->boost_cpu); + cpumask_set_cpu(boost_cpu, &ctx->boost_cpu); + dev_info(ctx->dev, "CPU boost: will use core %d\n", boost_cpu); + } else { + ctx->use_cpu_boost = false; + dev_info(ctx->dev, "CPU boost disabled, uniform topology\n"); + } +} + static int msm_11ad_probe(struct platform_device *pdev) { struct msm11ad_ctx *ctx; @@ -998,6 +1039,8 @@ static int msm_11ad_probe(struct platform_device *pdev) goto out_rc; } + msm_11ad_init_cpu_boost(ctx); + /* report */ dev_info(ctx->dev, "msm_11ad discovered. %p {\n" " gpio_en = %d\n" @@ -1074,6 +1117,34 @@ static struct platform_driver msm_11ad_driver = { }; module_platform_driver(msm_11ad_driver); +static void msm_11ad_set_boost_affinity(struct msm11ad_ctx *ctx) +{ + /* + * There is a very small window where user space can change the + * affinity after we changed it here and before setting the + * NO_BALANCING flag. Retry this several times as a workaround. + */ + int retries = 5, rc; + struct irq_desc *desc; + + while (retries > 0) { + irq_modify_status(ctx->pcidev->irq, IRQ_NO_BALANCING, 0); + rc = irq_set_affinity_hint(ctx->pcidev->irq, &ctx->boost_cpu); + if (rc) + dev_warn(ctx->dev, + "Failed set affinity, rc=%d\n", rc); + irq_modify_status(ctx->pcidev->irq, 0, IRQ_NO_BALANCING); + desc = irq_to_desc(ctx->pcidev->irq); + if (cpumask_equal(desc->irq_common_data.affinity, + &ctx->boost_cpu)) + break; + retries--; + } + + if (!retries) + dev_warn(ctx->dev, "failed to set CPU boost affinity\n"); +} + /* hooks for the wil6210 driver */ static int ops_bus_request(void *handle, u32 kbps /* KBytes/Sec */) { @@ -1102,6 +1173,35 @@ static int ops_bus_request(void *handle, u32 kbps /* KBytes/Sec */) "Failed msm_bus voting. kbps=%d vote=%d, rc=%d\n", kbps, vote, rc); + if (ctx->use_cpu_boost) { + bool was_boosted = ctx->is_cpu_boosted; + bool needs_boost = (kbps >= WIGIG_MIN_CPU_BOOST_KBPS); + + if (was_boosted != needs_boost) { + if (needs_boost) { + rc = core_ctl_set_boost(true); + if (rc) { + dev_err(ctx->dev, + "Failed enable boost rc=%d\n", + rc); + goto out; + } + msm_11ad_set_boost_affinity(ctx); + dev_dbg(ctx->dev, "CPU boost enabled\n"); + } else { + rc = core_ctl_set_boost(false); + if (rc) + dev_err(ctx->dev, + "Failed disable boost rc=%d\n", + rc); + irq_modify_status(ctx->pcidev->irq, + IRQ_NO_BALANCING, 0); + dev_dbg(ctx->dev, "CPU boost disabled\n"); + } + ctx->is_cpu_boosted = needs_boost; + } + } +out: return rc; }