It's helpful to be able to look at device link details from sysfs. So, expose it in sysfs. Say device-A is supplier of device-B. These are the additional files this patch would create: /sys/class/devlink/device-A:device-B/ auto_remove_on consumer/ -> .../device-B/ runtime_pm status supplier/ -> .../device-A/ sync_state_only /sys/devices/.../device-A/ consumer:device-B/ -> /sys/class/devlink/device-A:device-B/ /sys/devices/.../device-B/ supplier:device-A/ -> /sys/class/devlink/device-A:device-B/ That way: To get a list of all the device link in the system: ls /sys/class/devlink/ To get the consumer names and links of a device: ls -d /sys/devices/.../device-X/consumer:* To get the supplier names and links of a device: ls -d /sys/devices/.../device-X/supplier:*
Unified · Split
| @@ -0,0 +1,126 @@ | |||
| 1 | What: /sys/class/devlink/.../ | ||
| 2 | Date: May 2020 | ||
| 3 | Contact: Saravana Kannan <saravanak@google.com> | ||
| 4 | Description: | ||
| 5 | Provide a place in sysfs for the device link objects in the | ||
| 6 | kernel at any given time. The name of a device link directory, | ||
| 7 | denoted as ... above, is of the form <supplier>:<consumer> | ||
| 8 | where <supplier> is the supplier device name and <consumer> is | ||
| 9 | the consumer device name. | ||
| 10 | |||
| 11 | What: /sys/class/devlink/.../auto_remove_on | ||
| 12 | Date: May 2020 | ||
| 13 | Contact: Saravana Kannan <saravanak@google.com> | ||
| 14 | Description: | ||
| 15 | This file indicates if the device link will ever be | ||
| 16 | automatically removed by the driver core when the consumer and | ||
| 17 | supplier devices themselves are still present. | ||
| 18 | |||
| 19 | This will be one of the following strings: | ||
| 20 | |||
| 21 | 'consumer unbind' | ||
| 22 | 'supplier unbind' | ||
| 23 | 'never' | ||
| 24 | |||
| 25 | 'consumer unbind' means the device link will be removed when | ||
| 26 | the consumer's driver is unbound from the consumer device. | ||
| 27 | |||
| 28 | 'supplier unbind' means the device link will be removed when | ||
| 29 | the supplier's driver is unbound from the supplier device. | ||
| 30 | |||
| 31 | 'never' means the device link will not be automatically removed | ||
| 32 | when as long as the supplier and consumer devices themselves | ||
| 33 | are still present. | ||
| 34 | |||
| 35 | What: /sys/class/devlink/.../consumer | ||
| 36 | Date: May 2020 | ||
| 37 | Contact: Saravana Kannan <saravanak@google.com> | ||
| 38 | Description: | ||
| 39 | This file is a symlink to the consumer device's sysfs directory. | ||
| 40 | |||
| 41 | What: /sys/class/devlink/.../runtime_pm | ||
| 42 | Date: May 2020 | ||
| 43 | Contact: Saravana Kannan <saravanak@google.com> | ||
| 44 | Description: | ||
| 45 | This file indicates if the device link has any impact on the | ||
| 46 | runtime power management behavior of the consumer and supplier | ||
| 47 | devices. For example: Making sure the supplier doesn't enter | ||
| 48 | runtime suspend while the consumer is active. | ||
| 49 | |||
| 50 | This will be one of the following strings: | ||
| 51 | |||
| 52 | '0' - Does not affect runtime power management | ||
| 53 | '1' - Affects runtime power management | ||
| 54 | |||
| 55 | What: /sys/class/devlink/.../status | ||
| 56 | Date: May 2020 | ||
| 57 | Contact: Saravana Kannan <saravanak@google.com> | ||
| 58 | Description: | ||
| 59 | This file indicates the status of the device link. The status | ||
| 60 | of a device link is affected by whether the supplier and | ||
| 61 | consumer devices have been bound to their corresponding | ||
| 62 | drivers. The status of a device link also affects the binding | ||
| 63 | and unbinding of the supplier and consumer devices with their | ||
| 64 | drivers and also affects whether the software state of the | ||
| 65 | supplier device is synced with the hardware state of the | ||
| 66 | supplier device after boot up. | ||
| 67 | See also: sysfs-devices-state_synced. | ||
| 68 | |||
| 69 | This will be one of the following strings: | ||
| 70 | |||
| 71 | 'not tracked' | ||
| 72 | 'dormant' | ||
| 73 | 'available' | ||
| 74 | 'consumer probing' | ||
| 75 | 'active' | ||
| 76 | 'supplier unbinding' | ||
| 77 | 'unknown' | ||
| 78 | |||
| 79 | 'not tracked' means this device link does not track the status | ||
| 80 | and has no impact on the binding, unbinding and syncing the | ||
| 81 | hardware and software device state. | ||
| 82 | |||
| 83 | 'dormant' means the supplier and the consumer devices have not | ||
| 84 | bound to their driver. | ||
| 85 | |||
| 86 | 'available' means the supplier has bound to its driver and is | ||
| 87 | available to supply resources to the consumer device. | ||
| 88 | |||
| 89 | 'consumer probing' means the consumer device is currently | ||
| 90 | trying to bind to its driver. | ||
| 91 | |||
| 92 | 'active' means the supplier and consumer devices have both | ||
| 93 | bound successfully to their drivers. | ||
| 94 | |||
| 95 | 'supplier unbinding' means the supplier devices is currently in | ||
| 96 | the process of unbinding from its driver. | ||
| 97 | |||
| 98 | 'unknown' means the state of the device link is not any of the | ||
| 99 | above. If this is ever the value, there's a bug in the kernel. | ||
| 100 | |||
| 101 | What: /sys/class/devlink/.../supplier | ||
| 102 | Date: May 2020 | ||
| 103 | Contact: Saravana Kannan <saravanak@google.com> | ||
| 104 | Description: | ||
| 105 | This file is a symlink to the supplier device's sysfs directory. | ||
| 106 | |||
| 107 | What: /sys/class/devlink/.../sync_state_only | ||
| 108 | Date: May 2020 | ||
| 109 | Contact: Saravana Kannan <saravanak@google.com> | ||
| 110 | Description: | ||
| 111 | This file indicates if the device link is limited to only | ||
| 112 | affecting the syncing of the hardware and software state of the | ||
| 113 | supplier device. | ||
| 114 | |||
| 115 | This will be one of the following strings: | ||
| 116 | |||
| 117 | '0' | ||
| 118 | '1' - Affects runtime power management | ||
| 119 | |||
| 120 | '0' means the device link can affect other device behaviors | ||
| 121 | like binding/unbinding, suspend/resume, runtime power | ||
| 122 | management, etc. | ||
| 123 | |||
| 124 | '1' means the device link will only affect the syncing of | ||
| 125 | hardware and software state of the supplier device after boot | ||
| 126 | up and doesn't not affect other behaviors of the devices. | ||
| @@ -0,0 +1,8 @@ | |||
| 1 | What: /sys/devices/.../consumer:<consumer> | ||
| 2 | Date: May 2020 | ||
| 3 | Contact: Saravana Kannan <saravanak@google.com> | ||
| 4 | Description: | ||
| 5 | The /sys/devices/.../consumer:<consumer> are symlinks to device | ||
| 6 | links where this device is the supplier. <consumer> denotes the | ||
| 7 | name of the consumer in that device link. There can be zero or | ||
| 8 | more of these symlinks for a given device. | ||
| @@ -0,0 +1,8 @@ | |||
| 1 | What: /sys/devices/.../supplier:<supplier> | ||
| 2 | Date: May 2020 | ||
| 3 | Contact: Saravana Kannan <saravanak@google.com> | ||
| 4 | Description: | ||
| 5 | The /sys/devices/.../supplier:<supplier> are symlinks to device | ||
| 6 | links where this device is the consumer. <supplier> denotes the | ||
| 7 | name of the supplier in that device link. There can be zero or | ||
| 8 | more of these symlinks for a given device. | ||
| @@ -235,6 +235,186 @@ void device_pm_move_to_tail(struct device *dev) · 234 unmodified lines | |||
| 235 | device_links_read_unlock(idx); | 235 | device_links_read_unlock(idx); |
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | #define to_devlink(dev) container_of((dev), struct device_link, link_dev) | ||
| 239 | |||
| 240 | static ssize_t status_show(struct device *dev, | ||
| 241 | struct device_attribute *attr, char *buf) | ||
| 242 | { | ||
| 243 | char *status; | ||
| 244 | |||
| 245 | switch (to_devlink(dev)->status) { | ||
| 246 | case DL_STATE_NONE: | ||
| 247 | status = "not tracked"; break; | ||
| 248 | case DL_STATE_DORMANT: | ||
| 249 | status = "dormant"; break; | ||
| 250 | case DL_STATE_AVAILABLE: | ||
| 251 | status = "available"; break; | ||
| 252 | case DL_STATE_CONSUMER_PROBE: | ||
| 253 | status = "consumer probing"; break; | ||
| 254 | case DL_STATE_ACTIVE: | ||
| 255 | status = "active"; break; | ||
| 256 | case DL_STATE_SUPPLIER_UNBIND: | ||
| 257 | status = "supplier unbinding"; break; | ||
| 258 | default: | ||
| 259 | status = "unknown"; break; | ||
| 260 | } | ||
| 261 | return sprintf(buf, "%s\n", status); | ||
| 262 | } | ||
| 263 | static DEVICE_ATTR_RO(status); | ||
| 264 | |||
| 265 | static ssize_t auto_remove_on_show(struct device *dev, | ||
| 266 | struct device_attribute *attr, char *buf) | ||
| 267 | { | ||
| 268 | struct device_link *link = to_devlink(dev); | ||
| 269 | char *str; | ||
| 270 | |||
| 271 | if (link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER) | ||
| 272 | str = "supplier unbind"; | ||
| 273 | else if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) | ||
| 274 | str = "consumer unbind"; | ||
| 275 | else | ||
| 276 | str = "never"; | ||
| 277 | |||
| 278 | return sprintf(buf, "%s\n", str); | ||
| 279 | } | ||
| 280 | static DEVICE_ATTR_RO(auto_remove_on); | ||
| 281 | |||
| 282 | static ssize_t runtime_pm_show(struct device *dev, | ||
| 283 | struct device_attribute *attr, char *buf) | ||
| 284 | { | ||
| 285 | struct device_link *link = to_devlink(dev); | ||
| 286 | |||
| 287 | return sprintf(buf, "%d\n", !!(link->flags & DL_FLAG_PM_RUNTIME)); | ||
| 288 | } | ||
| 289 | static DEVICE_ATTR_RO(runtime_pm); | ||
| 290 | |||
| 291 | static ssize_t sync_state_only_show(struct device *dev, | ||
| 292 | struct device_attribute *attr, char *buf) | ||
| 293 | { | ||
| 294 | struct device_link *link = to_devlink(dev); | ||
| 295 | |||
| 296 | return sprintf(buf, "%d\n", !!(link->flags & DL_FLAG_SYNC_STATE_ONLY)); | ||
| 297 | } | ||
| 298 | static DEVICE_ATTR_RO(sync_state_only); | ||
| 299 | |||
| 300 | static struct attribute *devlink_attrs[] = { | ||
| 301 | &dev_attr_status.attr, | ||
| 302 | &dev_attr_auto_remove_on.attr, | ||
| 303 | &dev_attr_runtime_pm.attr, | ||
| 304 | &dev_attr_sync_state_only.attr, | ||
| 305 | NULL, | ||
| 306 | }; | ||
| 307 | ATTRIBUTE_GROUPS(devlink); | ||
| 308 | |||
| 309 | static void devlink_dev_release(struct device *dev) | ||
| 310 | { | ||
| 311 | kfree(to_devlink(dev)); | ||
| 312 | } | ||
| 313 | |||
| 314 | static struct class devlink_class = { | ||
| 315 | .name = "devlink", | ||
| 316 | .owner = THIS_MODULE, | ||
| 317 | .dev_groups = devlink_groups, | ||
| 318 | .dev_release = devlink_dev_release, | ||
| 319 | }; | ||
| 320 | |||
| 321 | static int devlink_add_symlinks(struct device *dev, | ||
| 322 | struct class_interface *class_intf) | ||
| 323 | { | ||
| 324 | int ret; | ||
| 325 | size_t len; | ||
| 326 | struct device_link *link = to_devlink(dev); | ||
| 327 | struct device *sup = link->supplier; | ||
| 328 | struct device *con = link->consumer; | ||
| 329 | char *buf; | ||
| 330 | |||
| 331 | len = max(strlen(dev_name(sup)), strlen(dev_name(con))); | ||
| 332 | len += strlen("supplier:") + 1; | ||
| 333 | buf = kzalloc(len, GFP_KERNEL); | ||
| 334 | if (!buf) | ||
| 335 | return -ENOMEM; | ||
| 336 | |||
| 337 | ret = sysfs_create_link(&link->link_dev.kobj, &sup->kobj, "supplier"); | ||
| 338 | if (ret) | ||
| 339 | goto out; | ||
| 340 | |||
| 341 | ret = sysfs_create_link(&link->link_dev.kobj, &con->kobj, "consumer"); | ||
| 342 | if (ret) | ||
| 343 | goto err_con; | ||
| 344 | |||
| 345 | snprintf(buf, len, "consumer:%s", dev_name(con)); | ||
| 346 | ret = sysfs_create_link(&sup->kobj, &link->link_dev.kobj, buf); | ||
| 347 | if (ret) | ||
| 348 | goto err_con_dev; | ||
| 349 | |||
| 350 | snprintf(buf, len, "supplier:%s", dev_name(sup)); | ||
| 351 | ret = sysfs_create_link(&con->kobj, &link->link_dev.kobj, buf); | ||
| 352 | if (ret) | ||
| 353 | goto err_sup_dev; | ||
| 354 | |||
| 355 | goto out; | ||
| 356 | |||
| 357 | err_sup_dev: | ||
| 358 | snprintf(buf, len, "consumer:%s", dev_name(con)); | ||
| 359 | sysfs_remove_link(&sup->kobj, buf); | ||
| 360 | err_con_dev: | ||
| 361 | sysfs_remove_link(&link->link_dev.kobj, "consumer"); | ||
| 362 | err_con: | ||
| 363 | sysfs_remove_link(&link->link_dev.kobj, "supplier"); | ||
| 364 | out: | ||
| 365 | kfree(buf); | ||
| 366 | return ret; | ||
| 367 | } | ||
| 368 | |||
| 369 | static void devlink_remove_symlinks(struct device *dev, | ||
| 370 | struct class_interface *class_intf) | ||
| 371 | { | ||
| 372 | struct device_link *link = to_devlink(dev); | ||
| 373 | size_t len; | ||
| 374 | struct device *sup = link->supplier; | ||
| 375 | struct device *con = link->consumer; | ||
| 376 | char *buf; | ||
| 377 | |||
| 378 | sysfs_remove_link(&link->link_dev.kobj, "consumer"); | ||
| 379 | sysfs_remove_link(&link->link_dev.kobj, "supplier"); | ||
| 380 | |||
| 381 | len = max(strlen(dev_name(sup)), strlen(dev_name(con))); | ||
| 382 | len += strlen("supplier:") + 1; | ||
| 383 | buf = kzalloc(len, GFP_KERNEL); | ||
| 384 | if (!buf) { | ||
| 385 | WARN(1, "Unable to properly free device link symlinks!\n"); | ||
| 386 | return; | ||
| 387 | } | ||
| 388 | |||
| 389 | snprintf(buf, len, "supplier:%s", dev_name(sup)); | ||
| 390 | sysfs_remove_link(&con->kobj, buf); | ||
| 391 | snprintf(buf, len, "consumer:%s", dev_name(con)); | ||
| 392 | sysfs_remove_link(&sup->kobj, buf); | ||
| 393 | kfree(buf); | ||
| 394 | } | ||
| 395 | |||
| 396 | static struct class_interface devlink_class_intf = { | ||
| 397 | .class = &devlink_class, | ||
| 398 | .add_dev = devlink_add_symlinks, | ||
| 399 | .remove_dev = devlink_remove_symlinks, | ||
| 400 | }; | ||
| 401 | |||
| 402 | static int __init devlink_class_init(void) | ||
| 403 | { | ||
| 404 | int ret; | ||
| 405 | |||
| 406 | ret = class_register(&devlink_class); | ||
| 407 | if (ret) | ||
| 408 | return ret; | ||
| 409 | |||
| 410 | ret = class_interface_register(&devlink_class_intf); | ||
| 411 | if (ret) | ||
| 412 | class_unregister(&devlink_class); | ||
| 413 | |||
| 414 | return ret; | ||
| 415 | } | ||
| 416 | postcore_initcall(devlink_class_init); | ||
| 417 | |||
| 238 | #define DL_MANAGED_LINK_FLAGS (DL_FLAG_AUTOREMOVE_CONSUMER | \ | 418 | #define DL_MANAGED_LINK_FLAGS (DL_FLAG_AUTOREMOVE_CONSUMER | \ |
| 239 | DL_FLAG_AUTOREMOVE_SUPPLIER | \ | 419 | DL_FLAG_AUTOREMOVE_SUPPLIER | \ |
| 240 | DL_FLAG_AUTOPROBE_CONSUMER | \ | 420 | DL_FLAG_AUTOPROBE_CONSUMER | \ |
| @@ -407,13 +587,6 @@ struct device_link *device_link_add(struct device *consumer, · 166 unmodified lines | |||
| 407 | 587 | ||
| 408 | refcount_set(&link->rpm_active, 1); | 588 | refcount_set(&link->rpm_active, 1); |
| 409 | 589 | ||
| 410 | if (flags & DL_FLAG_PM_RUNTIME) { | ||
| 411 | if (flags & DL_FLAG_RPM_ACTIVE) | ||
| 412 | refcount_inc(&link->rpm_active); | ||
| 413 | |||
| 414 | pm_runtime_new_link(consumer); | ||
| 415 | } | ||
| 416 | |||
| 417 | get_device(supplier); | 590 | get_device(supplier); |
| 418 | link->supplier = supplier; | 591 | link->supplier = supplier; |
| 419 | INIT_LIST_HEAD(&link->s_node); | 592 | INIT_LIST_HEAD(&link->s_node); |
| @@ -423,6 +596,25 @@ struct device_link *device_link_add(struct device *consumer, · 3 unmodified lines | |||
| 423 | link->flags = flags; | 596 | link->flags = flags; |
| 424 | kref_init(&link->kref); | 597 | kref_init(&link->kref); |
| 425 | 598 | ||
| 599 | link->link_dev.class = &devlink_class; | ||
| 600 | device_set_pm_not_required(&link->link_dev); | ||
| 601 | dev_set_name(&link->link_dev, "%s:%s", | ||
| 602 | dev_name(supplier), dev_name(consumer)); | ||
| 603 | if (device_register(&link->link_dev)) { | ||
| 604 | put_device(consumer); | ||
| 605 | put_device(supplier); | ||
| 606 | kfree(link); | ||
| 607 | link = NULL; | ||
| 608 | goto out; | ||
| 609 | } | ||
| 610 | |||
| 611 | if (flags & DL_FLAG_PM_RUNTIME) { | ||
| 612 | if (flags & DL_FLAG_RPM_ACTIVE) | ||
| 613 | refcount_inc(&link->rpm_active); | ||
| 614 | |||
| 615 | pm_runtime_new_link(consumer); | ||
| 616 | } | ||
| 617 | |||
| 426 | /* Determine the initial link state. */ | 618 | /* Determine the initial link state. */ |
| 427 | if (flags & DL_FLAG_STATELESS) | 619 | if (flags & DL_FLAG_STATELESS) |
| 428 | link->status = DL_STATE_NONE; | 620 | link->status = DL_STATE_NONE; |
| @@ -545,7 +737,7 @@ static void device_link_free(struct device_link *link) · 116 unmodified lines | |||
| 545 | 737 | ||
| 546 | put_device(link->consumer); | 738 | put_device(link->consumer); |
| 547 | put_device(link->supplier); | 739 | put_device(link->supplier); |
| 548 | kfree(link); | 740 | device_unregister(&link->link_dev); |
| 549 | } | 741 | } |
| 550 | 742 | ||
| 551 | #ifdef CONFIG_SRCU | 743 | #ifdef CONFIG_SRCU |
| @@ -1159,6 +1351,9 @@ static void device_links_purge(struct device *dev) · 607 unmodified lines | |||
| 1159 | { | 1351 | { |
| 1160 | struct device_link *link, *ln; | 1352 | struct device_link *link, *ln; |
| 1161 | 1353 | ||
| 1354 | if (dev->class == &devlink_class) | ||
| 1355 | return; | ||
| 1356 | |||
| 1162 | mutex_lock(&wfs_lock); | 1357 | mutex_lock(&wfs_lock); |
| 1163 | list_del(&dev->links.needs_suppliers); | 1358 | list_del(&dev->links.needs_suppliers); |
| 1164 | mutex_unlock(&wfs_lock); | 1359 | mutex_unlock(&wfs_lock); |
| @@ -386,34 +386,6 @@ enum device_link_state { · 385 unmodified lines | |||
| 386 | #define DL_FLAG_MANAGED BIT(6) | 386 | #define DL_FLAG_MANAGED BIT(6) |
| 387 | #define DL_FLAG_SYNC_STATE_ONLY BIT(7) | 387 | #define DL_FLAG_SYNC_STATE_ONLY BIT(7) |
| 388 | 388 | ||
| 389 | /** | ||
| 390 | * struct device_link - Device link representation. | ||
| 391 | * @supplier: The device on the supplier end of the link. | ||
| 392 | * @s_node: Hook to the supplier device's list of links to consumers. | ||
| 393 | * @consumer: The device on the consumer end of the link. | ||
| 394 | * @c_node: Hook to the consumer device's list of links to suppliers. | ||
| 395 | * @status: The state of the link (with respect to the presence of drivers). | ||
| 396 | * @flags: Link flags. | ||
| 397 | * @rpm_active: Whether or not the consumer device is runtime-PM-active. | ||
| 398 | * @kref: Count repeated addition of the same link. | ||
| 399 | * @rcu_head: An RCU head to use for deferred execution of SRCU callbacks. | ||
| 400 | * @supplier_preactivated: Supplier has been made active before consumer probe. | ||
| 401 | */ | ||
| 402 | struct device_link { | ||
| 403 | struct device *supplier; | ||
| 404 | struct list_head s_node; | ||
| 405 | struct device *consumer; | ||
| 406 | struct list_head c_node; | ||
| 407 | enum device_link_state status; | ||
| 408 | u32 flags; | ||
| 409 | refcount_t rpm_active; | ||
| 410 | struct kref kref; | ||
| 411 | #ifdef CONFIG_SRCU | ||
| 412 | struct rcu_head rcu_head; | ||
| 413 | #endif | ||
| 414 | bool supplier_preactivated; /* Owned by consumer probe. */ | ||
| 415 | }; | ||
| 416 | |||
| 417 | /** | 389 | /** |
| 418 | * enum dl_dev_state - Device driver presence tracking information. | 390 | * enum dl_dev_state - Device driver presence tracking information. |
| 419 | * @DL_DEV_NO_DRIVER: There is no driver attached to the device. | 391 | * @DL_DEV_NO_DRIVER: There is no driver attached to the device. |
| @@ -624,6 +596,36 @@ struct device { · 204 unmodified lines | |||
| 624 | #endif | 596 | #endif |
| 625 | }; | 597 | }; |
| 626 | 598 | ||
| 599 | /** | ||
| 600 | * struct device_link - Device link representation. | ||
| 601 | * @supplier: The device on the supplier end of the link. | ||
| 602 | * @s_node: Hook to the supplier device's list of links to consumers. | ||
| 603 | * @consumer: The device on the consumer end of the link. | ||
| 604 | * @c_node: Hook to the consumer device's list of links to suppliers. | ||
| 605 | * @link_dev: device used to expose link details in sysfs | ||
| 606 | * @status: The state of the link (with respect to the presence of drivers). | ||
| 607 | * @flags: Link flags. | ||
| 608 | * @rpm_active: Whether or not the consumer device is runtime-PM-active. | ||
| 609 | * @kref: Count repeated addition of the same link. | ||
| 610 | * @rcu_head: An RCU head to use for deferred execution of SRCU callbacks. | ||
| 611 | * @supplier_preactivated: Supplier has been made active before consumer probe. | ||
| 612 | */ | ||
| 613 | struct device_link { | ||
| 614 | struct device *supplier; | ||
| 615 | struct list_head s_node; | ||
| 616 | struct device *consumer; | ||
| 617 | struct list_head c_node; | ||
| 618 | struct device link_dev; | ||
| 619 | enum device_link_state status; | ||
| 620 | u32 flags; | ||
| 621 | refcount_t rpm_active; | ||
| 622 | struct kref kref; | ||
| 623 | #ifdef CONFIG_SRCU | ||
| 624 | struct rcu_head rcu_head; | ||
| 625 | #endif | ||
| 626 | bool supplier_preactivated; /* Owned by consumer probe. */ | ||
| 627 | }; | ||
| 628 | |||
| 627 | static inline struct device *kobj_to_dev(struct kobject *kobj) | 629 | static inline struct device *kobj_to_dev(struct kobject *kobj) |
| 628 | { | 630 | { |
| 629 | return container_of(kobj, struct device, kobj); | 631 | return container_of(kobj, struct device, kobj); |