cpu: add cpu boosting operation. 75/105275/4
authortaeyoung <ty317.kim@samsung.com>
Fri, 16 Dec 2016 06:58:58 +0000 (15:58 +0900)
committertaeyoung <ty317.kim@samsung.com>
Thu, 22 Dec 2016 04:47:29 +0000 (13:47 +0900)
Currently the code is experimental. deviced requests
to TRM to boost cpu.

Change-Id: I8b7cf84ffda9ad57d3adacb350a5ec23999e3a49
Signed-off-by: taeyoung <ty317.kim@samsung.com>
CMakeLists.txt
packaging/deviced.spec
src/core/common.h
src/core/device-notifier.h
src/cpu/cpu.conf [new file with mode: 0644]
src/cpu/pmqos-plugin.c [new file with mode: 0644]
src/cpu/pmqos.c [new file with mode: 0644]
src/cpu/pmqos.h [new file with mode: 0644]

index 14ce0f6..6f5cd6b 100755 (executable)
@@ -147,6 +147,11 @@ IF(IR_MODULE STREQUAL on)
        SET(SRCS ${SRCS} ${IR_SRCS})
 ENDIF()
 
+IF(TIZEN_FEATURE_CPU_MODULE STREQUAL on)
+       ADD_SOURCE(src/cpu CPU_SRCS)
+       SET(SRCS ${SRCS} ${CPU_SRCS})
+ENDIF()
+
 IF(TIZEN_FEATURE_USBHOST_TEST STREQUAL on)
        ADD_SOURCE(src/usb-host-test USB_HOST_TEST_SRCS)
        SET(SRCS ${SRCS} ${USB_HOST_TEST_SRCS})
@@ -272,6 +277,10 @@ IF(${USB_MODULE} STREQUAL on)
        ENDIF(${SDB_PRESTART} STREQUAL on)
 ENDIF()
 
+IF(TIZEN_FEATURE_CPU_MODULE STREQUAL on)
+       INSTALL_CONF(src/cpu cpu)
+ENDIF()
+
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/deviced.conf DESTINATION /etc/dbus-1/system.d)
 
 CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY)
index 1b2de31..86ecfa8 100644 (file)
@@ -16,6 +16,7 @@
 %define tzip_module off
 %define usb_module on
 %define usbhost_module off
+%define TIZEN_FEATURE_CPU_MODULE off
 %define TIZEN_FEATURE_USBHOST_TEST off
 %define TIZEN_FEATURE_TELEPHONY_MODULE off
 %define TIZEN_FEATURE_THERMAL_MODULE off
@@ -34,6 +35,7 @@
 %define touchscreen_module on
 %define tzip_module on
 %define usbhost_module on
+%define TIZEN_FEATURE_CPU_MODULE on
 %define TIZEN_FEATURE_USBHOST_TEST on
 %define TIZEN_FEATURE_TELEPHONY_MODULE on
 %define TIZEN_FEATURE_THERMAL_MODULE on
@@ -190,6 +192,7 @@ Deviced library for device control (devel)
        -DTZIP_MODULE=%{tzip_module} \
        -DUSB_MODULE=%{usb_module} \
        -DUSBHOST_MODULE=%{usbhost_module} \
+       -DTIZEN_FEATURE_CPU_MODULE=%{TIZEN_FEATURE_CPU_MODULE} \
        -DTIZEN_FEATURE_USBHOST_TEST=%{TIZEN_FEATURE_USBHOST_TEST} \
        -DTIZEN_FEATURE_TELEPHONY_MODULE=%{TIZEN_FEATURE_TELEPHONY_MODULE} \
        -DTHERMAL_MODULE=%{TIZEN_FEATURE_THERMAL_MODULE} \
@@ -302,6 +305,10 @@ systemctl daemon-reload
 %{_prefix}/lib/udev/rules.d/99-usbhost.rules
 %endif
 
+%if %{?TIZEN_FEATURE_CPU_MODULE} == on
+%config %{_sysconfdir}/deviced/cpu.conf
+%endif
+
 %files tools
 %manifest %{name}.manifest
 %{_bindir}/devicectl
index f9e627b..c93c83f 100644 (file)
 #define USEC_TO_MSEC(x)                ((double)x/1000)
 #endif
 
+#define DATA_VALUE_INT(x)       (*(int *)(x))
+#define DATA_VALUE_BOOL(x)      (*(bool *)(x))
+
 #define NANO_SECOND_MULTIPLIER  1000000 /* 1ms = 1,000,000 nsec */
 
 #ifndef safe_free
index ce8ef5b..2932517 100644 (file)
@@ -37,11 +37,13 @@ enum device_notifier_type {
        DEVICE_NOTIFIER_POWER_RESUME,
        DEVICE_NOTIFIER_POWEROFF,
        DEVICE_NOTIFIER_POWEROFF_HAPTIC,
-       DEVICE_NOTIFIER_PMQOS_OOM,
        DEVICE_NOTIFIER_PROCESS_BACKGROUND,
        DEVICE_NOTIFIER_PROCESS_FOREGROUND,
        DEVICE_NOTIFIER_USB_TETHERING_MODE,
        DEVICE_NOTIFIER_EVENT_HANDLER,
+       DEVICE_NOTIFIER_CPU_BOOST,
+       DEVICE_NOTIFIER_CPU_BOOST_LOWBAT,
+       DEVICE_NOTIFIER_CPU_BOOST_POWEROFF,
        /* Experimental for Specific device - contact to deviced owner */
        DEVICE_NOTIFIER_EARLY_BOOTING_DONE,
        DEVICE_NOTIFIER_SETTING_BRT_CHANGED,
@@ -53,6 +55,7 @@ enum device_notifier_type {
        DEVICE_NOTIFIER_PMQOS_LOWBAT,
        DEVICE_NOTIFIER_PMQOS_EMERGENCY,
        DEVICE_NOTIFIER_PMQOS_POWEROFF,
+       DEVICE_NOTIFIER_PMQOS_OOM,
        DEVICE_NOTIFIER_PMQOS_HALL,
        DEVICE_NOTIFIER_COOL_DOWN,
        DEVICE_NOTIFIER_FLIGHT_MODE,
diff --git a/src/cpu/cpu.conf b/src/cpu/cpu.conf
new file mode 100644 (file)
index 0000000..ca7fb39
--- /dev/null
@@ -0,0 +1,15 @@
+[PMQOS]
+
+############################
+### Add list of scenario ###
+############################
+[PmqosScenario]
+# set to "yes" scenario_support (Default value is no)
+# set scenario_num to be tested
+scenario_support=no
+scenario_num=0 # Maximum number of the scenarios is 500
+
+# describe the scenario section as follows
+#[Scenario0]
+#name=AppLaunch # (dbus method name)
+#support=yes
diff --git a/src/cpu/pmqos-plugin.c b/src/cpu/pmqos-plugin.c
new file mode 100644 (file)
index 0000000..acc65e5
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * deviced
+ *
+ * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include "core/log.h"
+#include "core/edbus-handler.h"
+#include "core/config-parser.h"
+#include "pmqos.h"
+
+#define SCENARIO_MAX 500
+
+static bool is_supported(const char *value)
+{
+       assert(value);
+
+       if (MATCH(value, "yes"))
+               return true;
+       return false;
+}
+
+static int pmqos_parse_scenario(struct parse_result *result, void *data)
+{
+       struct pmqos_scenario *scenarios = (struct pmqos_scenario *)data;
+
+       assert(result);
+       assert(result->section && result->name && result->value);
+
+       if (MATCH(result->name, "scenario_support")) {
+               scenarios->support = is_supported(result->value);
+               return 0;
+       }
+
+       if (MATCH(result->name, "scenario_num")) {
+               scenarios->num = atoi(result->value);
+               if (scenarios->num <= 0)
+                       return 0;
+               if (scenarios->num > SCENARIO_MAX)
+                       scenarios->num = SCENARIO_MAX;
+               scenarios->list = malloc(sizeof(struct scenario)*scenarios->num);
+               if (!scenarios->list) {
+                       _E("failed to allocat memory for scenario");
+                       return -errno;
+               }
+       }
+       return 0;
+}
+
+static int pmqos_parse_each_scenario(struct parse_result *result, void *user_data, unsigned int index)
+{
+       struct pmqos_scenario *scenarios = (struct pmqos_scenario *)user_data;
+
+       assert(result);
+       assert(result->section && result->name && result->value);
+
+       /* Do not support pmqos scenario */
+       if (!scenarios->support)
+               return 0;
+
+       /* Do not have pmqos scenario */
+       if (!scenarios->num)
+               return 0;
+
+       /* No item to parse */
+       if (index >= scenarios->num)
+               return 0;
+
+       /* Parse 'Scenario' section */
+       if (MATCH(result->name, "name"))
+               snprintf(scenarios->list[index].name,
+                               sizeof(scenarios->list[index].name), "%s", result->value);
+       else if (MATCH(result->name, "support"))
+               scenarios->list[index].support = is_supported(result->value);
+
+       return 0;
+}
+
+static int pmqos_load_config(struct parse_result *result, void *user_data)
+{
+       struct pmqos_scenario *scenarios = (struct pmqos_scenario *)user_data;
+       char name[NAME_MAX];
+       int ret;
+       static int index;
+
+       if (!result)
+               return 0;
+
+       if (!result->section || !result->name || !result->value)
+               return 0;
+
+       /* Parsing 'PMQOS' section */
+       if (MATCH(result->section, "PMQOS"))
+               return 0;
+
+       /* Parsing 'Pmqos Scenario' section */
+       if (MATCH(result->section, "PmqosScenario")) {
+               ret = pmqos_parse_scenario(result, user_data);
+               if (ret < 0)
+                       _E("failed to parse [PmqosScenario] section : %d", ret);
+               return ret;
+       }
+
+       /* Parsing 'Scenario' section */
+       for (index = 0; index < scenarios->num; ++index) {
+               snprintf(name, sizeof(name), "Scenario%d", index);
+
+               if (MATCH(result->section, name)) {
+                       ret = pmqos_parse_each_scenario(result, user_data, index);
+                       if (ret < 0)
+                               _E("failed to parse [Scenario%d] section : %d", index, ret);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+int release_pmqos_table(struct pmqos_scenario *scenarios)
+{
+       if (!scenarios)
+               return -EINVAL;
+
+       if (scenarios->num > 0 && !scenarios->list)
+               free(scenarios->list);
+
+       return 0;
+}
+
+int get_pmqos_table(const char *path, struct pmqos_scenario *scenarios)
+{
+       int ret;
+
+       /* get configuration file */
+       ret = config_parse(path, pmqos_load_config, scenarios);
+       if (ret < 0) {
+               _E("failed to load conficuration file(%s) : %d", path, ret);
+               release_pmqos_table(scenarios);
+               return ret;
+       }
+
+       return 0;
+}
diff --git a/src/cpu/pmqos.c b/src/cpu/pmqos.c
new file mode 100644 (file)
index 0000000..ce90a5d
--- /dev/null
@@ -0,0 +1,539 @@
+/*
+ * deviced
+ *
+ * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <limits.h>
+#include <Ecore.h>
+#include <device-node.h>
+#include <glib.h>
+#include <hw/cpu.h>
+
+#include "core/log.h"
+#include "core/edbus-handler.h"
+#include "core/devices.h"
+#include "core/common.h"
+#include "core/list.h"
+#include "core/device-notifier.h"
+#include "pmqos.h"
+
+#define DEFAULT_PMQOS_TIMER            3000
+
+#define PMQOS_CONF_PATH                "/etc/deviced/cpu.conf"
+#define MILLISECONDS(tv)       ((tv.tv_sec)*1000 + (tv.tv_nsec)/1000000)
+#define DELTA(a, b)            (MILLISECONDS(a) - MILLISECONDS(b))
+
+static gboolean pmqos_cpu_timer(gpointer data);
+
+struct pmqos_cpu {
+       char name[NAME_MAX];
+       int timeout;
+};
+
+static dd_list *pmqos_head;
+static guint unlock_timer;
+static struct timespec unlock_timer_start_st;
+static struct timespec unlock_timer_end_st;
+static struct pmqos_cpu unlock_timer_owner = {"NULL", 0};
+
+static struct cpu_device *cpu_dev;
+
+int set_cpu_pmqos(const char *name, int val)
+{
+       if (!cpu_dev ||
+               !cpu_dev->start_boost ||
+               !cpu_dev->stop_boost) {
+               _E("cpu device HAL does not exist");
+               return -ENODEV;
+       }
+
+       if (!name)
+               return -EINVAL;
+
+       if (val) {
+               _D("Set pm scenario : [Lock  ]%s", name);
+               return cpu_dev->start_boost((void *)name);
+       }
+
+       _D("Set pm scenario : [Unlock]%s", name);
+       return cpu_dev->stop_boost((void *)name);
+}
+
+static void pmqos_unlock_timeout_update(void)
+{
+       dd_list *elem;
+       struct pmqos_cpu *cpu;
+       int delta = 0;
+
+       clock_gettime(CLOCK_REALTIME, &unlock_timer_end_st);
+       delta = DELTA(unlock_timer_end_st, unlock_timer_start_st);
+
+       if (delta <= 0)
+               return;
+
+       DD_LIST_FOREACH(pmqos_head, elem, cpu) {
+               cpu->timeout -= delta;
+               if (cpu->timeout < 0)
+                       cpu->timeout = 0;
+               if (cpu->timeout > 0)
+                       continue;
+               /* Set cpu unlock */
+               set_cpu_pmqos(cpu->name, false);
+               /* Delete previous request */
+       }
+
+       DD_LIST_FOREACH(pmqos_head, elem, cpu) {
+               if (cpu->timeout > 0)
+                       continue;
+               DD_LIST_REMOVE(pmqos_head, cpu);
+               free(cpu);
+       }
+}
+
+static int pmqos_unlock_timer_start(void)
+{
+       int ret;
+       dd_list *elem;
+       struct pmqos_cpu *cpu;
+
+       if (unlock_timer) {
+               g_source_remove(unlock_timer);
+               unlock_timer = 0;
+       }
+
+       ret = DD_LIST_LENGTH(pmqos_head);
+       if (ret == 0)
+               return 0;
+
+       DD_LIST_FOREACH(pmqos_head, elem, cpu) {
+               if (cpu->timeout <= 0)
+                       continue;
+               snprintf(unlock_timer_owner.name, sizeof(unlock_timer_owner.name), "%s", cpu->name);
+               unlock_timer_owner.timeout = cpu->timeout;
+               clock_gettime(CLOCK_REALTIME, &unlock_timer_start_st);
+               unlock_timer = g_timeout_add(unlock_timer_owner.timeout, pmqos_cpu_timer, NULL);
+               if (unlock_timer == 0) {
+                       _E("fail init pmqos unlock %s %d", cpu->name, cpu->timeout);
+                       return -EPERM;
+               }
+               break;
+       }
+       return 0;
+}
+
+static int pmqos_cpu_cancel(const char *name)
+{
+       dd_list *elem;
+       struct pmqos_cpu *cpu;
+       size_t len;
+
+       if (!name)
+               return -EINVAL;
+
+       /* Find previous request */
+       len = strlen(name) + 1;
+       DD_LIST_FOREACH(pmqos_head, elem, cpu) {
+               if (!strncmp(cpu->name, name, len))
+                       break;
+       }
+       /* no cpu */
+       if (!cpu)
+               return 0;
+
+       /* unlock cpu */
+       set_cpu_pmqos(cpu->name, false);
+
+       /* delete cpu */
+       DD_LIST_REMOVE(pmqos_head, cpu);
+       free(cpu);
+
+       if (!strncmp(unlock_timer_owner.name, name, len)) {
+               /* undata cpu */
+               pmqos_unlock_timeout_update();
+               pmqos_unlock_timer_start();
+       }
+
+       return 0;
+}
+
+static gboolean pmqos_cpu_timer(gpointer data)
+{
+       int ret;
+
+       ret = pmqos_cpu_cancel(unlock_timer_owner.name);
+       if (ret < 0)
+               _E("Can not find %s request", unlock_timer_owner.name);
+
+       unlock_timer = 0;
+       return G_SOURCE_REMOVE;
+}
+
+static int compare_timeout(const void *a, const void *b)
+{
+       const struct pmqos_cpu *pmqos_a = (const struct pmqos_cpu *)a;
+       const struct pmqos_cpu *pmqos_b = (const struct pmqos_cpu *)b;
+
+       if (!pmqos_a)
+               return 1;
+       if (!pmqos_b)
+               return -1;
+
+       if (pmqos_a->timeout < pmqos_b->timeout)
+               return -1;
+       else if (pmqos_a->timeout > pmqos_b->timeout)
+               return 1;
+       return 0;
+}
+
+static int pmqos_cpu_request(const char *name, int val)
+{
+       dd_list *elem;
+       struct pmqos_cpu *cpu = NULL;
+       int ret;
+       size_t len;
+
+       /* Check valid parameter */
+       if (val > DEFAULT_PMQOS_TIMER) {
+               _I("The timer value cannot be higher than default time value(%dms)", DEFAULT_PMQOS_TIMER);
+               val = DEFAULT_PMQOS_TIMER;
+       }
+
+       /* find cpu */
+       len = strlen(name) + 1;
+       DD_LIST_FOREACH(pmqos_head, elem, cpu) {
+               if (!strncmp(cpu->name, name, len)) {
+                       cpu->timeout = val;
+                       break;
+               }
+       }
+
+       /* add cpu */
+       if (!cpu) {
+               cpu = calloc(1, sizeof(struct pmqos_cpu));
+               if (!cpu)
+                       return -ENOMEM;
+
+               snprintf(cpu->name, sizeof(cpu->name), "%s", name);
+               cpu->timeout = val;
+               DD_LIST_APPEND(pmqos_head, cpu);
+       }
+
+       /* sort cpu */
+       DD_LIST_SORT(pmqos_head, compare_timeout);
+
+       ret = pmqos_unlock_timer_start();
+       if (ret < 0)
+               return ret;
+
+       /* Set cpu lock */
+       set_cpu_pmqos(cpu->name, true);
+
+       return 0;
+}
+
+static int pmqos_lowbat(void *data)
+{
+       return set_cpu_pmqos("LowBattery", DATA_VALUE_INT(data));
+}
+
+static int pmqos_poweroff(void *data)
+{
+       return set_cpu_pmqos("PowerOff", DATA_VALUE_INT(data));
+}
+
+static DBusMessage *dbus_pmqos_handler(E_DBus_Object *obj, DBusMessage *msg)
+{
+       const char *member;
+       int val, ret;
+
+       if (!dbus_message_get_args(msg, NULL,
+                               DBUS_TYPE_INT32, &val,
+                               DBUS_TYPE_INVALID)) {
+               _E("there is no message");
+               ret = -EINVAL;
+               goto error;
+       }
+
+       if (val < 0) {
+               ret = -EINVAL;
+               goto error;
+       }
+
+       member = dbus_message_get_member(msg);
+
+       if (val)
+               ret = pmqos_cpu_request(member, val);
+       else
+               ret = pmqos_cpu_cancel(member);
+
+error:
+       return make_reply_message(msg, ret);
+}
+
+static DBusMessage *dbus_wifi_pmqos_handler(E_DBus_Object *obj, DBusMessage *msg)
+{
+       DBusMessageIter iter;
+       DBusMessage *reply;
+       const char *member;
+       char name[NAME_MAX];
+       int bps, val, ret;
+
+       if (!dbus_message_get_args(msg, NULL,
+                               DBUS_TYPE_INT32, &bps,
+                               DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID)) {
+               _E("there is no message");
+               ret = -EINVAL;
+               goto error;
+       }
+
+       if (bps < 0 || val < 0) {
+               ret = -EINVAL;
+               goto error;
+       }
+
+       member = dbus_message_get_member(msg);
+
+       /* combine bps and member */
+       snprintf(name, sizeof(name), "%s%d", member, bps);
+
+       if (val)
+               ret = pmqos_cpu_request(name, val);
+       else
+               ret = pmqos_cpu_cancel(name);
+
+error:
+       reply = dbus_message_new_method_return(msg);
+       dbus_message_iter_init_append(reply, &iter);
+       dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
+       return reply;
+}
+
+static DBusMessage *dbus_getdefaultlocktime(E_DBus_Object *obj, DBusMessage *msg)
+{
+       DBusMessageIter iter;
+       DBusMessage *reply;
+       int ret;
+
+       ret = DEFAULT_PMQOS_TIMER;
+
+       reply = dbus_message_new_method_return(msg);
+       dbus_message_iter_init_append(reply, &iter);
+       dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
+       return reply;
+}
+
+static int get_methods_from_conf(const char *path, struct edbus_method **edbus_methods)
+{
+       struct edbus_method *methods;
+       struct pmqos_scenario scenarios = { 0, };
+       int i, ret;
+
+       /* get pmqos table from conf */
+       ret = get_pmqos_table(path, &scenarios);
+       if (ret < 0) {
+               /* release scenarios memory */
+               release_pmqos_table(&scenarios);
+               return ret;
+       }
+
+       /* if do not support scenario */
+       if (!scenarios.support)
+               return 0;
+
+       /* if do not have scenarios */
+       if (scenarios.num <= 0)
+               return 0;
+
+       /* allocate edbus methods structure */
+       methods = malloc(sizeof(struct edbus_method) * scenarios.num);
+       if (!methods) {
+               _E("failed to allocate methods memory : %d", errno);
+               /* release scenarios memory */
+               release_pmqos_table(&scenarios);
+               return -errno;
+       }
+
+       /* set edbus_methods structure */
+       for (i = 0; i < scenarios.num; ++i) {
+
+               /* if this scenario does not support */
+               if (!scenarios.list[i].support) {
+                       _I("do not support [%s] scenario", scenarios.list[i].name);
+                       continue;
+               }
+
+               methods[i].member = scenarios.list[i].name;
+               methods[i].signature = "i";
+               methods[i].reply_signature = "i";
+               methods[i].func = dbus_pmqos_handler;
+               _D("support [%s] scenario", scenarios.list[i].name);
+       }
+
+       *edbus_methods = methods;
+       return scenarios.num;
+}
+
+/* Add pmqos name as alphabetically */
+static const struct edbus_method edbus_methods[] = {
+       { "AppLaunch",            "i",    "i", dbus_pmqos_handler },
+       { "AppLaunchHome",        "i",    "i", dbus_pmqos_handler },
+       { "BeautyShot",           "i",    "i", dbus_pmqos_handler },
+       { "Browser",              "i",    "i", dbus_pmqos_handler },
+       { "BrowserDash",          "i",    "i", dbus_pmqos_handler },
+       { "BrowserJavaScript",    "i",    "i", dbus_pmqos_handler },
+       { "BrowserLoading",       "i",    "i", dbus_pmqos_handler },
+       { "BrowserScroll",        "i",    "i", dbus_pmqos_handler },
+       { "CallSound",            "i",    "i", dbus_pmqos_handler },
+       { "CameraBurstShot",      "i",    "i", dbus_pmqos_handler },
+       { "CameraCaptureAtRec",   "i",    "i", dbus_pmqos_handler },
+       { "CameraPreview",        "i",    "i", dbus_pmqos_handler },
+       { "CameraRecording",      "i",    "i", dbus_pmqos_handler },
+       { "CameraSoundAndShot",   "i",    "i", dbus_pmqos_handler },
+       { "ContactSearch",        "i",    "i", dbus_pmqos_handler },
+       { "Emergency",            "i",    "i", dbus_pmqos_handler },
+       { "GalleryScroll",        "i",    "i", dbus_pmqos_handler },
+       { "GalleryRotation",      "i",    "i", dbus_pmqos_handler },
+       { "GetDefaultLockTime",  NULL,    "i", dbus_getdefaultlocktime },
+       { "GpsSerialCno",         "i",    "i", dbus_pmqos_handler },
+       { "GpuBoost",             "i",    "i", dbus_pmqos_handler },
+       { "GpuWakeup",            "i",    "i", dbus_pmqos_handler },
+       { "HomeScreen",           "i",    "i", dbus_pmqos_handler },
+       { "ImageViewer",          "i",    "i", dbus_pmqos_handler },
+       { "IMEInput",             "i",    "i", dbus_pmqos_handler },
+       { "LockScreen",           "i",    "i", dbus_pmqos_handler },
+       { "LowBattery",           "i",    "i", dbus_pmqos_handler },
+       { "MtpSendFile",          "i",    "i", dbus_pmqos_handler },
+       { "MusicPlayLcdOn",       "i",    "i", dbus_pmqos_handler },
+       { "PowerSaving",          "i",    "i", dbus_pmqos_handler },
+       { "ProcessCrashed",       "i",    "i", dbus_pmqos_handler },
+       { "ReservedMode",         "i",    "i", dbus_pmqos_handler },
+       { "ScreenMirroring",      "i",    "i", dbus_pmqos_handler },
+       { "SmemoZoom",            "i",    "i", dbus_pmqos_handler },
+       { "SVoice",               "i",    "i", dbus_pmqos_handler },
+       { "WebappLaunch",         "i",    "i", dbus_pmqos_handler },
+       { "WifiThroughput",      "ii",    "i", dbus_wifi_pmqos_handler },
+       { "PowerOff",             "i",    "i", dbus_pmqos_handler },
+       { "WebAppDrag",           "i",    "i", dbus_pmqos_handler },
+       { "WebAppFlick",          "i",    "i", dbus_pmqos_handler },
+       { "SensorWakeup",         "i",    "i", dbus_pmqos_handler },
+       { "UgLaunch",             "i",    "i", dbus_pmqos_handler },
+       { "MusicScroll",          "i",    "i", dbus_pmqos_handler },
+       { "FileScroll",           "i",    "i", dbus_pmqos_handler },
+       { "VideoScroll",          "i",    "i", dbus_pmqos_handler },
+       { "EmailScroll",          "i",    "i", dbus_pmqos_handler },
+       { "ContactScroll",        "i",    "i", dbus_pmqos_handler },
+       { "TizenStoreScroll",     "i",    "i", dbus_pmqos_handler },
+       { "CallLogScroll",        "i",    "i", dbus_pmqos_handler },
+       { "MyfilesScroll",        "i",    "i", dbus_pmqos_handler },
+};
+
+static int booting_done(void *data)
+{
+       static int done;
+       struct edbus_method *methods = NULL;
+       int ret, size;
+
+       if (data == NULL)
+               goto out;
+       done = *(int *)data;
+       if (!done)
+               goto out;
+       _I("booting done");
+
+       /* register edbus methods */
+       ret = register_edbus_interface_and_method(DEVICED_PATH_PMQOS,
+                       DEVICED_INTERFACE_PMQOS,
+                       edbus_methods, ARRAY_SIZE(edbus_methods));
+       if (ret < 0)
+               _E("fail to init edbus interface and method(%d)", ret);
+
+       /* get methods from config file */
+       size = get_methods_from_conf(PMQOS_CONF_PATH, &methods);
+       if (size < 0)
+               _E("failed to load configuration file(%s)", PMQOS_CONF_PATH);
+
+       /* register edbus methods for pmqos */
+       if (methods) {
+               ret = register_edbus_interface_and_method(DEVICED_PATH_PMQOS,
+                               DEVICED_INTERFACE_PMQOS,
+                               methods, size);
+               if (ret < 0)
+                       _E("fail to init edbus method from conf(%d)", ret);
+               free(methods);
+       }
+
+       /* register notifier for each event */
+       register_notifier(DEVICE_NOTIFIER_CPU_BOOST_LOWBAT, pmqos_lowbat);
+       register_notifier(DEVICE_NOTIFIER_CPU_BOOST_POWEROFF, pmqos_poweroff);
+
+out:
+       return done;
+}
+
+static int pmqos_probe(void *data)
+{
+       struct hw_info *info;
+       int r;
+
+       if (cpu_dev)
+               return 0;
+
+       r = hw_get_info(CPU_HARDWARE_DEVICE_ID,
+                       (const struct hw_info **)&info);
+       if (r < 0) {
+               _I("cpu shared library is not supported: %d", r);
+               return 0;
+       }
+
+       if (!info->open) {
+               _E("fail to open cpu device : open(NULL)");
+               return -EPERM;
+       }
+
+       r = info->open(info, NULL, (struct hw_common **)&cpu_dev);
+       if (r < 0) {
+               _E("fail to get cpu device structure : %d", r);
+               return -EPERM;
+       }
+
+       _D("cpu device structure load success");
+       return 0;
+}
+
+static void pmqos_init(void *data)
+{
+       register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
+}
+
+static void pmqos_exit(void *data)
+{
+       /* unregister notifier for each event */
+       unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
+       unregister_notifier(DEVICE_NOTIFIER_CPU_BOOST_LOWBAT, pmqos_lowbat);
+       unregister_notifier(DEVICE_NOTIFIER_CPU_BOOST_POWEROFF, pmqos_poweroff);
+}
+
+static const struct device_ops pmqos_device_ops = {
+       .name     = "pmqos",
+       .probe    = pmqos_probe,
+       .init     = pmqos_init,
+       .exit     = pmqos_exit,
+};
+
+DEVICE_OPS_REGISTER(&pmqos_device_ops)
diff --git a/src/cpu/pmqos.h b/src/cpu/pmqos.h
new file mode 100644 (file)
index 0000000..531847c
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * deviced
+ *
+ * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef __PMQOS_H__
+#define __PMQOS_H__
+
+#include <stdbool.h>
+#include <limits.h>
+
+struct pmqos_scenario {
+       struct scenario {
+               char name[NAME_MAX];
+               bool support;
+       } *list;
+       int num;
+       bool support;
+};
+
+int get_pmqos_table(const char *path, struct pmqos_scenario *scenarios);
+int release_pmqos_table(struct pmqos_scenario *scenarios);
+
+#endif /* __PMQOS_H__ */