#ifdef CONFIG_SYSFS /** * sysfs_show_current_clocksources - sysfs interface for current clocksource * @dev: unused * @attr: unused * @buf: char buffer to be filled with clocksource list * * Provides sysfs interface for listing current clocksource. */ static ssize_t sysfs_show_current_clocksources(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t count = 0;
mutex_lock(&clocksource_mutex); count = snprintf(buf, PAGE_SIZE, "%s\n", curr_clocksource->name); mutex_unlock(&clocksource_mutex);
return count; }
ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt) { size_t ret = cnt;
/* strings from sysfs write are not 0 terminated! */ if (!cnt || cnt >= CS_NAME_LEN) return -EINVAL;
/* strip of \n: */ if (buf[cnt-1] == '\n') cnt--; if (cnt > 0) memcpy(dst, buf, cnt); dst[cnt] = 0; return ret; }
/** * sysfs_override_clocksource - interface for manually overriding clocksource * @dev: unused * @attr: unused * @buf: name of override clocksource * @count: length of buffer * * Takes input from sysfs interface for manually overriding the default * clocksource selection. */ static ssize_t sysfs_override_clocksource(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { ssize_t ret;
mutex_lock(&clocksource_mutex);
ret = sysfs_get_uname(buf, override_name, count); if (ret >= 0) clocksource_select();
mutex_unlock(&clocksource_mutex);
return ret; }
/** * sysfs_unbind_current_clocksource - interface for manually unbinding clocksource * @dev: unused * @attr: unused * @buf: unused * @count: length of buffer * * Takes input from sysfs interface for manually unbinding a clocksource. */ static ssize_t sysfs_unbind_clocksource(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct clocksource *cs; char name[CS_NAME_LEN]; ssize_t ret;
ret = sysfs_get_uname(buf, name, count); if (ret < 0) return ret;
ret = -ENODEV; mutex_lock(&clocksource_mutex); list_for_each_entry(cs, &clocksource_list, list) { if (strcmp(cs->name, name)) continue; ret = clocksource_unbind(cs); break; } mutex_unlock(&clocksource_mutex);
return ret ? ret : count; }
/** * sysfs_show_available_clocksources - sysfs interface for listing clocksource * @dev: unused * @attr: unused * @buf: char buffer to be filled with clocksource list * * Provides sysfs interface for listing registered clocksources */ static ssize_t sysfs_show_available_clocksources(struct device *dev, struct device_attribute *attr, char *buf) { struct clocksource *src; ssize_t count = 0;
mutex_lock(&clocksource_mutex); list_for_each_entry(src, &clocksource_list, list) { /* * Don't show non-HRES clocksource if the tick code is * in one shot mode (highres=on or nohz=on) */ if (!tick_oneshot_mode_active() || (src->flags & CLOCK_SOURCE_VALID_FOR_HRES)) count += snprintf(buf + count, max((ssize_t)PAGE_SIZE - count, (ssize_t)0), "%s ", src->name); } mutex_unlock(&clocksource_mutex);
count += snprintf(buf + count, max((ssize_t)PAGE_SIZE - count, (ssize_t)0), "\n");
return count; }
/* * Sysfs setup bits: */ static DEVICE_ATTR(current_clocksource, 0644, sysfs_show_current_clocksources, sysfs_override_clocksource);
static DEVICE_ATTR(unbind_clocksource, 0200, NULL, sysfs_unbind_clocksource);
static DEVICE_ATTR(available_clocksource, 0444, sysfs_show_available_clocksources, NULL);
static struct bus_type clocksource_subsys = { .name = "clocksource", .dev_name = "clocksource", };
static struct device device_clocksource = { .id = 0, .bus = &clocksource_subsys, };
static int __init init_clocksource_sysfs(void) { int error = subsys_system_register(&clocksource_subsys, NULL);
if (!error) error = device_register(&device_clocksource); if (!error) error = device_create_file( &device_clocksource, &dev_attr_current_clocksource); if (!error) error = device_create_file(&device_clocksource, &dev_attr_unbind_clocksource); if (!error) error = device_create_file( &device_clocksource, &dev_attr_available_clocksource); return error; }
device_initcall(init_clocksource_sysfs); #endif /* CONFIG_SYSFS */
:/sys/bus/clocksource # ls ls devices drivers drivers_autoprobe drivers_probe uevent
/sys/bus/clocksource/devices/clocksource0 # ls ls available_clocksource current_clocksource power subsystem uevent