From patchwork Thu Feb 9 16:35:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 13134870 X-Patchwork-Delegate: daniel.lezcano@linaro.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C6583C636D7 for ; Thu, 9 Feb 2023 16:36:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229653AbjBIQgD (ORCPT ); Thu, 9 Feb 2023 11:36:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44230 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229450AbjBIQgC (ORCPT ); Thu, 9 Feb 2023 11:36:02 -0500 Received: from mail-ej1-x635.google.com (mail-ej1-x635.google.com [IPv6:2a00:1450:4864:20::635]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D27D35D1CD; Thu, 9 Feb 2023 08:36:01 -0800 (PST) Received: by mail-ej1-x635.google.com with SMTP id jg8so8089455ejc.6; Thu, 09 Feb 2023 08:36:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=NSMHddABkQrSZWKXpcNqaIw0Zi5wgSezoqZrfdPoFS4=; b=dQKC05DNRQQNdOpQUw+3c5rMOAUX4Mo+Jh82gM3mIG1vPs8HWsnnd8YY4HjIalA6n0 z91cj8Iuq0MfFAAq+flknH6vuHuGUQh58V/idFI9GfgqdTLJDNyiBGyW8lXSFpcWcAAH jqKXsuybEXM8AEe/gCkTJowqfByrXS27kiPYjkqnxd+01Bg5Pd01FhR8UfEAP3nCHbvu quwSzBtWESoBwPtvmgIm/mQr7cfYbHYkd4lFdItmfAeGbFSw4ghaGuY5HB+bL8SdQbuL 0QfuPU+TjuCeEwaTTHPAssI6FXykLevzh0SNfyBKgEHUUP/ww4iwixK1Dh0X/XCE8Kl8 Y9aw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=NSMHddABkQrSZWKXpcNqaIw0Zi5wgSezoqZrfdPoFS4=; b=5FWzgmN/QqlMfvhB1qGAOhY+XKtCr834nx/gj0PGs5oY72aPUxw0PA3qBdbxkGZDud XuLUVKzzz9KjhVVLdoqPwbJMMgJxe7zG591JgfewADo+Y2L6V0aMgopgIl4L2yQH1/qU jswCVrn2ysrL74dQhJdfSKM6IHOmAezWus0A2JG8dqVjsulWflu9F9IWLGZE2WWvzV1a VYhvfXO0AYYZ1D+tMSmfdI+wyeO464vHQVEMFtX0os1yujNkOB4jC+Cm1vENKlqmmerK p6C3+oi+6c6rb8wzGYEo/nEqsd9p7p4FwA6JJ/2fwGyEOjVdsf7Qsw8eh7VBc9Tq4ANk HRYA== X-Gm-Message-State: AO0yUKWGCjkQPaJ8AdSre06t5J4krO8GEkCzlreKU8RO/hnsFXvLbaxR qrW7h2nDIqMMLkJ9bqMYSbE= X-Google-Smtp-Source: AK7set+oKuYllmX96ewy+fm4I2U28/GcuB3wo8J+X44BcI7GRbtlqzC+GMcWeq3ZAHV2Gas3m5bolg== X-Received: by 2002:a17:906:86d6:b0:885:9ce9:dc79 with SMTP id j22-20020a17090686d600b008859ce9dc79mr12978483ejy.77.1675960560310; Thu, 09 Feb 2023 08:36:00 -0800 (PST) Received: from localhost (p200300e41f201d00f22f74fffe1f3a53.dip0.t-ipconnect.de. [2003:e4:1f20:1d00:f22f:74ff:fe1f:3a53]) by smtp.gmail.com with ESMTPSA id kv7-20020a17090778c700b0088f8ae18b6bsm1059203ejc.189.2023.02.09.08.35.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Feb 2023 08:36:00 -0800 (PST) From: Thierry Reding To: "Rafael J . Wysocki" , Daniel Lezcano Cc: Amit Kucheria , Zhang Rui , Jon Hunter , linux-pm@vger.kernel.org, linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/2] thermal: Add support for cooling device bind/unbind operations Date: Thu, 9 Feb 2023 17:35:54 +0100 Message-Id: <20230209163555.1993557-1-thierry.reding@gmail.com> X-Mailer: git-send-email 2.39.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org From: Thierry Reding Drivers for cooling devices can implement these operations when they need to perform extra work at the time when a cooling device is bound to a given thermal zone. Signed-off-by: Thierry Reding --- drivers/thermal/thermal_core.c | 11 +++++++++++ include/linux/thermal.h | 6 ++++++ 2 files changed, 17 insertions(+) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 0675df54c8e6..627fccd100ef 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -694,6 +694,14 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, mutex_unlock(&cdev->lock); mutex_unlock(&tz->lock); + if (cdev->ops->bind) { + result = cdev->ops->bind(cdev, tz, trip, upper, lower, weight); + if (result < 0) { + pr_err("failed to bind %s to %s: %d\n", cdev->type, + tz->type, result); + } + } + if (!result) return 0; @@ -730,6 +738,9 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, { struct thermal_instance *pos, *next; + if (cdev->ops->unbind) + cdev->ops->unbind(cdev, tz, trip); + mutex_lock(&tz->lock); mutex_lock(&cdev->lock); list_for_each_entry_safe(pos, next, &tz->thermal_instances, tz_node) { diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 2bb4bf33f4f3..95ed8a0cbba8 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -89,6 +89,12 @@ struct thermal_trip { }; struct thermal_cooling_device_ops { + int (*bind)(struct thermal_cooling_device *cdev, + struct thermal_zone_device *tz, int trip_id, + unsigned long upper, unsigned long lower, + unsigned int weight); + void (*unbind)(struct thermal_cooling_device *cdev, + struct thermal_zone_device *tz, int trip_id); int (*get_max_state) (struct thermal_cooling_device *, unsigned long *); int (*get_cur_state) (struct thermal_cooling_device *, unsigned long *); int (*set_cur_state) (struct thermal_cooling_device *, unsigned long); From patchwork Thu Feb 9 16:35:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 13134871 X-Patchwork-Delegate: daniel.lezcano@linaro.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2CDB8C64EC5 for ; Thu, 9 Feb 2023 16:36:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229683AbjBIQgF (ORCPT ); Thu, 9 Feb 2023 11:36:05 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44238 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229671AbjBIQgE (ORCPT ); Thu, 9 Feb 2023 11:36:04 -0500 Received: from mail-ed1-x52f.google.com (mail-ed1-x52f.google.com [IPv6:2a00:1450:4864:20::52f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B77B15D1D5; Thu, 9 Feb 2023 08:36:02 -0800 (PST) Received: by mail-ed1-x52f.google.com with SMTP id d40so1348168eda.8; Thu, 09 Feb 2023 08:36:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7EOfW6T6B8QOW9L3wKVd9xNkr96frILN3seTzII1LVE=; b=ZX+JqMWS64npOfK7R0bse7BLwv4cU1g674tUkbUzAY/HvZUneDmABSMLL90+m2PPoY 4aBPZzc2ZRRR9+bVz8G3rtWCH41NEEPNdJgeWHE6ZDxPD1ZTraA/ls1GybbIpcnVFB/Q +baxlHAXkLGnQ+lXV3em9PbwhVG34doUzTqdtrXW8/eaEKD2qX8AHP7i6Zb/DCouX2fF N5IxwZ/zBllT6zeGi/SOd1cXy0GyzodcTsfpiJM2/RRdj5lsvnsudge6r4R9Uv8PMw6T dwgUdw5Xl3YqJoXL2yUSTIrCePDfFgtG5su6ABBhiU8a49RO3xeOvhJsyU4lXFQzVvkS BoDw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7EOfW6T6B8QOW9L3wKVd9xNkr96frILN3seTzII1LVE=; b=psbU04tSMKnr5PbS2BfePKv+THkyhjQ/QXZO3Rm2ey3FyP58HR8aYKO/37NGUSc61l 7IEcVLxEOWsLUfsOS9gw/cW4NpccBY9pVISJZdRPJi2MrCa4UINr0j/OiZMi4VXX4WCR EjjpluCWGwwJ3xQB5Gt6FqOth1cxv5laK1gE6vPxJIhVFcwxzLyComIzKPV3Jlgs5mFP 1nh9vX4b6mvvOYp9hcbRI1MT2K3D7rRpoA7A4ORLdUmbcdgTyg4Pe4FpHskTmaTtmCoo shC2smCtkt/lwFzwbmFR5pRXZ1ztLPuJ8TiU89nzu/dTz4F00+KCt2p2g/CSI0SITqPK NNng== X-Gm-Message-State: AO0yUKWEzKhcfAZQUmt5RVYX5530ps5WBTPHQ49GPEuH4vITARs7NIdJ 1XQfRCKsOtcTOtJhptxhZMs= X-Google-Smtp-Source: AK7set88/Eyc2sOI0OXNCjP7sJ6JivBs3kJhEHYp65G7aJvUHGA2D2mY4wMVPRpsUrF0msUNUPOtzA== X-Received: by 2002:a50:cdc2:0:b0:4ab:1793:1254 with SMTP id h2-20020a50cdc2000000b004ab17931254mr4113459edj.13.1675960561165; Thu, 09 Feb 2023 08:36:01 -0800 (PST) Received: from localhost (p200300e41f201d00f22f74fffe1f3a53.dip0.t-ipconnect.de. [2003:e4:1f20:1d00:f22f:74ff:fe1f:3a53]) by smtp.gmail.com with ESMTPSA id e12-20020a50ec8c000000b0046b471596e6sm959335edr.57.2023.02.09.08.36.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Feb 2023 08:36:00 -0800 (PST) From: Thierry Reding To: "Rafael J . Wysocki" , Daniel Lezcano Cc: Amit Kucheria , Zhang Rui , Jon Hunter , linux-pm@vger.kernel.org, linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/2] thermal: tegra: Implement bind/unbind for cooling device Date: Thu, 9 Feb 2023 17:35:55 +0100 Message-Id: <20230209163555.1993557-2-thierry.reding@gmail.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20230209163555.1993557-1-thierry.reding@gmail.com> References: <20230209163555.1993557-1-thierry.reding@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org From: Thierry Reding The SOCTHERM hardware found on Tegra implements a way of throttling the CPU and GPU when a given temperature threshold is reached. As opposed to traditional cooling devices, the programming for this happens during the initialization stage rather than dynamically at runtime when the thermal framework gets notified of thresholds being crossed. Use the newly introduced ->bind() and ->unbind() operations to make sure the SOCTHERM programming happens at the right time. This allows us to get rid of calls to the get_thermal_instance() helper which is not supposed to be accessed by drivers. Reported-by: Daniel Lezcano Signed-off-by: Thierry Reding --- drivers/thermal/tegra/soctherm.c | 146 ++++++++++++++----------------- 1 file changed, 67 insertions(+), 79 deletions(-) diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c index 220873298d77..cdc8764e88aa 100644 --- a/drivers/thermal/tegra/soctherm.c +++ b/drivers/thermal/tegra/soctherm.c @@ -303,6 +303,8 @@ struct tegra_thermctl_zone { struct tegra_soctherm *ts; struct thermal_zone_device *tz; const struct tegra_tsensor_group *sg; + /* instance of an internal throttle cooling device */ + struct thermal_cooling_device *cdev; }; struct soctherm_oc_cfg { @@ -315,6 +317,7 @@ struct soctherm_oc_cfg { }; struct soctherm_throt_cfg { + struct tegra_soctherm *soctherm; const char *name; unsigned int id; u8 priority; @@ -585,10 +588,10 @@ static int tsensor_group_thermtrip_get(struct tegra_soctherm *ts, int id) static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, int trip_id, int temp) { struct tegra_thermctl_zone *zone = tz->devdata; - struct tegra_soctherm *ts = zone->ts; - struct thermal_trip trip; const struct tegra_tsensor_group *sg = zone->sg; + struct tegra_soctherm *ts = zone->ts; struct device *dev = zone->dev; + struct thermal_trip trip; int ret; if (!tz) @@ -610,26 +613,14 @@ static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, int trip return 0; } else if (trip.type == THERMAL_TRIP_HOT) { - int i; - - for (i = 0; i < THROTTLE_SIZE; i++) { - struct thermal_cooling_device *cdev; - struct soctherm_throt_cfg *stc; - - if (!ts->throt_cfgs[i].init) - continue; - - cdev = ts->throt_cfgs[i].cdev; - if (get_thermal_instance(tz, cdev, trip_id)) - stc = find_throttle_cfg_by_name(ts, cdev->type); - else - continue; + if (zone->cdev) { + struct soctherm_throt_cfg *stc = zone->cdev->devdata; return throttrip_program(dev, sg, stc, temp); } } - return 0; + return ret; } static void thermal_irq_enable(struct tegra_thermctl_zone *zn) @@ -687,26 +678,6 @@ static const struct thermal_zone_device_ops tegra_of_thermal_ops = { .set_trips = tegra_thermctl_set_trips, }; -static int get_hot_temp(struct thermal_zone_device *tz, int *trip_id, int *temp) -{ - int i, ret; - struct thermal_trip trip; - - for (i = 0; i < thermal_zone_get_num_trips(tz); i++) { - - ret = thermal_zone_get_trip(tz, i, &trip); - if (ret) - return -EINVAL; - - if (trip.type == THERMAL_TRIP_HOT) { - *trip_id = i; - return 0; - } - } - - return -EINVAL; -} - /** * tegra_soctherm_set_hwtrips() - set HW trip point from DT data * @dev: struct device * of the SOC_THERM instance @@ -736,8 +707,7 @@ static int tegra_soctherm_set_hwtrips(struct device *dev, struct thermal_zone_device *tz) { struct tegra_soctherm *ts = dev_get_drvdata(dev); - struct soctherm_throt_cfg *stc; - int i, trip, temperature, ret; + int temperature, ret; /* Get thermtrips. If missing, try to get critical trips. */ temperature = tsensor_group_thermtrip_get(ts, sg->id); @@ -754,42 +724,6 @@ static int tegra_soctherm_set_hwtrips(struct device *dev, dev_info(dev, "thermtrip: will shut down when %s reaches %d mC\n", sg->name, temperature); - ret = get_hot_temp(tz, &trip, &temperature); - if (ret) { - dev_info(dev, "throttrip: %s: missing hot temperature\n", - sg->name); - return 0; - } - - for (i = 0; i < THROTTLE_OC1; i++) { - struct thermal_cooling_device *cdev; - - if (!ts->throt_cfgs[i].init) - continue; - - cdev = ts->throt_cfgs[i].cdev; - if (get_thermal_instance(tz, cdev, trip)) - stc = find_throttle_cfg_by_name(ts, cdev->type); - else - continue; - - ret = throttrip_program(dev, sg, stc, temperature); - if (ret) { - dev_err(dev, "throttrip: %s: error during enable\n", - sg->name); - return ret; - } - - dev_info(dev, - "throttrip: will throttle when %s reaches %d mC\n", - sg->name, temperature); - break; - } - - if (i == THROTTLE_SIZE) - dev_info(dev, "throttrip: %s: missing throttle cdev\n", - sg->name); - return 0; } @@ -1497,6 +1431,55 @@ static int soctherm_clk_enable(struct platform_device *pdev, bool enable) return 0; } +static int throt_bind(struct thermal_cooling_device *cdev, + struct thermal_zone_device *tz, int trip_id, + unsigned long upper, unsigned long lower, + unsigned int weight) +{ + struct tegra_thermctl_zone *zone = tz->devdata; + struct device *dev = &cdev->device; + struct thermal_trip trip; + int err; + + err = thermal_zone_get_trip(tz, trip_id, &trip); + if (err < 0) + return err; + + if (trip.type == THERMAL_TRIP_HOT) { + struct soctherm_throt_cfg *stc = cdev->devdata; + + err = throttrip_program(zone->dev, zone->sg, stc, trip.temperature); + if (err < 0) { + dev_err(dev, "throttrip: %s: error during enable\n", + zone->sg->name); + return err; + } + + dev_info(dev, "throttrip: will throttle when %s reaches %d mC\n", + zone->sg->name, trip.temperature); + + /* keep a reference to this for ->set_trip_temp() */ + zone->cdev = cdev; + } + + return 0; +} + +static void throt_unbind(struct thermal_cooling_device *cdev, + struct thermal_zone_device *tz, int trip_id) +{ + struct tegra_thermctl_zone *zone = tz->devdata; + struct thermal_trip trip; + int err; + + err = __thermal_zone_get_trip(tz, trip_id, &trip); + if (err < 0) + return; + + if (trip.type == THERMAL_TRIP_HOT) + zone->cdev = NULL; +} + static int throt_get_cdev_max_state(struct thermal_cooling_device *cdev, unsigned long *max_state) { @@ -1507,7 +1490,8 @@ static int throt_get_cdev_max_state(struct thermal_cooling_device *cdev, static int throt_get_cdev_cur_state(struct thermal_cooling_device *cdev, unsigned long *cur_state) { - struct tegra_soctherm *ts = cdev->devdata; + struct soctherm_throt_cfg *stc = cdev->devdata; + struct tegra_soctherm *ts = stc->soctherm; u32 r; r = readl(ts->regs + THROT_STATUS); @@ -1526,6 +1510,8 @@ static int throt_set_cdev_state(struct thermal_cooling_device *cdev, } static const struct thermal_cooling_device_ops throt_cooling_ops = { + .bind = throt_bind, + .unbind = throt_unbind, .get_max_state = throt_get_cdev_max_state, .get_cur_state = throt_get_cdev_cur_state, .set_cur_state = throt_set_cdev_state, @@ -1576,8 +1562,8 @@ static int soctherm_thermtrips_parse(struct platform_device *pdev) } static void soctherm_oc_cfg_parse(struct device *dev, - struct device_node *np_oc, - struct soctherm_throt_cfg *stc) + struct device_node *np_oc, + struct soctherm_throt_cfg *stc) { u32 val; @@ -1694,13 +1680,15 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev) if (err) continue; + stc->soctherm = ts; + if (stc->id >= THROTTLE_OC1) { soctherm_oc_cfg_parse(dev, np_stcc, stc); stc->init = true; } else { tcd = thermal_of_cooling_device_register(np_stcc, - (char *)name, ts, + (char *)name, stc, &throt_cooling_ops); if (IS_ERR_OR_NULL(tcd)) { dev_err(dev,