drm/msm: Speed up interrupt processing upon commit

Since we know an interrupt will be arriving soon when a frame is
committed, we can anticipate it and prevent the CPU servicing that
interrupt from entering deep idle states. This reduces display rendering
latency.

Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com>
Signed-off-by: Diab Neiroukh <lazerl0rd@thezest.dev>
This commit is contained in:
Sultan Alsawaf 2020-12-26 18:27:26 -08:00 committed by spakkkk
parent c2e09bd1cf
commit 78d0f9faf4
3 changed files with 29 additions and 0 deletions

View File

@ -732,6 +732,10 @@ retry:
* mark our set of crtc's as busy:
*/
if (!atomic_cmpxchg_acquire(&priv->pm_req_set, 1, 0))
pm_qos_update_request(&priv->pm_irq_req, 100);
mod_delayed_work(system_unbound_wq, &priv->pm_unreq_dwork, HZ / 10);
/* Start Atomic */
spin_lock(&priv->pending_crtcs_event.lock);
ret = wait_event_interruptible_locked(priv->pending_crtcs_event,

View File

@ -860,6 +860,16 @@ static void msm_idle_init(struct drm_device *ddev)
spin_lock_init(&idle->lock);
}
static void msm_drm_pm_unreq(struct work_struct *work)
{
struct msm_drm_private *priv = container_of(to_delayed_work(work),
typeof(*priv),
pm_unreq_dwork);
pm_qos_update_request(&priv->pm_irq_req, PM_QOS_DEFAULT_VALUE);
atomic_set_release(&priv->pm_req_set, 0);
}
static int msm_drm_init(struct device *dev, struct drm_driver *drv)
{
struct platform_device *pdev = to_platform_device(dev);
@ -898,6 +908,9 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
INIT_LIST_HEAD(&priv->client_event_list);
INIT_LIST_HEAD(&priv->inactive_list);
priv->pm_req_set = (atomic_t)ATOMIC_INIT(0);
INIT_DELAYED_WORK(&priv->pm_unreq_dwork, msm_drm_pm_unreq);
ret = sde_power_resource_init(pdev, &priv->phandle);
if (ret) {
pr_err("sde power resource init failed\n");
@ -1243,8 +1256,13 @@ static void msm_irq_preinstall(struct drm_device *dev)
{
struct msm_drm_private *priv = dev->dev_private;
struct msm_kms *kms = priv->kms;
struct sde_kms *sde_kms = to_sde_kms(kms);
BUG_ON(!kms);
kms->funcs->irq_preinstall(kms);
priv->pm_irq_req.type = PM_QOS_REQ_AFFINE_IRQ;
priv->pm_irq_req.irq = sde_kms->irq_num;
pm_qos_add_request(&priv->pm_irq_req, PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
}
static int msm_irq_postinstall(struct drm_device *dev)
@ -1261,6 +1279,8 @@ static void msm_irq_uninstall(struct drm_device *dev)
struct msm_kms *kms = priv->kms;
BUG_ON(!kms);
kms->funcs->irq_uninstall(kms);
flush_delayed_work(&priv->pm_unreq_dwork);
pm_qos_remove_request(&priv->pm_irq_req);
}
static int msm_enable_vblank(struct drm_device *dev, unsigned int pipe)

View File

@ -26,6 +26,7 @@
#include <linux/component.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/pm_qos.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/list.h>
@ -722,6 +723,10 @@ struct msm_drm_private {
ktime_t complete_commit_time;
struct msm_idle idle;
struct pm_qos_request pm_irq_req;
struct delayed_work pm_unreq_dwork;
atomic_t pm_req_set;
};
/* get struct msm_kms * from drm_device * */