From nobody Tue Apr 7 11:52:57 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.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 0BF323C6A58 for ; Fri, 13 Mar 2026 16:44:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773420252; cv=none; b=FItl0vaL1GyTrnItUMPGretYtqhGRoUPlNxK80OctlBrqIzJxjOfgaECP7iPCWHB13mCHV/M27LyZoCUomHeJROa3qRZWINl20BAsc4ZOZwTdr8mAna9H1WnrexP7PIbXX2D2L0vDTHBsYL+5fjfqhGx0cI3hJLDqKxcyS2fPck= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773420252; c=relaxed/simple; bh=6RjRp0BMKBvqwmUs2I0l3tLNfJ+lEfqmjaaBafYyByA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Gnm+4He5995OkmJ7zT/JOy8rTGCrv3AMtGLmpxD/S8wI89ljs3Q4V7hbiTFTlYlOKybuqluXRlRSrxbY7VrJR7f1KTlSApvrzEp2Wq3y4Gxgyoo0MzQanbqFqLzepqwHAELR1JI/dBeWR7CtTJrbE8bFTcR+RRktQ0tIxT8UNZI= 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=HxChIL01; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b=CNOoPzdw; arc=none smtp.client-ip=170.10.133.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="HxChIL01"; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b="CNOoPzdw" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1773420250; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=VnD7BXzXySXk+jlzLn21Mtw8nvr+Gs1Ehlor65FMWLw=; b=HxChIL01ot+0W82URRX2sjEbBZsIESc/6elX456VNt/I6cJY+PmBmwJL/9r2aXkC2TgkTH o7Odqfc3ZKnOnJqf8wXg75Ev5Vr91vnTy9KzQHcVcLWm4ghydr2xIFIQoqcyb8GgqP1QRP fJel4A8Kro5KZzk+Bqoh4YnlvMrIgCM= Received: from mail-qk1-f199.google.com (mail-qk1-f199.google.com [209.85.222.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-48-G6Eds89SNdK7HVs-tGU7zA-1; Fri, 13 Mar 2026 12:44:06 -0400 X-MC-Unique: G6Eds89SNdK7HVs-tGU7zA-1 X-Mimecast-MFC-AGG-ID: G6Eds89SNdK7HVs-tGU7zA_1773420246 Received: by mail-qk1-f199.google.com with SMTP id af79cd13be357-8cd77e5e187so1315793385a.1 for ; Fri, 13 Mar 2026 09:44:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1773420246; x=1774025046; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=VnD7BXzXySXk+jlzLn21Mtw8nvr+Gs1Ehlor65FMWLw=; b=CNOoPzdwBFSKrfwbewNB1OXdAodFiLjO0BMa6wt8J6UNxLnje2D6B0HXuiOrZ76hNJ eZeIqoY+psU3rQckuyQE9KxtNRXxZzHL53W6kuS9lTMMA/q/5h2L9WEmYXsAkXgp5TEn 9yTffPQxXBF5/t8UjzVpE2VHCcl3pS4tnlXBfIq+lZSGXNuyfvU0qu8+em1U61xivg+g g+xs8Npg5yFyvWbU/dMG9wxojQzTXq6Nsh4zsQF8akmoECMMYPBQ11hKQf3CmTrQPQ7A lBshkx1iFMCRN6YGoSzSnV4d1GB+bOiM3DUMC9Hd9MJ2Y6C3SOiNx3K28O3BqyFAZuR0 zC3g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773420246; x=1774025046; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=VnD7BXzXySXk+jlzLn21Mtw8nvr+Gs1Ehlor65FMWLw=; b=plFegEeahEqz6K27+iqwjOf8R12hrUnlKgjdFOf64oA/MrN+PCFOnG1jLnA4S0y5Z3 LMEZkBzqwfrDPKiDp5blmhWvYfLhdMtLT1bsZe998i9MgpW+Pe2xSLYhNRDuGNUBKTND vF9OZekt3eOpDuWoUb+07DT578qcnRP+iE2pzswUoUB6Wp1JcuI/tOX7Fx4Ku0zdAqQV clHLjgCh1dwx6Lf7R2/2Llabz4qhDmfHTc6dGm+6LLi0t84FWpgaUB+DC3JKpDcGrlLp FmAMn2oyn744ycM+2sjTmG77wQsd/t//Wq98Wwvf6iSeFoiz6l7bPI2aNfWQUjJOjYL+ m1QA== X-Forwarded-Encrypted: i=1; AJvYcCWxol2qgITTYh6YdF0BWv02ka/ME1bfYUZPyYKo7+DhBZeIV353rIWhF5i2P9lJq29KZCzsb0su1tNecxw=@vger.kernel.org X-Gm-Message-State: AOJu0YwcU1HgKQUCa/b//iH8EgwFtQhGZYnITl4WHia7VLPkPfIc66zM d9nv1oXyHhZUTc+iZjtbbwOyDcnO8vrx2HG0JXyFcmMMd8FUX0+WzAKn/xEeqAOmF+4C3onP69+ zmIZuztv+Ngigko6Fyce3dzHJWC1ZOofVjynRXCU80jeoAlt8GIE7aCwgkB+MiURyFw== X-Gm-Gg: ATEYQzwAGxvZhYiNNQzXre+uZYBLd9N43s3zEiZ8WC3nPs3qq9u46mttl//gGuLxRKL AMbTxnLPnMIz3gEq1evpOAGXXicc7W1qP8RdCZzYjXyy1VOUfNy7OxHPYbzRCxxN3J4CgchZDqM sY3cGtLmWPX4BOv8NW68z5fDwNQ7sHsa7t9BqMbEZGoPzNzAEop90ul1l9gyWO4/zXammqiQeeb +phO0DtGf1z/Ne/FP8fYkf0SVsRIYfxA1AfDIGQUg0MAqPmER8eOpkPBXA2V2vNdiCk/GPz7ixT E4gTFz6cCO1KC79yPIKXHAP9mLOykQM8Yc8tHHJ1nCwWOMTHKrzKNdqxYHp2KMEiuFJ1lgKVwKG 7Fe1kTdRepit9KV/wplA71R5hXXJkc5kEWBGfUc0h2MENWYZbmbBJ2Jw2EMXU X-Received: by 2002:a05:620a:4044:b0:8cd:9020:f043 with SMTP id af79cd13be357-8cdb5a1c711mr554598185a.7.1773420246115; Fri, 13 Mar 2026 09:44:06 -0700 (PDT) X-Received: by 2002:a05:620a:4044:b0:8cd:9020:f043 with SMTP id af79cd13be357-8cdb5a1c711mr554592685a.7.1773420245521; Fri, 13 Mar 2026 09:44:05 -0700 (PDT) Received: from [192.168.1.3] (c-73-183-52-120.hsd1.pa.comcast.net. [73.183.52.120]) by smtp.gmail.com with ESMTPSA id af79cd13be357-8cda215c2a9sm587964785a.46.2026.03.13.09.44.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Mar 2026 09:44:04 -0700 (PDT) From: Brian Masney Date: Fri, 13 Mar 2026 12:43:09 -0400 Subject: [PATCH v6 2/7] clk: test: introduce test suite for sibling rate changes on a divider Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260313-clk-scaling-v6-2-ce89968c5247@redhat.com> References: <20260313-clk-scaling-v6-0-ce89968c5247@redhat.com> In-Reply-To: <20260313-clk-scaling-v6-0-ce89968c5247@redhat.com> To: Michael Turquette , Stephen Boyd , Maxime Ripard , Alberto Ruiz Cc: linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, Brian Masney X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=7367; i=bmasney@redhat.com; s=20250903; h=from:subject:message-id; bh=6RjRp0BMKBvqwmUs2I0l3tLNfJ+lEfqmjaaBafYyByA=; b=owGbwMvMwCW2/dJd9di6A+2Mp9WSGDK32J2w9Ll7frtT36aff1+Wsd1uOno6Zc/1ySHlv67P+ LDq3aaMeR2lLAxiXAyyYoosS3KNCiJSV9neu6PJAjOHlQlkCAMXpwBMRCqWkeHHyau/P3revy16 i7WUV7SH3Y3j0r/lC6qXf0uxObFVm7GF4X/Gq3kSnJuzrS+dyAw40t4cZK/1kXelx71mS4UTy+/ 2ZPEDAA== X-Developer-Key: i=bmasney@redhat.com; a=openpgp; fpr=A46D32705865AA3DDEDC2904B7D2DD275D7EC087 Introduce a kunit test suite that demonstrates the current behavior of how a clock can unknowingly change the rate of it's siblings. Some boards are unknowingly dependent on this behavior, and per discussions at the 2025 Linux Plumbers Conference in Tokyo, we can't break the existing behavior. So let's add kunit tests with the current behavior so that we can be made aware if that functionality changes in the future. The tests in this commit use the following simplified clk tree with the initial state: parent 24 MHz / \ child1 child2 24 MHz 24 MHz child1 and child2 both divider-only clocks that have CLK_SET_RATE_PARENT set, and the parent is capable of achieving any rate. Link: https://lore.kernel.org/linux-clk/aUSWU7UymULCXOeF@redhat.com/ Link: https://lpc.events/event/19/contributions/2152/ Signed-off-by: Brian Masney --- drivers/clk/clk_test.c | 146 +++++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 146 insertions(+) diff --git a/drivers/clk/clk_test.c b/drivers/clk/clk_test.c index 88e35f4419c958983578750356a97c0a45effb55..325da7c84ab2ecdcf6b7a023ce4= c2c4ef2d49862 100644 --- a/drivers/clk/clk_test.c +++ b/drivers/clk/clk_test.c @@ -7,6 +7,7 @@ #include #include #include +#include =20 /* Needed for clk_hw_get_clk() */ #include "clk.h" @@ -652,6 +653,150 @@ clk_multiple_parents_mux_test_suite =3D { .test_cases =3D clk_multiple_parents_mux_test_cases, }; =20 +struct clk_rate_change_sibling_div_div_context { + struct clk_dummy_context parent; + struct clk_dummy_div child1, child2; + struct clk *parent_clk, *child1_clk, *child2_clk; +}; + +struct clk_rate_change_sibling_div_div_test_param { + const char *desc; + const struct clk_ops *ops; + unsigned int extra_child_flags; +}; + +static const struct clk_rate_change_sibling_div_div_test_param +clk_rate_change_sibling_div_div_test_regular_ops_params[] =3D { + { + .desc =3D "regular_ops", + .ops =3D &clk_dummy_div_ops, + .extra_child_flags =3D 0, + }, +}; + +KUNIT_ARRAY_PARAM_DESC(clk_rate_change_sibling_div_div_test_regular_ops, + clk_rate_change_sibling_div_div_test_regular_ops_params, desc) + +static int clk_rate_change_sibling_div_div_test_init(struct kunit *test) +{ + const struct clk_rate_change_sibling_div_div_test_param *param =3D test->= param_value; + struct clk_rate_change_sibling_div_div_context *ctx; + int ret; + + ctx =3D kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + test->priv =3D ctx; + + ctx->parent.hw.init =3D CLK_HW_INIT_NO_PARENT("parent", &clk_dummy_rate_o= ps, 0); + ctx->parent.rate =3D 24 * HZ_PER_MHZ; + ret =3D clk_hw_register_kunit(test, NULL, &ctx->parent.hw); + if (ret) + return ret; + + ctx->child1.hw.init =3D CLK_HW_INIT_HW("child1", &ctx->parent.hw, + param->ops, + CLK_SET_RATE_PARENT | param->extra_child_flags); + ctx->child1.div =3D 1; + ret =3D clk_hw_register_kunit(test, NULL, &ctx->child1.hw); + if (ret) + return ret; + + ctx->child2.hw.init =3D CLK_HW_INIT_HW("child2", &ctx->parent.hw, + param->ops, + CLK_SET_RATE_PARENT | param->extra_child_flags); + ctx->child2.div =3D 1; + ret =3D clk_hw_register_kunit(test, NULL, &ctx->child2.hw); + if (ret) + return ret; + + ctx->parent_clk =3D clk_hw_get_clk(&ctx->parent.hw, NULL); + ctx->child1_clk =3D clk_hw_get_clk(&ctx->child1.hw, NULL); + ctx->child2_clk =3D clk_hw_get_clk(&ctx->child2.hw, NULL); + + KUNIT_EXPECT_EQ(test, clk_get_rate(ctx->parent_clk), 24 * HZ_PER_MHZ); + KUNIT_EXPECT_EQ(test, clk_get_rate(ctx->child1_clk), 24 * HZ_PER_MHZ); + KUNIT_EXPECT_EQ(test, clk_get_rate(ctx->child2_clk), 24 * HZ_PER_MHZ); + + return 0; +} + +static void clk_rate_change_sibling_div_div_test_exit(struct kunit *test) +{ + struct clk_rate_change_sibling_div_div_context *ctx =3D test->priv; + + clk_put(ctx->parent_clk); + clk_put(ctx->child1_clk); + clk_put(ctx->child2_clk); +} + +/* + * Test that, for a parent with two divider-only children with CLK_SET_RAT= E_PARENT set + * and one requests a rate compatible with the existing parent rate, the p= arent and + * sibling rates are not affected. + */ +static void clk_test_rate_change_sibling_div_div_1(struct kunit *test) +{ + struct clk_rate_change_sibling_div_div_context *ctx =3D test->priv; + int ret; + + ret =3D clk_set_rate(ctx->child1_clk, 6 * HZ_PER_MHZ); + KUNIT_ASSERT_EQ(test, ret, 0); + + KUNIT_EXPECT_EQ(test, clk_get_rate(ctx->parent_clk), 24 * HZ_PER_MHZ); + KUNIT_EXPECT_EQ(test, clk_get_rate(ctx->child1_clk), 6 * HZ_PER_MHZ); + KUNIT_EXPECT_EQ(test, ctx->child1.div, 4); + KUNIT_EXPECT_EQ(test, clk_get_rate(ctx->child2_clk), 24 * HZ_PER_MHZ); + KUNIT_EXPECT_EQ(test, ctx->child2.div, 1); +} + +/* + * Test that, for a parent with two divider-only children with CLK_SET_RAT= E_PARENT + * set and one requests a rate incompatible with the existing parent rate,= the + * sibling rate is also affected. This preserves existing behavior in the = clk + * core that some drivers may be unknowingly dependent on. + */ +static void clk_test_rate_change_sibling_div_div_2_v1(struct kunit *test) +{ + struct clk_rate_change_sibling_div_div_context *ctx =3D test->priv; + int ret; + + ret =3D clk_set_rate(ctx->child1_clk, 32 * HZ_PER_MHZ); + KUNIT_ASSERT_EQ(test, ret, 0); + + /* + * The last sibling rate change is the one that was successful, and + * wins. The parent, and two children are all changed to 32 MHz. This + * keeps the long-standing behavior of the clk core that some drivers + * may be unknowingly dependent on. + */ + KUNIT_EXPECT_EQ(test, clk_get_rate(ctx->parent_clk), 32 * HZ_PER_MHZ); + KUNIT_EXPECT_EQ(test, clk_get_rate(ctx->child1_clk), 32 * HZ_PER_MHZ); + KUNIT_EXPECT_EQ(test, ctx->child1.div, 1); + KUNIT_EXPECT_EQ(test, clk_get_rate(ctx->child2_clk), 32 * HZ_PER_MHZ); + KUNIT_EXPECT_EQ(test, ctx->child2.div, 1); +} + +static struct kunit_case clk_rate_change_sibling_div_div_cases[] =3D { + KUNIT_CASE_PARAM(clk_test_rate_change_sibling_div_div_1, + clk_rate_change_sibling_div_div_test_regular_ops_gen_params), + KUNIT_CASE_PARAM(clk_test_rate_change_sibling_div_div_2_v1, + clk_rate_change_sibling_div_div_test_regular_ops_gen_params), + {} +}; + +/* + * Test suite that creates a parent with two divider-only children, and + * documents the behavior of what happens to the sibling clock when one ch= ild + * changes its rate. + */ +static struct kunit_suite clk_rate_change_sibling_div_div_test_suite =3D { + .name =3D "clk-rate-change-sibling-div-div", + .init =3D clk_rate_change_sibling_div_div_test_init, + .exit =3D clk_rate_change_sibling_div_div_test_exit, + .test_cases =3D clk_rate_change_sibling_div_div_cases, +}; + static int clk_orphan_transparent_multiple_parent_mux_test_init(struct kunit *test) { @@ -3592,6 +3737,7 @@ kunit_test_suites( &clk_leaf_mux_set_rate_parent_test_suite, &clk_test_suite, &clk_multiple_parents_mux_test_suite, + &clk_rate_change_sibling_div_div_test_suite, &clk_mux_no_reparent_test_suite, &clk_mux_notifier_test_suite, &clk_orphan_transparent_multiple_parent_mux_test_suite, --=20 2.53.0