qseecom: Add support for bus scaling
Add support for scaling bus to various level:
LOW, MEDIUM, HIGH. Expose IOCTL to user space
clients to enable selecting a specific bus bandwidth
setting.
Change-Id: I8ef94b84464e86d3a71e4c78c502e99ef2e0ec9a
Signed-off-by: Mona Hossain <mhossain@codeaurora.org>
Signed-off-by: Zhen Kong <zkong@codeaurora.org>
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 84ac1c3..845b797 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -71,6 +71,9 @@
#define RPMB_SERVICE 0x2000
+#define QSEECOM_SEND_CMD_CRYPTO_TIMEOUT 2000
+#define QSEECOM_LOAD_APP_CRYPTO_TIMEOUT 2000
+
enum qseecom_clk_definitions {
CLK_DFAB = 0,
CLK_SFPB,
@@ -162,6 +165,12 @@
struct qseecom_clk qsee;
struct qseecom_clk ce_drv;
struct cdev cdev;
+
+ bool support_bus_scaling;
+ uint32_t cumulative_mode;
+ enum qseecom_bandwidth_request_mode current_mode;
+ struct timer_list bw_scale_down_timer;
+ struct work_struct bw_inactive_req_ws;
};
struct qseecom_client_handle {
@@ -191,6 +200,7 @@
atomic_t ioctl_count;
bool perf_enabled;
bool fast_load_enabled;
+ enum qseecom_bandwidth_request_mode mode;
};
enum qseecom_set_clear_key_flag {
@@ -320,6 +330,7 @@
return ret;
}
data->listener.id = 0;
+ data->type = QSEECOM_LISTENER_SERVICE;
if (!__qseecom_is_svc_unique(data, &rcvd_lstnr)) {
pr_err("Service is not unique and is already registered\n");
data->released = true;
@@ -428,6 +439,157 @@
return ret;
}
+static int __qseecom_set_msm_bus_request(uint32_t mode)
+{
+ int ret = 0;
+ struct qseecom_clk *qclk;
+
+ qclk = &qseecom.qsee;
+ if (qclk->ce_core_src_clk != NULL) {
+ if (mode == INACTIVE) {
+ __qseecom_disable_clk(CLK_QSEE);
+ } else {
+ ret = __qseecom_enable_clk(CLK_QSEE);
+ if (ret)
+ pr_err("CLK enabling failed (%d) MODE (%d)\n",
+ ret, mode);
+ }
+ }
+
+ if ((!ret) && (qseecom.current_mode != mode)) {
+ ret = msm_bus_scale_client_update_request(
+ qseecom.qsee_perf_client, mode);
+ if (ret) {
+ pr_err("Bandwidth req failed(%d) MODE (%d)\n",
+ ret, mode);
+ if (qclk->ce_core_src_clk != NULL) {
+ if (mode == INACTIVE)
+ __qseecom_enable_clk(CLK_QSEE);
+ else
+ __qseecom_disable_clk(CLK_QSEE);
+ }
+ }
+ qseecom.current_mode = mode;
+ }
+ return ret;
+}
+
+static void qseecom_bw_inactive_req_work(struct work_struct *work)
+{
+ mutex_lock(&app_access_lock);
+ mutex_lock(&qsee_bw_mutex);
+ __qseecom_set_msm_bus_request(INACTIVE);
+ pr_debug("current_mode = %d, cumulative_mode = %d\n",
+ qseecom.current_mode, qseecom.cumulative_mode);
+ mutex_unlock(&qsee_bw_mutex);
+ mutex_unlock(&app_access_lock);
+ return;
+}
+
+static void qseecom_scale_bus_bandwidth_timer_callback(unsigned long data)
+{
+ schedule_work(&qseecom.bw_inactive_req_ws);
+ return;
+}
+
+static int qseecom_scale_bus_bandwidth_timer(uint32_t mode, uint32_t duration)
+{
+ int32_t ret = 0;
+ int32_t request_mode = INACTIVE;
+
+ mutex_lock(&qsee_bw_mutex);
+ if (mode == 0) {
+ if (qseecom.cumulative_mode > MEDIUM)
+ request_mode = HIGH;
+ else
+ request_mode = qseecom.cumulative_mode;
+ } else {
+ request_mode = mode;
+ }
+ __qseecom_set_msm_bus_request(request_mode);
+
+ del_timer_sync(&(qseecom.bw_scale_down_timer));
+ qseecom.bw_scale_down_timer.expires = jiffies +
+ msecs_to_jiffies(duration);
+ add_timer(&(qseecom.bw_scale_down_timer));
+
+ mutex_unlock(&qsee_bw_mutex);
+ return ret;
+}
+
+
+static int qseecom_unregister_bus_bandwidth_needs(
+ struct qseecom_dev_handle *data)
+{
+ int32_t ret = 0;
+
+ qseecom.cumulative_mode -= data->mode;
+ data->mode = INACTIVE;
+
+ return ret;
+}
+
+static int __qseecom_register_bus_bandwidth_needs(
+ struct qseecom_dev_handle *data, uint32_t request_mode)
+{
+ int32_t ret = 0;
+
+ if (data->mode == INACTIVE) {
+ qseecom.cumulative_mode += request_mode;
+ data->mode = request_mode;
+ } else {
+ if (data->mode != request_mode) {
+ qseecom.cumulative_mode -= data->mode;
+ qseecom.cumulative_mode += request_mode;
+ data->mode = request_mode;
+ }
+ }
+ return ret;
+}
+
+static int qseecom_scale_bus_bandwidth(struct qseecom_dev_handle *data,
+ void __user *argp)
+{
+ int32_t ret = 0;
+ int32_t req_mode;
+
+ ret = copy_from_user(&req_mode, argp, sizeof(req_mode));
+ if (ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
+ if (req_mode > HIGH) {
+ pr_err("Invalid bandwidth mode (%d)\n", req_mode);
+ return ret;
+ }
+ mutex_lock(&qsee_bw_mutex);
+ ret = __qseecom_register_bus_bandwidth_needs(data, req_mode);
+ mutex_unlock(&qsee_bw_mutex);
+
+ return ret;
+}
+
+static void __qseecom_disable_clk_scale_down(struct qseecom_dev_handle *data)
+{
+ if (!qseecom.support_bus_scaling)
+ qsee_disable_clock_vote(data, CLK_SFPB);
+ return;
+}
+
+static int __qseecom_enable_clk_scale_up(struct qseecom_dev_handle *data)
+{
+ int ret = 0;
+ if (qseecom.support_bus_scaling) {
+ qseecom_scale_bus_bandwidth_timer(
+ MEDIUM, QSEECOM_LOAD_APP_CRYPTO_TIMEOUT);
+ } else {
+ ret = qsee_vote_for_clock(data, CLK_SFPB);
+ if (ret)
+ pr_err("Fail vote for clk SFPB ret %d\n", ret);
+ }
+ return ret;
+}
+
static int qseecom_set_client_mem_param(struct qseecom_dev_handle *data,
void __user *argp)
{
@@ -618,7 +780,7 @@
u32 app_id = 0;
struct ion_handle *ihandle; /* Ion handle */
struct qseecom_load_img_req load_img_req;
- int32_t ret;
+ int32_t ret = 0;
ion_phys_addr_t pa = 0;
uint32_t len;
struct qseecom_command_scm_resp resp;
@@ -633,16 +795,16 @@
return -EFAULT;
}
/* Vote for the SFPB clock */
- ret = qsee_vote_for_clock(data, CLK_SFPB);
+ ret = __qseecom_enable_clk_scale_up(data);
if (ret)
- pr_warning("Unable to vote for SFPB clock");
+ return ret;
req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
load_img_req.img_name[MAX_APP_NAME_SIZE-1] = '\0';
memcpy(req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE);
ret = __qseecom_check_app_exists(req);
if (ret < 0) {
- qsee_disable_clock_vote(data, CLK_SFPB);
+ __qseecom_disable_clk_scale_down(data);
return ret;
}
@@ -668,7 +830,7 @@
load_img_req.ifd_data_fd);
if (IS_ERR_OR_NULL(ihandle)) {
pr_err("Ion client could not retrieve the handle\n");
- qsee_disable_clock_vote(data, CLK_SFPB);
+ __qseecom_disable_clk_scale_down(data);
return -ENOMEM;
}
@@ -693,7 +855,7 @@
pr_err("scm_call to load app failed\n");
if (!IS_ERR_OR_NULL(ihandle))
ion_free(qseecom.ion_clnt, ihandle);
- qsee_disable_clock_vote(data, CLK_SFPB);
+ __qseecom_disable_clk_scale_down(data);
return -EINVAL;
}
@@ -701,7 +863,7 @@
pr_err("scm_call rsp.result is QSEOS_RESULT_FAILURE\n");
if (!IS_ERR_OR_NULL(ihandle))
ion_free(qseecom.ion_clnt, ihandle);
- qsee_disable_clock_vote(data, CLK_SFPB);
+ __qseecom_disable_clk_scale_down(data);
return -EFAULT;
}
@@ -712,7 +874,7 @@
ret);
if (!IS_ERR_OR_NULL(ihandle))
ion_free(qseecom.ion_clnt, ihandle);
- qsee_disable_clock_vote(data, CLK_SFPB);
+ __qseecom_disable_clk_scale_down(data);
return ret;
}
}
@@ -722,7 +884,7 @@
resp.result);
if (!IS_ERR_OR_NULL(ihandle))
ion_free(qseecom.ion_clnt, ihandle);
- qsee_disable_clock_vote(data, CLK_SFPB);
+ __qseecom_disable_clk_scale_down(data);
return -EFAULT;
}
@@ -731,7 +893,7 @@
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry) {
pr_err("kmalloc failed\n");
- qsee_disable_clock_vote(data, CLK_SFPB);
+ __qseecom_disable_clk_scale_down(data);
return -ENOMEM;
}
entry->app_id = app_id;
@@ -754,10 +916,10 @@
if (copy_to_user(argp, &load_img_req, sizeof(load_img_req))) {
pr_err("copy_to_user failed\n");
kzfree(entry);
- qsee_disable_clock_vote(data, CLK_SFPB);
+ __qseecom_disable_clk_scale_down(data);
return -EFAULT;
}
- qsee_disable_clock_vote(data, CLK_SFPB);
+ __qseecom_disable_clk_scale_down(data);
return 0;
}
@@ -936,6 +1098,8 @@
return -EINVAL;
}
+ data->type = QSEECOM_SECURE_SERVICE;
+
switch (req.cmd_id) {
case QSEOS_RPMB_PROVISION_KEY_COMMAND:
case QSEOS_RPMB_ERASE_COMMAND:
@@ -948,15 +1112,25 @@
return -EINVAL;
}
- ret = qsee_vote_for_clock(data, CLK_DFAB);
- if (ret) {
- pr_err("Failed to vote for DFAB clock%d\n", ret);
- return ret;
- }
- ret = qsee_vote_for_clock(data, CLK_SFPB);
- if (ret) {
- pr_err("Failed to vote for SFPB clock%d\n", ret);
- goto exit_reset_dfab_freq;
+ if (qseecom.support_bus_scaling) {
+ qseecom_scale_bus_bandwidth_timer(HIGH,
+ QSEECOM_SEND_CMD_CRYPTO_TIMEOUT);
+ if (ret) {
+ pr_err("Fail to set bw HIGH%d\n", ret);
+ return ret;
+ }
+ } else {
+ ret = qsee_vote_for_clock(data, CLK_DFAB);
+ if (ret) {
+ pr_err("Failed to vote for DFAB clock%d\n", ret);
+ return ret;
+ }
+ ret = qsee_vote_for_clock(data, CLK_SFPB);
+ if (ret) {
+ qsee_disable_clock_vote(data, CLK_DFAB);
+ pr_err("Failed to vote for SFPB clock%d\n", ret);
+ goto exit;
+ }
}
msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle,
@@ -970,7 +1144,11 @@
ION_IOC_INV_CACHES);
if (ret) {
pr_err("qseecom_scm_call failed with err: %d\n", ret);
- goto exit_reset_sdfab_freq;
+ if (!qseecom.support_bus_scaling) {
+ qsee_disable_clock_vote(data, CLK_DFAB);
+ qsee_disable_clock_vote(data, CLK_SFPB);
+ }
+ goto exit;
}
switch (resp.result) {
@@ -993,10 +1171,7 @@
ret = -EINVAL;
break;
}
-exit_reset_sdfab_freq:
- qsee_disable_clock_vote(data, CLK_SFPB);
-exit_reset_dfab_freq:
- qsee_disable_clock_vote(data, CLK_DFAB);
+exit:
return ret;
}
@@ -1479,10 +1654,9 @@
/* Populate the remaining parameters */
load_req.qsee_cmd_id = QSEOS_APP_START_COMMAND;
memcpy(load_req.app_name, appname, MAX_APP_NAME_SIZE);
- ret = qsee_vote_for_clock(data, CLK_SFPB);
+ ret = __qseecom_enable_clk_scale_up(data);
if (ret) {
kzfree(img_data);
- pr_warning("Unable to vote for SFPB clock");
return -EIO;
}
@@ -1494,7 +1668,7 @@
kzfree(img_data);
if (ret) {
pr_err("scm_call to load failed : ret %d\n", ret);
- qsee_disable_clock_vote(data, CLK_SFPB);
+ __qseecom_disable_clk_scale_down(data);
return -EIO;
}
@@ -1517,7 +1691,7 @@
ret = -EINVAL;
break;
}
- qsee_disable_clock_vote(data, CLK_SFPB);
+ __qseecom_disable_clk_scale_down(data);
return ret;
}
@@ -1546,9 +1720,8 @@
/* Populate the remaining parameters */
load_req.qsee_cmd_id = QSEOS_LOAD_SERV_IMAGE_COMMAND;
/* Vote for the SFPB clock */
- ret = qsee_vote_for_clock(data, CLK_SFPB);
+ ret = __qseecom_enable_clk_scale_up(data);
if (ret) {
- pr_err("Unable to vote for SFPB clock: ret = %d", ret);
kzfree(img_data);
return -EIO;
}
@@ -1584,7 +1757,7 @@
}
}
kzfree(img_data);
- qsee_disable_clock_vote(data, CLK_SFPB);
+ __qseecom_disable_clk_scale_down(data);
return ret;
}
@@ -1794,10 +1967,24 @@
pr_err("Unable to find the handle, exiting\n");
else
ret = qseecom_unload_app(data);
- if (data->fast_load_enabled == true)
- qsee_disable_clock_vote(data, CLK_SFPB);
- if (data->perf_enabled == true)
- qsee_disable_clock_vote(data, CLK_DFAB);
+
+ if (qseecom.support_bus_scaling) {
+ mutex_lock(&qsee_bw_mutex);
+ if (data->mode != INACTIVE) {
+ qseecom_unregister_bus_bandwidth_needs(data);
+ if (qseecom.cumulative_mode == INACTIVE) {
+ ret = __qseecom_set_msm_bus_request(INACTIVE);
+ if (ret)
+ pr_err("Fail to scale down bus\n");
+ }
+ }
+ mutex_unlock(&qsee_bw_mutex);
+ } else {
+ if (data->fast_load_enabled == true)
+ qsee_disable_clock_vote(data, CLK_SFPB);
+ if (data->perf_enabled == true)
+ qsee_disable_clock_vote(data, CLK_DFAB);
+ }
if (ret == 0) {
kzfree(data);
kzfree(*handle);
@@ -1828,7 +2015,9 @@
mutex_lock(&app_access_lock);
atomic_inc(&data->ioctl_count);
-
+ if (qseecom.support_bus_scaling)
+ qseecom_scale_bus_bandwidth_timer(INACTIVE,
+ QSEECOM_SEND_CMD_CRYPTO_TIMEOUT);
ret = __qseecom_send_cmd(data, &req);
atomic_dec(&data->ioctl_count);
@@ -1851,17 +2040,30 @@
return -EINVAL;
}
if (high) {
- ret = qsee_vote_for_clock(handle->dev, CLK_DFAB);
- if (ret)
- pr_err("Failed to vote for DFAB clock%d\n", ret);
- ret = qsee_vote_for_clock(handle->dev, CLK_SFPB);
- if (ret) {
- pr_err("Failed to vote for SFPB clock%d\n", ret);
- qsee_disable_clock_vote(handle->dev, CLK_DFAB);
+ if (qseecom.support_bus_scaling) {
+ mutex_lock(&qsee_bw_mutex);
+ __qseecom_register_bus_bandwidth_needs(handle->dev,
+ HIGH);
+ mutex_unlock(&qsee_bw_mutex);
+ if (ret)
+ pr_err("Failed to scale bus (med) %d\n", ret);
+ } else {
+ ret = qsee_vote_for_clock(handle->dev, CLK_DFAB);
+ if (ret)
+ pr_err("Failed to vote for DFAB clock%d\n",
+ ret);
+ ret = qsee_vote_for_clock(handle->dev, CLK_SFPB);
+ if (ret) {
+ pr_err("Failed to vote for SFPB clock%d\n",
+ ret);
+ qsee_disable_clock_vote(handle->dev, CLK_DFAB);
+ }
}
} else {
- qsee_disable_clock_vote(handle->dev, CLK_DFAB);
- qsee_disable_clock_vote(handle->dev, CLK_SFPB);
+ if (!qseecom.support_bus_scaling) {
+ qsee_disable_clock_vote(handle->dev, CLK_DFAB);
+ qsee_disable_clock_vote(handle->dev, CLK_SFPB);
+ }
}
return ret;
}
@@ -2206,9 +2408,8 @@
}
/* Vote for the SFPB clock */
- ret = qsee_vote_for_clock(data, CLK_SFPB);
+ ret = __qseecom_enable_clk_scale_up(data);
if (ret) {
- pr_err("Unable to vote for SFPB clock: ret = %d", ret);
ret = -EIO;
goto exit_cpu_restore;
}
@@ -2246,7 +2447,7 @@
}
exit_disable_clock:
- qsee_disable_clock_vote(data, CLK_SFPB);
+ __qseecom_disable_clk_scale_down(data);
exit_cpu_restore:
/* Restore the CPU mask */
mask = CPU_MASK_ALL;
@@ -2797,6 +2998,7 @@
break;
}
case QSEECOM_IOCTL_SEND_CMD_REQ: {
+ pr_debug("qseecom.current_mode %d\n", qseecom.current_mode);
if ((data->client.app_id == 0) ||
(data->type != QSEECOM_CLIENT_APP)) {
pr_err("send cmd req: invalid handle (%d) app_id(%d)\n",
@@ -2806,6 +3008,9 @@
}
/* Only one client allowed here at a time */
mutex_lock(&app_access_lock);
+ if (qseecom.support_bus_scaling)
+ qseecom_scale_bus_bandwidth_timer(INACTIVE,
+ QSEECOM_SEND_CMD_CRYPTO_TIMEOUT);
atomic_inc(&data->ioctl_count);
ret = qseecom_send_cmd(data, argp);
atomic_dec(&data->ioctl_count);
@@ -2816,6 +3021,7 @@
break;
}
case QSEECOM_IOCTL_SEND_MODFD_CMD_REQ: {
+ pr_debug("qseecom.current_mode %d\n", qseecom.current_mode);
if ((data->client.app_id == 0) ||
(data->type != QSEECOM_CLIENT_APP)) {
pr_err("send mdfd cmd: invalid handle (%d) appid(%d)\n",
@@ -2825,6 +3031,9 @@
}
/* Only one client allowed here at a time */
mutex_lock(&app_access_lock);
+ if (qseecom.support_bus_scaling)
+ qseecom_scale_bus_bandwidth_timer(INACTIVE,
+ QSEECOM_SEND_CMD_CRYPTO_TIMEOUT);
atomic_inc(&data->ioctl_count);
ret = qseecom_send_modfd_cmd(data, argp);
atomic_dec(&data->ioctl_count);
@@ -2951,12 +3160,18 @@
break;
}
atomic_inc(&data->ioctl_count);
- ret = qsee_vote_for_clock(data, CLK_DFAB);
- if (ret)
- pr_err("Failed to vote for DFAB clock%d\n", ret);
- ret = qsee_vote_for_clock(data, CLK_SFPB);
- if (ret)
- pr_err("Failed to vote for SFPB clock%d\n", ret);
+ if (qseecom.support_bus_scaling) {
+ mutex_lock(&qsee_bw_mutex);
+ __qseecom_register_bus_bandwidth_needs(data, HIGH);
+ mutex_unlock(&qsee_bw_mutex);
+ } else {
+ ret = qsee_vote_for_clock(data, CLK_DFAB);
+ if (ret)
+ pr_err("Fail to vote for DFAB clock%d\n", ret);
+ ret = qsee_vote_for_clock(data, CLK_SFPB);
+ if (ret)
+ pr_err("Fail to vote for SFPB clock%d\n", ret);
+ }
atomic_dec(&data->ioctl_count);
break;
}
@@ -2976,8 +3191,24 @@
break;
}
atomic_inc(&data->ioctl_count);
+ if (!qseecom.support_bus_scaling) {
qsee_disable_clock_vote(data, CLK_DFAB);
qsee_disable_clock_vote(data, CLK_SFPB);
+ }
+ atomic_dec(&data->ioctl_count);
+ break;
+ }
+
+ case QSEECOM_IOCTL_SET_BUS_SCALING_REQ: {
+ if ((data->client.app_id == 0) ||
+ (data->type != QSEECOM_CLIENT_APP)) {
+ pr_err("set bus scale: invalid handle (%d) appid(%d)\n",
+ data->type, data->client.app_id);
+ ret = -EINVAL;
+ break;
+ }
+ atomic_inc(&data->ioctl_count);
+ ret = qseecom_scale_bus_bandwidth(data, argp);
atomic_dec(&data->ioctl_count);
break;
}
@@ -3176,6 +3407,7 @@
data->abort = 0;
data->type = QSEECOM_GENERIC;
data->released = false;
+ data->mode = INACTIVE;
init_waitqueue_head(&data->abort_wq);
atomic_set(&data->ioctl_count, 0);
@@ -3188,8 +3420,8 @@
int ret = 0;
if (data->released == false) {
- pr_warn("data: released = false, type = %d, data = 0x%x\n",
- data->type, (u32)data);
+ pr_warn("data: released=false, type=%d, mode=%d, data=0x%x\n",
+ data->type, data->mode, (u32)data);
switch (data->type) {
case QSEECOM_LISTENER_SERVICE:
ret = qseecom_unregister_listener(data);
@@ -3212,11 +3444,23 @@
}
}
- if (data->fast_load_enabled == true)
- qsee_disable_clock_vote(data, CLK_SFPB);
- if (data->perf_enabled == true)
- qsee_disable_clock_vote(data, CLK_DFAB);
-
+ if (qseecom.support_bus_scaling) {
+ mutex_lock(&qsee_bw_mutex);
+ if (data->mode != INACTIVE) {
+ qseecom_unregister_bus_bandwidth_needs(data);
+ if (qseecom.cumulative_mode == INACTIVE) {
+ ret = __qseecom_set_msm_bus_request(INACTIVE);
+ if (ret)
+ pr_err("Fail to scale down bus\n");
+ }
+ }
+ mutex_unlock(&qsee_bw_mutex);
+ } else {
+ if (data->fast_load_enabled == true)
+ qsee_disable_clock_vote(data, CLK_SFPB);
+ if (data->perf_enabled == true)
+ qsee_disable_clock_vote(data, CLK_DFAB);
+ }
kfree(data);
return ret;
@@ -3359,6 +3603,10 @@
qseecom.qsee.ce_core_src_clk = NULL;
qseecom.qsee.ce_bus_clk = NULL;
+ qseecom.cumulative_mode = 0;
+ qseecom.current_mode = INACTIVE;
+ qseecom.support_bus_scaling = false;
+
qseecom.ce_drv.ce_core_clk = NULL;
qseecom.ce_drv.ce_clk = NULL;
qseecom.ce_drv.ce_core_src_clk = NULL;
@@ -3438,7 +3686,11 @@
/* register client for bus scaling */
if (pdev->dev.of_node) {
-
+ qseecom.support_bus_scaling =
+ of_property_read_bool((&pdev->dev)->of_node,
+ "qcom,support-bus-scaling");
+ pr_warn("support_bus_scaling=0x%x",
+ qseecom.support_bus_scaling);
if (of_property_read_u32((&pdev->dev)->of_node,
"qcom,disk-encrypt-pipe-pair",
&qseecom.ce_info.disk_encrypt_pipe)) {
@@ -3531,7 +3783,13 @@
qseecom_platform_support = (struct msm_bus_scale_pdata *)
pdev->dev.platform_data;
}
-
+ if (qseecom.support_bus_scaling) {
+ init_timer(&(qseecom.bw_scale_down_timer));
+ INIT_WORK(&qseecom.bw_inactive_req_ws,
+ qseecom_bw_inactive_req_work);
+ qseecom.bw_scale_down_timer.function =
+ qseecom_scale_bus_bandwidth_timer_callback;
+ }
qseecom.qsee_perf_client = msm_bus_scale_register_client(
qseecom_platform_support);
@@ -3597,6 +3855,11 @@
if (pdev->dev.platform_data != NULL)
msm_bus_scale_unregister_client(qseecom.qsee_perf_client);
+ if (qseecom.support_bus_scaling) {
+ cancel_work_sync(&qseecom.bw_inactive_req_ws);
+ del_timer_sync(&qseecom.bw_scale_down_timer);
+ }
+
/* register client for bus scaling */
if (pdev->dev.of_node) {
__qseecom_deinit_clk(CLK_QSEE);
diff --git a/include/linux/qseecom.h b/include/linux/qseecom.h
index 6d2db8f3..a45c34c 100644
--- a/include/linux/qseecom.h
+++ b/include/linux/qseecom.h
@@ -163,6 +163,13 @@
QSEOS_UNPROTECT_PROTECTED_BUFFER,
};
+enum qseecom_bandwidth_request_mode {
+ INACTIVE = 0,
+ LOW,
+ MEDIUM,
+ HIGH,
+};
+
/*
* struct qseecom_send_modfd_resp - for send command ioctl request
* @req_len - command buffer length
@@ -177,7 +184,6 @@
enum qseecom_buffer_protection protection_mode; /* in */
};
-
#define QSEECOM_IOC_MAGIC 0x97
@@ -246,4 +252,8 @@
#define QSEECOM_IOCTL_UNPROTECT_BUF \
_IOWR(QSEECOM_IOC_MAGIC, 22, int)
+
+#define QSEECOM_IOCTL_SET_BUS_SCALING_REQ \
+ _IOWR(QSEECOM_IOC_MAGIC, 23, int)
+
#endif /* __QSEECOM_H_ */