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