From patchwork Fri Jun 2 15:20:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 102616 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp1116272vqr; Fri, 2 Jun 2023 08:36:37 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4L3ML4SFa5j834yBwfNKXa2v+jznWC//CzT3V2biV0Zh2Q9YJc2s1fNvIE2DVAcc4ITt6z X-Received: by 2002:a05:6a20:ce4f:b0:10e:de4f:3437 with SMTP id id15-20020a056a20ce4f00b0010ede4f3437mr12050724pzb.39.1685720197550; Fri, 02 Jun 2023 08:36:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685720197; cv=none; d=google.com; s=arc-20160816; b=XjD0iu96aNwocLAUEPn7znSVijYdarVb2YxPDHn2M9ToUl/lTOQK0RssM0HCrG0v1I B9eJCFJcVjZkGcmvMvec7PrbBhpzi3UNZ3DUuBIO66wI/KPDoWj8KyIzSZFyp3C/cFLT r8F2pxpqimgL0NducyeJAAZg1DsXN5dz4G1wKTw5vvok90BkIcMxmSYVI8OyMpz4i6iW 1W0iwpCbHz7KhIFPyB6N2Zx/s7ubuOHBh47vS99zrAlQYdfEYV2l/VGWhYXA7VwZs9Gw snZIdwaiz3rPC56277yyvoAOpXBnY3ojCkoJiFTwuumaWW8ci6UFEJASFT2KU4a+G0d5 BFHA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=1+0wvEkmuRaS6dM8BCLiHfZ2bWZbzRYUsxvKoS6Y9OU=; b=XRFYYBD7sswkU730Tcr4OkEaRqxJyewC2eEbMdQyxJFwFZV06HzrUjbZuGi8o0O/Xq CN/EI99JneZlDV2nnKz6i0xorCbk27R1GS8HUBo4pQBmIw4dKyhjbVFmSnQHVCL6JG5s m+j5xJTAEpndSJgzWs9PmbvQuZ0zWS/zInpQPpHmFekseCopw+eMJIE3Dv7JgrR87lDD W0AmNFGbn26jiPzfguqxxx3qXgajnMO5NMIia5L0q7MqDyu8I3H8CIC9SbSHlyvBHoid DWtcNlbE3Xif+0pfuGPXK/nogS8AwtmieidhfVci1HdTuT2THB/f8aTI7JENPWbJCDkR kF6g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=CezCuPSP; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id s19-20020a639253000000b0053b64127cddsi1131936pgn.212.2023.06.02.08.36.25; Fri, 02 Jun 2023 08:36:37 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=CezCuPSP; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236581AbjFBPVD (ORCPT + 99 others); Fri, 2 Jun 2023 11:21:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38608 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236560AbjFBPU6 (ORCPT ); Fri, 2 Jun 2023 11:20:58 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6343C1B7; Fri, 2 Jun 2023 08:20:56 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id C89D6635D3; Fri, 2 Jun 2023 15:20:55 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D4EF7C433D2; Fri, 2 Jun 2023 15:20:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685719255; bh=4NRmaXZV297pCf/rzgJTExz6ocam8P1xhVXw4bHqhwg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=CezCuPSP1yDJ7fqWIjHJEy2EY8N1mLl2hdhNeXNTmTDrBKVoFB77r5WU1ZKkyglbw XykNoFSLRHFAu62ySD2DSe2B0/ybHRQiKmTjyg8akhr8OSrb2Exyxa/17Zhw293Ong 6oA0bZDFkGEaIiyWqEpYCSaxKO/ws6vIKuQ2141KnF5qtt0m+USJDCAL7OQVoF4vga vzWYPsdXpH9rgi4Ae7QptezyWdXCIBAp4xkb7aQuoWSW7BqjanD08gnr1xBM/x6gUX 3FZHKm38GR5SEuwITddtN9pvpjAlU4WBNUErVGiyuT4CVQQ1Mrm1IL6In2MMhOwqXl osFmaqaNkh0aA== From: Maxime Ripard Date: Fri, 02 Jun 2023 17:20:44 +0200 Subject: [PATCH RESEND 2/2] drivers: base: Add basic devm tests for platform devices MIME-Version: 1.0 Message-Id: <20230329-kunit-devm-inconsistencies-test-v1-2-015b1574d673@kernel.org> References: <20230329-kunit-devm-inconsistencies-test-v1-0-015b1574d673@kernel.org> In-Reply-To: <20230329-kunit-devm-inconsistencies-test-v1-0-015b1574d673@kernel.org> To: Greg Kroah-Hartman , "Rafael J. Wysocki" Cc: Brendan Higgins , David Gow , linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-kernel@vger.kernel.org, Maxime Ripard X-Mailer: b4 0.13-dev-02a79 X-Developer-Signature: v=1; a=openpgp-sha256; l=9290; i=mripard@kernel.org; h=from:subject:message-id; bh=+upD3Qwmbf0hj4qFxXxO0So+EHopJEk8H+Mz64g5xMs=; b=owGbwMvMwCX2+D1vfrpE4FHG02pJDClVHOemsz3e+juBZXYFW6iFbXwQz51YtXPs6p1aSir+7wVf 9md3lLIwiHExyIopssQImy+JOzXrdScb3zyYOaxMIEMYuDgFYCKyAYwMx9sPMRz7yDhRqTjzi9Mv44 WcZ4XX/P3/hGdh06uF70r3qTIy9CbVn75aF6Q+p+DM8X278pX1brY+uHK08sF5l8SZ+slpbAA= X-Developer-Key: i=mripard@kernel.org; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D X-Spam-Status: No, score=-4.6 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1767605741847986175?= X-GMAIL-MSGID: =?utf-8?q?1767605741847986175?= From: Maxime Ripard Platform devices show some inconsistencies with how devm resources are released when the device has been probed and when it hasn't. Let's add a few tests to exercise thos paths and odd cases. Signed-off-by: Maxime Ripard --- drivers/base/test/Makefile | 1 + drivers/base/test/platform-device-test.c | 278 +++++++++++++++++++++++++++++++ 2 files changed, 279 insertions(+) diff --git a/drivers/base/test/Makefile b/drivers/base/test/Makefile index d589ca3fa8fc..e321dfc7e922 100644 --- a/drivers/base/test/Makefile +++ b/drivers/base/test/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_TEST_ASYNC_DRIVER_PROBE) += test_async_driver_probe.o obj-$(CONFIG_DM_KUNIT_TEST) += root-device-test.o +obj-$(CONFIG_DM_KUNIT_TEST) += platform-device-test.o obj-$(CONFIG_DRIVER_PE_KUNIT_TEST) += property-entry-test.o CFLAGS_property-entry-test.o += $(DISABLE_STRUCTLEAK_PLUGIN) diff --git a/drivers/base/test/platform-device-test.c b/drivers/base/test/platform-device-test.c new file mode 100644 index 000000000000..2779c6dfac06 --- /dev/null +++ b/drivers/base/test/platform-device-test.c @@ -0,0 +1,278 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +#include +#include + +#define DEVICE_NAME "test" + +struct test_priv { + bool probe_done; + bool release_done; + wait_queue_head_t release_wq; + struct device *dev; +}; + +static void devm_device_action(void *ptr) +{ + struct test_priv *priv = ptr; + + priv->release_done = true; + wake_up_interruptible(&priv->release_wq); +} + +static void devm_put_device_action(void *ptr) +{ + struct test_priv *priv = ptr; + + put_device(priv->dev); + priv->release_done = true; + wake_up_interruptible(&priv->release_wq); +} + +#define RELEASE_TIMEOUT_MS 500 + +static void platform_device_devm_register_unregister_test(struct kunit *test) +{ + struct platform_device *pdev; + struct test_priv *priv; + int ret; + + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); + init_waitqueue_head(&priv->release_wq); + + pdev = platform_device_alloc(DEVICE_NAME, PLATFORM_DEVID_NONE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); + + ret = platform_device_add(pdev); + KUNIT_ASSERT_EQ(test, ret, 0); + + priv->dev = &pdev->dev; + + ret = devm_add_action_or_reset(priv->dev, devm_device_action, priv); + KUNIT_ASSERT_EQ(test, ret, 0); + + platform_device_unregister(pdev); + + ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done, + msecs_to_jiffies(RELEASE_TIMEOUT_MS)); + KUNIT_EXPECT_GT(test, ret, 0); +} + +static void platform_device_devm_register_get_put_unregister_test(struct kunit *test) +{ + struct platform_device *pdev; + struct test_priv *priv; + int ret; + + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); + init_waitqueue_head(&priv->release_wq); + + pdev = platform_device_alloc(DEVICE_NAME, PLATFORM_DEVID_NONE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); + + ret = platform_device_add(pdev); + KUNIT_ASSERT_EQ(test, ret, 0); + + priv->dev = &pdev->dev; + + get_device(priv->dev); + + ret = devm_add_action_or_reset(priv->dev, devm_device_action, priv); + KUNIT_ASSERT_EQ(test, ret, 0); + + put_device(priv->dev); + + platform_device_unregister(pdev); + + ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done, + msecs_to_jiffies(RELEASE_TIMEOUT_MS)); + KUNIT_EXPECT_GT(test, ret, 0); +} + +static void platform_device_devm_register_get_unregister_with_devm_test(struct kunit *test) +{ + struct platform_device *pdev; + struct test_priv *priv; + int ret; + + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); + init_waitqueue_head(&priv->release_wq); + + pdev = platform_device_alloc(DEVICE_NAME, PLATFORM_DEVID_NONE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); + + ret = platform_device_add(pdev); + KUNIT_ASSERT_EQ(test, ret, 0); + + priv->dev = &pdev->dev; + + get_device(priv->dev); + + ret = devm_add_action_or_reset(priv->dev, devm_put_device_action, priv); + KUNIT_ASSERT_EQ(test, ret, 0); + + platform_device_unregister(pdev); + + ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done, + msecs_to_jiffies(RELEASE_TIMEOUT_MS)); + KUNIT_EXPECT_GT(test, ret, 0); +} + +static int fake_probe(struct platform_device *pdev) +{ + struct test_priv *priv = platform_get_drvdata(pdev); + + priv->probe_done = true; + wake_up_interruptible(&priv->release_wq); + + return 0; +} + +static struct platform_driver fake_driver = { + .probe = fake_probe, + .driver = { + .name = DEVICE_NAME, + }, +}; + +static void probed_platform_device_devm_register_unregister_test(struct kunit *test) +{ + struct platform_device *pdev; + struct test_priv *priv; + int ret; + + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); + init_waitqueue_head(&priv->release_wq); + + ret = platform_driver_register(&fake_driver); + KUNIT_ASSERT_EQ(test, ret, 0); + + pdev = platform_device_alloc(DEVICE_NAME, PLATFORM_DEVID_NONE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); + + priv->dev = &pdev->dev; + platform_set_drvdata(pdev, priv); + + ret = platform_device_add(pdev); + KUNIT_ASSERT_EQ(test, ret, 0); + + ret = wait_event_interruptible_timeout(priv->release_wq, priv->probe_done, + msecs_to_jiffies(RELEASE_TIMEOUT_MS)); + KUNIT_ASSERT_GT(test, ret, 0); + + ret = devm_add_action_or_reset(priv->dev, devm_device_action, priv); + KUNIT_ASSERT_EQ(test, ret, 0); + + platform_device_unregister(pdev); + + ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done, + msecs_to_jiffies(RELEASE_TIMEOUT_MS)); + KUNIT_EXPECT_GT(test, ret, 0); + + platform_driver_unregister(&fake_driver); +} + +static void probed_platform_device_devm_register_get_put_unregister_test(struct kunit *test) +{ + struct platform_device *pdev; + struct test_priv *priv; + int ret; + + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); + init_waitqueue_head(&priv->release_wq); + + ret = platform_driver_register(&fake_driver); + KUNIT_ASSERT_EQ(test, ret, 0); + + pdev = platform_device_alloc(DEVICE_NAME, PLATFORM_DEVID_NONE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); + + priv->dev = &pdev->dev; + platform_set_drvdata(pdev, priv); + + ret = platform_device_add(pdev); + KUNIT_ASSERT_EQ(test, ret, 0); + + ret = wait_event_interruptible_timeout(priv->release_wq, priv->probe_done, + msecs_to_jiffies(RELEASE_TIMEOUT_MS)); + KUNIT_ASSERT_GT(test, ret, 0); + + get_device(priv->dev); + + ret = devm_add_action_or_reset(priv->dev, devm_device_action, priv); + KUNIT_ASSERT_EQ(test, ret, 0); + + put_device(priv->dev); + + platform_device_unregister(pdev); + + ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done, + msecs_to_jiffies(RELEASE_TIMEOUT_MS)); + KUNIT_EXPECT_GT(test, ret, 0); + + platform_driver_unregister(&fake_driver); +} + +static void probed_platform_device_devm_register_get_unregister_with_devm_test(struct kunit *test) +{ + struct platform_device *pdev; + struct test_priv *priv; + int ret; + + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); + init_waitqueue_head(&priv->release_wq); + + ret = platform_driver_register(&fake_driver); + KUNIT_ASSERT_EQ(test, ret, 0); + + pdev = platform_device_alloc(DEVICE_NAME, PLATFORM_DEVID_NONE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); + + priv->dev = &pdev->dev; + platform_set_drvdata(pdev, priv); + + ret = platform_device_add(pdev); + KUNIT_ASSERT_EQ(test, ret, 0); + + ret = wait_event_interruptible_timeout(priv->release_wq, priv->probe_done, + msecs_to_jiffies(RELEASE_TIMEOUT_MS)); + KUNIT_ASSERT_GT(test, ret, 0); + + get_device(priv->dev); + + ret = devm_add_action_or_reset(priv->dev, devm_put_device_action, priv); + KUNIT_ASSERT_EQ(test, ret, 0); + + platform_device_unregister(pdev); + + ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done, + msecs_to_jiffies(RELEASE_TIMEOUT_MS)); + KUNIT_EXPECT_GT(test, ret, 0); + + platform_driver_unregister(&fake_driver); +} + +static struct kunit_case platform_device_devm_tests[] = { + KUNIT_CASE(platform_device_devm_register_unregister_test), + KUNIT_CASE(platform_device_devm_register_get_put_unregister_test), + KUNIT_CASE(platform_device_devm_register_get_unregister_with_devm_test), + KUNIT_CASE(probed_platform_device_devm_register_unregister_test), + KUNIT_CASE(probed_platform_device_devm_register_get_put_unregister_test), + KUNIT_CASE(probed_platform_device_devm_register_get_unregister_with_devm_test), + {} +}; + +static struct kunit_suite platform_device_devm_test_suite = { + .name = "platform-device-devm", + .test_cases = platform_device_devm_tests, +}; + +kunit_test_suite(platform_device_devm_test_suite);