History

driver core: Expose device link details in sysfs

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:*

Saravana Kannan committed 6 years ago

Commit 287905e1 parent fe940d75 files · +375 −36Browse files

Unified · Split

5 files
  1. Documentation/ABI/testing/sysfs-class-devlink +126 −0
  2. Documentation/ABI/testing/sysfs-devices-consumer +8 −0
  3. Documentation/ABI/testing/sysfs-devices-supplier +8 −0
  4. drivers/base/core.c +203 −8
  5. include/linux/device.h +30 −28
Documentation/ABI/testing/sysfs-class-devlink+126−0
@@ -0,0 +1,126 @@
1What: /sys/class/devlink/.../
2Date: May 2020
3Contact: Saravana Kannan <saravanak@google.com>
4Description:
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
11What: /sys/class/devlink/.../auto_remove_on
12Date: May 2020
13Contact: Saravana Kannan <saravanak@google.com>
14Description:
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
35What: /sys/class/devlink/.../consumer
36Date: May 2020
37Contact: Saravana Kannan <saravanak@google.com>
38Description:
39 This file is a symlink to the consumer device's sysfs directory.
40
41What: /sys/class/devlink/.../runtime_pm
42Date: May 2020
43Contact: Saravana Kannan <saravanak@google.com>
44Description:
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
55What: /sys/class/devlink/.../status
56Date: May 2020
57Contact: Saravana Kannan <saravanak@google.com>
58Description:
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
101What: /sys/class/devlink/.../supplier
102Date: May 2020
103Contact: Saravana Kannan <saravanak@google.com>
104Description:
105 This file is a symlink to the supplier device's sysfs directory.
106
107What: /sys/class/devlink/.../sync_state_only
108Date: May 2020
109Contact: Saravana Kannan <saravanak@google.com>
110Description:
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.
Documentation/ABI/testing/sysfs-devices-consumer+8−0
@@ -0,0 +1,8 @@
1What: /sys/devices/.../consumer:<consumer>
2Date: May 2020
3Contact: Saravana Kannan <saravanak@google.com>
4Description:
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.
Documentation/ABI/testing/sysfs-devices-supplier+8−0
@@ -0,0 +1,8 @@
1What: /sys/devices/.../supplier:<supplier>
2Date: May 2020
3Contact: Saravana Kannan <saravanak@google.com>
4Description:
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.
drivers/base/core.c+203−8
@@ -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
240static 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}
263static DEVICE_ATTR_RO(status);
264
265static 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}
280static DEVICE_ATTR_RO(auto_remove_on);
281
282static 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}
289static DEVICE_ATTR_RO(runtime_pm);
290
291static 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}
298static DEVICE_ATTR_RO(sync_state_only);
299
300static 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};
307ATTRIBUTE_GROUPS(devlink);
308
309static void devlink_dev_release(struct device *dev)
310{
311 kfree(to_devlink(dev));
312}
313
314static struct class devlink_class = {
315 .name = "devlink",
316 .owner = THIS_MODULE,
317 .dev_groups = devlink_groups,
318 .dev_release = devlink_dev_release,
319};
320
321static 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
357err_sup_dev:
358 snprintf(buf, len, "consumer:%s", dev_name(con));
359 sysfs_remove_link(&sup->kobj, buf);
360err_con_dev:
361 sysfs_remove_link(&link->link_dev.kobj, "consumer");
362err_con:
363 sysfs_remove_link(&link->link_dev.kobj, "supplier");
364out:
365 kfree(buf);
366 return ret;
367}
368
369static 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
396static struct class_interface devlink_class_intf = {
397 .class = &devlink_class,
398 .add_dev = devlink_add_symlinks,
399 .remove_dev = devlink_remove_symlinks,
400};
401
402static 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}
416postcore_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_SRCU743#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);
include/linux/device.h+30−28
@@ -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 */
402struct 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#endif596#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 */
613struct 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
627static inline struct device *kobj_to_dev(struct kobject *kobj)629static 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);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t