|
@@ -16,6 +16,7 @@
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/module.h>
|
|
|
#include <linux/smp.h>
|
|
|
+#include <linux/device.h>
|
|
|
|
|
|
#include "tick-internal.h"
|
|
|
|
|
@@ -460,4 +461,89 @@ void clockevents_notify(unsigned long reason, void *arg)
|
|
|
raw_spin_unlock_irqrestore(&clockevents_lock, flags);
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(clockevents_notify);
|
|
|
+
|
|
|
+#ifdef CONFIG_SYSFS
|
|
|
+struct bus_type clockevents_subsys = {
|
|
|
+ .name = "clockevents",
|
|
|
+ .dev_name = "clockevent",
|
|
|
+};
|
|
|
+
|
|
|
+static DEFINE_PER_CPU(struct device, tick_percpu_dev);
|
|
|
+static struct tick_device *tick_get_tick_dev(struct device *dev);
|
|
|
+
|
|
|
+static ssize_t sysfs_show_current_tick_dev(struct device *dev,
|
|
|
+ struct device_attribute *attr,
|
|
|
+ char *buf)
|
|
|
+{
|
|
|
+ struct tick_device *td;
|
|
|
+ ssize_t count = 0;
|
|
|
+
|
|
|
+ raw_spin_lock_irq(&clockevents_lock);
|
|
|
+ td = tick_get_tick_dev(dev);
|
|
|
+ if (td && td->evtdev)
|
|
|
+ count = snprintf(buf, PAGE_SIZE, "%s\n", td->evtdev->name);
|
|
|
+ raw_spin_unlock_irq(&clockevents_lock);
|
|
|
+ return count;
|
|
|
+}
|
|
|
+static DEVICE_ATTR(current_device, 0444, sysfs_show_current_tick_dev, NULL);
|
|
|
+
|
|
|
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
|
|
|
+static struct device tick_bc_dev = {
|
|
|
+ .init_name = "broadcast",
|
|
|
+ .id = 0,
|
|
|
+ .bus = &clockevents_subsys,
|
|
|
+};
|
|
|
+
|
|
|
+static struct tick_device *tick_get_tick_dev(struct device *dev)
|
|
|
+{
|
|
|
+ return dev == &tick_bc_dev ? tick_get_broadcast_device() :
|
|
|
+ &per_cpu(tick_cpu_device, dev->id);
|
|
|
+}
|
|
|
+
|
|
|
+static __init int tick_broadcast_init_sysfs(void)
|
|
|
+{
|
|
|
+ int err = device_register(&tick_bc_dev);
|
|
|
+
|
|
|
+ if (!err)
|
|
|
+ err = device_create_file(&tick_bc_dev, &dev_attr_current_device);
|
|
|
+ return err;
|
|
|
+}
|
|
|
+#else
|
|
|
+static struct tick_device *tick_get_tick_dev(struct device *dev)
|
|
|
+{
|
|
|
+ return &per_cpu(tick_cpu_device, dev->id);
|
|
|
+}
|
|
|
+static inline int tick_broadcast_init_sysfs(void) { return 0; }
|
|
|
#endif
|
|
|
+
|
|
|
+static int __init tick_init_sysfs(void)
|
|
|
+{
|
|
|
+ int cpu;
|
|
|
+
|
|
|
+ for_each_possible_cpu(cpu) {
|
|
|
+ struct device *dev = &per_cpu(tick_percpu_dev, cpu);
|
|
|
+ int err;
|
|
|
+
|
|
|
+ dev->id = cpu;
|
|
|
+ dev->bus = &clockevents_subsys;
|
|
|
+ err = device_register(dev);
|
|
|
+ if (!err)
|
|
|
+ err = device_create_file(dev, &dev_attr_current_device);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+ return tick_broadcast_init_sysfs();
|
|
|
+}
|
|
|
+
|
|
|
+static int __init clockevents_init_sysfs(void)
|
|
|
+{
|
|
|
+ int err = subsys_system_register(&clockevents_subsys, NULL);
|
|
|
+
|
|
|
+ if (!err)
|
|
|
+ err = tick_init_sysfs();
|
|
|
+ return err;
|
|
|
+}
|
|
|
+device_initcall(clockevents_init_sysfs);
|
|
|
+#endif /* SYSFS */
|
|
|
+
|
|
|
+#endif /* GENERIC_CLOCK_EVENTS */
|