From: "Ai Li" <aili@codeaurora.org>
To: mgross@linux.intel.com
Cc: linux-pm@lists.linux-foundation.org
Subject: Re: adding handles to pm_qos?
Date: Fri, 30 Oct 2009 19:53:42 -0600 [thread overview]
Message-ID: <000001ca59cc$fc6999e0$f53ccda0$@org> (raw)
In-Reply-To: <20091030145609.GA21256@linux.intel.com>
> Oh.
>
> This will not scale with the aggregation logic very well at all
> if
> pm_qos update requirement gets hit per transaction through a
> driver code
> path, then I think some thought on the scalability is needed and
> perhaps
> a change to the aggregation design for such uses.
>
> Do you have a patch for the handle implementation I could look
> at?
Here is the patch that I use with the test code. There are three new
functions:
void *pm_qos_get(int qos, char *name);
int pm_qos_put(void *handle);
int pm_qos_update_requirement_direct(void *handle, s32 new_value);
In the test, I wanted to keep the existing interface intact so I
could compare them at the same time. For the formal code submission,
a different approach may work better.
--- include/linux/pm_qos_params.h.orig
+++ include/linux/pm_qos_params.h
@@ -16,7 +16,11 @@
int pm_qos_add_requirement(int qos, char *name, s32 value);
int pm_qos_update_requirement(int qos, char *name, s32 new_value);
-void pm_qos_remove_requirement(int qos, char *name);
+int pm_qos_remove_requirement(int qos, char *name);
+
+void *pm_qos_get(int qos, char *name);
+int pm_qos_put(void *handle);
+int pm_qos_update_requirement_direct(void *handle, s32 new_value);
int pm_qos_requirement(int qos);
--- kernel/pm_qos_params.c.orig
+++ kernel/pm_qos_params.c
@@ -55,6 +55,8 @@ struct requirement_list {
s32 kbps;
};
char *name;
+ int pm_qos_class;
+ int handle_count;
};
static s32 max_compare(s32 v1, s32 v2);
@@ -210,7 +212,9 @@ EXPORT_SYMBOL_GPL(pm_qos_requirement);
int pm_qos_add_requirement(int pm_qos_class, char *name, s32 value)
{
struct requirement_list *dep;
+ struct requirement_list *node;
unsigned long flags;
+ int retval;
dep = kzalloc(sizeof(struct requirement_list), GFP_KERNEL);
if (dep) {
@@ -219,10 +223,25 @@ int pm_qos_add_requirement(int pm_qos_class,
char *name, s32 value)
else
dep->value = value;
dep->name = kstrdup(name, GFP_KERNEL);
- if (!dep->name)
+ if (!dep->name) {
+ retval = -ENOMEM;
goto cleanup;
+ }
+ dep->pm_qos_class = pm_qos_class;
spin_lock_irqsave(&pm_qos_lock, flags);
+ /* make sure the new name is unique */
+ list_for_each_entry(node,
+
&pm_qos_array[pm_qos_class]->requirements.list, list) {
+ if (strcmp(node->name, name) == 0) {
+ spin_unlock_irqrestore(&pm_qos_lock,
flags);
+
+ kfree(dep->name);
+ retval = -EINVAL;
+ goto cleanup;
+ }
+ }
+
list_add(&dep->list,
&pm_qos_array[pm_qos_class]->requirements.list);
spin_unlock_irqrestore(&pm_qos_lock, flags);
@@ -231,9 +250,11 @@ int pm_qos_add_requirement(int pm_qos_class,
char *name, s32 value)
return 0;
}
+ retval = -ENOMEM;
+
cleanup:
kfree(dep);
- return -ENOMEM;
+ return retval;
}
EXPORT_SYMBOL_GPL(pm_qos_add_requirement);
@@ -282,8 +303,10 @@ EXPORT_SYMBOL_GPL(pm_qos_update_requirement);
*
* Will remove named qos request from pm_qos_class list of
parameters and
* recompute the current target value for the pm_qos_class.
+ *
+ * If there are outstanding handles to the request, -EBUSY is
returned.
*/
-void pm_qos_remove_requirement(int pm_qos_class, char *name)
+int pm_qos_remove_requirement(int pm_qos_class, char *name)
{
unsigned long flags;
struct requirement_list *node;
@@ -293,6 +316,11 @@ void pm_qos_remove_requirement(int pm_qos_class,
char *name)
list_for_each_entry(node,
&pm_qos_array[pm_qos_class]->requirements.list, list)
{
if (strcmp(node->name, name) == 0) {
+ if (node->handle_count > 0) {
+ spin_unlock_irqrestore(&pm_qos_lock,
flags);
+ return -EBUSY;
+ }
+
kfree(node->name);
list_del(&node->list);
kfree(node);
@@ -303,9 +331,83 @@ void pm_qos_remove_requirement(int pm_qos_class,
char *name)
spin_unlock_irqrestore(&pm_qos_lock, flags);
if (pending_update)
update_target(pm_qos_class);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
+/* pm_qos_get - returns an opaque handle to the existing qos request
+ * @pm_qos_class: identifies which list of qos request to us
+ * @name: identifies the request
+ *
+ * Will increment the reference count as well.
+ *
+ * If the named request isn't in the list then NULL is returned.
+ */
+void *pm_qos_get(int pm_qos_class, char *name)
+{
+ unsigned long flags;
+ struct requirement_list *node;
+ struct requirement_list *handle = NULL;
+
+ spin_lock_irqsave(&pm_qos_lock, flags);
+ list_for_each_entry(node,
+ &pm_qos_array[pm_qos_class]->requirements.list, list)
{
+ if (strcmp(node->name, name) == 0) {
+ node->handle_count++;
+ handle = node;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&pm_qos_lock, flags);
+ return handle;
+}
+EXPORT_SYMBOL_GPL(pm_qos_get);
+
+/* pm_qos_put - release the handle of the existing qos request
+ * @handle: previously acquired through pm_qos_get
+ *
+ * Will decrement the reference count as well. Caller should no
+ * longer use the handle after this call.
+ */
+int pm_qos_put(void *handle)
+{
+ unsigned long flags;
+ struct requirement_list *node = (struct requirement_list *)
handle;
+
+ spin_lock_irqsave(&pm_qos_lock, flags);
+ BUG_ON(node->handle_count == 0);
+ node->handle_count--;
+ spin_unlock_irqrestore(&pm_qos_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pm_qos_put);
+
+/* pm_qos_update_requirement_direct - modifies an existing qos
request
+ * @handle: previously acquired through pm_qos_get
+ * @value: defines the qos request
+ *
+ * Updates an existing qos requirement for the pm_qos_class of
parameters along
+ * with updating the target pm_qos_class value.
+ */
+int pm_qos_update_requirement_direct(void *handle, s32 new_value)
+{
+ unsigned long flags;
+ struct requirement_list *node = (struct requirement_list *)
handle;
+
+ spin_lock_irqsave(&pm_qos_lock, flags);
+ if (new_value == PM_QOS_DEFAULT_VALUE)
+ node->value =
pm_qos_array[node->pm_qos_class]->default_value;
+ else
+ node->value = new_value;
+ spin_unlock_irqrestore(&pm_qos_lock, flags);
+ update_target(node->pm_qos_class);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pm_qos_update_requirement_direct);
+
/**
* pm_qos_add_notifier - sets notification entry for changes to
target value
* @pm_qos_class: identifies which qos target changes should be
notified.
~Ai
next prev parent reply other threads:[~2009-10-31 1:53 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-10-14 17:24 adding handles to pm_qos? Ai Li
2009-10-23 22:53 ` mgross
2009-10-28 0:37 ` Ai Li
2009-10-30 14:56 ` mgross
2009-10-31 1:53 ` Ai Li [this message]
2009-11-03 20:29 ` mgross
2009-11-18 1:06 ` Ai Li
2009-11-27 17:23 ` 640E9920
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='000001ca59cc$fc6999e0$f53ccda0$@org' \
--to=aili@codeaurora.org \
--cc=linux-pm@lists.linux-foundation.org \
--cc=mgross@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox