From dbcbd3650f305df708b569517c063c7644cf0d89 Mon Sep 17 00:00:00 2001 From: Marco Pagani Date: Thu, 25 Jul 2024 14:50:29 +0200 Subject: [PATCH 1/5] fpga: Simplify and improve fpga mgr test using deferred actions Use deferred actions to simplify the test suite and avoid potential memory leaks when test cases fail. Remove unnecessary calls to kunit_device_unregister() since kunit devices are tied to the test context and released by a deferred action when the test is completed. Signed-off-by: Marco Pagani Acked-by: Xu Yilun Link: https://lore.kernel.org/r/20240725125031.308195-2-marpagan@redhat.com Signed-off-by: Xu Yilun --- drivers/fpga/tests/fpga-mgr-test.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/fpga/tests/fpga-mgr-test.c b/drivers/fpga/tests/fpga-mgr-test.c index 125b3a4d43c6..9cb37aefbac4 100644 --- a/drivers/fpga/tests/fpga-mgr-test.c +++ b/drivers/fpga/tests/fpga-mgr-test.c @@ -44,6 +44,16 @@ struct mgr_ctx { struct mgr_stats stats; }; +/* + * Wrappers to avoid cast warnings when passing action functions directly + * to kunit_add_action(). + */ +KUNIT_DEFINE_ACTION_WRAPPER(sg_free_table_wrapper, sg_free_table, + struct sg_table *); + +KUNIT_DEFINE_ACTION_WRAPPER(fpga_image_info_free_wrapper, fpga_image_info_free, + struct fpga_image_info *); + /** * init_test_buffer() - Allocate and initialize a test image in a buffer. * @test: KUnit test context object. @@ -257,6 +267,9 @@ static void fpga_mgr_test_img_load_sgt(struct kunit *test) KUNIT_ASSERT_EQ(test, ret, 0); sg_init_one(sgt->sgl, img_buf, IMAGE_SIZE); + ret = kunit_add_action_or_reset(test, sg_free_table_wrapper, sgt); + KUNIT_ASSERT_EQ(test, ret, 0); + ctx->img_info->sgt = sgt; ret = fpga_mgr_load(ctx->mgr, ctx->img_info); @@ -273,13 +286,12 @@ static void fpga_mgr_test_img_load_sgt(struct kunit *test) KUNIT_EXPECT_EQ(test, ctx->stats.op_write_init_seq, ctx->stats.op_parse_header_seq + 1); KUNIT_EXPECT_EQ(test, ctx->stats.op_write_sg_seq, ctx->stats.op_parse_header_seq + 2); KUNIT_EXPECT_EQ(test, ctx->stats.op_write_complete_seq, ctx->stats.op_parse_header_seq + 3); - - sg_free_table(ctx->img_info->sgt); } static int fpga_mgr_test_init(struct kunit *test) { struct mgr_ctx *ctx; + int ret; ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); @@ -294,19 +306,14 @@ static int fpga_mgr_test_init(struct kunit *test) ctx->img_info = fpga_image_info_alloc(ctx->dev); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->img_info); + ret = kunit_add_action_or_reset(test, fpga_image_info_free_wrapper, ctx->img_info); + KUNIT_ASSERT_EQ(test, ret, 0); + test->priv = ctx; return 0; } -static void fpga_mgr_test_exit(struct kunit *test) -{ - struct mgr_ctx *ctx = test->priv; - - fpga_image_info_free(ctx->img_info); - kunit_device_unregister(test, ctx->dev); -} - static struct kunit_case fpga_mgr_test_cases[] = { KUNIT_CASE(fpga_mgr_test_get), KUNIT_CASE(fpga_mgr_test_lock), @@ -318,7 +325,6 @@ static struct kunit_case fpga_mgr_test_cases[] = { static struct kunit_suite fpga_mgr_suite = { .name = "fpga_mgr", .init = fpga_mgr_test_init, - .exit = fpga_mgr_test_exit, .test_cases = fpga_mgr_test_cases, }; From 3c2c01849c01e7e3c99124a7fb7f238b7c9a2348 Mon Sep 17 00:00:00 2001 From: Marco Pagani Date: Thu, 25 Jul 2024 14:50:30 +0200 Subject: [PATCH 2/5] fpga: Simplify and improve fpga bridge test using deferred actions Use deferred actions to simplify the test suite and avoid potential memory leaks when test cases fail. Remove unnecessary calls to kunit_device_unregister() since kunit devices are tied to the test context and released by a deferred action when the test is completed. Signed-off-by: Marco Pagani Acked-by: Xu Yilun Link: https://lore.kernel.org/r/20240725125031.308195-3-marpagan@redhat.com Signed-off-by: Xu Yilun --- drivers/fpga/tests/fpga-bridge-test.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/fpga/tests/fpga-bridge-test.c b/drivers/fpga/tests/fpga-bridge-test.c index 2f7a24f23808..b9ab29809e96 100644 --- a/drivers/fpga/tests/fpga-bridge-test.c +++ b/drivers/fpga/tests/fpga-bridge-test.c @@ -23,6 +23,13 @@ struct bridge_ctx { struct bridge_stats stats; }; +/* + * Wrapper to avoid a cast warning when passing the action function directly + * to kunit_add_action(). + */ +KUNIT_DEFINE_ACTION_WRAPPER(fpga_bridge_unregister_wrapper, fpga_bridge_unregister, + struct fpga_bridge *); + static int op_enable_set(struct fpga_bridge *bridge, bool enable) { struct bridge_stats *stats = bridge->priv; @@ -50,6 +57,7 @@ static const struct fpga_bridge_ops fake_bridge_ops = { static struct bridge_ctx *register_test_bridge(struct kunit *test, const char *dev_name) { struct bridge_ctx *ctx; + int ret; ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); @@ -61,13 +69,10 @@ static struct bridge_ctx *register_test_bridge(struct kunit *test, const char *d &ctx->stats); KUNIT_ASSERT_FALSE(test, IS_ERR_OR_NULL(ctx->bridge)); - return ctx; -} + ret = kunit_add_action_or_reset(test, fpga_bridge_unregister_wrapper, ctx->bridge); + KUNIT_ASSERT_EQ(test, ret, 0); -static void unregister_test_bridge(struct kunit *test, struct bridge_ctx *ctx) -{ - fpga_bridge_unregister(ctx->bridge); - kunit_device_unregister(test, ctx->dev); + return ctx; } static void fpga_bridge_test_get(struct kunit *test) @@ -141,8 +146,6 @@ static void fpga_bridge_test_get_put_list(struct kunit *test) fpga_bridges_put(&bridge_list); KUNIT_EXPECT_TRUE(test, list_empty(&bridge_list)); - - unregister_test_bridge(test, ctx_1); } static int fpga_bridge_test_init(struct kunit *test) @@ -152,11 +155,6 @@ static int fpga_bridge_test_init(struct kunit *test) return 0; } -static void fpga_bridge_test_exit(struct kunit *test) -{ - unregister_test_bridge(test, test->priv); -} - static struct kunit_case fpga_bridge_test_cases[] = { KUNIT_CASE(fpga_bridge_test_get), KUNIT_CASE(fpga_bridge_test_toggle), @@ -167,7 +165,6 @@ static struct kunit_case fpga_bridge_test_cases[] = { static struct kunit_suite fpga_bridge_suite = { .name = "fpga_bridge", .init = fpga_bridge_test_init, - .exit = fpga_bridge_test_exit, .test_cases = fpga_bridge_test_cases, }; From d783ed2f5fe7850fb7f6296ae267e2efcf877319 Mon Sep 17 00:00:00 2001 From: Marco Pagani Date: Thu, 25 Jul 2024 14:50:31 +0200 Subject: [PATCH 3/5] fpga: Simplify and improve fpga region test using deferred actions Use deferred actions to simplify the test suite and avoid potential memory leaks when test cases fail. Remove unnecessary calls to kunit_device_unregister() since kunit devices are tied to the test context and released by a deferred action when the test is completed. Other changes: fix a typo by changing the test suite name to fpga_region in the kunit_suite struct. Signed-off-by: Marco Pagani Acked-by: Xu Yilun Link: https://lore.kernel.org/r/20240725125031.308195-4-marpagan@redhat.com Signed-off-by: Xu Yilun --- drivers/fpga/tests/fpga-region-test.c | 41 ++++++++++++++++----------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/drivers/fpga/tests/fpga-region-test.c b/drivers/fpga/tests/fpga-region-test.c index bcf0651df261..6a108cafded8 100644 --- a/drivers/fpga/tests/fpga-region-test.c +++ b/drivers/fpga/tests/fpga-region-test.c @@ -35,6 +35,19 @@ struct test_ctx { struct mgr_stats mgr_stats; }; +/* + * Wrappers to avoid cast warnings when passing action functions directly + * to kunit_add_action(). + */ +KUNIT_DEFINE_ACTION_WRAPPER(fpga_image_info_free_wrapper, fpga_image_info_free, + struct fpga_image_info *); + +KUNIT_DEFINE_ACTION_WRAPPER(fpga_bridge_unregister_wrapper, fpga_bridge_unregister, + struct fpga_bridge *); + +KUNIT_DEFINE_ACTION_WRAPPER(fpga_region_unregister_wrapper, fpga_region_unregister, + struct fpga_region *); + static int op_write(struct fpga_manager *mgr, const char *buf, size_t count) { struct mgr_stats *stats = mgr->priv; @@ -111,6 +124,9 @@ static void fpga_region_test_program_fpga(struct kunit *test) img_info = fpga_image_info_alloc(ctx->mgr_dev); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, img_info); + ret = kunit_add_action_or_reset(test, fpga_image_info_free_wrapper, img_info); + KUNIT_ASSERT_EQ(test, ret, 0); + img_info->buf = img_buf; img_info->count = sizeof(img_buf); @@ -130,8 +146,6 @@ static void fpga_region_test_program_fpga(struct kunit *test) KUNIT_EXPECT_EQ(test, 2, ctx->bridge_stats.cycles_count); fpga_bridges_put(&ctx->region->bridge_list); - - fpga_image_info_free(img_info); } /* @@ -144,6 +158,7 @@ static int fpga_region_test_init(struct kunit *test) { struct test_ctx *ctx; struct fpga_region_info region_info = { 0 }; + int ret; ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); @@ -164,6 +179,9 @@ static int fpga_region_test_init(struct kunit *test) ctx->bridge_stats.enable = true; + ret = kunit_add_action_or_reset(test, fpga_bridge_unregister_wrapper, ctx->bridge); + KUNIT_ASSERT_EQ(test, ret, 0); + ctx->region_dev = kunit_device_register(test, "fpga-region-test-dev"); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->region_dev); @@ -174,24 +192,14 @@ static int fpga_region_test_init(struct kunit *test) ctx->region = fpga_region_register_full(ctx->region_dev, ®ion_info); KUNIT_ASSERT_FALSE(test, IS_ERR_OR_NULL(ctx->region)); + ret = kunit_add_action_or_reset(test, fpga_region_unregister_wrapper, ctx->region); + KUNIT_ASSERT_EQ(test, ret, 0); + test->priv = ctx; return 0; } -static void fpga_region_test_exit(struct kunit *test) -{ - struct test_ctx *ctx = test->priv; - - fpga_region_unregister(ctx->region); - kunit_device_unregister(test, ctx->region_dev); - - fpga_bridge_unregister(ctx->bridge); - kunit_device_unregister(test, ctx->bridge_dev); - - kunit_device_unregister(test, ctx->mgr_dev); -} - static struct kunit_case fpga_region_test_cases[] = { KUNIT_CASE(fpga_region_test_class_find), KUNIT_CASE(fpga_region_test_program_fpga), @@ -199,9 +207,8 @@ static struct kunit_case fpga_region_test_cases[] = { }; static struct kunit_suite fpga_region_suite = { - .name = "fpga_mgr", + .name = "fpga_region", .init = fpga_region_test_init, - .exit = fpga_region_test_exit, .test_cases = fpga_region_test_cases, }; From 4168ced7e02bef642a3641aec3b81107a5996707 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 29 Jul 2024 12:42:22 +0200 Subject: [PATCH 4/5] fpga: socfpga: Rename 'timeout' variable as 'time_left' There is a confusing pattern in the kernel to use a variable named 'timeout' to store the result of wait_for_completion_interruptible_timeout() causing patterns like: timeout = wait_for_completion_interruptible_timeout(...) if (!timeout) return -ETIMEDOUT; with all kinds of permutations. Use 'time_left' as a variable to make the code self explaining. Fix to the proper variable type 'long' while here. Signed-off-by: Wolfram Sang Acked-by: Xu Yilun Link: https://lore.kernel.org/r/20240729104319.2658-1-wsa+renesas@sang-engineering.com Signed-off-by: Xu Yilun --- drivers/fpga/socfpga.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/fpga/socfpga.c b/drivers/fpga/socfpga.c index 723ea0ad3f09..b08b4bb8f650 100644 --- a/drivers/fpga/socfpga.c +++ b/drivers/fpga/socfpga.c @@ -301,16 +301,17 @@ static irqreturn_t socfpga_fpga_isr(int irq, void *dev_id) static int socfpga_fpga_wait_for_config_done(struct socfpga_fpga_priv *priv) { - int timeout, ret = 0; + int ret = 0; + long time_left; socfpga_fpga_disable_irqs(priv); init_completion(&priv->status_complete); socfpga_fpga_enable_irqs(priv, SOCFPGA_FPGMGR_MON_CONF_DONE); - timeout = wait_for_completion_interruptible_timeout( + time_left = wait_for_completion_interruptible_timeout( &priv->status_complete, msecs_to_jiffies(10)); - if (timeout == 0) + if (time_left == 0) ret = -ETIMEDOUT; socfpga_fpga_disable_irqs(priv); From 8de36789bd038ae24e29c40cbbc9e7d59604f54f Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 29 Jul 2024 12:42:23 +0200 Subject: [PATCH 5/5] fpga: zynq-fpga: Rename 'timeout' variable as 'time_left' There is a confusing pattern in the kernel to use a variable named 'timeout' to store the result of wait_for_completion_timeout() causing patterns like: timeout = wait_for_completion_timeout(...) if (!timeout) return -ETIMEDOUT; with all kinds of permutations. Use 'time_left' as a variable to make the code self explaining. Signed-off-by: Wolfram Sang Acked-by: Michal Simek Acked-by: Xu Yilun Link: https://lore.kernel.org/r/20240729104319.2658-2-wsa+renesas@sang-engineering.com Signed-off-by: Xu Yilun --- drivers/fpga/zynq-fpga.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c index 0ac93183d201..4db3d80e10b0 100644 --- a/drivers/fpga/zynq-fpga.c +++ b/drivers/fpga/zynq-fpga.c @@ -387,7 +387,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr, struct sg_table *sgt) const char *why; int err; u32 intr_status; - unsigned long timeout; + unsigned long time_left; unsigned long flags; struct scatterlist *sg; int i; @@ -427,8 +427,8 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr, struct sg_table *sgt) zynq_step_dma(priv); spin_unlock_irqrestore(&priv->dma_lock, flags); - timeout = wait_for_completion_timeout(&priv->dma_done, - msecs_to_jiffies(DMA_TIMEOUT_MS)); + time_left = wait_for_completion_timeout(&priv->dma_done, + msecs_to_jiffies(DMA_TIMEOUT_MS)); spin_lock_irqsave(&priv->dma_lock, flags); zynq_fpga_set_irq(priv, 0); @@ -452,7 +452,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr, struct sg_table *sgt) if (priv->cur_sg || !((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) { - if (timeout == 0) + if (time_left == 0) why = "DMA timed out"; else why = "DMA did not complete";