#ifdef CONFIG_SYSFS static 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);
/* We don't support the abomination of removable broadcast devices */ static ssize_t sysfs_unbind_tick_dev(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { char name[CS_NAME_LEN]; ssize_t ret = sysfs_get_uname(buf, name, count); struct clock_event_device *ce;
if (ret < 0) return ret;
ret = -ENODEV; mutex_lock(&clockevents_mutex); raw_spin_lock_irq(&clockevents_lock); list_for_each_entry(ce, &clockevent_devices, list) { if (!strcmp(ce->name, name)) { ret = __clockevents_try_unbind(ce, dev->id); break; } } raw_spin_unlock_irq(&clockevents_lock); /* * We hold clockevents_mutex, so ce can't go away */ if (ret == -EAGAIN) ret = clockevents_unbind(ce, dev->id); mutex_unlock(&clockevents_mutex); return ret ? ret : count; } static DEVICE_ATTR(unbind_device, 0200, NULL, sysfs_unbind_tick_dev);
#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) err = device_create_file(dev, &dev_attr_unbind_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 */
Linux 内核时钟架构之时钟事件设备SYS接口
最新推荐文章于 2023-04-08 16:21:06 发布