msm: ipa3: support ipa clk scaling for pcie modem

Add the QMI support to change ipa clk scaling
from PCIE modem.

Change-Id: Iee77ff4b8027c2a042f2e6c640749cdec09d92dc
Signed-off-by: Arnav Sharma <arnav_s@codeaurora.org>
This commit is contained in:
Skylar Chang
2019-05-24 14:51:23 -07:00
کامیت شده توسط Arnav Sharma
والد 17d30030db
کامیت 710f989e84
8فایلهای تغییر یافته به همراه142 افزوده شده و 21 حذف شده

مشاهده پرونده

@@ -6708,7 +6708,7 @@ static int get_ipa_dts_pm_info(struct platform_device *pdev,
result = of_property_read_string_index(pdev->dev.of_node,
"qcom,scaling-exceptions",
i * ipa_drv_res->pm_init.threshold_size,
i * (ipa_drv_res->pm_init.threshold_size + 1),
&ex[i].usecase);
if (result) {
IPAERR("failed to read qcom,scaling-exceptions");
@@ -6721,7 +6721,8 @@ static int get_ipa_dts_pm_info(struct platform_device *pdev,
result = of_property_read_string_index(
pdev->dev.of_node,
"qcom,scaling-exceptions",
i * ipa_drv_res->pm_init.threshold_size + j + 1,
i * (ipa_drv_res->pm_init.threshold_size + 1)
+ j + 1,
&str);
if (result) {
IPAERR("failed to read qcom,scaling-exceptions"

مشاهده پرونده

@@ -12,6 +12,7 @@
#include "../ipa_rm_i.h"
#include "ipahal/ipahal_nat.h"
#include "ipa_odl.h"
#include "ipa_qmi_service.h"
#define IPA_MAX_ENTRY_STRING_LEN 500
#define IPA_MAX_MSG_LEN 4096
@@ -319,17 +320,41 @@ static ssize_t ipa3_write_keep_awake(struct file *file, const char __user *buf,
{
s8 option = 0;
int ret;
uint32_t bw_mbps = 0;
ret = kstrtos8_from_user(buf, count, 0, &option);
if (ret)
return ret;
if (option == 1)
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
else if (option == 0)
switch (option) {
case 0:
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
else
bw_mbps = 0;
break;
case 1:
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
bw_mbps = 0;
break;
case 2:
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
bw_mbps = 700;
break;
case 3:
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
bw_mbps = 3000;
break;
case 4:
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
bw_mbps = 7000;
break;
default:
pr_err("Not support this vote (%d)\n", option);
return -EFAULT;
}
if (ipa3_vote_for_bus_bw(&bw_mbps)) {
IPAERR("Failed to vote for bus BW (%u)\n", bw_mbps);
return -EFAULT;
}
return count;
}

مشاهده پرونده

@@ -318,6 +318,30 @@ int ipa_setup_odl_pipe(void)
}
/**
* ipa3_odl_register_pm - Register odl client for PM
*
* This function will register 1 client with IPA PM to represent odl
* in clock scaling calculation:
* - "ODL" - this client will be activated when pipe connected
*/
static int ipa3_odl_register_pm(void)
{
int result = 0;
struct ipa_pm_register_params pm_reg;
memset(&pm_reg, 0, sizeof(pm_reg));
pm_reg.name = "ODL";
pm_reg.group = IPA_PM_GROUP_DEFAULT;
pm_reg.skip_clk_vote = true;
result = ipa_pm_register(&pm_reg, &ipa3_odl_ctx->odl_pm_hdl);
if (result) {
IPAERR("failed to create IPA PM client %d\n", result);
return result;
}
return result;
}
int ipa3_odl_pipe_open(void)
{
int ret = 0;
@@ -367,6 +391,10 @@ static int ipa_adpl_open(struct inode *inode, struct file *filp)
IPADBG("Called the function :\n");
if (ipa3_odl_ctx->odl_state.odl_init &&
!ipa3_odl_ctx->odl_state.adpl_open) {
/* Activate ipa_pm*/
ret = ipa_pm_activate_sync(ipa3_odl_ctx->odl_pm_hdl);
if (ret)
IPAERR("failed to activate pm\n");
ipa3_odl_ctx->odl_state.adpl_open = true;
ret = ipa3_odl_pipe_open();
} else {
@@ -380,8 +408,13 @@ static int ipa_adpl_open(struct inode *inode, struct file *filp)
static int ipa_adpl_release(struct inode *inode, struct file *filp)
{
int ret = 0;
/* Deactivate ipa_pm */
ret = ipa_pm_deactivate_sync(ipa3_odl_ctx->odl_pm_hdl);
if (ret)
IPAERR("failed to activate pm\n");
ipa3_odl_pipe_cleanup(false);
return 0;
return ret;
}
void ipa3_odl_pipe_cleanup(bool is_ssr)
@@ -668,6 +701,13 @@ int ipa_odl_init(void)
}
ipa3_odl_ctx->odl_state.odl_init = true;
/* register ipa_pm */
result = ipa3_odl_register_pm();
if (result) {
IPAWANERR("ipa3_odl_register_pm failed, ret: %d\n",
result);
}
return 0;
cdev1_add_fail:
device_destroy(odl_cdev[1].class, odl_cdev[1].dev_num);

مشاهده پرونده

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*/
#ifndef _IPA3_ODL_H_
@@ -56,6 +56,7 @@ struct ipa_odl_context {
struct odl_state_bit_mask odl_state;
bool odl_ctl_msg_wq_flag;
struct ipa3_odlstats stats;
u32 odl_pm_hdl;
};
struct ipa3_push_msg_odl {

مشاهده پرونده

@@ -361,7 +361,7 @@ static int do_clk_scaling(void)
mutex_unlock(&ipa_pm_ctx->client_mutex);
for (i = 0; i < clk_scaling->threshold_size; i++) {
if (tput > clk_scaling->current_threshold[i])
if (tput >= clk_scaling->current_threshold[i])
new_th_idx++;
}
@@ -526,15 +526,19 @@ static int find_next_open_array_element(const char *name)
*/
static int add_client_to_exception_list(u32 hdl)
{
int i;
int i, len = 0;
struct ipa_pm_exception_list *exception;
mutex_lock(&ipa_pm_ctx->client_mutex);
len = strlen(ipa_pm_ctx->clients[hdl]->name);
for (i = 0; i < ipa_pm_ctx->clk_scaling.exception_size; i++) {
exception = &ipa_pm_ctx->clk_scaling.exception_list[i];
if (strnstr(exception->clients, ipa_pm_ctx->clients[hdl]->name,
strlen(exception->clients))) {
len) && (strlen(exception->clients)
== len)) {
exception->pending--;
IPA_PM_DBG("Pending: %d\n",
exception->pending);
if (exception->pending < 0) {
WARN_ON(1);
@@ -568,6 +572,8 @@ static int remove_client_from_exception_list(u32 hdl)
exception = &ipa_pm_ctx->clk_scaling.exception_list[i];
if (exception->bitmask & (1 << hdl)) {
exception->pending++;
IPA_PM_DBG("Pending: %d\n",
exception->pending);
exception->bitmask &= ~(1 << hdl);
}
}
@@ -651,6 +657,7 @@ int ipa_pm_init(struct ipa_pm_init_params *params)
clk_scaling->exception_list[i].pending++;
}
/* for the first client */
clk_scaling->exception_list[i].pending++;
IPA_PM_DBG("Pending: %d\n",
clk_scaling->exception_list[i].pending);

مشاهده پرونده

@@ -12,7 +12,7 @@
#define IPA_PM_MAX_CLIENTS 32 /* actual max is value -1 since we start from 1*/
#define IPA_PM_MAX_EX_CL 64
#define IPA_PM_THRESHOLD_MAX 5
#define IPA_PM_EXCEPTION_MAX 2
#define IPA_PM_EXCEPTION_MAX 5
#define IPA_PM_DEFERRED_TIMEOUT 10
/*

مشاهده پرونده

@@ -313,7 +313,7 @@ static void ipa3_handle_mhi_alloc_channel_req(struct qmi_handle *qmi_handle,
resp = imp_handle_allocate_channel_req(ch_alloc_req);
if (!resp) {
IPAWANERR("imp handle allocate channel req fails");
IPAWANERR("imp handle allocate channel req fails\n");
return;
}
@@ -338,18 +338,62 @@ static void ipa3_handle_mhi_vote_req(struct qmi_handle *qmi_handle,
const void *decoded_msg)
{
struct ipa_mhi_clk_vote_req_msg_v01 *vote_req;
struct ipa_mhi_clk_vote_resp_msg_v01 *resp = NULL;
struct ipa_mhi_clk_vote_resp_msg_v01 *resp = NULL, resp2;
int rc;
uint32_t bw_mbps = 0;
vote_req = (struct ipa_mhi_clk_vote_req_msg_v01 *)decoded_msg;
IPAWANDBG("Received QMI_IPA_MHI_CLK_VOTE_REQ_V01(%d)\n",
vote_req->mhi_vote);
resp = imp_handle_vote_req(vote_req->mhi_vote);
if (!resp) {
IPAWANERR("imp handle allocate channel req fails");
return;
memset(&resp2, 0, sizeof(struct ipa_mhi_clk_vote_resp_msg_v01));
/* for mpm used for ipa clk voting */
if (ipa3_is_apq()) {
IPAWANDBG("Throughput(%d:%d) clk-rate(%d:%d)\n",
vote_req->tput_value_valid,
vote_req->tput_value,
vote_req->clk_rate_valid,
vote_req->clk_rate);
if (vote_req->clk_rate_valid) {
switch (vote_req->clk_rate) {
case QMI_IPA_CLOCK_RATE_LOW_SVS_V01:
bw_mbps = 0;
break;
case QMI_IPA_CLOCK_RATE_SVS_V01:
bw_mbps = 350;
break;
case QMI_IPA_CLOCK_RATE_NOMINAL_V01:
bw_mbps = 690;
break;
case QMI_IPA_CLOCK_RATE_TURBO_V01:
bw_mbps = 1200;
break;
default:
IPAWANERR("Note supported clk_rate (%d)\n",
vote_req->clk_rate);
bw_mbps = 0;
resp2.resp.result = IPA_QMI_RESULT_FAILURE_V01;
resp2.resp.error =
IPA_QMI_ERR_NOT_SUPPORTED_V01;
break;
}
if (ipa3_vote_for_bus_bw(&bw_mbps)) {
IPAWANERR("Failed to vote BW (%u)\n", bw_mbps);
resp2.resp.result = IPA_QMI_RESULT_FAILURE_V01;
resp2.resp.error =
IPA_QMI_ERR_NOT_SUPPORTED_V01;
}
resp = &resp2;
}
} else {
resp = imp_handle_vote_req(vote_req->mhi_vote);
if (!resp) {
IPAWANERR("imp handle allocate channel req fails");
return;
}
IPAWANDBG("start sending QMI_IPA_MHI_CLK_VOTE_RESP_V01\n");
}
IPAWANDBG("start sending QMI_IPA_MHI_CLK_VOTE_RESP_V01\n");
IPAWANDBG("qmi_snd_rsp: result %d, err %d\n",
resp->resp.result, resp->resp.error);
@@ -1419,7 +1463,7 @@ static void ipa3_q6_clnt_svc_arrive(struct work_struct *work)
return;
IPAWANDBG("Q6 QMI service available now\n");
if (ipa3_ctx->platform_type == IPA_PLAT_TYPE_APQ) {
if (ipa3_is_apq()) {
ipa3_qmi_modem_init_fin = true;
IPAWANDBG("QMI-client complete, ipa3_qmi_modem_init_fin : %d\n",
ipa3_qmi_modem_init_fin);
@@ -1812,6 +1856,8 @@ int ipa3_vote_for_bus_bw(uint32_t *bw_mbps)
{
int ret;
IPAWANDBG("Bus BW is %d\n", *bw_mbps);
if (bw_mbps == NULL) {
IPAWANERR("Bus BW is invalid\n");
return -EINVAL;

مشاهده پرونده

@@ -2161,6 +2161,7 @@ int ipa3_wwan_set_modem_perf_profile(int throughput)
int ret;
int tether_bridge_handle = 0;
IPAWANDBG("throughput: %d\n", throughput);
/* query rmnet-tethering handle */
tether_bridge_handle = ipa3_teth_bridge_get_pm_hdl();
if (tether_bridge_handle > 0) {
@@ -2170,7 +2171,7 @@ int ipa3_wwan_set_modem_perf_profile(int throughput)
}
/* for TETH MODEM on softap/rndis */
ret = ipa_pm_set_throughput(rmnet_ipa3_ctx->q6_teth_pm_hdl,
throughput);
throughput);
return ret;
}