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 @@
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.
Documentation/ABI/testing/sysfs-devices-consumer+8−0
@@ -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.
Documentation/ABI/testing/sysfs-devices-supplier+8−0
@@ -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.
drivers/base/core.c+203−8
@@ -235,6 +235,186 @@ void device_pm_move_to_tail(struct device *dev) · 234 unmodified lines
235235 device_links_read_unlock(idx);
236236 }
237237
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+
238418 #define DL_MANAGED_LINK_FLAGS (DL_FLAG_AUTOREMOVE_CONSUMER | \
239419 DL_FLAG_AUTOREMOVE_SUPPLIER | \
240420 DL_FLAG_AUTOPROBE_CONSUMER | \
@@ -407,13 +587,6 @@ struct device_link *device_link_add(struct device *consumer, · 166 unmodified lines
407587
408588 refcount_set(&link->rpm_active, 1);
409589
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−
417590 get_device(supplier);
418591 link->supplier = supplier;
419592 INIT_LIST_HEAD(&link->s_node);
@@ -423,6 +596,25 @@ struct device_link *device_link_add(struct device *consumer, · 3 unmodified lines
423596 link->flags = flags;
424597 kref_init(&link->kref);
425598
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+
426618 /* Determine the initial link state. */
427619 if (flags & DL_FLAG_STATELESS)
428620 link->status = DL_STATE_NONE;
@@ -545,7 +737,7 @@ static void device_link_free(struct device_link *link) · 116 unmodified lines
545737
546738 put_device(link->consumer);
547739 put_device(link->supplier);
548− kfree(link);
740+ device_unregister(&link->link_dev);
549741 }
550742
551743 #ifdef CONFIG_SRCU
@@ -1159,6 +1351,9 @@ static void device_links_purge(struct device *dev) · 607 unmodified lines
11591351 {
11601352 struct device_link *link, *ln;
11611353
1354+ if (dev->class == &devlink_class)
1355+ return;
1356+
11621357 mutex_lock(&wfs_lock);
11631358 list_del(&dev->links.needs_suppliers);
11641359 mutex_unlock(&wfs_lock);
include/linux/device.h+30−28
@@ -386,34 +386,6 @@ enum device_link_state { · 385 unmodified lines
386386 #define DL_FLAG_MANAGED BIT(6)
387387 #define DL_FLAG_SYNC_STATE_ONLY BIT(7)
388388
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−
417389 /**
418390 * enum dl_dev_state - Device driver presence tracking information.
419391 * @DL_DEV_NO_DRIVER: There is no driver attached to the device.
@@ -624,6 +596,36 @@ struct device { · 204 unmodified lines
624596 #endif
625597 };
626598
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+
627629 static inline struct device *kobj_to_dev(struct kobject *kobj)
628630 {
629631 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