xref: /linux/drivers/fpga/tests/fpga-bridge-test.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
1  // SPDX-License-Identifier: GPL-2.0
2  /*
3   * KUnit test for the FPGA Bridge
4   *
5   * Copyright (C) 2023 Red Hat, Inc.
6   *
7   * Author: Marco Pagani <marpagan@redhat.com>
8   */
9  
10  #include <kunit/device.h>
11  #include <kunit/test.h>
12  #include <linux/fpga/fpga-bridge.h>
13  #include <linux/module.h>
14  #include <linux/types.h>
15  
16  struct bridge_stats {
17  	bool enable;
18  };
19  
20  struct bridge_ctx {
21  	struct fpga_bridge *bridge;
22  	struct device *dev;
23  	struct bridge_stats stats;
24  };
25  
26  /*
27   * Wrapper to avoid a cast warning when passing the action function directly
28   * to kunit_add_action().
29   */
30  KUNIT_DEFINE_ACTION_WRAPPER(fpga_bridge_unregister_wrapper, fpga_bridge_unregister,
31  			    struct fpga_bridge *);
32  
op_enable_set(struct fpga_bridge * bridge,bool enable)33  static int op_enable_set(struct fpga_bridge *bridge, bool enable)
34  {
35  	struct bridge_stats *stats = bridge->priv;
36  
37  	stats->enable = enable;
38  
39  	return 0;
40  }
41  
42  /*
43   * Fake FPGA bridge that implements only the enable_set op to track
44   * the state.
45   */
46  static const struct fpga_bridge_ops fake_bridge_ops = {
47  	.enable_set = op_enable_set,
48  };
49  
50  /**
51   * register_test_bridge() - Register a fake FPGA bridge for testing.
52   * @test: KUnit test context object.
53   * @dev_name: name of the kunit device to be registered
54   *
55   * Return: Context of the newly registered FPGA bridge.
56   */
register_test_bridge(struct kunit * test,const char * dev_name)57  static struct bridge_ctx *register_test_bridge(struct kunit *test, const char *dev_name)
58  {
59  	struct bridge_ctx *ctx;
60  	int ret;
61  
62  	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
63  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
64  
65  	ctx->dev = kunit_device_register(test, dev_name);
66  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->dev);
67  
68  	ctx->bridge = fpga_bridge_register(ctx->dev, "Fake FPGA bridge", &fake_bridge_ops,
69  					   &ctx->stats);
70  	KUNIT_ASSERT_FALSE(test, IS_ERR_OR_NULL(ctx->bridge));
71  
72  	ret = kunit_add_action_or_reset(test, fpga_bridge_unregister_wrapper, ctx->bridge);
73  	KUNIT_ASSERT_EQ(test, ret, 0);
74  
75  	return ctx;
76  }
77  
fpga_bridge_test_get(struct kunit * test)78  static void fpga_bridge_test_get(struct kunit *test)
79  {
80  	struct bridge_ctx *ctx = test->priv;
81  	struct fpga_bridge *bridge;
82  
83  	bridge = fpga_bridge_get(ctx->dev, NULL);
84  	KUNIT_EXPECT_PTR_EQ(test, bridge, ctx->bridge);
85  
86  	bridge = fpga_bridge_get(ctx->dev, NULL);
87  	KUNIT_EXPECT_EQ(test, PTR_ERR(bridge), -EBUSY);
88  
89  	fpga_bridge_put(ctx->bridge);
90  }
91  
fpga_bridge_test_toggle(struct kunit * test)92  static void fpga_bridge_test_toggle(struct kunit *test)
93  {
94  	struct bridge_ctx *ctx = test->priv;
95  	int ret;
96  
97  	ret = fpga_bridge_disable(ctx->bridge);
98  	KUNIT_EXPECT_EQ(test, ret, 0);
99  	KUNIT_EXPECT_FALSE(test, ctx->stats.enable);
100  
101  	ret = fpga_bridge_enable(ctx->bridge);
102  	KUNIT_EXPECT_EQ(test, ret, 0);
103  	KUNIT_EXPECT_TRUE(test, ctx->stats.enable);
104  }
105  
106  /* Test the functions for getting and controlling a list of bridges */
fpga_bridge_test_get_put_list(struct kunit * test)107  static void fpga_bridge_test_get_put_list(struct kunit *test)
108  {
109  	struct list_head bridge_list;
110  	struct bridge_ctx *ctx_0, *ctx_1;
111  	int ret;
112  
113  	ctx_0 = test->priv;
114  	ctx_1 = register_test_bridge(test, "fpga-bridge-test-dev-1");
115  
116  	INIT_LIST_HEAD(&bridge_list);
117  
118  	/* Get bridge 0 and add it to the list */
119  	ret = fpga_bridge_get_to_list(ctx_0->dev, NULL, &bridge_list);
120  	KUNIT_EXPECT_EQ(test, ret, 0);
121  
122  	KUNIT_EXPECT_PTR_EQ(test, ctx_0->bridge,
123  			    list_first_entry_or_null(&bridge_list, struct fpga_bridge, node));
124  
125  	/* Get bridge 1 and add it to the list */
126  	ret = fpga_bridge_get_to_list(ctx_1->dev, NULL, &bridge_list);
127  	KUNIT_EXPECT_EQ(test, ret, 0);
128  
129  	KUNIT_EXPECT_PTR_EQ(test, ctx_1->bridge,
130  			    list_first_entry_or_null(&bridge_list, struct fpga_bridge, node));
131  
132  	/* Disable an then enable both bridges from the list */
133  	ret = fpga_bridges_disable(&bridge_list);
134  	KUNIT_EXPECT_EQ(test, ret, 0);
135  
136  	KUNIT_EXPECT_FALSE(test, ctx_0->stats.enable);
137  	KUNIT_EXPECT_FALSE(test, ctx_1->stats.enable);
138  
139  	ret = fpga_bridges_enable(&bridge_list);
140  	KUNIT_EXPECT_EQ(test, ret, 0);
141  
142  	KUNIT_EXPECT_TRUE(test, ctx_0->stats.enable);
143  	KUNIT_EXPECT_TRUE(test, ctx_1->stats.enable);
144  
145  	/* Put and remove both bridges from the list */
146  	fpga_bridges_put(&bridge_list);
147  
148  	KUNIT_EXPECT_TRUE(test, list_empty(&bridge_list));
149  }
150  
fpga_bridge_test_init(struct kunit * test)151  static int fpga_bridge_test_init(struct kunit *test)
152  {
153  	test->priv = register_test_bridge(test, "fpga-bridge-test-dev-0");
154  
155  	return 0;
156  }
157  
158  static struct kunit_case fpga_bridge_test_cases[] = {
159  	KUNIT_CASE(fpga_bridge_test_get),
160  	KUNIT_CASE(fpga_bridge_test_toggle),
161  	KUNIT_CASE(fpga_bridge_test_get_put_list),
162  	{}
163  };
164  
165  static struct kunit_suite fpga_bridge_suite = {
166  	.name = "fpga_bridge",
167  	.init = fpga_bridge_test_init,
168  	.test_cases = fpga_bridge_test_cases,
169  };
170  
171  kunit_test_suite(fpga_bridge_suite);
172  
173  MODULE_LICENSE("GPL");
174