Received: by 2002:a05:7412:8d10:b0:f3:1519:9f41 with SMTP id bj16csp4647181rdb; Tue, 12 Dec 2023 05:48:50 -0800 (PST) X-Google-Smtp-Source: AGHT+IHtOL70+Tl4e02AHtOQb9zCxDPJKBvwoupIRFy8wZMJd0zlhZtfj+99VL63YjPCCFhK+sKj X-Received: by 2002:a17:903:32d0:b0:1d0:8be8:bb6a with SMTP id i16-20020a17090332d000b001d08be8bb6amr6953975plr.67.1702388929759; Tue, 12 Dec 2023 05:48:49 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1702388929; cv=none; d=google.com; s=arc-20160816; b=KAJRoT6+fb6xiKdw4jLE3i3/975BUZztESEdo5jxV9Uug5Xw5ABC5x3YPkL+oqroMn GtMeaehDllcpCfHiddeOoa7J9lzYV0xOjq4oUjBWsrzNU1wMXkZ/Q+qhMt2/dfpYNFCU g0VJTnAL9NFICLLHcsjZY7+hjuqaTj0GMHgAXK/Df1LPxWzdw3b29wYSjzr48QiKRUFX hww9H3/UP4Rf2752ybndg8vogDICwSBqxd7mMd+s0D/VSt31kogQ9i1PWRb6jYB5UwAB 3lPxOnU2CJ4TnRHL1kju0rYKuSbyyL6ZzTcFlda/oxfM6+tzXUhyt5pBt7KMwCMaqYMv /cGA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=HAIjlm7sNBAs3NXfUHy1MPnaNZWkzolnVmQh9b/zDr8=; fh=8IgpUQ2T6XGOjA/qDosxdUSIIBz0a6nQ23NA8pgv1Tg=; b=cz7fd/ST2qc92YDj2X3L4S42+Ln8Gjx21PzszQJut29purzUnGXD5J5bvOkOa4Dn+Y N6KvnZdYJMlfAx6Ke5pZaj9DppNugR0qD9ewyZ5i7+w4Stb8vdawTQ3CKnXz74+MXk0Y wuLWuiDe0qcwPOk4hFLRzMgGkPEtfpBy9PqJ9MwTwSdQLaWjSwCQ/WF+5FddqJkhHXCC Dxe146OsqkL7PwblJEmUv59K00vYlT5UluP24Fp52P3RcLTBwmxYcjlw1o1blKKuQVgj s/k1SBucvy/n4LqvmhKall4ipeoM8mO7583eWUb85PULwO9PQKGtmhJdzAGfNEhibNzo b1kA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from fry.vger.email (fry.vger.email. [23.128.96.38]) by mx.google.com with ESMTPS id i13-20020a170902c94d00b001d0b31591d2si7804720pla.476.2023.12.12.05.48.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Dec 2023 05:48:49 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) client-ip=23.128.96.38; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by fry.vger.email (Postfix) with ESMTP id 82B5D80A1E16; Tue, 12 Dec 2023 05:48:41 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at fry.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376385AbjLLNsD (ORCPT + 99 others); Tue, 12 Dec 2023 08:48:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43204 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376333AbjLLNr4 (ORCPT ); Tue, 12 Dec 2023 08:47:56 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 7B44910A; Tue, 12 Dec 2023 05:48:01 -0800 (PST) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 9659F1756; Tue, 12 Dec 2023 05:48:47 -0800 (PST) Received: from e129166.arm.com (unknown [10.57.82.227]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 125DA3F738; Tue, 12 Dec 2023 05:47:59 -0800 (PST) From: Lukasz Luba To: linux-kernel@vger.kernel.org, daniel.lezcano@linaro.org, rafael@kernel.org Cc: linux-pm@vger.kernel.org, rui.zhang@intel.com, lukasz.luba@arm.com Subject: [PATCH v2 3/8] thermal: gov_power_allocator: Move memory allocation out of throttle() Date: Tue, 12 Dec 2023 13:48:39 +0000 Message-Id: <20231212134844.1213381-4-lukasz.luba@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231212134844.1213381-1-lukasz.luba@arm.com> References: <20231212134844.1213381-1-lukasz.luba@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-0.8 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on fry.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (fry.vger.email [0.0.0.0]); Tue, 12 Dec 2023 05:48:41 -0800 (PST) The new thermal callback allows to react to the change of cooling instances in the thermal zone. Move the memory allocation to that new callback and save CPU cycles in the throttle() code path. Signed-off-by: Lukasz Luba --- drivers/thermal/gov_power_allocator.c | 144 ++++++++++++++++++++------ 1 file changed, 113 insertions(+), 31 deletions(-) diff --git a/drivers/thermal/gov_power_allocator.c b/drivers/thermal/gov_power_allocator.c index 38e1e89ba10c..3328c3ec71f2 100644 --- a/drivers/thermal/gov_power_allocator.c +++ b/drivers/thermal/gov_power_allocator.c @@ -61,6 +61,13 @@ static inline s64 div_frac(s64 x, s64 y) * @trip_switch_on should be NULL. * @trip_max: last passive trip point of the thermal zone. The * temperature we are controlling for. + * @num_actors: number of cooling devices supporting IPA callbacks + * @buffer_size: IPA internal buffer size + * @req_power: IPA buffer for requested power + * @max_power: IPA buffer for max allocatable power + * @granted_power: IPA buffer for granted power + * @extra_actor_power: IPA buffer for extra power + * @weighted_req_power: IPA buffer for weighted requested power */ struct power_allocator_params { bool allocated_tzp; @@ -69,6 +76,13 @@ struct power_allocator_params { u32 sustainable_power; const struct thermal_trip *trip_switch_on; const struct thermal_trip *trip_max; + int num_actors; + int buffer_size; + u32 *req_power; + u32 *max_power; + u32 *granted_power; + u32 *extra_actor_power; + u32 *weighted_req_power; }; /** @@ -387,39 +401,24 @@ static int allocate_power(struct thermal_zone_device *tz, int control_temp) u32 *weighted_req_power; u32 power_range, weight; int total_weight = 0; - int num_actors = 0; int i = 0; - list_for_each_entry(instance, &tz->thermal_instances, tz_node) { + if (!params->num_actors) + return -ENODEV; + + list_for_each_entry(instance, &tz->thermal_instances, tz_node) if ((instance->trip == params->trip_max) && - cdev_is_power_actor(instance->cdev)) { - num_actors++; + cdev_is_power_actor(instance->cdev)) total_weight += instance->weight; - } - } - - if (!num_actors) - return -ENODEV; - /* - * We need to allocate five arrays of the same size: - * req_power, max_power, granted_power, extra_actor_power and - * weighted_req_power. They are going to be needed until this - * function returns. Allocate them all in one go to simplify - * the allocation and deallocation logic. - */ - BUILD_BUG_ON(sizeof(*req_power) != sizeof(*max_power)); - BUILD_BUG_ON(sizeof(*req_power) != sizeof(*granted_power)); - BUILD_BUG_ON(sizeof(*req_power) != sizeof(*extra_actor_power)); - BUILD_BUG_ON(sizeof(*req_power) != sizeof(*weighted_req_power)); - req_power = kcalloc(num_actors * 5, sizeof(*req_power), GFP_KERNEL); - if (!req_power) - return -ENOMEM; + /* Clean all buffers for new power estimations */ + memset(params->req_power, 0, params->buffer_size); - max_power = &req_power[num_actors]; - granted_power = &req_power[2 * num_actors]; - extra_actor_power = &req_power[3 * num_actors]; - weighted_req_power = &req_power[4 * num_actors]; + req_power = params->req_power; + max_power = params->max_power; + granted_power = params->granted_power; + extra_actor_power = params->extra_actor_power; + weighted_req_power = params->weighted_req_power; list_for_each_entry(instance, &tz->thermal_instances, tz_node) { cdev = instance->cdev; @@ -453,7 +452,7 @@ static int allocate_power(struct thermal_zone_device *tz, int control_temp) power_range = pid_controller(tz, control_temp, max_allocatable_power); - divvy_up_power(weighted_req_power, max_power, num_actors, + divvy_up_power(weighted_req_power, max_power, params->num_actors, total_weighted_req_power, power_range, granted_power, extra_actor_power); @@ -474,12 +473,10 @@ static int allocate_power(struct thermal_zone_device *tz, int control_temp) trace_thermal_power_allocator(tz, req_power, total_req_power, granted_power, total_granted_power, - num_actors, power_range, + params->num_actors, power_range, max_allocatable_power, tz->temperature, control_temp - tz->temperature); - kfree(req_power); - return 0; } @@ -606,6 +603,81 @@ static int check_power_actors(struct thermal_zone_device *tz, return ret; } +static void _power_buffers_init(struct power_allocator_params *params, + u32 *req_power, u32 *max_power, + u32 *granted_power, u32 *extra_actor_power, + u32 *weighted_req_power) + +{ + /* Setup internal buffers for power calculations. */ + params->req_power = req_power; + params->max_power = max_power; + params->granted_power = granted_power; + params->extra_actor_power = extra_actor_power; + params->weighted_req_power = weighted_req_power; +} + +static int allocate_actors_buffer(struct power_allocator_params *params, + int num_actors) +{ + u32 *req_power; + int ret; + + kfree(params->req_power); + + /* There might be no cooling devices yet. */ + if (!num_actors) { + ret = -EINVAL; + goto clean_buffers; + } + + req_power = kcalloc(num_actors * 5, sizeof(u32), GFP_KERNEL); + if (!req_power) { + ret = -ENOMEM; + goto clean_buffers; + } + + params->num_actors = num_actors; + params->buffer_size = num_actors * 5 * sizeof(u32); + + _power_buffers_init(params, req_power, &req_power[params->num_actors], + &req_power[2 * params->num_actors], + &req_power[3 * params->num_actors], + &req_power[4 * params->num_actors]); + + return 0; + +clean_buffers: + params->num_actors = -EINVAL; + params->buffer_size = 0; + _power_buffers_init(params, NULL, NULL, NULL, NULL, NULL); + return ret; +} + +static void power_allocator_update_tz(struct thermal_zone_device *tz, + enum thermal_notify_event reason) +{ + struct power_allocator_params *params = tz->governor_data; + struct thermal_instance *instance; + int num_actors = 0; + + switch (reason) { + case THERMAL_INSTANCE_LIST_UPDATE: + list_for_each_entry(instance, &tz->thermal_instances, tz_node) + if ((instance->trip == params->trip_max) && + cdev_is_power_actor(instance->cdev)) + num_actors++; + + if (num_actors == params->num_actors) + return; + + allocate_actors_buffer(params, num_actors); + break; + default: + break; + } +} + /** * power_allocator_bind() - bind the power_allocator governor to a thermal zone * @tz: thermal zone to bind it to @@ -639,6 +711,13 @@ static int power_allocator_bind(struct thermal_zone_device *tz) return ret; } + ret = allocate_actors_buffer(params, ret); + if (ret) { + dev_warn(&tz->device, "power_allocator: allocation failed\n"); + kfree(params); + return ret; + } + if (!tz->tzp) { tz->tzp = kzalloc(sizeof(*tz->tzp), GFP_KERNEL); if (!tz->tzp) { @@ -663,6 +742,7 @@ static int power_allocator_bind(struct thermal_zone_device *tz) return 0; free_params: + kfree(params->req_power); kfree(params); return ret; @@ -679,6 +759,7 @@ static void power_allocator_unbind(struct thermal_zone_device *tz) tz->tzp = NULL; } + kfree(params->req_power); kfree(tz->governor_data); tz->governor_data = NULL; } @@ -717,5 +798,6 @@ static struct thermal_governor thermal_gov_power_allocator = { .bind_to_tz = power_allocator_bind, .unbind_from_tz = power_allocator_unbind, .throttle = power_allocator_throttle, + .update_tz = power_allocator_update_tz, }; THERMAL_GOVERNOR_DECLARE(thermal_gov_power_allocator); -- 2.25.1