/* Test that we can bind/unbind and the lists update correctly */ static int dm_test_ordering(struct unit_test_state *uts) { struct dm_test_state *dms = uts->priv; struct udevice *dev, *dev_penultimate, *dev_last, *test_dev; int pingret; ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual, &dev)); ut_assert(dev); /* Bind two new devices (numbers 4 and 5) */ ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual, &dev_penultimate)); ut_assert(dev_penultimate); ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual, &dev_last)); ut_assert(dev_last); /* Now remove device 3 */ ut_assertok(device_remove(dev)); ut_assertok(device_unbind(dev)); /* The device numbering should have shifted down one */ ut_assertok(uclass_find_device(UCLASS_TEST, 3, &test_dev)); ut_assert(dev_penultimate == test_dev); ut_assertok(uclass_find_device(UCLASS_TEST, 4, &test_dev)); ut_assert(dev_last == test_dev); /* Add back the original device 3, now in position 5 */ ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual, &dev)); ut_assert(dev); /* Try ping */ ut_assertok(test_ping(dev, 100, &pingret)); ut_assert(pingret == 102); /* Remove 3 and 4 */ ut_assertok(device_remove(dev_penultimate)); ut_assertok(device_unbind(dev_penultimate)); ut_assertok(device_remove(dev_last)); ut_assertok(device_unbind(dev_last)); /* Our device should now be in position 3 */ ut_assertok(uclass_find_device(UCLASS_TEST, 3, &test_dev)); ut_assert(dev == test_dev); /* Now remove device 3 */ ut_assertok(device_remove(dev)); ut_assertok(device_unbind(dev)); return 0; }
/* Test that pre-relocation devices work as expected */ static int dm_test_pre_reloc(struct dm_test_state *dms) { struct udevice *dev; /* The normal driver should refuse to bind before relocation */ ut_asserteq(-EPERM, device_bind_by_name(dms->root, true, &driver_info_manual, &dev)); /* But this one is marked pre-reloc */ ut_assertok(device_bind_by_name(dms->root, true, &driver_info_pre_reloc, &dev)); return 0; }
int dm_init(void) { int ret; if (gd->dm_root) { dm_warn("Virtual root driver already exists!\n"); return -EINVAL; } INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST); #if defined(CONFIG_NEEDS_MANUAL_RELOC) fix_drivers(); fix_uclass(); #endif ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST); if (ret) return ret; #if CONFIG_IS_ENABLED(OF_CONTROL) DM_ROOT_NON_CONST->of_offset = 0; #endif ret = device_probe(DM_ROOT_NON_CONST); if (ret) return ret; return 0; }
/* Test that we can bind, probe, remove, unbind a driver */ static int dm_test_lifecycle(struct unit_test_state *uts) { struct dm_test_state *dms = uts->priv; int op_count[DM_TEST_OP_COUNT]; struct udevice *dev, *test_dev; int pingret; int ret; memcpy(op_count, dm_testdrv_op_count, sizeof(op_count)); ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual, &dev)); ut_assert(dev); ut_assert(dm_testdrv_op_count[DM_TEST_OP_BIND] == op_count[DM_TEST_OP_BIND] + 1); ut_assert(!dev->priv); /* Probe the device - it should fail allocating private data */ dms->force_fail_alloc = 1; ret = device_probe(dev); ut_assert(ret == -ENOMEM); ut_assert(dm_testdrv_op_count[DM_TEST_OP_PROBE] == op_count[DM_TEST_OP_PROBE] + 1); ut_assert(!dev->priv); /* Try again without the alloc failure */ dms->force_fail_alloc = 0; ut_assertok(device_probe(dev)); ut_assert(dm_testdrv_op_count[DM_TEST_OP_PROBE] == op_count[DM_TEST_OP_PROBE] + 2); ut_assert(dev->priv); /* This should be device 3 in the uclass */ ut_assertok(uclass_find_device(UCLASS_TEST, 3, &test_dev)); ut_assert(dev == test_dev); /* Try ping */ ut_assertok(test_ping(dev, 100, &pingret)); ut_assert(pingret == 102); /* Now remove device 3 */ ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_PRE_REMOVE]); ut_assertok(device_remove(dev)); ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_PRE_REMOVE]); ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_UNBIND]); ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_PRE_UNBIND]); ut_assertok(device_unbind(dev)); ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_UNBIND]); ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_PRE_UNBIND]); return 0; }
/** * create_children() - Create children of a parent node * * @dms: Test system state * @parent: Parent device * @count: Number of children to create * @key: Key value to put in first child. Subsequence children * receive an incrementing value * @child: If not NULL, then the child device pointers are written into * this array. * @return 0 if OK, -ve on error */ static int create_children(struct unit_test_state *uts, struct udevice *parent, int count, int key, struct udevice *child[]) { struct udevice *dev; int i; for (i = 0; i < count; i++) { struct dm_test_pdata *pdata; ut_assertok(device_bind_by_name(parent, false, &driver_info_manual, &dev)); pdata = calloc(1, sizeof(*pdata)); pdata->ping_add = key + i; dev->platdata = pdata; if (child) child[i] = dev; } return 0; }
int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only) { struct driver_info *info = ll_entry_start(struct driver_info, driver_info); const int n_ents = ll_entry_count(struct driver_info, driver_info); struct driver_info *entry; struct udevice *dev; int result = 0; int ret; for (entry = info; entry != info + n_ents; entry++) { ret = device_bind_by_name(parent, pre_reloc_only, entry, &dev); if (ret && ret != -EPERM) { dm_warn("No match for driver '%s'\n", entry->name); if (!result || ret != -ENOENT) result = ret; } } return result; }
int dm_init(void) { int ret; if (gd->dm_root) { dm_warn("Virtual root driver already exists!\n"); return -EINVAL; } INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST); ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST); if (ret) return ret; #ifdef CONFIG_OF_CONTROL DM_ROOT_NON_CONST->of_offset = 0; #endif ret = device_probe(DM_ROOT_NON_CONST); if (ret) return ret; return 0; }