1*5ac79730SStephen Boyd // SPDX-License-Identifier: GPL-2.0 2*5ac79730SStephen Boyd /* 3*5ac79730SStephen Boyd * Test managed platform driver 4*5ac79730SStephen Boyd */ 5*5ac79730SStephen Boyd 6*5ac79730SStephen Boyd #include <linux/completion.h> 7*5ac79730SStephen Boyd #include <linux/device/bus.h> 8*5ac79730SStephen Boyd #include <linux/device/driver.h> 9*5ac79730SStephen Boyd #include <linux/platform_device.h> 10*5ac79730SStephen Boyd 11*5ac79730SStephen Boyd #include <kunit/platform_device.h> 12*5ac79730SStephen Boyd #include <kunit/resource.h> 13*5ac79730SStephen Boyd 14*5ac79730SStephen Boyd struct kunit_platform_device_alloc_params { 15*5ac79730SStephen Boyd const char *name; 16*5ac79730SStephen Boyd int id; 17*5ac79730SStephen Boyd }; 18*5ac79730SStephen Boyd 19*5ac79730SStephen Boyd static int kunit_platform_device_alloc_init(struct kunit_resource *res, void *context) 20*5ac79730SStephen Boyd { 21*5ac79730SStephen Boyd struct kunit_platform_device_alloc_params *params = context; 22*5ac79730SStephen Boyd struct platform_device *pdev; 23*5ac79730SStephen Boyd 24*5ac79730SStephen Boyd pdev = platform_device_alloc(params->name, params->id); 25*5ac79730SStephen Boyd if (!pdev) 26*5ac79730SStephen Boyd return -ENOMEM; 27*5ac79730SStephen Boyd 28*5ac79730SStephen Boyd res->data = pdev; 29*5ac79730SStephen Boyd 30*5ac79730SStephen Boyd return 0; 31*5ac79730SStephen Boyd } 32*5ac79730SStephen Boyd 33*5ac79730SStephen Boyd static void kunit_platform_device_alloc_exit(struct kunit_resource *res) 34*5ac79730SStephen Boyd { 35*5ac79730SStephen Boyd struct platform_device *pdev = res->data; 36*5ac79730SStephen Boyd 37*5ac79730SStephen Boyd platform_device_put(pdev); 38*5ac79730SStephen Boyd } 39*5ac79730SStephen Boyd 40*5ac79730SStephen Boyd /** 41*5ac79730SStephen Boyd * kunit_platform_device_alloc() - Allocate a KUnit test managed platform device 42*5ac79730SStephen Boyd * @test: test context 43*5ac79730SStephen Boyd * @name: device name of platform device to alloc 44*5ac79730SStephen Boyd * @id: identifier of platform device to alloc. 45*5ac79730SStephen Boyd * 46*5ac79730SStephen Boyd * Allocate a test managed platform device. The device is put when the test completes. 47*5ac79730SStephen Boyd * 48*5ac79730SStephen Boyd * Return: Allocated platform device on success, NULL on failure. 49*5ac79730SStephen Boyd */ 50*5ac79730SStephen Boyd struct platform_device * 51*5ac79730SStephen Boyd kunit_platform_device_alloc(struct kunit *test, const char *name, int id) 52*5ac79730SStephen Boyd { 53*5ac79730SStephen Boyd struct kunit_platform_device_alloc_params params = { 54*5ac79730SStephen Boyd .name = name, 55*5ac79730SStephen Boyd .id = id, 56*5ac79730SStephen Boyd }; 57*5ac79730SStephen Boyd 58*5ac79730SStephen Boyd return kunit_alloc_resource(test, 59*5ac79730SStephen Boyd kunit_platform_device_alloc_init, 60*5ac79730SStephen Boyd kunit_platform_device_alloc_exit, 61*5ac79730SStephen Boyd GFP_KERNEL, ¶ms); 62*5ac79730SStephen Boyd } 63*5ac79730SStephen Boyd EXPORT_SYMBOL_GPL(kunit_platform_device_alloc); 64*5ac79730SStephen Boyd 65*5ac79730SStephen Boyd static void kunit_platform_device_add_exit(struct kunit_resource *res) 66*5ac79730SStephen Boyd { 67*5ac79730SStephen Boyd struct platform_device *pdev = res->data; 68*5ac79730SStephen Boyd 69*5ac79730SStephen Boyd platform_device_unregister(pdev); 70*5ac79730SStephen Boyd } 71*5ac79730SStephen Boyd 72*5ac79730SStephen Boyd static bool 73*5ac79730SStephen Boyd kunit_platform_device_alloc_match(struct kunit *test, 74*5ac79730SStephen Boyd struct kunit_resource *res, void *match_data) 75*5ac79730SStephen Boyd { 76*5ac79730SStephen Boyd struct platform_device *pdev = match_data; 77*5ac79730SStephen Boyd 78*5ac79730SStephen Boyd return res->data == pdev && res->free == kunit_platform_device_alloc_exit; 79*5ac79730SStephen Boyd } 80*5ac79730SStephen Boyd 81*5ac79730SStephen Boyd KUNIT_DEFINE_ACTION_WRAPPER(platform_device_unregister_wrapper, 82*5ac79730SStephen Boyd platform_device_unregister, struct platform_device *); 83*5ac79730SStephen Boyd /** 84*5ac79730SStephen Boyd * kunit_platform_device_add() - Register a KUnit test managed platform device 85*5ac79730SStephen Boyd * @test: test context 86*5ac79730SStephen Boyd * @pdev: platform device to add 87*5ac79730SStephen Boyd * 88*5ac79730SStephen Boyd * Register a test managed platform device. The device is unregistered when the 89*5ac79730SStephen Boyd * test completes. 90*5ac79730SStephen Boyd * 91*5ac79730SStephen Boyd * Return: 0 on success, negative errno on failure. 92*5ac79730SStephen Boyd */ 93*5ac79730SStephen Boyd int kunit_platform_device_add(struct kunit *test, struct platform_device *pdev) 94*5ac79730SStephen Boyd { 95*5ac79730SStephen Boyd struct kunit_resource *res; 96*5ac79730SStephen Boyd int ret; 97*5ac79730SStephen Boyd 98*5ac79730SStephen Boyd ret = platform_device_add(pdev); 99*5ac79730SStephen Boyd if (ret) 100*5ac79730SStephen Boyd return ret; 101*5ac79730SStephen Boyd 102*5ac79730SStephen Boyd res = kunit_find_resource(test, kunit_platform_device_alloc_match, pdev); 103*5ac79730SStephen Boyd if (res) { 104*5ac79730SStephen Boyd /* 105*5ac79730SStephen Boyd * Transfer the reference count of the platform device if it 106*5ac79730SStephen Boyd * was allocated with kunit_platform_device_alloc(). In this 107*5ac79730SStephen Boyd * case, calling platform_device_put() when the test exits from 108*5ac79730SStephen Boyd * kunit_platform_device_alloc_exit() would lead to reference 109*5ac79730SStephen Boyd * count underflow because platform_device_unregister_wrapper() 110*5ac79730SStephen Boyd * calls platform_device_unregister() which also calls 111*5ac79730SStephen Boyd * platform_device_put(). 112*5ac79730SStephen Boyd * 113*5ac79730SStephen Boyd * Usually callers transfer the refcount initialized in 114*5ac79730SStephen Boyd * platform_device_alloc() to platform_device_add() by calling 115*5ac79730SStephen Boyd * platform_device_unregister() when platform_device_add() 116*5ac79730SStephen Boyd * succeeds or platform_device_put() when it fails. KUnit has to 117*5ac79730SStephen Boyd * keep this straight by redirecting the free routine for the 118*5ac79730SStephen Boyd * resource to the right function. Luckily this only has to 119*5ac79730SStephen Boyd * account for the success scenario. 120*5ac79730SStephen Boyd */ 121*5ac79730SStephen Boyd res->free = kunit_platform_device_add_exit; 122*5ac79730SStephen Boyd kunit_put_resource(res); 123*5ac79730SStephen Boyd } else { 124*5ac79730SStephen Boyd ret = kunit_add_action_or_reset(test, platform_device_unregister_wrapper, pdev); 125*5ac79730SStephen Boyd if (ret) 126*5ac79730SStephen Boyd return ret; 127*5ac79730SStephen Boyd } 128*5ac79730SStephen Boyd 129*5ac79730SStephen Boyd return 0; 130*5ac79730SStephen Boyd } 131*5ac79730SStephen Boyd EXPORT_SYMBOL_GPL(kunit_platform_device_add); 132*5ac79730SStephen Boyd 133*5ac79730SStephen Boyd struct kunit_platform_device_probe_nb { 134*5ac79730SStephen Boyd struct completion *x; 135*5ac79730SStephen Boyd struct device *dev; 136*5ac79730SStephen Boyd struct notifier_block nb; 137*5ac79730SStephen Boyd }; 138*5ac79730SStephen Boyd 139*5ac79730SStephen Boyd static int kunit_platform_device_probe_notify(struct notifier_block *nb, 140*5ac79730SStephen Boyd unsigned long event, void *data) 141*5ac79730SStephen Boyd { 142*5ac79730SStephen Boyd struct kunit_platform_device_probe_nb *knb; 143*5ac79730SStephen Boyd struct device *dev = data; 144*5ac79730SStephen Boyd 145*5ac79730SStephen Boyd knb = container_of(nb, struct kunit_platform_device_probe_nb, nb); 146*5ac79730SStephen Boyd if (event != BUS_NOTIFY_BOUND_DRIVER || knb->dev != dev) 147*5ac79730SStephen Boyd return NOTIFY_DONE; 148*5ac79730SStephen Boyd 149*5ac79730SStephen Boyd complete(knb->x); 150*5ac79730SStephen Boyd 151*5ac79730SStephen Boyd return NOTIFY_OK; 152*5ac79730SStephen Boyd } 153*5ac79730SStephen Boyd 154*5ac79730SStephen Boyd static void kunit_platform_device_probe_nb_remove(void *nb) 155*5ac79730SStephen Boyd { 156*5ac79730SStephen Boyd bus_unregister_notifier(&platform_bus_type, nb); 157*5ac79730SStephen Boyd } 158*5ac79730SStephen Boyd 159*5ac79730SStephen Boyd /** 160*5ac79730SStephen Boyd * kunit_platform_device_prepare_wait_for_probe() - Prepare a completion 161*5ac79730SStephen Boyd * variable to wait for a platform device to probe 162*5ac79730SStephen Boyd * @test: test context 163*5ac79730SStephen Boyd * @pdev: platform device to prepare to wait for probe of 164*5ac79730SStephen Boyd * @x: completion variable completed when @dev has probed 165*5ac79730SStephen Boyd * 166*5ac79730SStephen Boyd * Prepare a completion variable @x to wait for @pdev to probe. Waiting on the 167*5ac79730SStephen Boyd * completion forces a preemption, allowing the platform driver to probe. 168*5ac79730SStephen Boyd * 169*5ac79730SStephen Boyd * Example 170*5ac79730SStephen Boyd * 171*5ac79730SStephen Boyd * .. code-block:: c 172*5ac79730SStephen Boyd * 173*5ac79730SStephen Boyd * static int kunit_platform_driver_probe(struct platform_device *pdev) 174*5ac79730SStephen Boyd * { 175*5ac79730SStephen Boyd * return 0; 176*5ac79730SStephen Boyd * } 177*5ac79730SStephen Boyd * 178*5ac79730SStephen Boyd * static void kunit_platform_driver_test(struct kunit *test) 179*5ac79730SStephen Boyd * { 180*5ac79730SStephen Boyd * struct platform_device *pdev; 181*5ac79730SStephen Boyd * struct platform_driver *pdrv; 182*5ac79730SStephen Boyd * DECLARE_COMPLETION_ONSTACK(comp); 183*5ac79730SStephen Boyd * 184*5ac79730SStephen Boyd * pdev = kunit_platform_device_alloc(test, "kunit-platform", -1); 185*5ac79730SStephen Boyd * KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); 186*5ac79730SStephen Boyd * KUNIT_ASSERT_EQ(test, 0, kunit_platform_device_add(test, pdev)); 187*5ac79730SStephen Boyd * 188*5ac79730SStephen Boyd * pdrv = kunit_kzalloc(test, sizeof(*pdrv), GFP_KERNEL); 189*5ac79730SStephen Boyd * KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdrv); 190*5ac79730SStephen Boyd * 191*5ac79730SStephen Boyd * pdrv->probe = kunit_platform_driver_probe; 192*5ac79730SStephen Boyd * pdrv->driver.name = "kunit-platform"; 193*5ac79730SStephen Boyd * pdrv->driver.owner = THIS_MODULE; 194*5ac79730SStephen Boyd * 195*5ac79730SStephen Boyd * KUNIT_ASSERT_EQ(test, 0, kunit_platform_device_prepare_wait_for_probe(test, pdev, &comp)); 196*5ac79730SStephen Boyd * KUNIT_ASSERT_EQ(test, 0, kunit_platform_driver_register(test, pdrv)); 197*5ac79730SStephen Boyd * 198*5ac79730SStephen Boyd * KUNIT_EXPECT_NE(test, 0, wait_for_completion_timeout(&comp, 3 * HZ)); 199*5ac79730SStephen Boyd * } 200*5ac79730SStephen Boyd * 201*5ac79730SStephen Boyd * Return: 0 on success, negative errno on failure. 202*5ac79730SStephen Boyd */ 203*5ac79730SStephen Boyd int kunit_platform_device_prepare_wait_for_probe(struct kunit *test, 204*5ac79730SStephen Boyd struct platform_device *pdev, 205*5ac79730SStephen Boyd struct completion *x) 206*5ac79730SStephen Boyd { 207*5ac79730SStephen Boyd struct device *dev = &pdev->dev; 208*5ac79730SStephen Boyd struct kunit_platform_device_probe_nb *knb; 209*5ac79730SStephen Boyd bool bound; 210*5ac79730SStephen Boyd 211*5ac79730SStephen Boyd knb = kunit_kzalloc(test, sizeof(*knb), GFP_KERNEL); 212*5ac79730SStephen Boyd if (!knb) 213*5ac79730SStephen Boyd return -ENOMEM; 214*5ac79730SStephen Boyd 215*5ac79730SStephen Boyd knb->nb.notifier_call = kunit_platform_device_probe_notify; 216*5ac79730SStephen Boyd knb->dev = dev; 217*5ac79730SStephen Boyd knb->x = x; 218*5ac79730SStephen Boyd 219*5ac79730SStephen Boyd device_lock(dev); 220*5ac79730SStephen Boyd bound = device_is_bound(dev); 221*5ac79730SStephen Boyd if (bound) { 222*5ac79730SStephen Boyd device_unlock(dev); 223*5ac79730SStephen Boyd complete(x); 224*5ac79730SStephen Boyd kunit_kfree(test, knb); 225*5ac79730SStephen Boyd return 0; 226*5ac79730SStephen Boyd } 227*5ac79730SStephen Boyd 228*5ac79730SStephen Boyd bus_register_notifier(&platform_bus_type, &knb->nb); 229*5ac79730SStephen Boyd device_unlock(&pdev->dev); 230*5ac79730SStephen Boyd 231*5ac79730SStephen Boyd return kunit_add_action_or_reset(test, kunit_platform_device_probe_nb_remove, &knb->nb); 232*5ac79730SStephen Boyd } 233*5ac79730SStephen Boyd EXPORT_SYMBOL_GPL(kunit_platform_device_prepare_wait_for_probe); 234*5ac79730SStephen Boyd 235*5ac79730SStephen Boyd KUNIT_DEFINE_ACTION_WRAPPER(platform_driver_unregister_wrapper, 236*5ac79730SStephen Boyd platform_driver_unregister, struct platform_driver *); 237*5ac79730SStephen Boyd /** 238*5ac79730SStephen Boyd * kunit_platform_driver_register() - Register a KUnit test managed platform driver 239*5ac79730SStephen Boyd * @test: test context 240*5ac79730SStephen Boyd * @drv: platform driver to register 241*5ac79730SStephen Boyd * 242*5ac79730SStephen Boyd * Register a test managed platform driver. This allows callers to embed the 243*5ac79730SStephen Boyd * @drv in a container structure and use container_of() in the probe function 244*5ac79730SStephen Boyd * to pass information to KUnit tests. 245*5ac79730SStephen Boyd * 246*5ac79730SStephen Boyd * Example 247*5ac79730SStephen Boyd * 248*5ac79730SStephen Boyd * .. code-block:: c 249*5ac79730SStephen Boyd * 250*5ac79730SStephen Boyd * struct kunit_test_context { 251*5ac79730SStephen Boyd * struct platform_driver pdrv; 252*5ac79730SStephen Boyd * const char *data; 253*5ac79730SStephen Boyd * }; 254*5ac79730SStephen Boyd * 255*5ac79730SStephen Boyd * static inline struct kunit_test_context * 256*5ac79730SStephen Boyd * to_test_context(struct platform_device *pdev) 257*5ac79730SStephen Boyd * { 258*5ac79730SStephen Boyd * return container_of(to_platform_driver(pdev->dev.driver), 259*5ac79730SStephen Boyd * struct kunit_test_context, 260*5ac79730SStephen Boyd * pdrv); 261*5ac79730SStephen Boyd * } 262*5ac79730SStephen Boyd * 263*5ac79730SStephen Boyd * static int kunit_platform_driver_probe(struct platform_device *pdev) 264*5ac79730SStephen Boyd * { 265*5ac79730SStephen Boyd * struct kunit_test_context *ctx; 266*5ac79730SStephen Boyd * 267*5ac79730SStephen Boyd * ctx = to_test_context(pdev); 268*5ac79730SStephen Boyd * ctx->data = "test data"; 269*5ac79730SStephen Boyd * 270*5ac79730SStephen Boyd * return 0; 271*5ac79730SStephen Boyd * } 272*5ac79730SStephen Boyd * 273*5ac79730SStephen Boyd * static void kunit_platform_driver_test(struct kunit *test) 274*5ac79730SStephen Boyd * { 275*5ac79730SStephen Boyd * struct kunit_test_context *ctx; 276*5ac79730SStephen Boyd * 277*5ac79730SStephen Boyd * ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); 278*5ac79730SStephen Boyd * KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); 279*5ac79730SStephen Boyd * 280*5ac79730SStephen Boyd * ctx->pdrv.probe = kunit_platform_driver_probe; 281*5ac79730SStephen Boyd * ctx->pdrv.driver.name = "kunit-platform"; 282*5ac79730SStephen Boyd * ctx->pdrv.driver.owner = THIS_MODULE; 283*5ac79730SStephen Boyd * 284*5ac79730SStephen Boyd * KUNIT_EXPECT_EQ(test, 0, kunit_platform_driver_register(test, &ctx->pdrv)); 285*5ac79730SStephen Boyd * <... wait for driver to probe ...> 286*5ac79730SStephen Boyd * KUNIT_EXPECT_STREQ(test, ctx->data, "test data"); 287*5ac79730SStephen Boyd * } 288*5ac79730SStephen Boyd * 289*5ac79730SStephen Boyd * Return: 0 on success, negative errno on failure. 290*5ac79730SStephen Boyd */ 291*5ac79730SStephen Boyd int kunit_platform_driver_register(struct kunit *test, 292*5ac79730SStephen Boyd struct platform_driver *drv) 293*5ac79730SStephen Boyd { 294*5ac79730SStephen Boyd int ret; 295*5ac79730SStephen Boyd 296*5ac79730SStephen Boyd ret = platform_driver_register(drv); 297*5ac79730SStephen Boyd if (ret) 298*5ac79730SStephen Boyd return ret; 299*5ac79730SStephen Boyd 300*5ac79730SStephen Boyd return kunit_add_action_or_reset(test, platform_driver_unregister_wrapper, drv); 301*5ac79730SStephen Boyd } 302*5ac79730SStephen Boyd EXPORT_SYMBOL_GPL(kunit_platform_driver_register); 303