From patchwork Thu Jun 25 10:54:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 191739 Delivered-To: patch@linaro.org Received: by 2002:a54:3249:0:0:0:0:0 with SMTP id g9csp1206602ecs; Thu, 25 Jun 2020 03:54:37 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxg8cFAjTpKgRuQGceFBCOhxdtN7NR0prqm3VAOW0+pwYa/YON9U3ZEKQM3qsh9GCXPX/1R X-Received: by 2002:a50:a881:: with SMTP id k1mr30691778edc.12.1593082477759; Thu, 25 Jun 2020 03:54:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1593082477; cv=none; d=google.com; s=arc-20160816; b=pBzgtLGvbxat/rf20l+36/aISINUuKNYGpMNeh51lH5rcKKq84lgifqoV0hdERlcLZ 924WVADTC2XDVKAhV4fz0+Byo04PSylUCLl6GkQspjujPMzVKNve31PvpLAeHPT0hMKT svY1gCBzF7OAXPXzK2iex8TtUhTb0qHwq4EziIGrceZkEMyB7SlhuPuG5XTw1fC+oVlb afXOjgWaFdtTighyLHCahFglwQ7YBXo4xj9Rv0H0Om/GaWJWCS7Lua8hT8Ob8a3a77f7 zg3SJqkdx9M6JhqNzE6rnizWeBSjNGxDqbRCQRquNuOB20+4A1QE5ABq+akeJ5bowO/Y Ef5w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=Yx0lD7fGCawYLo67/HEDDyL+lrRFtxEIUe5sUIZ62J4=; b=Gj3s+IXNjF4+/jMVLaCzit02NbF7wl1qRxTocHBoIC3In63gQRjS0wsfdgztwzVGh3 0hH3zJ9c5xaWqeTrTBoPAWD/LU2H/BIEWFCCXWj/Snhcj2KKjg27MKEixBlBr/L9U/yj a+WO7uSRUYLkAyuHr3/9KoEZfH8lgynOISWHHBD/241RFT+JyLamW+PoSmkXwIZYhcfT rrfeY99iGWexlP6l3ubkgoLHvNpLIZgouAPts0i03TY5/UoYin2BPmt50NPtfnqca7F3 PPkeQrtwfn+q8PbiBLECl80NsNEVbfPRrIzHVEnOzvxQmxSQgtNVNKGR8e/bRnWNJf6K UUwA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=KFzDILri; spf=pass (google.com: domain of linux-pm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-pm-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id lx8si6348144ejb.415.2020.06.25.03.54.37; Thu, 25 Jun 2020 03:54:37 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-pm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=KFzDILri; spf=pass (google.com: domain of linux-pm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-pm-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2404105AbgFYKyg (ORCPT + 10 others); Thu, 25 Jun 2020 06:54:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41758 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2403952AbgFYKyg (ORCPT ); Thu, 25 Jun 2020 06:54:36 -0400 Received: from mail-pg1-x542.google.com (mail-pg1-x542.google.com [IPv6:2607:f8b0:4864:20::542]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E3DC9C0613ED for ; Thu, 25 Jun 2020 03:54:35 -0700 (PDT) Received: by mail-pg1-x542.google.com with SMTP id o13so160558pgf.0 for ; Thu, 25 Jun 2020 03:54:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=Yx0lD7fGCawYLo67/HEDDyL+lrRFtxEIUe5sUIZ62J4=; b=KFzDILrifAGB9mux0K0myeWdvE++5mwEPTLiZlUHtmvaSd5Zbbi+N3aDQqCfvRoADy vgu0THEKzIO32WFExI06AHflnZAeytfQquxOij2If7MxulGyiquIDz2kpgr2AJd62yFE 3EZvh4hdkirQqJk9q1MFSAbrG6rxcjUIzDerLiZOKUwQDsgK6eKLTA39sis77KVz1WCW 3ABVAvDmDdqCrr64wSHg8vwrkmjxjunuQRddTA1lZ/o5ZNmBfPvqa38Wq3dg9cKfx6xR j+chsV3sY3Dt/QO9DgGVZcTCU2SFcl7FcON/wIZIgrJ/iJxcQWBQzn0Kaqflv4RwZ8n6 L3eg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=Yx0lD7fGCawYLo67/HEDDyL+lrRFtxEIUe5sUIZ62J4=; b=bXfNppJQRQ8t/2ChXUlUnk335umZxvh4EBT6QwhbpsLTMLKpQ59tPHUz4pBwg/Ff4R abMUsULOikffhkn4SoxCgff1q2M31UwL0jQDDjz5vwIM5HHCb5E6uAK1ZwGBWZZ2pOo9 q2syGEsMYN09N4gNtoej/steOyoo8MCdVaybz0QR8x3aZA8VtNNg8PggKJH//Ka3esmb gD6ZGYNd4HqDNHLgGyy5p+wNWQofTI4IsZ8vRF8AL9c/rzHOuf1k+r51+RJ8thMRh6GT qkrbnfYnrJ4oY/6q4T2UwoFycTCRC4XMDLRGzfVArHF2zrlmwOvSrybqSHERLLD9RQWg 3WbQ== X-Gm-Message-State: AOAM530K/nCSWwZjSDHFI+u+SDgW4RoirlWFeVcoAkRHEA4Pfj9dDbx7 PsMQ7Z8FUCFkE4vWRou0+iYHOA== X-Received: by 2002:aa7:82d5:: with SMTP id f21mr7333895pfn.244.1593082475155; Thu, 25 Jun 2020 03:54:35 -0700 (PDT) Received: from localhost ([122.172.111.76]) by smtp.gmail.com with ESMTPSA id u4sm23045364pfl.102.2020.06.25.03.54.34 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 25 Jun 2020 03:54:34 -0700 (PDT) From: Viresh Kumar To: Rafael Wysocki , Viresh Kumar Cc: linux-pm@vger.kernel.org, Vincent Guittot , Quentin Perret , linux-kernel@vger.kernel.org Subject: [PATCH] cpufreq: Fix locking issues with governors Date: Thu, 25 Jun 2020 16:24:16 +0530 Message-Id: <49c7d64460cdb39b006991e5251260eb0eea9f2a.1593082448.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.25.0.rc1.19.g042ed3e048af MIME-Version: 1.0 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org The locking around governors handling isn't adequate currently. The list of governors should never be traversed without locking in place. Also we must make sure the governor isn't removed while it is still referenced by code. Reported-by: Quentin Perret Signed-off-by: Viresh Kumar --- drivers/cpufreq/cpufreq.c | 59 ++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 23 deletions(-) -- 2.25.0.rc1.19.g042ed3e048af diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 4b1a5c0173cf..dad6b85f4c89 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -624,6 +624,24 @@ static struct cpufreq_governor *find_governor(const char *str_governor) return NULL; } +static struct cpufreq_governor *get_governor(const char *str_governor) +{ + struct cpufreq_governor *t; + + mutex_lock(&cpufreq_governor_mutex); + t = find_governor(str_governor); + if (!t) + goto unlock; + + if (!try_module_get(t->owner)) + t = NULL; + +unlock: + mutex_unlock(&cpufreq_governor_mutex); + + return t; +} + static unsigned int cpufreq_parse_policy(char *str_governor) { if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN)) @@ -643,28 +661,14 @@ static struct cpufreq_governor *cpufreq_parse_governor(char *str_governor) { struct cpufreq_governor *t; - mutex_lock(&cpufreq_governor_mutex); - - t = find_governor(str_governor); - if (!t) { - int ret; - - mutex_unlock(&cpufreq_governor_mutex); - - ret = request_module("cpufreq_%s", str_governor); - if (ret) - return NULL; - - mutex_lock(&cpufreq_governor_mutex); + t = get_governor(str_governor); + if (t) + return t; - t = find_governor(str_governor); - } - if (t && !try_module_get(t->owner)) - t = NULL; - - mutex_unlock(&cpufreq_governor_mutex); + if (request_module("cpufreq_%s", str_governor)) + return NULL; - return t; + return get_governor(str_governor); } /** @@ -818,12 +822,14 @@ static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy, goto out; } + mutex_lock(&cpufreq_governor_mutex); for_each_governor(t) { if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2))) - goto out; + break; i += scnprintf(&buf[i], CPUFREQ_NAME_PLEN, "%s ", t->name); } + mutex_unlock(&cpufreq_governor_mutex); out: i += sprintf(&buf[i], "\n"); return i; @@ -1060,11 +1066,14 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy) { struct cpufreq_governor *gov = NULL; unsigned int pol = CPUFREQ_POLICY_UNKNOWN; + bool put_governor = false; + int ret; if (has_target()) { /* Update policy governor to the one used before hotplug. */ - gov = find_governor(policy->last_governor); + gov = get_governor(policy->last_governor); if (gov) { + put_governor = true; pr_debug("Restoring governor %s for cpu %d\n", policy->governor->name, policy->cpu); } else if (default_governor) { @@ -1091,7 +1100,11 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy) return -ENODATA; } - return cpufreq_set_policy(policy, gov, pol); + ret = cpufreq_set_policy(policy, gov, pol); + if (put_governor) + module_put(gov->owner); + + return ret; } static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)