Author | Tokens | Token Proportion | Commits | Commit Proportion |
---|---|---|---|---|
Mark Pearson | 813 | 91.55% | 1 | 16.67% |
Gergo Koteles | 51 | 5.74% | 1 | 16.67% |
Hans de Goede | 10 | 1.13% | 2 | 33.33% |
Jiaxun Yang | 8 | 0.90% | 1 | 16.67% |
Maximilian Luz | 6 | 0.68% | 1 | 16.67% |
Total | 888 | 6 |
// SPDX-License-Identifier: GPL-2.0-or-later /* Platform profile sysfs interface */ #include <linux/acpi.h> #include <linux/bits.h> #include <linux/init.h> #include <linux/mutex.h> #include <linux/platform_profile.h> #include <linux/sysfs.h> static struct platform_profile_handler *cur_profile; static DEFINE_MUTEX(profile_lock); static const char * const profile_names[] = { [PLATFORM_PROFILE_LOW_POWER] = "low-power", [PLATFORM_PROFILE_COOL] = "cool", [PLATFORM_PROFILE_QUIET] = "quiet", [PLATFORM_PROFILE_BALANCED] = "balanced", [PLATFORM_PROFILE_BALANCED_PERFORMANCE] = "balanced-performance", [PLATFORM_PROFILE_PERFORMANCE] = "performance", }; static_assert(ARRAY_SIZE(profile_names) == PLATFORM_PROFILE_LAST); static ssize_t platform_profile_choices_show(struct device *dev, struct device_attribute *attr, char *buf) { int len = 0; int err, i; err = mutex_lock_interruptible(&profile_lock); if (err) return err; if (!cur_profile) { mutex_unlock(&profile_lock); return -ENODEV; } for_each_set_bit(i, cur_profile->choices, PLATFORM_PROFILE_LAST) { if (len == 0) len += sysfs_emit_at(buf, len, "%s", profile_names[i]); else len += sysfs_emit_at(buf, len, " %s", profile_names[i]); } len += sysfs_emit_at(buf, len, "\n"); mutex_unlock(&profile_lock); return len; } static ssize_t platform_profile_show(struct device *dev, struct device_attribute *attr, char *buf) { enum platform_profile_option profile = PLATFORM_PROFILE_BALANCED; int err; err = mutex_lock_interruptible(&profile_lock); if (err) return err; if (!cur_profile) { mutex_unlock(&profile_lock); return -ENODEV; } err = cur_profile->profile_get(cur_profile, &profile); mutex_unlock(&profile_lock); if (err) return err; /* Check that profile is valid index */ if (WARN_ON((profile < 0) || (profile >= ARRAY_SIZE(profile_names)))) return -EIO; return sysfs_emit(buf, "%s\n", profile_names[profile]); } static ssize_t platform_profile_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int err, i; err = mutex_lock_interruptible(&profile_lock); if (err) return err; if (!cur_profile) { mutex_unlock(&profile_lock); return -ENODEV; } /* Scan for a matching profile */ i = sysfs_match_string(profile_names, buf); if (i < 0) { mutex_unlock(&profile_lock); return -EINVAL; } /* Check that platform supports this profile choice */ if (!test_bit(i, cur_profile->choices)) { mutex_unlock(&profile_lock); return -EOPNOTSUPP; } err = cur_profile->profile_set(cur_profile, i); if (!err) sysfs_notify(acpi_kobj, NULL, "platform_profile"); mutex_unlock(&profile_lock); if (err) return err; return count; } static DEVICE_ATTR_RO(platform_profile_choices); static DEVICE_ATTR_RW(platform_profile); static struct attribute *platform_profile_attrs[] = { &dev_attr_platform_profile_choices.attr, &dev_attr_platform_profile.attr, NULL }; static const struct attribute_group platform_profile_group = { .attrs = platform_profile_attrs }; void platform_profile_notify(void) { if (!cur_profile) return; sysfs_notify(acpi_kobj, NULL, "platform_profile"); } EXPORT_SYMBOL_GPL(platform_profile_notify); int platform_profile_cycle(void) { enum platform_profile_option profile; enum platform_profile_option next; int err; err = mutex_lock_interruptible(&profile_lock); if (err) return err; if (!cur_profile) { mutex_unlock(&profile_lock); return -ENODEV; } err = cur_profile->profile_get(cur_profile, &profile); if (err) { mutex_unlock(&profile_lock); return err; } next = find_next_bit_wrap(cur_profile->choices, PLATFORM_PROFILE_LAST, profile + 1); if (WARN_ON(next == PLATFORM_PROFILE_LAST)) { mutex_unlock(&profile_lock); return -EINVAL; } err = cur_profile->profile_set(cur_profile, next); mutex_unlock(&profile_lock); if (!err) sysfs_notify(acpi_kobj, NULL, "platform_profile"); return err; } EXPORT_SYMBOL_GPL(platform_profile_cycle); int platform_profile_register(struct platform_profile_handler *pprof) { int err; mutex_lock(&profile_lock); /* We can only have one active profile */ if (cur_profile) { mutex_unlock(&profile_lock); return -EEXIST; } /* Sanity check the profile handler field are set */ if (!pprof || bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST) || !pprof->profile_set || !pprof->profile_get) { mutex_unlock(&profile_lock); return -EINVAL; } err = sysfs_create_group(acpi_kobj, &platform_profile_group); if (err) { mutex_unlock(&profile_lock); return err; } cur_profile = pprof; mutex_unlock(&profile_lock); return 0; } EXPORT_SYMBOL_GPL(platform_profile_register); int platform_profile_remove(void) { sysfs_remove_group(acpi_kobj, &platform_profile_group); mutex_lock(&profile_lock); cur_profile = NULL; mutex_unlock(&profile_lock); return 0; } EXPORT_SYMBOL_GPL(platform_profile_remove); MODULE_AUTHOR("Mark Pearson <markpearson@lenovo.com>"); MODULE_LICENSE("GPL");
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1