From nobody Mon Feb 9 03:45:24 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 39FDC3A0B0F for ; Fri, 16 Jan 2026 18:47:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768589256; cv=none; b=B5W7M4YawyENilN9T/dVYtUVfxuMxZXB8LtK77WLvefZWlwZjzMGuw8MFsUHvhijz4jlT5BgRDPXl5qItphc5vKYWZcKlI/3ossumTiBnKHyJ/QdjXBqSSEHeSu3y5wDGPAOdsxXEQdkwZjS/be803+mOXDBej3UwFy5zhJUDWo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768589256; c=relaxed/simple; bh=WomW7o++hqA3CZhZh+c/A1kRySGsTBktO4eA86cy478=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MarvNIUyqfr0XhdgLIrkQrCwa/NHPuZMov6al3nPY3k/gMOp1Cs84XtIO9Y8VvkKgWpHA4OB1NOv27fUMtWWIlNniIMBAGmLj/0c/t3BKzSxw5Ch0y1xs3jbdi0JHwuUrIZbKlEvElwtJ1/13xJAQp6kbmYbYR6yMTwrsgfXkoM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=BaRF5yaI; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="BaRF5yaI" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768589254; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cLmYWISvdFcVupMzsZHmCRs81gS/4QwR4ldZUKtuStM=; b=BaRF5yaIVT1hUMfFUvmZZttpppEWtvVKj6zhZ93PDgW33nHdVhqe5gLYZ5qyI/1Ue6+8O0 bxDV4AUt4OGBcvzgF1gW38yFnQG5gR1PjdEBqZos7hxChjRbeXYEROyz0YVVfelN6X23zd 3mdU2KPdYUsjY1CrnpdaQP5lb+IP/5g= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-161-NQ3dXMBkM8umQlVYvBzx4Q-1; Fri, 16 Jan 2026 13:47:29 -0500 X-MC-Unique: NQ3dXMBkM8umQlVYvBzx4Q-1 X-Mimecast-MFC-AGG-ID: NQ3dXMBkM8umQlVYvBzx4Q_1768589246 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E9FF118005B3; Fri, 16 Jan 2026 18:47:25 +0000 (UTC) Received: from p16v.luc.cera.cz (unknown [10.44.34.71]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 5B3B21955F67; Fri, 16 Jan 2026 18:47:18 +0000 (UTC) From: Ivan Vecera To: netdev@vger.kernel.org Cc: Alexander Lobakin , Andrew Lunn , Arkadiusz Kubalewski , Conor Dooley , "David S. Miller" , Eric Dumazet , Grzegorz Nitka , Jakub Kicinski , Jiri Pirko , Jonathan Lemon , Krzysztof Kozlowski , Leon Romanovsky , Mark Bloch , Michal Schmidt , Paolo Abeni , Petr Oros , Prathosh Satish , Przemek Kitszel , Richard Cochran , Rob Herring , Saeed Mahameed , Saravana Kannan , Tariq Toukan , Tony Nguyen , Vadim Fedorenko , devicetree@vger.kernel.org, intel-wired-lan@lists.osuosl.org, linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org Subject: [PATCH net-next v2 08/12] dpll: Enhance and consolidate reference counting logic Date: Fri, 16 Jan 2026 19:46:06 +0100 Message-ID: <20260116184610.147591-9-ivecera@redhat.com> In-Reply-To: <20260116184610.147591-1-ivecera@redhat.com> References: <20260116184610.147591-1-ivecera@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Content-Type: text/plain; charset="utf-8" Refactor the reference counting mechanism for DPLL devices and pins to improve consistency and prevent potential lifetime issues. Introduce internal helpers __dpll_{device,pin}_{hold,put}() to centralize reference management. Update the internal XArray reference helpers (dpll_xa_ref_*) to automatically grab a reference to the target object when it is added to a list, and release it when removed. This ensures that objects linked internally (e.g., pins referenced by parent pins) are properly kept alive without relying on the caller to manually manage the count. Consequently, remove the now redundant manual `refcount_inc/dec` calls in dpll_pin_on_pin_{,un}register()`, as ownership is now correctly handled by the dpll_xa_ref_* functions. Additionally, ensure that dpll_device_{,un}register()` takes/releases a reference to the device, ensuring the device object remains valid for the duration of its registration. Signed-off-by: Ivan Vecera --- drivers/dpll/dpll_core.c | 74 +++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c index 156f95de8e8e8..f2a77eb1b9916 100644 --- a/drivers/dpll/dpll_core.c +++ b/drivers/dpll/dpll_core.c @@ -84,6 +84,45 @@ void dpll_pin_notify(struct dpll_pin *pin, unsigned long= action) call_dpll_notifiers(action, &info); } =20 +static void __dpll_device_hold(struct dpll_device *dpll) +{ + refcount_inc(&dpll->refcount); +} + +static void __dpll_device_put(struct dpll_device *dpll) +{ + if (refcount_dec_and_test(&dpll->refcount)) { + ASSERT_DPLL_NOT_REGISTERED(dpll); + WARN_ON_ONCE(!xa_empty(&dpll->pin_refs)); + xa_destroy(&dpll->pin_refs); + xa_erase(&dpll_device_xa, dpll->id); + WARN_ON(!list_empty(&dpll->registration_list)); + kfree(dpll); + } +} + +static void __dpll_pin_hold(struct dpll_pin *pin) +{ + refcount_inc(&pin->refcount); +} + +static void dpll_pin_idx_free(u32 pin_idx); +static void dpll_pin_prop_free(struct dpll_pin_properties *prop); + +static void __dpll_pin_put(struct dpll_pin *pin) +{ + if (refcount_dec_and_test(&pin->refcount)) { + xa_erase(&dpll_pin_xa, pin->id); + xa_destroy(&pin->dpll_refs); + xa_destroy(&pin->parent_refs); + xa_destroy(&pin->ref_sync_pins); + dpll_pin_prop_free(&pin->prop); + fwnode_handle_put(pin->fwnode); + dpll_pin_idx_free(pin->pin_idx); + kfree_rcu(pin, rcu); + } +} + struct dpll_device *dpll_device_get_by_id(int id) { if (xa_get_mark(&dpll_device_xa, id, DPLL_REGISTERED)) @@ -155,6 +194,7 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll= _pin *pin, reg->ops =3D ops; reg->priv =3D priv; reg->cookie =3D cookie; + __dpll_pin_hold(pin); if (ref_exists) refcount_inc(&ref->refcount); list_add_tail(®->list, &ref->registration_list); @@ -177,6 +217,7 @@ static int dpll_xa_ref_pin_del(struct xarray *xa_pins, = struct dpll_pin *pin, if (WARN_ON(!reg)) return -EINVAL; list_del(®->list); + __dpll_pin_put(pin); kfree(reg); if (refcount_dec_and_test(&ref->refcount)) { xa_erase(xa_pins, i); @@ -236,6 +277,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dp= ll_device *dpll, reg->ops =3D ops; reg->priv =3D priv; reg->cookie =3D cookie; + __dpll_device_hold(dpll); if (ref_exists) refcount_inc(&ref->refcount); list_add_tail(®->list, &ref->registration_list); @@ -258,6 +300,7 @@ dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dp= ll_device *dpll, if (WARN_ON(!reg)) return; list_del(®->list); + __dpll_device_put(dpll); kfree(reg); if (refcount_dec_and_test(&ref->refcount)) { xa_erase(xa_dplls, i); @@ -328,8 +371,8 @@ dpll_device_get(u64 clock_id, u32 device_idx, struct mo= dule *module) if (dpll->clock_id =3D=3D clock_id && dpll->device_idx =3D=3D device_idx && dpll->module =3D=3D module) { + __dpll_device_hold(dpll); ret =3D dpll; - refcount_inc(&ret->refcount); break; } } @@ -352,14 +395,7 @@ EXPORT_SYMBOL_GPL(dpll_device_get); void dpll_device_put(struct dpll_device *dpll) { mutex_lock(&dpll_lock); - if (refcount_dec_and_test(&dpll->refcount)) { - ASSERT_DPLL_NOT_REGISTERED(dpll); - WARN_ON_ONCE(!xa_empty(&dpll->pin_refs)); - xa_destroy(&dpll->pin_refs); - xa_erase(&dpll_device_xa, dpll->id); - WARN_ON(!list_empty(&dpll->registration_list)); - kfree(dpll); - } + __dpll_device_put(dpll); mutex_unlock(&dpll_lock); } EXPORT_SYMBOL_GPL(dpll_device_put); @@ -421,6 +457,7 @@ int dpll_device_register(struct dpll_device *dpll, enum= dpll_type type, reg->ops =3D ops; reg->priv =3D priv; dpll->type =3D type; + __dpll_device_hold(dpll); first_registration =3D list_empty(&dpll->registration_list); list_add_tail(®->list, &dpll->registration_list); if (!first_registration) { @@ -460,6 +497,7 @@ void dpll_device_unregister(struct dpll_device *dpll, return; } list_del(®->list); + __dpll_device_put(dpll); kfree(reg); =20 if (!list_empty(&dpll->registration_list)) { @@ -671,8 +709,8 @@ dpll_pin_get(u64 clock_id, u32 pin_idx, struct module *= module, if (pos->clock_id =3D=3D clock_id && pos->pin_idx =3D=3D pin_idx && pos->module =3D=3D module) { + __dpll_pin_hold(pos); ret =3D pos; - refcount_inc(&ret->refcount); break; } } @@ -695,16 +733,7 @@ EXPORT_SYMBOL_GPL(dpll_pin_get); void dpll_pin_put(struct dpll_pin *pin) { mutex_lock(&dpll_lock); - if (refcount_dec_and_test(&pin->refcount)) { - xa_erase(&dpll_pin_xa, pin->id); - xa_destroy(&pin->dpll_refs); - xa_destroy(&pin->parent_refs); - xa_destroy(&pin->ref_sync_pins); - dpll_pin_prop_free(&pin->prop); - fwnode_handle_put(pin->fwnode); - dpll_pin_idx_free(pin->pin_idx); - kfree_rcu(pin, rcu); - } + __dpll_pin_put(pin); mutex_unlock(&dpll_lock); } EXPORT_SYMBOL_GPL(dpll_pin_put); @@ -745,8 +774,8 @@ struct dpll_pin *fwnode_dpll_pin_find(struct fwnode_han= dle *fwnode) mutex_lock(&dpll_lock); xa_for_each(&dpll_pin_xa, index, pin) { if (pin->fwnode =3D=3D fwnode) { + __dpll_pin_hold(pin); ret =3D pin; - refcount_inc(&ret->refcount); break; } } @@ -971,7 +1000,6 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, = struct dpll_pin *pin, ret =3D dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv, pin); if (ret) goto unlock; - refcount_inc(&pin->refcount); xa_for_each(&parent->dpll_refs, i, ref) { ret =3D __dpll_pin_register(ref->dpll, pin, ops, priv, parent); if (ret) { @@ -991,7 +1019,6 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, = struct dpll_pin *pin, parent); dpll_pin_delete_ntf(pin); } - refcount_dec(&pin->refcount); dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin); unlock: mutex_unlock(&dpll_lock); @@ -1018,7 +1045,6 @@ void dpll_pin_on_pin_unregister(struct dpll_pin *pare= nt, struct dpll_pin *pin, mutex_lock(&dpll_lock); dpll_pin_delete_ntf(pin); dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin); - refcount_dec(&pin->refcount); xa_for_each(&pin->dpll_refs, i, ref) __dpll_pin_unregister(ref->dpll, pin, ops, priv, parent); mutex_unlock(&dpll_lock); --=20 2.52.0