From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 296B6441049 for ; Tue, 5 May 2026 14:45:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777992303; cv=none; b=OUxgqW874X0IS2s8K8Hzyttf4X48QOyUgctXL5xFOICroLLOAqU44KEyE8DhsvNZrdbJMKaAYyMhsJDssVZvepkAadaRnLGO6cCuhCwoEN0/bPjIc8HZ3YbeFiZwP7WFn7kI3+dgNaLx6TSKWOjle3VpfK9cAKw18uYIC2lzAnc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777992303; c=relaxed/simple; bh=IU/cdzUqfeGxvfFTNL/M2rcmyaOccfuj4+fvZ9iKlII=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=pidINXH6Ofgu3/I1Nyn+XzqjrfByKNBk4TElQuLXLQyiEcsppWaHSPBYBzEgfSDcskvHAHaR61us8aqi3nsR0gQHsGXXi9S4uOfFSbPn8FA6Ve5RMVZdWAmtbuVMM9PowjwtbdavBWjGr+2rCKTBaI8jwzmvAvaz8jHBgVi8W9U= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=Fx1vILPK; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=A8w3ugbx; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="Fx1vILPK"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="A8w3ugbx" Received: from pps.filterd (m0279864.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 645EKw8a152048 for ; Tue, 5 May 2026 14:45:01 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:message-id:mime-version :subject:to; s=qcppdkim1; bh=F/2DXIW8O7JiMZgQ32rB3ikdUmEbQGqpgJc U1snQGfU=; b=Fx1vILPKD9TSFkF7w9iLgvDV+pDGdn7gTKHqTZoyGPN1zEp4JuL pMVeCErbZf2V5U2z9xp1E+74Rwyz3d6R9IVzCQNCkLTuDoOnrhyuCt5Iiv4kkUDc UgPFPPPukrgOOQlgy6HPmO3nzSi83YgSiXlEk0AOBro7s6DNSkf4BOG3Byh60G2I 2QUkHgYh9X//xehHOGoK0uOq3bjAHHZ10+iHSlp6mf7uVE2dV8Dwukq98qnxteui EYxRbrhs1bKgmPhIGZavsGojQlYfpQyx41RKcNaSTSTa34vXZz3neUzcBAsEwqJe QBnYGpo5INMqp1tonT8JVQzKt9lt78l1hLw== Received: from mail-vs1-f69.google.com (mail-vs1-f69.google.com [209.85.217.69]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4dyj8083pu-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Tue, 05 May 2026 14:45:01 +0000 (GMT) Received: by mail-vs1-f69.google.com with SMTP id ada2fe7eead31-62e59da69d7so1478509137.1 for ; Tue, 05 May 2026 07:45:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1777992300; x=1778597100; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=F/2DXIW8O7JiMZgQ32rB3ikdUmEbQGqpgJcU1snQGfU=; b=A8w3ugbx+OXD/xSBZK82fz2zpz0IH1Nu4iAnTycqSs8o5OoM2sDJfmo8DNtqk1Vc8v WBlj4zeoNNrn7huE+KVesDpSZYfv1rMfwwZBvUqBrbL+aLBQkP5te6O359YUgNALs+H8 F1INBGfaLFXiKgyteW6tRXCn+raPX9rdAOVBLovn89d3nY5HLt5tF3tzwGB67uT+jKXj 8G+aOhy9T+rPtjma/OlkNh409qujDL4+8KSAfGTivuHaUflUrZuyxRw+uXTpSpE4msS2 cMfjnZERz2B2fCrFLDFnuOlUPYkHecOtXjKZmb94zrZSTcGfTYzJYsHoOfNeZkcnnvKS Q+Nw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777992300; x=1778597100; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=F/2DXIW8O7JiMZgQ32rB3ikdUmEbQGqpgJcU1snQGfU=; b=f1kwuA/BJw3Op/5cgsYag3MRzwh/4caAlebVTiAySE0yqQhJ2hLAxRasjT5sD7lQMr eFp+q0t/Z9MzzhBjNswSSfeaYMI46G2AJLtG5kynr8DR9Y7sQtk4REjBbMBG1My4pLtI eliV3t3RjzhJOFpi4WBDLkbFFGooi+zycpzgwWFF6OmcxWinEIJ4lTIBAWMJ7kV9mIGw hr22Mc4BkI/oROlMqeEtNXwH058aCiUnQWuN6gBwJijljIMAOKiG40txS1Z5m3cy/py7 oHa+v0Y5PRwtJSlBuqhb/Jcu5OVLt5GpzjI+6iDgY5hgDZ4Q3/ycH8jVErDVB2Wnw1sH LnYA== X-Forwarded-Encrypted: i=1; AFNElJ95lgMD018FQywBZw97eHJM0lyJhBBiSCv4vn+5XP+Cj80C0gGGl953lHeGioHX5AjOJTxgUxKWCrKMtMg=@vger.kernel.org X-Gm-Message-State: AOJu0Yzlb0MSaJzzpooQ+crx8ISOw9nMPCUVwTK/+5Jnm09IBbss4SJm VHCVYmoRmr68GRTDGSrvAsja5j+Cdut+Ek4mqJmc++5XMyHAoSSW6J5Vjjc1kwz01Mr6It6oVpP murOn5cue4oBSodjuPDdtCwKhrP/9znxpMNOOmOquNbr4gu0doLafBaHcBzbpzy6kTKM= X-Gm-Gg: AeBDiesMPNXsDcO8jUGDBFZJeyFzFa2+7NGJcdtLTveGzBprYCZNcB7NXqkG24o/691 Bc7Ecm8A5A4rtBR5nNK7u9TBEkvqU/ogKyItwg8+nZNJp7en10KlCkT5USDo65ya5h5pBU0vVW0 9UMDZYXXiNmnlZpebUgCiT2p+gZ0aEK/vHrnKnT/Cktad+iBXTelyzv89+TCLdTwI/u77JNNO3X MkgEmrJu7FkXJFIHKVt3NmOtpwkd+W2CLgHiA+N4L/8EjiF7rUwu+Np9eIum2+zmwGs5j9ko7bK YjvBuTA1qhtGV4uN3toZBJLHMUyV1vjuFXzfBsZg+AepmYrrWGFRMoB8c+7y2uWa6kaCwRidGvc exmuCap9AmFHXYJ0JGRUs1gB2uLgTOTjAZfh07J7MZEW7fSVGGOKzcXNKOXw= X-Received: by 2002:a05:6102:2b96:b0:609:4db5:de7c with SMTP id ada2fe7eead31-62d85ad9d4dmr6934923137.13.1777992299281; Tue, 05 May 2026 07:44:59 -0700 (PDT) X-Received: by 2002:a05:6102:2b96:b0:609:4db5:de7c with SMTP id ada2fe7eead31-62d85ad9d4dmr6934903137.13.1777992298745; Tue, 05 May 2026 07:44:58 -0700 (PDT) Received: from mai.box.freepro.com ([2a05:6e02:1041:c10:3d0:c2e8:9f02:5c9d]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-45055960022sm5138984f8f.26.2026.05.05.07.44.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 May 2026 07:44:58 -0700 (PDT) From: Daniel Lezcano To: rafael@kernel.org Cc: rui.zhang@intel.com, lukasz.luba@arm.com, daniel.lezcano@oss.qualcomm.com, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] thermal/core: Split __thermal_cooling_device_register() into two functions Date: Tue, 5 May 2026 16:44:47 +0200 Message-ID: <20260505144447.2853933-1-daniel.lezcano@oss.qualcomm.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Authority-Analysis: v=2.4 cv=XvnK/1F9 c=1 sm=1 tr=0 ts=69fa026d cx=c_pps a=5HAIKLe1ejAbszaTRHs9Ug==:117 a=xqWC_Br6kY4A:10 a=NGcC8JguVDcA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=DJpcGTmdVt4CTyJn9g5Z:22 a=VwQbUJbxAAAA:8 a=EUspDBNiAAAA:8 a=q-1SiEWiNDsYHmDIksMA:9 a=gYDTvv6II1OnSo0itH1n:22 X-Proofpoint-ORIG-GUID: RBeKTPSLp7KwVrFGxVyJmAUJdYh5i1Cu X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNTA1MDE0MSBTYWx0ZWRfX/pavtBuPaBpp CyEK2pTPSU0hgpulHWRC+iVEVMGW5YfYDNlIkol30GykYfbRrm3TWbCVuRdpn14nMl4q53DCZKv tDZx3DgVkWkjkmmmAYWPLFKh2uUKU0mf07cfSM9OuIo54aA4fDFUrHPvS2OnTSUh1rQH325ZCyF HZg3HLg2NvCzB0UaVhimRdauShYTPmGBLh86vd2s6JGUbmamn9G0WETVX8uf6RcrwWGYmOMHuCv QOLChSQ/egmcYaB/HP8hEd5V9iKamatdJK+g8np9rzDJ265r3O9mSEo0++ZRrtptM2n0l8rjUAR Oh1s3gBhXJqKVaR1slWd+E0gVgYJv750cPABunPgWh20vXwalNJZyOhGYlsUTNCiYYdxC23OojU g6SOqXc4VkpAcLqjnDUxCZ8E9gVuAAwhbE/XU1JmEN6vH0gojZ28XjJPfP+Wx8q4ws+K86yXyd7 a96TnmDV5dJK8s4aQtA== X-Proofpoint-GUID: RBeKTPSLp7KwVrFGxVyJmAUJdYh5i1Cu X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.51,FMLib:17.12.100.49 definitions=2026-05-05_02,2026-04-30_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 bulkscore=0 suspectscore=0 priorityscore=1501 lowpriorityscore=0 adultscore=0 clxscore=1015 spamscore=0 phishscore=0 impostorscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2604200000 definitions=main-2605050141 In preparation for the upcoming changes separating OF and non-OF code, split __thermal_cooling_device_register() into allocation and addition phases. This allows moving the device node assignment out of the core initialization path. This change is not a trivial split. The lifetime of the cooling device is managed by the device core through put_device(), which triggers thermal_release() to free all associated resources. With the introduction of thermal_cooling_device_alloc(), the allocation path must mirror what thermal_release() undoes. In contrast, thermal_cooling_device_add() must not perform any rollback and relies on put_device() for cleanup on error paths. This avoids both double free and resource leaks. As part of this rework, add the missing device_initialize() call when allocating the cooling device. Suggested-by: Rafael J. Wysocki Signed-off-by: Daniel Lezcano --- drivers/thermal/thermal_core.c | 117 ++++++++++++++++++++------------- 1 file changed, 73 insertions(+), 44 deletions(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 664a4cc95199..fd4c61197d1e 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1040,29 +1040,10 @@ static void thermal_cooling_device_init_complete(struct thermal_cooling_device * thermal_zone_cdev_bind(tz, cdev); } -/** - * __thermal_cooling_device_register() - register a new thermal cooling device - * @np: a pointer to a device tree node. - * @type: the thermal cooling device type. - * @devdata: device private data. - * @ops: standard thermal cooling devices callbacks. - * - * This interface function adds a new thermal cooling device (fan/processor/...) - * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself - * to all the thermal zone devices registered at the same time. - * It also gives the opportunity to link the cooling device to a device tree - * node, so that it can be bound to a thermal zone created out of device tree. - * - * Return: a pointer to the created struct thermal_cooling_device or an - * ERR_PTR. Caller must check return value with IS_ERR*() helpers. - */ static struct thermal_cooling_device * -__thermal_cooling_device_register(struct device_node *np, - const char *type, void *devdata, - const struct thermal_cooling_device_ops *ops) +thermal_cooling_device_alloc(const char *type, const struct thermal_cooling_device_ops *ops) { struct thermal_cooling_device *cdev; - unsigned long current_state; int ret; if (!ops || !ops->get_max_state || !ops->get_cur_state || @@ -1076,6 +1057,8 @@ __thermal_cooling_device_register(struct device_node *np, if (!cdev) return ERR_PTR(-ENOMEM); + cdev->ops = ops; + ret = ida_alloc(&thermal_cdev_ida, GFP_KERNEL); if (ret < 0) goto out_kfree_cdev; @@ -1087,17 +1070,36 @@ __thermal_cooling_device_register(struct device_node *np, goto out_ida_remove; } + return cdev; + +out_ida_remove: + ida_free(&thermal_cdev_ida, cdev->id); +out_kfree_cdev: + kfree(cdev); + return ERR_PTR(ret); +} + +static int thermal_cooling_device_add(struct thermal_cooling_device *cdev, void *devdata) +{ + unsigned long current_state; + int ret; + mutex_init(&cdev->lock); INIT_LIST_HEAD(&cdev->thermal_instances); - cdev->np = np; - cdev->ops = ops; cdev->updated = false; cdev->device.class = &thermal_class; + device_initialize(&cdev->device); cdev->devdata = devdata; + thermal_cooling_device_setup_sysfs(cdev); + + ret = dev_set_name(&cdev->device, "cooling_device%d", cdev->id); + if (ret) + goto out_put_device; + ret = cdev->ops->get_max_state(cdev, &cdev->max_state); if (ret) - goto out_cdev_type; + goto out_put_device; /* * The cooling device's current state is only needed for debug @@ -1111,35 +1113,62 @@ __thermal_cooling_device_register(struct device_node *np, if (ret) current_state = ULONG_MAX; - thermal_cooling_device_setup_sysfs(cdev); - - ret = dev_set_name(&cdev->device, "cooling_device%d", cdev->id); - if (ret) - goto out_cooling_dev; - ret = device_register(&cdev->device); - if (ret) { - /* thermal_release() handles rest of the cleanup */ - put_device(&cdev->device); - return ERR_PTR(ret); - } + if (ret) + goto out_put_device; if (current_state <= cdev->max_state) thermal_debug_cdev_add(cdev, current_state); thermal_cooling_device_init_complete(cdev); - return cdev; + return 0; -out_cooling_dev: - thermal_cooling_device_destroy_sysfs(cdev); -out_cdev_type: - kfree_const(cdev->type); -out_ida_remove: - ida_free(&thermal_cdev_ida, cdev->id); -out_kfree_cdev: - kfree(cdev); - return ERR_PTR(ret); +out_put_device: + /* + * The device core will release the memory via + * thermal_release() after put_device() is called in the error + * path + */ + put_device(&cdev->device); + return ret; +} + +/** + * __thermal_cooling_device_register() - register a new thermal cooling device + * @np: a pointer to a device tree node. + * @type: the thermal cooling device type. + * @devdata: device private data. + * @ops: standard thermal cooling devices callbacks. + * + * This interface function adds a new thermal cooling device (fan/processor/...) + * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself + * to all the thermal zone devices registered at the same time. + * It also gives the opportunity to link the cooling device to a device tree + * node, so that it can be bound to a thermal zone created out of device tree. + * + * Return: a pointer to the created struct thermal_cooling_device or an + * ERR_PTR. Caller must check return value with IS_ERR*() helpers. + */ +static struct thermal_cooling_device * +__thermal_cooling_device_register(struct device_node *np, + const char *type, void *devdata, + const struct thermal_cooling_device_ops *ops) +{ + struct thermal_cooling_device *cdev; + int ret; + + cdev = thermal_cooling_device_alloc(type, ops); + if (IS_ERR(cdev)) + return cdev; + + cdev->np = np; + + ret = thermal_cooling_device_add(cdev, devdata); + if (ret) + return ERR_PTR(ret); + + return cdev; } /** -- 2.43.0