1 // SPDX-License-Identifier: GPL-2.0
3 * KUnit test for the FPGA Region
5 * Copyright (C) 2023 Red Hat, Inc.
7 * Author: Marco Pagani <marpagan@redhat.com>
10 #include <kunit/device.h>
11 #include <kunit/test.h>
12 #include <linux/fpga/fpga-bridge.h>
13 #include <linux/fpga/fpga-mgr.h>
14 #include <linux/fpga/fpga-region.h>
15 #include <linux/module.h>
16 #include <linux/types.h>
28 struct fpga_manager
*mgr
;
29 struct device
*mgr_dev
;
30 struct fpga_bridge
*bridge
;
31 struct device
*bridge_dev
;
32 struct fpga_region
*region
;
33 struct device
*region_dev
;
34 struct bridge_stats bridge_stats
;
35 struct mgr_stats mgr_stats
;
39 * Wrappers to avoid cast warnings when passing action functions directly
40 * to kunit_add_action().
42 KUNIT_DEFINE_ACTION_WRAPPER(fpga_image_info_free_wrapper
, fpga_image_info_free
,
43 struct fpga_image_info
*);
45 KUNIT_DEFINE_ACTION_WRAPPER(fpga_bridge_unregister_wrapper
, fpga_bridge_unregister
,
46 struct fpga_bridge
*);
48 KUNIT_DEFINE_ACTION_WRAPPER(fpga_region_unregister_wrapper
, fpga_region_unregister
,
49 struct fpga_region
*);
51 static int op_write(struct fpga_manager
*mgr
, const char *buf
, size_t count
)
53 struct mgr_stats
*stats
= mgr
->priv
;
61 * Fake FPGA manager that implements only the write op to count the number
62 * of programming cycles. The internals of the programming sequence are
63 * tested in the Manager suite since they are outside the responsibility
66 static const struct fpga_manager_ops fake_mgr_ops
= {
70 static int op_enable_set(struct fpga_bridge
*bridge
, bool enable
)
72 struct bridge_stats
*stats
= bridge
->priv
;
74 if (!stats
->enable
&& enable
)
75 stats
->cycles_count
++;
77 stats
->enable
= enable
;
83 * Fake FPGA bridge that implements only enable_set op to count the number
84 * of activation cycles.
86 static const struct fpga_bridge_ops fake_bridge_ops
= {
87 .enable_set
= op_enable_set
,
90 static int fake_region_get_bridges(struct fpga_region
*region
)
92 struct fpga_bridge
*bridge
= region
->priv
;
94 return fpga_bridge_get_to_list(bridge
->dev
.parent
, region
->info
, ®ion
->bridge_list
);
97 static int fake_region_match(struct device
*dev
, const void *data
)
99 return dev
->parent
== data
;
102 static void fpga_region_test_class_find(struct kunit
*test
)
104 struct test_ctx
*ctx
= test
->priv
;
105 struct fpga_region
*region
;
107 region
= fpga_region_class_find(NULL
, ctx
->region_dev
, fake_region_match
);
108 KUNIT_EXPECT_PTR_EQ(test
, region
, ctx
->region
);
110 put_device(®ion
->dev
);
114 * FPGA Region programming test. The Region must call get_bridges() to get
115 * and control the bridges, and then the Manager for the actual programming.
117 static void fpga_region_test_program_fpga(struct kunit
*test
)
119 struct test_ctx
*ctx
= test
->priv
;
120 struct fpga_image_info
*img_info
;
124 img_info
= fpga_image_info_alloc(ctx
->mgr_dev
);
125 KUNIT_ASSERT_NOT_ERR_OR_NULL(test
, img_info
);
127 ret
= kunit_add_action_or_reset(test
, fpga_image_info_free_wrapper
, img_info
);
128 KUNIT_ASSERT_EQ(test
, ret
, 0);
130 img_info
->buf
= img_buf
;
131 img_info
->count
= sizeof(img_buf
);
133 ctx
->region
->info
= img_info
;
134 ret
= fpga_region_program_fpga(ctx
->region
);
135 KUNIT_ASSERT_EQ(test
, ret
, 0);
137 KUNIT_EXPECT_EQ(test
, 1, ctx
->mgr_stats
.write_count
);
138 KUNIT_EXPECT_EQ(test
, 1, ctx
->bridge_stats
.cycles_count
);
140 fpga_bridges_put(&ctx
->region
->bridge_list
);
142 ret
= fpga_region_program_fpga(ctx
->region
);
143 KUNIT_ASSERT_EQ(test
, ret
, 0);
145 KUNIT_EXPECT_EQ(test
, 2, ctx
->mgr_stats
.write_count
);
146 KUNIT_EXPECT_EQ(test
, 2, ctx
->bridge_stats
.cycles_count
);
148 fpga_bridges_put(&ctx
->region
->bridge_list
);
152 * The configuration used in this test suite uses a single bridge to
153 * limit the code under test to a single unit. The functions used by the
154 * Region for getting and controlling bridges are tested (with a list of
155 * multiple bridges) in the Bridge suite.
157 static int fpga_region_test_init(struct kunit
*test
)
159 struct test_ctx
*ctx
;
160 struct fpga_region_info region_info
= { 0 };
163 ctx
= kunit_kzalloc(test
, sizeof(*ctx
), GFP_KERNEL
);
164 KUNIT_ASSERT_NOT_ERR_OR_NULL(test
, ctx
);
166 ctx
->mgr_dev
= kunit_device_register(test
, "fpga-manager-test-dev");
167 KUNIT_ASSERT_NOT_ERR_OR_NULL(test
, ctx
->mgr_dev
);
169 ctx
->mgr
= devm_fpga_mgr_register(ctx
->mgr_dev
, "Fake FPGA Manager",
170 &fake_mgr_ops
, &ctx
->mgr_stats
);
171 KUNIT_ASSERT_FALSE(test
, IS_ERR_OR_NULL(ctx
->mgr
));
173 ctx
->bridge_dev
= kunit_device_register(test
, "fpga-bridge-test-dev");
174 KUNIT_ASSERT_NOT_ERR_OR_NULL(test
, ctx
->bridge_dev
);
176 ctx
->bridge
= fpga_bridge_register(ctx
->bridge_dev
, "Fake FPGA Bridge",
177 &fake_bridge_ops
, &ctx
->bridge_stats
);
178 KUNIT_ASSERT_FALSE(test
, IS_ERR_OR_NULL(ctx
->bridge
));
180 ctx
->bridge_stats
.enable
= true;
182 ret
= kunit_add_action_or_reset(test
, fpga_bridge_unregister_wrapper
, ctx
->bridge
);
183 KUNIT_ASSERT_EQ(test
, ret
, 0);
185 ctx
->region_dev
= kunit_device_register(test
, "fpga-region-test-dev");
186 KUNIT_ASSERT_NOT_ERR_OR_NULL(test
, ctx
->region_dev
);
188 region_info
.mgr
= ctx
->mgr
;
189 region_info
.priv
= ctx
->bridge
;
190 region_info
.get_bridges
= fake_region_get_bridges
;
192 ctx
->region
= fpga_region_register_full(ctx
->region_dev
, ®ion_info
);
193 KUNIT_ASSERT_FALSE(test
, IS_ERR_OR_NULL(ctx
->region
));
195 ret
= kunit_add_action_or_reset(test
, fpga_region_unregister_wrapper
, ctx
->region
);
196 KUNIT_ASSERT_EQ(test
, ret
, 0);
203 static struct kunit_case fpga_region_test_cases
[] = {
204 KUNIT_CASE(fpga_region_test_class_find
),
205 KUNIT_CASE(fpga_region_test_program_fpga
),
209 static struct kunit_suite fpga_region_suite
= {
210 .name
= "fpga_region",
211 .init
= fpga_region_test_init
,
212 .test_cases
= fpga_region_test_cases
,
215 kunit_test_suite(fpga_region_suite
);
217 MODULE_LICENSE("GPL");