From: Simon Glass Date: Mon, 30 Dec 2019 04:19:28 +0000 (-0700) Subject: dm: devres: Add a new OFDATA phase X-Git-Url: http://git.dujemihanovic.xyz/%22http:/www.sics.se/static/git-favicon.png?a=commitdiff_plain;h=42a0ce576f33ad413662e7178f05db2f36de9896;p=u-boot.git dm: devres: Add a new OFDATA phase Since the ofdata_to_platdata() method can allocate resources, add it as a new devres phase. Signed-off-by: Simon Glass --- diff --git a/drivers/core/devres.c b/drivers/core/devres.c index 5376118f12..237b42653c 100644 --- a/drivers/core/devres.c +++ b/drivers/core/devres.c @@ -20,10 +20,12 @@ /** enum devres_phase - Shows where resource was allocated * * DEVRES_PHASE_BIND: In the bind() method + * DEVRES_PHASE_OFDATA: In the ofdata_to_platdata() method * DEVRES_PHASE_PROBE: In the probe() method */ enum devres_phase { DEVRES_PHASE_BIND, + DEVRES_PHASE_OFDATA, DEVRES_PHASE_PROBE, }; @@ -102,8 +104,12 @@ void devres_add(struct udevice *dev, void *res) devres_log(dev, dr, "ADD"); assert_noisy(list_empty(&dr->entry)); - dr->phase = dev->flags & DM_FLAG_BOUND ? DEVRES_PHASE_PROBE : - DEVRES_PHASE_BIND; + if (dev->flags & DM_FLAG_PLATDATA_VALID) + dr->phase = DEVRES_PHASE_PROBE; + else if (dev->flags & DM_FLAG_BOUND) + dr->phase = DEVRES_PHASE_OFDATA; + else + dr->phase = DEVRES_PHASE_BIND; list_add_tail(&dr->entry, &dev->devres_head); } @@ -184,12 +190,12 @@ int devres_release(struct udevice *dev, dr_release_t release, } static void release_nodes(struct udevice *dev, struct list_head *head, - bool probe_only) + bool probe_and_ofdata_only) { struct devres *dr, *tmp; list_for_each_entry_safe_reverse(dr, tmp, head, entry) { - if (probe_only && dr->phase != DEVRES_PHASE_PROBE) + if (probe_and_ofdata_only && dr->phase == DEVRES_PHASE_BIND) break; devres_log(dev, dr, "REL"); dr->release(dev, dr->data); @@ -209,6 +215,8 @@ void devres_release_all(struct udevice *dev) } #ifdef CONFIG_DEBUG_DEVRES +static char *const devres_phase_name[] = {"BIND", "OFDATA", "PROBE"}; + static void dump_resources(struct udevice *dev, int depth) { struct devres *dr; @@ -219,7 +227,7 @@ static void dump_resources(struct udevice *dev, int depth) list_for_each_entry(dr, &dev->devres_head, entry) printf(" %p (%lu byte) %s %s\n", dr, (unsigned long)dr->size, dr->name, - dr->phase == DEVRES_PHASE_PROBE ? "PROBE" : "BIND"); + devres_phase_name[dr->phase]); list_for_each_entry(child, &dev->child_head, sibling_node) dump_resources(child, depth + 1); diff --git a/include/test/test.h b/include/test/test.h index 5977c59d3f..e5bef4759a 100644 --- a/include/test/test.h +++ b/include/test/test.h @@ -52,8 +52,9 @@ enum { TEST_DEVRES_COUNT = 10, TEST_DEVRES_TOTAL = TEST_DEVRES_SIZE * TEST_DEVRES_COUNT, - /* A different size */ + /* A few different sizes */ TEST_DEVRES_SIZE2 = 15, + TEST_DEVRES_SIZE3 = 37, }; #endif /* __TEST_TEST_H */ diff --git a/test/dm/devres.c b/test/dm/devres.c index c351844db9..e7331897de 100644 --- a/test/dm/devres.c +++ b/test/dm/devres.c @@ -140,6 +140,7 @@ static int dm_test_devres_kcalloc(struct unit_test_state *uts) } DM_TEST(dm_test_devres_kcalloc, DM_TESTF_SCAN_PDATA); +/* Test devres releases resources automatically as expected */ static int dm_test_devres_phase(struct unit_test_state *uts) { struct devres_stats stats; @@ -154,14 +155,21 @@ static int dm_test_devres_phase(struct unit_test_state *uts) ut_asserteq(1, stats.allocs); ut_asserteq(TEST_DEVRES_SIZE, stats.total_size); + /* Getting platdata should add one allocation */ + ut_assertok(device_ofdata_to_platdata(dev)); + devres_get_stats(dev, &stats); + ut_asserteq(2, stats.allocs); + ut_asserteq(TEST_DEVRES_SIZE + TEST_DEVRES_SIZE3, 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); + ut_asserteq(3, stats.allocs); + ut_asserteq(TEST_DEVRES_SIZE + TEST_DEVRES_SIZE2 + TEST_DEVRES_SIZE3, + stats.total_size); - /* Removing the device should drop one allocation */ + /* Removing the device should drop both those allocations */ device_remove(dev, DM_REMOVE_NORMAL); devres_get_stats(dev, &stats); ut_asserteq(1, stats.allocs); diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c index bbac37761d..d59c449ce0 100644 --- a/test/dm/test-fdt.c +++ b/test/dm/test-fdt.c @@ -159,6 +159,7 @@ struct dm_testdevres_pdata { struct dm_testdevres_priv { void *ptr; + void *ptr_ofdata; }; static int testdevres_drv_bind(struct udevice *dev) @@ -170,6 +171,15 @@ static int testdevres_drv_bind(struct udevice *dev) return 0; } +static int testdevres_drv_ofdata_to_platdata(struct udevice *dev) +{ + struct dm_testdevres_priv *priv = dev_get_priv(dev); + + priv->ptr_ofdata = devm_kmalloc(dev, TEST_DEVRES_SIZE3, 0); + + return 0; +} + static int testdevres_drv_probe(struct udevice *dev) { struct dm_testdevres_priv *priv = dev_get_priv(dev); @@ -189,6 +199,7 @@ U_BOOT_DRIVER(testdevres_drv) = { .of_match = testdevres_ids, .id = UCLASS_TEST_DEVRES, .bind = testdevres_drv_bind, + .ofdata_to_platdata = testdevres_drv_ofdata_to_platdata, .probe = testdevres_drv_probe, .platdata_auto_alloc_size = sizeof(struct dm_testdevres_pdata), .priv_auto_alloc_size = sizeof(struct dm_testdevres_priv),