Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpu: host1x: Provide a proper struct bus_type

Previously the struct bus_type exported by the host1x infrastructure was
only a very basic skeleton. Turn that implementation into a more full-
fledged bus to support proper probe ordering and power management.

Note that the bus infrastructure needs to be available before any of the
drivers can be registered. This is automatically ensured if all drivers
are built as loadable modules (via symbol dependencies). If all drivers
are built-in there are no such guarantees and the link order determines
the initcall ordering. Adjust drivers/gpu/Makefile to make sure that the
host1x bus infrastructure is initialized prior to any of its users (only
drm/tegra currently).

v2: Fix building host1x and tegra-drm as modules
Reported-by: Dave Airlie <airlied@gmail.com>

Reviewed-by: Sean Paul <seanpaul@chromium.org>
Reviewed-by: Mark Zhang <markz@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>

+107 -49
+4 -1
drivers/gpu/Makefile
··· 1 - obj-y += drm/ vga/ 1 + # drm/tegra depends on host1x, so if both drivers are built-in care must be 2 + # taken to initialize them in the correct order. Link order is the only way 3 + # to ensure this currently. 2 4 obj-$(CONFIG_TEGRA_HOST1X) += host1x/ 5 + obj-y += drm/ vga/ 3 6 obj-$(CONFIG_IMX_IPUV3_CORE) += ipu-v3/
+3 -1
drivers/gpu/drm/tegra/drm.c
··· 912 912 }; 913 913 914 914 static struct host1x_driver host1x_drm_driver = { 915 - .name = "drm", 915 + .driver = { 916 + .name = "drm", 917 + }, 916 918 .probe = host1x_drm_probe, 917 919 .remove = host1x_drm_remove, 918 920 .subdevs = host1x_drm_subdevs,
+80 -39
drivers/gpu/host1x/bus.c
··· 72 72 /** 73 73 * host1x_device_parse_dt() - scan device tree and add matching subdevices 74 74 */ 75 - static int host1x_device_parse_dt(struct host1x_device *device) 75 + static int host1x_device_parse_dt(struct host1x_device *device, 76 + struct host1x_driver *driver) 76 77 { 77 78 struct device_node *np; 78 79 int err; 79 80 80 81 for_each_child_of_node(device->dev.parent->of_node, np) { 81 - if (of_match_node(device->driver->subdevs, np) && 82 + if (of_match_node(driver->subdevs, np) && 82 83 of_device_is_available(np)) { 83 84 err = host1x_subdev_add(device, np); 84 85 if (err < 0) ··· 110 109 mutex_unlock(&device->clients_lock); 111 110 mutex_unlock(&device->subdevs_lock); 112 111 113 - /* 114 - * When all subdevices have been registered, the composite device is 115 - * ready to be probed. 116 - */ 117 112 if (list_empty(&device->subdevs)) { 118 - err = device->driver->probe(device); 113 + err = device_add(&device->dev); 119 114 if (err < 0) 120 - dev_err(&device->dev, "probe failed for %ps: %d\n", 121 - device->driver, err); 115 + dev_err(&device->dev, "failed to add: %d\n", err); 122 116 else 123 - device->bound = true; 117 + device->registered = true; 124 118 } 125 119 } 126 120 ··· 123 127 struct host1x_subdev *subdev) 124 128 { 125 129 struct host1x_client *client = subdev->client; 126 - int err; 127 130 128 131 /* 129 132 * If all subdevices have been activated, we're about to remove the 130 133 * first active subdevice, so unload the driver first. 131 134 */ 132 - if (list_empty(&device->subdevs) && device->bound) { 133 - err = device->driver->remove(device); 134 - if (err < 0) 135 - dev_err(&device->dev, "remove failed: %d\n", err); 136 - 137 - device->bound = false; 135 + if (list_empty(&device->subdevs)) { 136 + if (device->registered) { 137 + device->registered = false; 138 + device_del(&device->dev); 139 + } 138 140 } 139 141 140 142 /* ··· 259 265 return -ENODEV; 260 266 } 261 267 262 - static struct bus_type host1x_bus_type = { 263 - .name = "host1x", 268 + static int host1x_device_match(struct device *dev, struct device_driver *drv) 269 + { 270 + return strcmp(dev_name(dev), drv->name) == 0; 271 + } 272 + 273 + static int host1x_device_probe(struct device *dev) 274 + { 275 + struct host1x_driver *driver = to_host1x_driver(dev->driver); 276 + struct host1x_device *device = to_host1x_device(dev); 277 + 278 + if (driver->probe) 279 + return driver->probe(device); 280 + 281 + return 0; 282 + } 283 + 284 + static int host1x_device_remove(struct device *dev) 285 + { 286 + struct host1x_driver *driver = to_host1x_driver(dev->driver); 287 + struct host1x_device *device = to_host1x_device(dev); 288 + 289 + if (driver->remove) 290 + return driver->remove(device); 291 + 292 + return 0; 293 + } 294 + 295 + static void host1x_device_shutdown(struct device *dev) 296 + { 297 + struct host1x_driver *driver = to_host1x_driver(dev->driver); 298 + struct host1x_device *device = to_host1x_device(dev); 299 + 300 + if (driver->shutdown) 301 + driver->shutdown(device); 302 + } 303 + 304 + static const struct dev_pm_ops host1x_device_pm_ops = { 305 + .suspend = pm_generic_suspend, 306 + .resume = pm_generic_resume, 307 + .freeze = pm_generic_freeze, 308 + .thaw = pm_generic_thaw, 309 + .poweroff = pm_generic_poweroff, 310 + .restore = pm_generic_restore, 264 311 }; 265 312 266 - int host1x_bus_init(void) 267 - { 268 - return bus_register(&host1x_bus_type); 269 - } 270 - 271 - void host1x_bus_exit(void) 272 - { 273 - bus_unregister(&host1x_bus_type); 274 - } 313 + struct bus_type host1x_bus_type = { 314 + .name = "host1x", 315 + .match = host1x_device_match, 316 + .probe = host1x_device_probe, 317 + .remove = host1x_device_remove, 318 + .shutdown = host1x_device_shutdown, 319 + .pm = &host1x_device_pm_ops, 320 + }; 275 321 276 322 static void __host1x_device_del(struct host1x_device *device) 277 323 { ··· 381 347 if (!device) 382 348 return -ENOMEM; 383 349 350 + device_initialize(&device->dev); 351 + 384 352 mutex_init(&device->subdevs_lock); 385 353 INIT_LIST_HEAD(&device->subdevs); 386 354 INIT_LIST_HEAD(&device->active); ··· 393 357 394 358 device->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask; 395 359 device->dev.dma_mask = &device->dev.coherent_dma_mask; 360 + dev_set_name(&device->dev, "%s", driver->driver.name); 396 361 device->dev.release = host1x_device_release; 397 - dev_set_name(&device->dev, "%s", driver->name); 398 362 device->dev.bus = &host1x_bus_type; 399 363 device->dev.parent = host1x->dev; 400 364 401 - err = device_register(&device->dev); 402 - if (err < 0) 403 - return err; 404 - 405 - err = host1x_device_parse_dt(device); 365 + err = host1x_device_parse_dt(device, driver); 406 366 if (err < 0) { 407 - device_unregister(&device->dev); 367 + kfree(device); 408 368 return err; 409 369 } 410 370 ··· 431 399 static void host1x_device_del(struct host1x *host1x, 432 400 struct host1x_device *device) 433 401 { 434 - device_unregister(&device->dev); 402 + if (device->registered) { 403 + device->registered = false; 404 + device_del(&device->dev); 405 + } 406 + 407 + put_device(&device->dev); 435 408 } 436 409 437 410 static void host1x_attach_driver(struct host1x *host1x, ··· 511 474 return 0; 512 475 } 513 476 514 - int host1x_driver_register(struct host1x_driver *driver) 477 + int host1x_driver_register_full(struct host1x_driver *driver, 478 + struct module *owner) 515 479 { 516 480 struct host1x *host1x; 517 481 ··· 529 491 530 492 mutex_unlock(&devices_lock); 531 493 532 - return 0; 494 + driver->driver.bus = &host1x_bus_type; 495 + driver->driver.owner = owner; 496 + 497 + return driver_register(&driver->driver); 533 498 } 534 - EXPORT_SYMBOL(host1x_driver_register); 499 + EXPORT_SYMBOL(host1x_driver_register_full); 535 500 536 501 void host1x_driver_unregister(struct host1x_driver *driver) 537 502 {
+2 -2
drivers/gpu/host1x/bus.h
··· 18 18 #ifndef HOST1X_BUS_H 19 19 #define HOST1X_BUS_H 20 20 21 + struct bus_type; 21 22 struct host1x; 22 23 23 - int host1x_bus_init(void); 24 - void host1x_bus_exit(void); 24 + extern struct bus_type host1x_bus_type; 25 25 26 26 int host1x_register(struct host1x *host1x); 27 27 int host1x_unregister(struct host1x *host1x);
+3 -3
drivers/gpu/host1x/dev.c
··· 216 216 { 217 217 int err; 218 218 219 - err = host1x_bus_init(); 219 + err = bus_register(&host1x_bus_type); 220 220 if (err < 0) 221 221 return err; 222 222 ··· 233 233 unregister_host1x: 234 234 platform_driver_unregister(&tegra_host1x_driver); 235 235 unregister_bus: 236 - host1x_bus_exit(); 236 + bus_unregister(&host1x_bus_type); 237 237 return err; 238 238 } 239 239 module_init(tegra_host1x_init); ··· 242 242 { 243 243 platform_driver_unregister(&tegra_mipi_driver); 244 244 platform_driver_unregister(&tegra_host1x_driver); 245 - host1x_bus_exit(); 245 + bus_unregister(&host1x_bus_type); 246 246 } 247 247 module_exit(tegra_host1x_exit); 248 248
+15 -3
include/linux/host1x.h
··· 250 250 struct host1x_device; 251 251 252 252 struct host1x_driver { 253 + struct device_driver driver; 254 + 253 255 const struct of_device_id *subdevs; 254 256 struct list_head list; 255 - const char *name; 256 257 257 258 int (*probe)(struct host1x_device *device); 258 259 int (*remove)(struct host1x_device *device); 260 + void (*shutdown)(struct host1x_device *device); 259 261 }; 260 262 261 - int host1x_driver_register(struct host1x_driver *driver); 263 + static inline struct host1x_driver * 264 + to_host1x_driver(struct device_driver *driver) 265 + { 266 + return container_of(driver, struct host1x_driver, driver); 267 + } 268 + 269 + int host1x_driver_register_full(struct host1x_driver *driver, 270 + struct module *owner); 262 271 void host1x_driver_unregister(struct host1x_driver *driver); 272 + 273 + #define host1x_driver_register(driver) \ 274 + host1x_driver_register_full(driver, THIS_MODULE) 263 275 264 276 struct host1x_device { 265 277 struct host1x_driver *driver; ··· 285 273 struct mutex clients_lock; 286 274 struct list_head clients; 287 275 288 - bool bound; 276 + bool registered; 289 277 }; 290 278 291 279 static inline struct host1x_device *to_host1x_device(struct device *dev)