1 // SPDX-License-Identifier: GPL-2.0 1 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/platform_device.h> 10 11 #include <kunit/platform_device.h> 12 #include <kunit/resource.h> 13 14 struct kunit_platform_device_alloc_params { 15 const char *name; 16 int id; 17 }; 18 19 static int kunit_platform_device_alloc_init(st 20 { 21 struct kunit_platform_device_alloc_par 22 struct platform_device *pdev; 23 24 pdev = platform_device_alloc(params->n 25 if (!pdev) 26 return -ENOMEM; 27 28 res->data = pdev; 29 30 return 0; 31 } 32 33 static void kunit_platform_device_alloc_exit(s 34 { 35 struct platform_device *pdev = res->da 36 37 platform_device_put(pdev); 38 } 39 40 /** 41 * kunit_platform_device_alloc() - Allocate a 42 * @test: test context 43 * @name: device name of platform device to al 44 * @id: identifier of platform device to alloc 45 * 46 * Allocate a test managed platform device. Th 47 * 48 * Return: Allocated platform device on succes 49 */ 50 struct platform_device * 51 kunit_platform_device_alloc(struct kunit *test 52 { 53 struct kunit_platform_device_alloc_par 54 .name = name, 55 .id = id, 56 }; 57 58 return kunit_alloc_resource(test, 59 kunit_plat 60 kunit_plat 61 GFP_KERNEL 62 } 63 EXPORT_SYMBOL_GPL(kunit_platform_device_alloc) 64 65 static void kunit_platform_device_add_exit(str 66 { 67 struct platform_device *pdev = res->da 68 69 platform_device_unregister(pdev); 70 } 71 72 static bool 73 kunit_platform_device_alloc_match(struct kunit 74 struct kunit 75 { 76 struct platform_device *pdev = match_d 77 78 return res->data == pdev && res->free 79 } 80 81 KUNIT_DEFINE_ACTION_WRAPPER(platform_device_un 82 platform_device_un 83 /** 84 * kunit_platform_device_add() - Register a KU 85 * @test: test context 86 * @pdev: platform device to add 87 * 88 * Register a test managed platform device. Th 89 * test completes. 90 * 91 * Return: 0 on success, negative errno on fai 92 */ 93 int kunit_platform_device_add(struct kunit *te 94 { 95 struct kunit_resource *res; 96 int ret; 97 98 ret = platform_device_add(pdev); 99 if (ret) 100 return ret; 101 102 res = kunit_find_resource(test, kunit_ 103 if (res) { 104 /* 105 * Transfer the reference coun 106 * was allocated with kunit_pl 107 * case, calling platform_devi 108 * kunit_platform_device_alloc 109 * count underflow because pla 110 * calls platform_device_unreg 111 * platform_device_put(). 112 * 113 * Usually callers transfer th 114 * platform_device_alloc() to 115 * platform_device_unregister( 116 * succeeds or platform_device 117 * keep this straight by redir 118 * resource to the right funct 119 * account for the success sce 120 */ 121 res->free = kunit_platform_dev 122 kunit_put_resource(res); 123 } else { 124 ret = kunit_add_action_or_rese 125 if (ret) 126 return ret; 127 } 128 129 return 0; 130 } 131 EXPORT_SYMBOL_GPL(kunit_platform_device_add); 132 133 struct kunit_platform_device_probe_nb { 134 struct completion *x; 135 struct device *dev; 136 struct notifier_block nb; 137 }; 138 139 static int kunit_platform_device_probe_notify( 140 141 { 142 struct kunit_platform_device_probe_nb 143 struct device *dev = data; 144 145 knb = container_of(nb, struct kunit_pl 146 if (event != BUS_NOTIFY_BOUND_DRIVER | 147 return NOTIFY_DONE; 148 149 complete(knb->x); 150 151 return NOTIFY_OK; 152 } 153 154 static void kunit_platform_device_probe_nb_rem 155 { 156 bus_unregister_notifier(&platform_bus_ 157 } 158 159 /** 160 * kunit_platform_device_prepare_wait_for_prob 161 * variable to wait for a platform device to p 162 * @test: test context 163 * @pdev: platform device to prepare to wait f 164 * @x: completion variable completed when @dev 165 * 166 * Prepare a completion variable @x to wait fo 167 * completion forces a preemption, allowing th 168 * 169 * Example 170 * 171 * .. code-block:: c 172 * 173 * static int kunit_platform_driver_probe 174 * { 175 * return 0; 176 * } 177 * 178 * static void kunit_platform_driver_test 179 * { 180 * struct platform_device *pdev; 181 * struct platform_driver *pdrv; 182 * DECLARE_COMPLETION_ONSTACK(com 183 * 184 * pdev = kunit_platform_device_a 185 * KUNIT_ASSERT_NOT_ERR_OR_NULL(t 186 * KUNIT_ASSERT_EQ(test, 0, kunit 187 * 188 * pdrv = kunit_kzalloc(test, siz 189 * KUNIT_ASSERT_NOT_ERR_OR_NULL(t 190 * 191 * pdrv->probe = kunit_platform_d 192 * pdrv->driver.name = "kunit-pla 193 * pdrv->driver.owner = THIS_MODU 194 * 195 * KUNIT_ASSERT_EQ(test, 0, kunit 196 * KUNIT_ASSERT_EQ(test, 0, kunit 197 * 198 * KUNIT_EXPECT_NE(test, 0, wait_ 199 * } 200 * 201 * Return: 0 on success, negative errno on fai 202 */ 203 int kunit_platform_device_prepare_wait_for_pro 204 205 206 { 207 struct device *dev = &pdev->dev; 208 struct kunit_platform_device_probe_nb 209 bool bound; 210 211 knb = kunit_kzalloc(test, sizeof(*knb) 212 if (!knb) 213 return -ENOMEM; 214 215 knb->nb.notifier_call = kunit_platform 216 knb->dev = dev; 217 knb->x = x; 218 219 device_lock(dev); 220 bound = device_is_bound(dev); 221 if (bound) { 222 device_unlock(dev); 223 complete(x); 224 kunit_kfree(test, knb); 225 return 0; 226 } 227 228 bus_register_notifier(&platform_bus_ty 229 device_unlock(&pdev->dev); 230 231 return kunit_add_action_or_reset(test, 232 } 233 EXPORT_SYMBOL_GPL(kunit_platform_device_prepar 234 235 KUNIT_DEFINE_ACTION_WRAPPER(platform_driver_un 236 platform_driver_un 237 /** 238 * kunit_platform_driver_register() - Register 239 * @test: test context 240 * @drv: platform driver to register 241 * 242 * Register a test managed platform driver. Th 243 * @drv in a container structure and use conta 244 * to pass information to KUnit tests. 245 * 246 * Example 247 * 248 * .. code-block:: c 249 * 250 * struct kunit_test_context { 251 * struct platform_driver pdrv; 252 * const char *data; 253 * }; 254 * 255 * static inline struct kunit_test_contex 256 * to_test_context(struct platform_device 257 * { 258 * return container_of(to_platfor 259 * struct kun 260 * pdrv); 261 * } 262 * 263 * static int kunit_platform_driver_probe 264 * { 265 * struct kunit_test_context *ctx 266 * 267 * ctx = to_test_context(pdev); 268 * ctx->data = "test data"; 269 * 270 * return 0; 271 * } 272 * 273 * static void kunit_platform_driver_test 274 * { 275 * struct kunit_test_context *ctx 276 * 277 * ctx = kunit_kzalloc(test, size 278 * KUNIT_ASSERT_NOT_ERR_OR_NULL(t 279 * 280 * ctx->pdrv.probe = kunit_platfo 281 * ctx->pdrv.driver.name = "kunit 282 * ctx->pdrv.driver.owner = THIS_ 283 * 284 * KUNIT_EXPECT_EQ(test, 0, kunit 285 * <... wait for driver to probe 286 * KUNIT_EXPECT_STREQ(test, ctx-> 287 * } 288 * 289 * Return: 0 on success, negative errno on fai 290 */ 291 int kunit_platform_driver_register(struct kuni 292 struct plat 293 { 294 int ret; 295 296 ret = platform_driver_register(drv); 297 if (ret) 298 return ret; 299 300 return kunit_add_action_or_reset(test, 301 } 302 EXPORT_SYMBOL_GPL(kunit_platform_driver_regist 303
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.