drm/msm: add SDE IRQ domain before creating DRM objects
Currently all connectors list SDE as their parent interrupt controller. With commit <f5dd86c92d63df7a2790149d1cb9588c004695b0> (<drm/msm/sde: reorganize top level interrupt handling code>), the SDE IRQ domains get added after DRM init functions of the connectors. This is incorrect as the irq request calls of the connectors shall fail if the domain of the parent is not added yet. Fix this by re-ordering the sde_kms_int() function to reflect the correct order and remove the IRQ domain addition from irq_preinstall calls as that will be very late for the connectors. Change-Id: Ie1364840e2f018361e54470516d48c3facf59272 Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org>
This commit is contained in:
parent
83fc94fbb9
commit
9a0a010c8e
4 changed files with 125 additions and 90 deletions
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2015-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
|
||||
|
@ -432,6 +432,99 @@ void sde_core_irq_uninstall(struct sde_kms *sde_kms)
|
|||
sde_kms->irq_obj.total_irqs = 0;
|
||||
}
|
||||
|
||||
static void sde_hw_irq_mask(struct irq_data *irqd)
|
||||
{
|
||||
struct sde_kms *sde_kms;
|
||||
|
||||
if (!irqd || !irq_data_get_irq_chip_data(irqd)) {
|
||||
SDE_ERROR("invalid parameters irqd %d\n", irqd != 0);
|
||||
return;
|
||||
}
|
||||
sde_kms = irq_data_get_irq_chip_data(irqd);
|
||||
|
||||
smp_mb__before_atomic();
|
||||
clear_bit(irqd->hwirq, &sde_kms->irq_controller.enabled_mask);
|
||||
smp_mb__after_atomic();
|
||||
}
|
||||
|
||||
static void sde_hw_irq_unmask(struct irq_data *irqd)
|
||||
{
|
||||
struct sde_kms *sde_kms;
|
||||
|
||||
if (!irqd || !irq_data_get_irq_chip_data(irqd)) {
|
||||
SDE_ERROR("invalid parameters irqd %d\n", irqd != 0);
|
||||
return;
|
||||
}
|
||||
sde_kms = irq_data_get_irq_chip_data(irqd);
|
||||
|
||||
smp_mb__before_atomic();
|
||||
set_bit(irqd->hwirq, &sde_kms->irq_controller.enabled_mask);
|
||||
smp_mb__after_atomic();
|
||||
}
|
||||
|
||||
static struct irq_chip sde_hw_irq_chip = {
|
||||
.name = "sde",
|
||||
.irq_mask = sde_hw_irq_mask,
|
||||
.irq_unmask = sde_hw_irq_unmask,
|
||||
};
|
||||
|
||||
static int sde_hw_irqdomain_map(struct irq_domain *domain,
|
||||
unsigned int irq, irq_hw_number_t hwirq)
|
||||
{
|
||||
struct sde_kms *sde_kms;
|
||||
int rc;
|
||||
|
||||
if (!domain || !domain->host_data) {
|
||||
SDE_ERROR("invalid parameters domain %d\n", domain != 0);
|
||||
return -EINVAL;
|
||||
}
|
||||
sde_kms = domain->host_data;
|
||||
|
||||
irq_set_chip_and_handler(irq, &sde_hw_irq_chip, handle_level_irq);
|
||||
rc = irq_set_chip_data(irq, sde_kms);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct irq_domain_ops sde_hw_irqdomain_ops = {
|
||||
.map = sde_hw_irqdomain_map,
|
||||
.xlate = irq_domain_xlate_onecell,
|
||||
};
|
||||
|
||||
int sde_core_irq_domain_add(struct sde_kms *sde_kms)
|
||||
{
|
||||
struct device *dev;
|
||||
struct irq_domain *domain;
|
||||
|
||||
if (!sde_kms->dev || !sde_kms->dev->dev) {
|
||||
pr_err("invalid device handles\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev = sde_kms->dev->dev;
|
||||
|
||||
domain = irq_domain_add_linear(dev->of_node, 32,
|
||||
&sde_hw_irqdomain_ops, sde_kms);
|
||||
if (!domain) {
|
||||
pr_err("failed to add irq_domain\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sde_kms->irq_controller.enabled_mask = 0;
|
||||
sde_kms->irq_controller.domain = domain;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sde_core_irq_domain_fini(struct sde_kms *sde_kms)
|
||||
{
|
||||
if (sde_kms->irq_controller.domain) {
|
||||
irq_domain_remove(sde_kms->irq_controller.domain);
|
||||
sde_kms->irq_controller.domain = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
irqreturn_t sde_core_irq(struct sde_kms *sde_kms)
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2015-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
|
||||
|
@ -37,6 +37,20 @@ int sde_core_irq_postinstall(struct sde_kms *sde_kms);
|
|||
*/
|
||||
void sde_core_irq_uninstall(struct sde_kms *sde_kms);
|
||||
|
||||
/**
|
||||
* sde_core_irq_domain_add - Add core IRQ domain for SDE
|
||||
* @sde_kms: SDE handle
|
||||
* @return: none
|
||||
*/
|
||||
int sde_core_irq_domain_add(struct sde_kms *sde_kms);
|
||||
|
||||
/**
|
||||
* sde_core_irq_domain_fini - uninstall core IRQ domain
|
||||
* @sde_kms: SDE handle
|
||||
* @return: 0 if success; error code otherwise
|
||||
*/
|
||||
int sde_core_irq_domain_fini(struct sde_kms *sde_kms);
|
||||
|
||||
/**
|
||||
* sde_core_irq - core IRQ handler
|
||||
* @sde_kms: SDE handle
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2015-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
|
||||
|
@ -49,86 +49,14 @@ irqreturn_t sde_irq(struct msm_kms *kms)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void sde_hw_irq_mask(struct irq_data *irqd)
|
||||
{
|
||||
struct sde_kms *sde_kms;
|
||||
|
||||
if (!irqd || !irq_data_get_irq_chip_data(irqd)) {
|
||||
SDE_ERROR("invalid parameters irqd %d\n", irqd != 0);
|
||||
return;
|
||||
}
|
||||
sde_kms = irq_data_get_irq_chip_data(irqd);
|
||||
|
||||
smp_mb__before_atomic();
|
||||
clear_bit(irqd->hwirq, &sde_kms->irq_controller.enabled_mask);
|
||||
smp_mb__after_atomic();
|
||||
}
|
||||
|
||||
static void sde_hw_irq_unmask(struct irq_data *irqd)
|
||||
{
|
||||
struct sde_kms *sde_kms;
|
||||
|
||||
if (!irqd || !irq_data_get_irq_chip_data(irqd)) {
|
||||
SDE_ERROR("invalid parameters irqd %d\n", irqd != 0);
|
||||
return;
|
||||
}
|
||||
sde_kms = irq_data_get_irq_chip_data(irqd);
|
||||
|
||||
smp_mb__before_atomic();
|
||||
set_bit(irqd->hwirq, &sde_kms->irq_controller.enabled_mask);
|
||||
smp_mb__after_atomic();
|
||||
}
|
||||
|
||||
static struct irq_chip sde_hw_irq_chip = {
|
||||
.name = "sde",
|
||||
.irq_mask = sde_hw_irq_mask,
|
||||
.irq_unmask = sde_hw_irq_unmask,
|
||||
};
|
||||
|
||||
static int sde_hw_irqdomain_map(struct irq_domain *domain,
|
||||
unsigned int irq, irq_hw_number_t hwirq)
|
||||
{
|
||||
struct sde_kms *sde_kms;
|
||||
int rc;
|
||||
|
||||
if (!domain || !domain->host_data) {
|
||||
SDE_ERROR("invalid parameters domain %d\n", domain != 0);
|
||||
return -EINVAL;
|
||||
}
|
||||
sde_kms = domain->host_data;
|
||||
|
||||
irq_set_chip_and_handler(irq, &sde_hw_irq_chip, handle_level_irq);
|
||||
rc = irq_set_chip_data(irq, sde_kms);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct irq_domain_ops sde_hw_irqdomain_ops = {
|
||||
.map = sde_hw_irqdomain_map,
|
||||
.xlate = irq_domain_xlate_onecell,
|
||||
};
|
||||
|
||||
void sde_irq_preinstall(struct msm_kms *kms)
|
||||
{
|
||||
struct sde_kms *sde_kms = to_sde_kms(kms);
|
||||
struct device *dev;
|
||||
struct irq_domain *domain;
|
||||
|
||||
if (!sde_kms->dev || !sde_kms->dev->dev) {
|
||||
pr_err("invalid device handles\n");
|
||||
return;
|
||||
}
|
||||
dev = sde_kms->dev->dev;
|
||||
|
||||
domain = irq_domain_add_linear(dev->of_node, 32,
|
||||
&sde_hw_irqdomain_ops, sde_kms);
|
||||
if (!domain) {
|
||||
pr_err("failed to add irq_domain\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sde_kms->irq_controller.enabled_mask = 0;
|
||||
sde_kms->irq_controller.domain = domain;
|
||||
|
||||
sde_core_irq_preinstall(sde_kms);
|
||||
}
|
||||
|
@ -158,9 +86,5 @@ void sde_irq_uninstall(struct msm_kms *kms)
|
|||
}
|
||||
|
||||
sde_core_irq_uninstall(sde_kms);
|
||||
|
||||
if (sde_kms->irq_controller.domain) {
|
||||
irq_domain_remove(sde_kms->irq_controller.domain);
|
||||
sde_kms->irq_controller.domain = NULL;
|
||||
}
|
||||
sde_core_irq_domain_fini(sde_kms);
|
||||
}
|
||||
|
|
|
@ -811,6 +811,9 @@ static int _sde_kms_drm_obj_init(struct sde_kms *sde_kms)
|
|||
priv = dev->dev_private;
|
||||
catalog = sde_kms->catalog;
|
||||
|
||||
ret = sde_core_irq_domain_add(sde_kms);
|
||||
if (ret)
|
||||
goto fail_irq;
|
||||
/*
|
||||
* Query for underlying display drivers, and create connectors,
|
||||
* bridges and encoders for them.
|
||||
|
@ -869,6 +872,8 @@ static int _sde_kms_drm_obj_init(struct sde_kms *sde_kms)
|
|||
return 0;
|
||||
fail:
|
||||
_sde_kms_drm_obj_destroy(sde_kms);
|
||||
fail_irq:
|
||||
sde_core_irq_domain_fini(sde_kms);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1219,6 +1224,14 @@ static int sde_kms_hw_init(struct msm_kms *kms)
|
|||
goto perf_err;
|
||||
}
|
||||
|
||||
sde_kms->hw_intr = sde_hw_intr_init(sde_kms->mmio, sde_kms->catalog);
|
||||
if (IS_ERR_OR_NULL(sde_kms->hw_intr)) {
|
||||
rc = PTR_ERR(sde_kms->hw_intr);
|
||||
SDE_ERROR("hw_intr init failed: %d\n", rc);
|
||||
sde_kms->hw_intr = NULL;
|
||||
goto hw_intr_init_err;
|
||||
}
|
||||
|
||||
/*
|
||||
* _sde_kms_drm_obj_init should create the DRM related objects
|
||||
* i.e. CRTCs, planes, encoders, connectors and so forth
|
||||
|
@ -1244,21 +1257,12 @@ static int sde_kms_hw_init(struct msm_kms *kms)
|
|||
*/
|
||||
dev->mode_config.allow_fb_modifiers = true;
|
||||
|
||||
sde_kms->hw_intr = sde_hw_intr_init(sde_kms->mmio, sde_kms->catalog);
|
||||
if (IS_ERR_OR_NULL(sde_kms->hw_intr)) {
|
||||
rc = PTR_ERR(sde_kms->hw_intr);
|
||||
SDE_ERROR("hw_intr init failed: %d\n", rc);
|
||||
sde_kms->hw_intr = NULL;
|
||||
goto hw_intr_init_err;
|
||||
}
|
||||
|
||||
sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
|
||||
return 0;
|
||||
|
||||
hw_intr_init_err:
|
||||
_sde_kms_drm_obj_destroy(sde_kms);
|
||||
drm_obj_init_err:
|
||||
sde_core_perf_destroy(&sde_kms->perf);
|
||||
hw_intr_init_err:
|
||||
perf_err:
|
||||
power_error:
|
||||
sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
|
||||
|
|
Loading…
Add table
Reference in a new issue