diff options
author | Sivaram Nair <sivaramn@nvidia.com> | 2012-10-17 15:37:03 +0300 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-10-21 14:04:40 -0700 |
commit | dcab056238219358a14368f30f48403f22af937b (patch) | |
tree | b9042b457a670b4e9cd02daa642674fa20988bb4 /drivers/edp | |
parent | 1676e148bce39dd0b8993ab4cf4442db5b0868dd (diff) |
pm: EDP: enable updates via sysfs
This patch allows the user space to issue E-state and threshold change
requests. E-state updates are allowed only if the change is guaranteed
to be approved.
Change-Id: Id31f06ebb95f0b1fdfce205cb17038cb7a9eb30e
Signed-off-by: Sivaram Nair <sivaramn@nvidia.com>
Reviewed-on: http://git-master/r/145256
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>
Reviewed-by: Juha Tukkinen <jtukkinen@nvidia.com>
Diffstat (limited to 'drivers/edp')
-rw-r--r-- | drivers/edp/edp.c | 27 | ||||
-rw-r--r-- | drivers/edp/edp_internal.h | 4 | ||||
-rw-r--r-- | drivers/edp/sysfs.c | 61 |
3 files changed, 76 insertions, 16 deletions
diff --git a/drivers/edp/edp.c b/drivers/edp/edp.c index b82375be6fcd..a2bd3adec333 100644 --- a/drivers/edp/edp.c +++ b/drivers/edp/edp.c @@ -410,8 +410,8 @@ int edp_unregister_client(struct edp_client *client) } EXPORT_SYMBOL(edp_unregister_client); -static int update_client_request(struct edp_client *client, unsigned int req, - int *approved) +int edp_update_client_request_unlocked(struct edp_client *client, + unsigned int req, int *approved) { int r; @@ -434,7 +434,7 @@ int edp_update_client_request(struct edp_client *client, unsigned int req, int r; mutex_lock(&edp_lock); - r = update_client_request(client, req, approved); + r = edp_update_client_request_unlocked(client, req, approved); mutex_unlock(&edp_lock); return r; @@ -568,18 +568,23 @@ int edp_unregister_loan(struct edp_client *lender, struct edp_client *borrower) } EXPORT_SYMBOL(edp_unregister_loan); -int edp_update_loan_threshold(struct edp_client *client, unsigned int threshold) +int edp_update_loan_threshold_unlocked(struct edp_client *client, + unsigned int threshold) { - int r = -EINVAL; + if (!registered_client(client)) + return -EINVAL; - mutex_lock(&edp_lock); + client->ithreshold = threshold; + update_loans(client); + return 0; +} - if (registered_client(client)) { - client->ithreshold = threshold; - update_loans(client); - r = 0; - } +int edp_update_loan_threshold(struct edp_client *client, unsigned int threshold) +{ + int r; + mutex_lock(&edp_lock); + r = edp_update_loan_threshold_unlocked(client, threshold); mutex_unlock(&edp_lock); return r; diff --git a/drivers/edp/edp_internal.h b/drivers/edp/edp_internal.h index a0b969308646..51b11ea65f2c 100644 --- a/drivers/edp/edp_internal.h +++ b/drivers/edp/edp_internal.h @@ -54,6 +54,10 @@ static inline unsigned int req_index(struct edp_client *c) extern struct mutex edp_lock; extern struct list_head edp_governors; +int edp_update_client_request_unlocked(struct edp_client *client, + unsigned int req, int *approved); +int edp_update_loan_threshold_unlocked(struct edp_client *client, + unsigned int threshold); struct edp_governor *edp_find_governor_unlocked(const char *s); int edp_set_governor_unlocked(struct edp_manager *mgr, struct edp_governor *gov); diff --git a/drivers/edp/sysfs.c b/drivers/edp/sysfs.c index d23996bc7ac9..c8baf88fc191 100644 --- a/drivers/edp/sysfs.c +++ b/drivers/edp/sysfs.c @@ -174,6 +174,7 @@ struct client_entry { struct client_attr { struct attribute attr; ssize_t (*show)(struct edp_client *, char *); + ssize_t (*store)(struct edp_client *, const char *); }; static ssize_t states_show(struct edp_client *c, char *s) @@ -214,6 +215,23 @@ static ssize_t request_show(struct edp_client *c, char *s) return scnprintf(s, PAGE_SIZE, "%u\n", req_level(c)); } +/* Allow only updates that are guaranteed to succeed */ +static ssize_t request_store(struct edp_client *c, const char *s) +{ + unsigned int id; + + if (sscanf(s, "%u", &id) != 1) + return -EINVAL; + + if (id >= c->num_states) + return -EINVAL; + + if (id < c->e0_index && id < req_index(c)) + return -EPERM; + + return edp_update_client_request_unlocked(c, id, NULL); +} + static ssize_t current_show(struct edp_client *c, char *s) { return scnprintf(s, PAGE_SIZE, "%u\n", cur_level(c)); @@ -221,8 +239,17 @@ static ssize_t current_show(struct edp_client *c, char *s) static ssize_t threshold_show(struct edp_client *c, char *s) { - return scnprintf(s, PAGE_SIZE, "%u\n", - c->num_loans ? c->ithreshold : 0); + return scnprintf(s, PAGE_SIZE, "%u\n", c->ithreshold); +} + +static ssize_t threshold_store(struct edp_client *c, const char *s) +{ + unsigned int tv; + + if (sscanf(s, "%u", &tv) != 1) + return -EINVAL; + + return edp_update_loan_threshold_unlocked(c, tv); } static ssize_t borrowers_show(struct edp_client *c, char *s) @@ -240,8 +267,10 @@ struct client_attr attr_num_states = __ATTR_RO(num_states); struct client_attr attr_e0 = __ATTR_RO(e0); struct client_attr attr_max_borrowers = __ATTR_RO(max_borrowers); struct client_attr attr_priority = __ATTR_RO(priority); -struct client_attr attr_request = __ATTR_RO(request); -struct client_attr attr_threshold = __ATTR_RO(threshold); +struct client_attr attr_request = __ATTR(request, 0644, request_show, + request_store); +struct client_attr attr_threshold = __ATTR(threshold, 0644, threshold_show, + threshold_store); struct client_attr attr_borrowers = __ATTR_RO(borrowers); struct client_attr attr_loans = __ATTR_RO(loans); struct client_attr attr_current = { @@ -286,8 +315,30 @@ static ssize_t client_state_show(struct kobject *kobj, return r; } +static ssize_t client_state_store(struct kobject *kobj, + struct attribute *attr, const char *buf, size_t count) +{ + ssize_t r = -EINVAL; + struct edp_client *c; + struct client_attr *cattr; + + mutex_lock(&edp_lock); + + c = to_client(kobj); + cattr = container_of(attr, struct client_attr, attr); + if (c && cattr) { + if (cattr->store) + r = cattr->store(c, buf); + } + + mutex_unlock(&edp_lock); + + return r ?: count; +} + static const struct sysfs_ops client_sysfs_ops = { - .show = client_state_show + .show = client_state_show, + .store = client_state_store }; static struct kobj_type ktype_client = { |