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:
parent
c2e09bd1cf
commit
78d0f9faf4
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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 * */
|
||||
|
Loading…
Reference in New Issue
Block a user