dm: devres: Add tests
The devres functionality has very few users in U-Boot, but it still should have tests. Add a few basic tests of the main functions. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
dc12ebbbdb
commit
8d6320cc4d
@ -223,6 +223,19 @@ void dm_dump_devres(void)
|
||||
if (root)
|
||||
dump_resources(root, 0);
|
||||
}
|
||||
|
||||
void devres_get_stats(const struct udevice *dev, struct devres_stats *stats)
|
||||
{
|
||||
struct devres *dr;
|
||||
|
||||
stats->allocs = 0;
|
||||
stats->total_size = 0;
|
||||
list_for_each_entry(dr, &dev->devres_head, entry) {
|
||||
stats->allocs++;
|
||||
stats->total_size += dr->size;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -15,6 +15,17 @@
|
||||
typedef void (*dr_release_t)(struct udevice *dev, void *res);
|
||||
typedef int (*dr_match_t)(struct udevice *dev, void *res, void *match_data);
|
||||
|
||||
/**
|
||||
* struct devres_stats - Information about devres allocations for a device
|
||||
*
|
||||
* @allocs: Number of allocations
|
||||
* @total_size: Total size of allocations in bytes
|
||||
*/
|
||||
struct devres_stats {
|
||||
int allocs;
|
||||
int total_size;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEVRES
|
||||
|
||||
#ifdef CONFIG_DEBUG_DEVRES
|
||||
@ -189,6 +200,9 @@ static inline void *devm_kcalloc(struct udevice *dev,
|
||||
*/
|
||||
void devm_kfree(struct udevice *dev, void *ptr);
|
||||
|
||||
/* Get basic stats on allocations */
|
||||
void devres_get_stats(const struct udevice *dev, struct devres_stats *stats);
|
||||
|
||||
#else /* ! CONFIG_DEVRES */
|
||||
|
||||
static inline void *devres_alloc(dr_release_t release, size_t size, gfp_t gfp)
|
||||
@ -265,5 +279,11 @@ static inline void devm_kfree(struct udevice *dev, void *ptr)
|
||||
{
|
||||
kfree(ptr);
|
||||
}
|
||||
|
||||
static inline void devres_get_stats(const struct udevice *dev,
|
||||
struct devres_stats *stats)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* DEVRES */
|
||||
#endif /* _DM_DEVRES_H */
|
||||
|
@ -18,6 +18,7 @@ obj-$(CONFIG_BLK) += blk.o
|
||||
obj-$(CONFIG_BOARD) += board.o
|
||||
obj-$(CONFIG_DM_BOOTCOUNT) += bootcount.o
|
||||
obj-$(CONFIG_CLK) += clk.o clk_ccf.o
|
||||
obj-$(CONFIG_DEVRES) += devres.o
|
||||
obj-$(CONFIG_VIDEO_MIPI_DSI) += dsi_host.o
|
||||
obj-$(CONFIG_DM_ETH) += eth.o
|
||||
obj-$(CONFIG_FIRMWARE) += firmware.o
|
||||
|
178
test/dm/devres.c
Normal file
178
test/dm/devres.c
Normal file
@ -0,0 +1,178 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Tests for the devres (
|
||||
*
|
||||
* Copyright 2019 Google LLC
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <dm.h>
|
||||
#include <malloc.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/test.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
#include <test/ut.h>
|
||||
|
||||
/* Test that devm_kmalloc() allocates memory, free when device is removed */
|
||||
static int dm_test_devres_alloc(struct unit_test_state *uts)
|
||||
{
|
||||
ulong mem_start, mem_dev, mem_kmalloc;
|
||||
struct udevice *dev;
|
||||
void *ptr;
|
||||
|
||||
mem_start = ut_check_delta(0);
|
||||
ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
|
||||
mem_dev = ut_check_delta(mem_start);
|
||||
ut_assert(mem_dev > 0);
|
||||
|
||||
/* This should increase allocated memory */
|
||||
ptr = devm_kmalloc(dev, TEST_DEVRES_SIZE, 0);
|
||||
ut_assert(ptr != NULL);
|
||||
mem_kmalloc = ut_check_delta(mem_dev);
|
||||
ut_assert(mem_kmalloc > 0);
|
||||
|
||||
/* Check that ptr is freed */
|
||||
device_remove(dev, DM_REMOVE_NORMAL);
|
||||
ut_asserteq(0, ut_check_delta(mem_start));
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_devres_alloc, DM_TESTF_SCAN_PDATA);
|
||||
|
||||
/* Test devm_kfree() can be used to free memory too */
|
||||
static int dm_test_devres_free(struct unit_test_state *uts)
|
||||
{
|
||||
ulong mem_start, mem_dev, mem_kmalloc;
|
||||
struct udevice *dev;
|
||||
void *ptr;
|
||||
|
||||
mem_start = ut_check_delta(0);
|
||||
ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
|
||||
mem_dev = ut_check_delta(mem_start);
|
||||
ut_assert(mem_dev > 0);
|
||||
|
||||
ptr = devm_kmalloc(dev, TEST_DEVRES_SIZE, 0);
|
||||
ut_assert(ptr != NULL);
|
||||
mem_kmalloc = ut_check_delta(mem_dev);
|
||||
ut_assert(mem_kmalloc > 0);
|
||||
|
||||
/* Free the ptr and check that memory usage goes down */
|
||||
devm_kfree(dev, ptr);
|
||||
ut_assert(ut_check_delta(mem_kmalloc) < 0);
|
||||
|
||||
device_remove(dev, DM_REMOVE_NORMAL);
|
||||
ut_asserteq(0, ut_check_delta(mem_start));
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_devres_free, DM_TESTF_SCAN_PDATA);
|
||||
|
||||
|
||||
/* Test that kzalloc() returns memory that is zeroed */
|
||||
static int dm_test_devres_kzalloc(struct unit_test_state *uts)
|
||||
{
|
||||
struct udevice *dev;
|
||||
u8 *ptr, val;
|
||||
int i;
|
||||
|
||||
ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
|
||||
|
||||
ptr = devm_kzalloc(dev, TEST_DEVRES_SIZE, 0);
|
||||
ut_assert(ptr != NULL);
|
||||
for (val = 0, i = 0; i < TEST_DEVRES_SIZE; i++)
|
||||
val |= *ptr;
|
||||
ut_asserteq(0, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_devres_kzalloc, DM_TESTF_SCAN_PDATA);
|
||||
|
||||
/* Test that devm_kmalloc_array() allocates an array that can be set */
|
||||
static int dm_test_devres_kmalloc_array(struct unit_test_state *uts)
|
||||
{
|
||||
ulong mem_start, mem_dev;
|
||||
struct udevice *dev;
|
||||
u8 *ptr;
|
||||
|
||||
mem_start = ut_check_delta(0);
|
||||
ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
|
||||
mem_dev = ut_check_delta(mem_start);
|
||||
|
||||
ptr = devm_kmalloc_array(dev, TEST_DEVRES_COUNT, TEST_DEVRES_SIZE, 0);
|
||||
ut_assert(ptr != NULL);
|
||||
memset(ptr, '\xff', TEST_DEVRES_TOTAL);
|
||||
ut_assert(ut_check_delta(mem_dev) > 0);
|
||||
|
||||
device_remove(dev, DM_REMOVE_NORMAL);
|
||||
ut_asserteq(0, ut_check_delta(mem_start));
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_devres_kmalloc_array, DM_TESTF_SCAN_PDATA);
|
||||
|
||||
/* Test that devm_kcalloc() allocates a zeroed array */
|
||||
static int dm_test_devres_kcalloc(struct unit_test_state *uts)
|
||||
{
|
||||
ulong mem_start, mem_dev;
|
||||
struct udevice *dev;
|
||||
u8 *ptr, val;
|
||||
int i;
|
||||
|
||||
mem_start = ut_check_delta(0);
|
||||
ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
|
||||
mem_dev = ut_check_delta(mem_start);
|
||||
ut_assert(mem_dev > 0);
|
||||
|
||||
/* This should increase allocated memory */
|
||||
ptr = devm_kcalloc(dev, TEST_DEVRES_SIZE, TEST_DEVRES_COUNT, 0);
|
||||
ut_assert(ptr != NULL);
|
||||
ut_assert(ut_check_delta(mem_dev) > 0);
|
||||
for (val = 0, i = 0; i < TEST_DEVRES_TOTAL; i++)
|
||||
val |= *ptr;
|
||||
ut_asserteq(0, val);
|
||||
|
||||
/* Check that ptr is freed */
|
||||
device_remove(dev, DM_REMOVE_NORMAL);
|
||||
ut_asserteq(0, ut_check_delta(mem_start));
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_devres_kcalloc, DM_TESTF_SCAN_PDATA);
|
||||
|
||||
static int dm_test_devres_phase(struct unit_test_state *uts)
|
||||
{
|
||||
struct devres_stats stats;
|
||||
struct udevice *dev;
|
||||
|
||||
/*
|
||||
* The device is bound already, so find it and check that it has the
|
||||
* allocation created in the bind() method.
|
||||
*/
|
||||
ut_assertok(uclass_find_first_device(UCLASS_TEST_DEVRES, &dev));
|
||||
devres_get_stats(dev, &stats);
|
||||
ut_asserteq(1, stats.allocs);
|
||||
ut_asserteq(TEST_DEVRES_SIZE, stats.total_size);
|
||||
|
||||
/* Probing the device should add one allocation */
|
||||
ut_assertok(uclass_first_device(UCLASS_TEST_DEVRES, &dev));
|
||||
ut_assert(dev != NULL);
|
||||
devres_get_stats(dev, &stats);
|
||||
ut_asserteq(2, stats.allocs);
|
||||
ut_asserteq(TEST_DEVRES_SIZE + TEST_DEVRES_SIZE2, stats.total_size);
|
||||
|
||||
/* Removing the device should drop one allocation */
|
||||
device_remove(dev, DM_REMOVE_NORMAL);
|
||||
devres_get_stats(dev, &stats);
|
||||
ut_asserteq(1, stats.allocs);
|
||||
ut_asserteq(TEST_DEVRES_SIZE, stats.total_size);
|
||||
|
||||
/* Unbinding removes the other. Note this access a freed pointer */
|
||||
device_unbind(dev);
|
||||
devres_get_stats(dev, &stats);
|
||||
ut_asserteq(0, stats.allocs);
|
||||
ut_asserteq(0, stats.total_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_devres_phase, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|
Loading…
Reference in New Issue
Block a user