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:

کامیت شده توسط
Arnav Sharma

والد
17d30030db
کامیت
710f989e84
@@ -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;
|
||||
}
|
||||
|
مرجع در شماره جدید
Block a user