drm/msm/sde: cleanup core perf implementation
Current perf and crtc module supports multiple
real time and non-realtime client with different
API checks. These APIs are duplicated and checks
in perf modules are specific to real time vs non-
realtime. This patch cleans up the solution and
make it generalize to support the rsc type bw
client also. A crtc/encoder can now easily switch
between apps rsc vs display rsc by single rsc mode
flag to provide its bandwidth on certain client.
Change-Id: I9e2e09919949bff6e8ca1e5ae7b58449535a4c1a
Signed-off-by: Dhaval Patel <pdhaval@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/sde/sde_core_perf.c b/drivers/gpu/drm/msm/sde/sde_core_perf.c
index 0ba644d..7a68f91 100644
--- a/drivers/gpu/drm/msm/sde/sde_core_perf.c
+++ b/drivers/gpu/drm/msm/sde/sde_core_perf.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -22,16 +22,10 @@
#include "msm_prop.h"
#include "sde_kms.h"
-#include "sde_fence.h"
-#include "sde_formats.h"
-#include "sde_hw_sspp.h"
#include "sde_trace.h"
#include "sde_crtc.h"
-#include "sde_plane.h"
-#include "sde_encoder.h"
-#include "sde_wb.h"
+#include "sde_rsc.h"
#include "sde_core_perf.h"
-#include "sde_trace.h"
static struct sde_kms *_sde_crtc_get_kms(struct drm_crtc *crtc)
{
@@ -59,20 +53,23 @@
static bool _sde_core_video_mode_intf_connected(struct drm_crtc *crtc)
{
struct drm_crtc *tmp_crtc;
+ bool intf_connected = false;
if (!crtc)
- return 0;
+ goto end;
drm_for_each_crtc(tmp_crtc, crtc->dev) {
if ((sde_crtc_get_intf_mode(tmp_crtc) == INTF_MODE_VIDEO) &&
_sde_core_perf_crtc_is_power_on(tmp_crtc)) {
SDE_DEBUG("video interface connected crtc:%d\n",
tmp_crtc->base.id);
- return true;
+ intf_connected = true;
+ goto end;
}
}
- return false;
+end:
+ return intf_connected;
}
int sde_core_perf_crtc_check(struct drm_crtc *crtc,
@@ -80,6 +77,7 @@
{
u32 bw, threshold;
u64 bw_sum_of_intfs = 0;
+ enum sde_crtc_client_type curr_client_type;
bool is_video_mode;
struct sde_crtc_state *sde_cstate;
struct drm_crtc *tmp_crtc;
@@ -97,16 +95,18 @@
}
/* we only need bandwidth check on real-time clients (interfaces) */
- if (sde_crtc_is_wb(crtc))
+ if (sde_crtc_get_client_type(crtc) == NRT_CLIENT)
return 0;
sde_cstate = to_sde_crtc_state(state);
bw_sum_of_intfs = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_AB);
+ curr_client_type = sde_crtc_get_client_type(crtc);
drm_for_each_crtc(tmp_crtc, crtc->dev) {
if (_sde_core_perf_crtc_is_power_on(tmp_crtc) &&
- sde_crtc_is_rt(tmp_crtc) && tmp_crtc != crtc) {
+ (sde_crtc_get_client_type(tmp_crtc) == curr_client_type) &&
+ (tmp_crtc != crtc)) {
struct sde_crtc_state *tmp_cstate =
to_sde_crtc_state(tmp_crtc->state);
@@ -131,7 +131,7 @@
return -E2BIG;
} else if (bw > threshold) {
sde_cstate->cur_perf.bw_ctl = 0;
- SDE_DEBUG("exceeds bandwidth: %ukb > %ukb\n", bw, threshold);
+ SDE_ERROR("exceeds bandwidth: %ukb > %ukb\n", bw, threshold);
return -E2BIG;
}
@@ -158,23 +158,23 @@
perf->max_per_pipe_ib, perf->bw_ctl);
}
-static u64 _sde_core_perf_crtc_calc_client_vote(struct sde_kms *kms,
- struct drm_crtc *crtc, struct sde_core_perf_params *perf,
- bool nrt_client, u32 core_clk)
+static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms,
+ struct drm_crtc *crtc)
{
- u64 bw_sum_of_intfs = 0;
+ u64 bw_sum_of_intfs = 0, bus_ab_quota, bus_ib_quota;
+ struct sde_core_perf_params perf = {0};
+ enum sde_crtc_client_type curr_client_type
+ = sde_crtc_get_client_type(crtc);
struct drm_crtc *tmp_crtc;
+ struct sde_crtc_state *sde_cstate;
+ struct msm_drm_private *priv = kms->dev->dev_private;
drm_for_each_crtc(tmp_crtc, crtc->dev) {
- if (_sde_core_perf_crtc_is_power_on(crtc) &&
- /* RealTime clients */
- ((!nrt_client) ||
- /* Non-RealTime clients */
- (nrt_client && sde_crtc_is_nrt(tmp_crtc)))) {
- struct sde_crtc_state *sde_cstate =
- to_sde_crtc_state(tmp_crtc->state);
+ if (_sde_core_perf_crtc_is_power_on(tmp_crtc) &&
+ (curr_client_type == sde_crtc_get_client_type(tmp_crtc))) {
+ sde_cstate = to_sde_crtc_state(tmp_crtc->state);
- perf->max_per_pipe_ib = max(perf->max_per_pipe_ib,
+ perf.max_per_pipe_ib = max(perf.max_per_pipe_ib,
sde_cstate->cur_perf.max_per_pipe_ib);
bw_sum_of_intfs += sde_cstate->cur_perf.bw_ctl;
@@ -185,57 +185,38 @@
}
}
- return bw_sum_of_intfs;
-}
+ bus_ab_quota = max(bw_sum_of_intfs, kms->perf.perf_tune.min_bus_vote);
+ bus_ib_quota = perf.max_per_pipe_ib;
-static void _sde_core_perf_crtc_update_client_vote(struct sde_kms *kms,
- struct sde_core_perf_params *params, bool nrt_client, u64 bw_vote)
-{
- struct msm_drm_private *priv = kms->dev->dev_private;
- u64 bus_ab_quota, bus_ib_quota;
+ switch (curr_client_type) {
+ case NRT_CLIENT:
+ sde_power_data_bus_set_quota(&priv->phandle, kms->core_client,
+ SDE_POWER_HANDLE_DATA_BUS_CLIENT_NRT,
+ bus_ab_quota, bus_ib_quota);
+ SDE_DEBUG("client:%s ab=%llu ib=%llu\n", "nrt",
+ bus_ab_quota, bus_ib_quota);
+ break;
- bus_ab_quota = max(bw_vote, kms->perf.perf_tune.min_bus_vote);
- bus_ib_quota = params->max_per_pipe_ib;
-
- SDE_ATRACE_INT("bus_quota", bus_ib_quota);
- sde_power_data_bus_set_quota(&priv->phandle, kms->core_client,
- nrt_client ? SDE_POWER_HANDLE_DATA_BUS_CLIENT_NRT :
+ case RT_CLIENT:
+ sde_power_data_bus_set_quota(&priv->phandle, kms->core_client,
SDE_POWER_HANDLE_DATA_BUS_CLIENT_RT,
- bus_ab_quota, bus_ib_quota);
- SDE_DEBUG("client:%s ab=%llu ib=%llu\n", nrt_client ? "nrt" : "rt",
- bus_ab_quota, bus_ib_quota);
-}
+ bus_ab_quota, bus_ib_quota);
+ SDE_DEBUG("client:%s ab=%llu ib=%llu\n", "rt",
+ bus_ab_quota, bus_ib_quota);
+ break;
-static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms,
- struct drm_crtc *crtc, u32 core_clk)
-{
- u64 bw_sum_of_rt_intfs = 0, bw_sum_of_nrt_intfs = 0;
- struct sde_core_perf_params params = {0};
+ case RT_RSC_CLIENT:
+ sde_cstate = to_sde_crtc_state(crtc->state);
+ sde_rsc_client_vote(sde_cstate->rsc_client, bus_ab_quota,
+ bus_ib_quota);
+ SDE_DEBUG("client:%s ab=%llu ib=%llu\n", "rt_rsc",
+ bus_ab_quota, bus_ib_quota);
+ break;
- SDE_ATRACE_BEGIN(__func__);
-
- /*
- * non-real time client
- */
- if (sde_crtc_is_nrt(crtc)) {
- bw_sum_of_nrt_intfs = _sde_core_perf_crtc_calc_client_vote(
- kms, crtc, ¶ms, true, core_clk);
- _sde_core_perf_crtc_update_client_vote(kms, ¶ms, true,
- bw_sum_of_nrt_intfs);
+ default:
+ SDE_ERROR("invalid client type:%d\n", curr_client_type);
+ break;
}
-
- /*
- * real time client
- */
- if (!sde_crtc_is_nrt(crtc) ||
- sde_crtc_is_wb(crtc)) {
- bw_sum_of_rt_intfs = _sde_core_perf_crtc_calc_client_vote(kms,
- crtc, ¶ms, false, core_clk);
- _sde_core_perf_crtc_update_client_vote(kms, ¶ms, false,
- bw_sum_of_rt_intfs);
- }
-
- SDE_ATRACE_END(__func__);
}
/**
@@ -265,9 +246,9 @@
sde_cstate = to_sde_crtc_state(crtc->state);
- /* only do this for command panel or writeback */
+ /* only do this for command mode rt client (non-rsc client) */
if ((sde_crtc_get_intf_mode(crtc) != INTF_MODE_CMD) &&
- (sde_crtc_get_intf_mode(crtc) != INTF_MODE_WB_LINE))
+ (sde_crtc_get_client_type(crtc) != RT_RSC_CLIENT))
return;
/*
@@ -288,22 +269,15 @@
sde_cstate->cur_perf.bw_ctl = 0;
sde_cstate->new_perf.bw_ctl = 0;
SDE_DEBUG("Release BW crtc=%d\n", crtc->base.id);
- _sde_core_perf_crtc_update_bus(kms, crtc, 0);
+ _sde_core_perf_crtc_update_bus(kms, crtc);
}
}
-static int _sde_core_select_clk_lvl(struct sde_kms *kms,
- u32 clk_rate)
-{
- return clk_round_rate(kms->perf.core_clk, clk_rate);
-}
-
static u32 _sde_core_perf_get_core_clk_rate(struct sde_kms *kms)
{
u32 clk_rate = 0;
struct drm_crtc *crtc;
struct sde_crtc_state *sde_cstate;
- int ncrtc = 0;
drm_for_each_crtc(crtc, kms->dev) {
if (_sde_core_perf_crtc_is_power_on(crtc)) {
@@ -312,11 +286,9 @@
clk_rate);
clk_rate = clk_round_rate(kms->perf.core_clk, clk_rate);
}
- ncrtc++;
}
- clk_rate = _sde_core_select_clk_lvl(kms, clk_rate);
- SDE_DEBUG("clk:%u ncrtc:%d\n", clk_rate, ncrtc);
+ SDE_DEBUG("clk:%u\n", clk_rate);
return clk_rate;
}
@@ -351,8 +323,6 @@
SDE_DEBUG("crtc:%d stop_req:%d core_clk:%u\n",
crtc->base.id, stop_req, kms->perf.core_clk_rate);
- SDE_ATRACE_BEGIN(__func__);
-
old = &sde_cstate->cur_perf;
new = &sde_cstate->new_perf;
@@ -392,38 +362,28 @@
update_clk = 1;
}
- /*
- * Calculate mdp clock before bandwidth calculation. If traffic shaper
- * is enabled and clock increased, the bandwidth calculation can
- * use the new clock for the rotator bw calculation.
- */
- if (update_clk)
- clk_rate = _sde_core_perf_get_core_clk_rate(kms);
-
if (update_bus)
- _sde_core_perf_crtc_update_bus(kms, crtc, clk_rate);
+ _sde_core_perf_crtc_update_bus(kms, crtc);
/*
* Update the clock after bandwidth vote to ensure
* bandwidth is available before clock rate is increased.
*/
if (update_clk) {
- SDE_ATRACE_INT(kms->perf.clk_name, clk_rate);
+ clk_rate = _sde_core_perf_get_core_clk_rate(kms);
+
SDE_EVT32(kms->dev, stop_req, clk_rate);
ret = sde_power_clk_set_rate(&priv->phandle,
kms->perf.clk_name, clk_rate);
if (ret) {
SDE_ERROR("failed to set %s clock rate %u\n",
kms->perf.clk_name, clk_rate);
- goto end;
+ return;
}
kms->perf.core_clk_rate = clk_rate;
SDE_DEBUG("update clk rate = %d HZ\n", clk_rate);
}
-
-end:
- SDE_ATRACE_END(__func__);
}
#ifdef CONFIG_DEBUG_FS
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index ed9fd5d..7563074 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -417,7 +417,6 @@
SDE_EVT32(DRMID(crtc));
/* identify connectors attached to this crtc */
- cstate->is_rt = false;
cstate->num_connectors = 0;
drm_for_each_connector(conn, crtc->dev)
@@ -425,9 +424,6 @@
cstate->num_connectors < MAX_CONNECTORS) {
cstate->connectors[cstate->num_connectors++] = conn;
sde_connector_prepare_fence(conn);
-
- if (conn->connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
- cstate->is_rt = true;
}
if (cstate->num_connectors > 0 && cstate->connectors[0]->encoder)
@@ -440,15 +436,6 @@
sde_fence_prepare(&sde_crtc->output_fence);
}
-bool sde_crtc_is_rt(struct drm_crtc *crtc)
-{
- if (!crtc || !crtc->state) {
- SDE_ERROR("invalid crtc or state\n");
- return true;
- }
- return to_sde_crtc_state(crtc->state)->is_rt;
-}
-
/* if file!=NULL, this is preclose potential cancel-flip path */
static void _sde_crtc_complete_flip(struct drm_crtc *crtc,
struct drm_file *file)
@@ -1869,7 +1856,7 @@
struct sde_crtc_state *cstate = to_sde_crtc_state(crtc->state);
seq_printf(s, "num_connectors: %d\n", cstate->num_connectors);
- seq_printf(s, "is_rt: %d\n", cstate->is_rt);
+ seq_printf(s, "client type: %d\n", sde_crtc_get_client_type(crtc));
seq_printf(s, "intf_mode: %d\n", cstate->intf_mode);
seq_printf(s, "bw_ctl: %llu\n", cstate->cur_perf.bw_ctl);
seq_printf(s, "core_clk_rate: %u\n", cstate->cur_perf.core_clk_rate);
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index 91fdaed..f254977 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -31,6 +31,20 @@
#define SDE_CRTC_FRAME_EVENT_SIZE 2
/**
+ * enum sde_crtc_client_type: crtc client type
+ * @RT_CLIENT: RealTime client like video/cmd mode display
+ * voting through apps rsc
+ * @NRT_CLIENT: Non-RealTime client like WB display
+ * voting through apps rsc
+ * @RT_RSC_CLIENT: Realtime display RSC voting client
+ */
+enum sde_crtc_client_type {
+ RT_CLIENT,
+ NRT_CLIENT,
+ RT_RSC_CLIENT,
+};
+
+/**
* struct sde_crtc_mixer: stores the map for each virtual pipeline in the CRTC
* @hw_lm: LM HW Driver context
* @hw_ctl: CTL Path HW driver context
@@ -136,8 +150,9 @@
* @base: Base drm crtc state structure
* @connectors : Currently associated drm connectors
* @num_connectors: Number of associated drm connectors
- * @is_rt : Whether or not the current commit contains RT connectors
* @intf_mode : Interface mode of the primary connector
+ * @rsc_mode : Client vote through sde rsc
+ * @rsc_client : sde rsc client when mode is valid
* @property_values: Current crtc property values
* @input_fence_timeout_ns : Cached input fence timeout, in ns
* @property_blobs: Reference pointers for blob properties
@@ -151,8 +166,9 @@
struct drm_connector *connectors[MAX_CONNECTORS];
int num_connectors;
- bool is_rt;
enum sde_intf_mode intf_mode;
+ bool rsc_mode;
+ struct sde_rsc_client *rsc_client;
uint64_t property_values[CRTC_PROP_COUNT];
uint64_t input_fence_timeout_ns;
@@ -255,13 +271,6 @@
void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
/**
- * sde_crtc_is_rt - query whether real time connectors are present on the crtc
- * @crtc: Pointer to drm crtc structure
- * Returns: True if a connector is present with real time constraints
- */
-bool sde_crtc_is_rt(struct drm_crtc *crtc);
-
-/**
* sde_crtc_get_intf_mode - get interface mode of the given crtc
* @crtc: Pointert to crtc
*/
@@ -274,24 +283,16 @@
}
/**
- * sde_core_perf_crtc_is_wb - check if writeback is primary output of this crtc
+ * sde_crtc_get_client_type - check the crtc type- rt, nrt, rsc, etc.
* @crtc: Pointer to crtc
*/
-static inline bool sde_crtc_is_wb(struct drm_crtc *crtc)
+static inline bool sde_crtc_get_client_type(struct drm_crtc *crtc)
{
struct sde_crtc_state *cstate =
crtc ? to_sde_crtc_state(crtc->state) : NULL;
- return cstate ? (cstate->intf_mode == INTF_MODE_WB_LINE) : false;
-}
-
-/**
- * sde_crtc_is_nrt - check if primary output of this crtc is non-realtime client
- * @crtc: Pointer to crtc
- */
-static inline bool sde_crtc_is_nrt(struct drm_crtc *crtc)
-{
- return sde_crtc_is_wb(crtc);
+ return cstate && (cstate->intf_mode == INTF_MODE_WB_LINE) ? NRT_CLIENT
+ : cstate && cstate->rsc_mode ? RT_RSC_CLIENT : RT_CLIENT;
}
/**
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index d22c93f..6a31e1d 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -862,8 +862,7 @@
if (sde_enc->disp_info.is_primary) {
ret = sde_rsc_client_vote(sde_enc->rsc_client,
SDE_POWER_HANDLE_DATA_BUS_IB_QUOTA,
- SDE_POWER_HANDLE_DATA_BUS_AB_QUOTA,
- true);
+ SDE_POWER_HANDLE_DATA_BUS_AB_QUOTA);
if (ret)
SDE_ERROR("sde rsc client vote failed ret:%d\n", ret);
}
@@ -1303,7 +1302,6 @@
}
mutex_unlock(&sde_enc->enc_lock);
-
return ret;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index e144a0d..46508c7b 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -1203,7 +1203,7 @@
return 0;
pstate->pending = true;
- psde->is_rt_pipe = sde_crtc_is_rt(crtc);
+ psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
_sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
/* update roi config */