summaryrefslogtreecommitdiff
path: root/drivers/edp
diff options
context:
space:
mode:
authorSivaram Nair <sivaramn@nvidia.com>2012-10-17 15:37:03 +0300
committerSimone Willett <swillett@nvidia.com>2012-10-21 14:04:40 -0700
commitdcab056238219358a14368f30f48403f22af937b (patch)
treeb9042b457a670b4e9cd02daa642674fa20988bb4 /drivers/edp
parent1676e148bce39dd0b8993ab4cf4442db5b0868dd (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.c27
-rw-r--r--drivers/edp/edp_internal.h4
-rw-r--r--drivers/edp/sysfs.c61
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 = {