Commit 7c5925af authored by Gustavo Pimentel's avatar Gustavo Pimentel Committed by Lorenzo Pieralisi

PCI: dwc: Move MSI IRQs allocation to IRQ domains hierarchical API

Implement a multiplexed IRQ domain hierarchy API in the pcie-designware
host bridge driver that funnels all MSI IRQs into a single parent
interrupt, moving away from the obsolete struct msi_controller based
API.

Although the old implementation API is still available, pcie-designware
will now use the multiplexed IRQ domains hierarchical API.

Remove all existing dwc based host bridges MSI IRQs handlers, in that the
hierarchical API now handles MSI IRQs through the hierarchical/chained
MSI domain implementation.
Signed-off-by: default avatarGustavo Pimentel <gustavo.pimentel@synopsys.com>
Signed-off-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Tested-by: default avatarNiklas Cassel <niklas.cassel@axis.com>
Tested-by: default avatarShawn Guo <shawn.guo@linaro.org>
Acked-by: default avatarJingoo Han <jingoohan1@gmail.com>
Acked-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
parent 7928b2cb
......@@ -294,15 +294,6 @@ static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg)
return IRQ_HANDLED;
}
static irqreturn_t exynos_pcie_msi_irq_handler(int irq, void *arg)
{
struct exynos_pcie *ep = arg;
struct dw_pcie *pci = ep->pci;
struct pcie_port *pp = &pci->pp;
return dw_handle_msi_irq(pp);
}
static void exynos_pcie_msi_init(struct exynos_pcie *ep)
{
struct dw_pcie *pci = ep->pci;
......@@ -428,15 +419,6 @@ static int __init exynos_add_pcie_port(struct exynos_pcie *ep,
dev_err(dev, "failed to get msi irq\n");
return pp->msi_irq;
}
ret = devm_request_irq(dev, pp->msi_irq,
exynos_pcie_msi_irq_handler,
IRQF_SHARED | IRQF_NO_THREAD,
"exynos-pcie", ep);
if (ret) {
dev_err(dev, "failed to request msi irq\n");
return ret;
}
}
pp->root_bus_nr = -1;
......
......@@ -542,15 +542,6 @@ static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie)
return -EINVAL;
}
static irqreturn_t imx6_pcie_msi_handler(int irq, void *arg)
{
struct imx6_pcie *imx6_pcie = arg;
struct dw_pcie *pci = imx6_pcie->pci;
struct pcie_port *pp = &pci->pp;
return dw_handle_msi_irq(pp);
}
static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
{
struct dw_pcie *pci = imx6_pcie->pci;
......@@ -674,15 +665,6 @@ static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie,
dev_err(dev, "failed to get MSI irq\n");
return -ENODEV;
}
ret = devm_request_irq(dev, pp->msi_irq,
imx6_pcie_msi_handler,
IRQF_SHARED | IRQF_NO_THREAD,
"mx6-pcie-msi", imx6_pcie);
if (ret) {
dev_err(dev, "failed to request MSI irq\n");
return ret;
}
}
pp->root_bus_nr = -1;
......
......@@ -120,20 +120,15 @@ void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset)
}
}
static void ks_dw_pcie_msi_irq_ack(struct irq_data *d)
void ks_dw_pcie_msi_irq_ack(int irq, struct pcie_port *pp)
{
u32 offset, reg_offset, bit_pos;
u32 reg_offset, bit_pos;
struct keystone_pcie *ks_pcie;
struct msi_desc *msi;
struct pcie_port *pp;
struct dw_pcie *pci;
msi = irq_data_get_msi_desc(d);
pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
pci = to_dw_pcie_from_pp(pp);
ks_pcie = to_keystone_pcie(pci);
offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
update_reg_offset_bit_pos(offset, &reg_offset, &bit_pos);
update_reg_offset_bit_pos(irq, &reg_offset, &bit_pos);
ks_dw_app_writel(ks_pcie, MSI0_IRQ_STATUS + (reg_offset << 4),
BIT(bit_pos));
......@@ -162,85 +157,9 @@ void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
BIT(bit_pos));
}
static void ks_dw_pcie_msi_irq_mask(struct irq_data *d)
{
struct msi_desc *msi;
struct pcie_port *pp;
u32 offset;
msi = irq_data_get_msi_desc(d);
pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
/* Mask the end point if PVM implemented */
if (IS_ENABLED(CONFIG_PCI_MSI)) {
if (msi->msi_attrib.maskbit)
pci_msi_mask_irq(d);
}
ks_dw_pcie_msi_clear_irq(pp, offset);
}
static void ks_dw_pcie_msi_irq_unmask(struct irq_data *d)
{
struct msi_desc *msi;
struct pcie_port *pp;
u32 offset;
msi = irq_data_get_msi_desc(d);
pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
/* Mask the end point if PVM implemented */
if (IS_ENABLED(CONFIG_PCI_MSI)) {
if (msi->msi_attrib.maskbit)
pci_msi_unmask_irq(d);
}
ks_dw_pcie_msi_set_irq(pp, offset);
}
static struct irq_chip ks_dw_pcie_msi_irq_chip = {
.name = "Keystone-PCIe-MSI-IRQ",
.irq_ack = ks_dw_pcie_msi_irq_ack,
.irq_mask = ks_dw_pcie_msi_irq_mask,
.irq_unmask = ks_dw_pcie_msi_irq_unmask,
};
static int ks_dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
irq_hw_number_t hwirq)
{
irq_set_chip_and_handler(irq, &ks_dw_pcie_msi_irq_chip,
handle_level_irq);
irq_set_chip_data(irq, domain->host_data);
return 0;
}
static const struct irq_domain_ops ks_dw_pcie_msi_domain_ops = {
.map = ks_dw_pcie_msi_map,
};
int ks_dw_pcie_msi_host_init(struct pcie_port *pp, struct msi_controller *chip)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
struct device *dev = pci->dev;
int i;
pp->irq_domain = irq_domain_add_linear(ks_pcie->msi_intc_np,
MAX_MSI_IRQS,
&ks_dw_pcie_msi_domain_ops,
chip);
if (!pp->irq_domain) {
dev_err(dev, "irq domain init failed\n");
return -ENXIO;
}
for (i = 0; i < MAX_MSI_IRQS; i++)
irq_create_mapping(pp->irq_domain, i);
return 0;
return dw_pcie_allocate_domains(pp);
}
void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie)
......
......@@ -297,6 +297,7 @@ static const struct dw_pcie_host_ops keystone_pcie_host_ops = {
.msi_clear_irq = ks_dw_pcie_msi_clear_irq,
.get_msi_addr = ks_dw_pcie_get_msi_addr,
.msi_host_init = ks_dw_pcie_msi_host_init,
.msi_irq_ack = ks_dw_pcie_msi_irq_ack,
.scan_bus = ks_dw_pcie_v3_65_scan_bus,
};
......
......@@ -49,6 +49,7 @@ int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 *val);
void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie);
void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie);
void ks_dw_pcie_msi_irq_ack(int i, struct pcie_port *pp);
void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq);
void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq);
void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp);
......
......@@ -383,15 +383,6 @@ static const struct dw_pcie_host_ops artpec6_pcie_host_ops = {
.host_init = artpec6_pcie_host_init,
};
static irqreturn_t artpec6_pcie_msi_handler(int irq, void *arg)
{
struct artpec6_pcie *artpec6_pcie = arg;
struct dw_pcie *pci = artpec6_pcie->pci;
struct pcie_port *pp = &pci->pp;
return dw_handle_msi_irq(pp);
}
static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie,
struct platform_device *pdev)
{
......@@ -406,15 +397,6 @@ static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie,
dev_err(dev, "failed to get MSI irq\n");
return pp->msi_irq;
}
ret = devm_request_irq(dev, pp->msi_irq,
artpec6_pcie_msi_handler,
IRQF_SHARED | IRQF_NO_THREAD,
"artpec6-pcie-msi", artpec6_pcie);
if (ret) {
dev_err(dev, "failed to request MSI irq\n");
return ret;
}
}
pp->root_bus_nr = -1;
......
This diff is collapsed.
......@@ -25,13 +25,6 @@ struct dw_plat_pcie {
struct dw_pcie *pci;
};
static irqreturn_t dw_plat_pcie_msi_irq_handler(int irq, void *arg)
{
struct pcie_port *pp = arg;
return dw_handle_msi_irq(pp);
}
static int dw_plat_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
......@@ -63,15 +56,6 @@ static int dw_plat_add_pcie_port(struct pcie_port *pp,
pp->msi_irq = platform_get_irq(pdev, 0);
if (pp->msi_irq < 0)
return pp->msi_irq;
ret = devm_request_irq(dev, pp->msi_irq,
dw_plat_pcie_msi_irq_handler,
IRQF_SHARED | IRQF_NO_THREAD,
"dw-plat-pcie-msi", pp);
if (ret) {
dev_err(dev, "failed to request MSI IRQ\n");
return ret;
}
}
pp->root_bus_nr = -1;
......
......@@ -114,6 +114,7 @@
*/
#define MAX_MSI_IRQS 32
#define MAX_MSI_CTRLS (MAX_MSI_IRQS / 32)
#define MSI_DEF_NUM_VECTORS 32
/* Maximum number of inbound/outbound iATUs */
#define MAX_IATU_IN 256
......@@ -149,7 +150,9 @@ struct dw_pcie_host_ops {
phys_addr_t (*get_msi_addr)(struct pcie_port *pp);
u32 (*get_msi_data)(struct pcie_port *pp, int pos);
void (*scan_bus)(struct pcie_port *pp);
void (*set_num_vectors)(struct pcie_port *pp);
int (*msi_host_init)(struct pcie_port *pp, struct msi_controller *chip);
void (*msi_irq_ack)(int irq, struct pcie_port *pp);
};
struct pcie_port {
......@@ -174,7 +177,11 @@ struct pcie_port {
const struct dw_pcie_host_ops *ops;
int msi_irq;
struct irq_domain *irq_domain;
struct irq_domain *msi_domain;
dma_addr_t msi_data;
u32 num_vectors;
u32 irq_status[MAX_MSI_CTRLS];
raw_spinlock_t lock;
DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
};
......@@ -316,8 +323,10 @@ static inline void dw_pcie_dbi_ro_wr_dis(struct dw_pcie *pci)
#ifdef CONFIG_PCIE_DW_HOST
irqreturn_t dw_handle_msi_irq(struct pcie_port *pp);
void dw_pcie_msi_init(struct pcie_port *pp);
void dw_pcie_free_msi(struct pcie_port *pp);
void dw_pcie_setup_rc(struct pcie_port *pp);
int dw_pcie_host_init(struct pcie_port *pp);
int dw_pcie_allocate_domains(struct pcie_port *pp);
#else
static inline irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
{
......@@ -328,6 +337,10 @@ static inline void dw_pcie_msi_init(struct pcie_port *pp)
{
}
static inline void dw_pcie_free_msi(struct pcie_port *pp)
{
}
static inline void dw_pcie_setup_rc(struct pcie_port *pp)
{
}
......@@ -336,6 +349,11 @@ static inline int dw_pcie_host_init(struct pcie_port *pp)
{
return 0;
}
static inline int dw_pcie_allocate_domains(struct pcie_port *pp)
{
return 0;
}
#endif
#ifdef CONFIG_PCIE_DW_EP
......
......@@ -207,13 +207,6 @@ static struct dw_pcie_host_ops histb_pcie_host_ops = {
.host_init = histb_pcie_host_init,
};
static irqreturn_t histb_pcie_msi_irq_handler(int irq, void *arg)
{
struct pcie_port *pp = arg;
return dw_handle_msi_irq(pp);
}
static void histb_pcie_host_disable(struct histb_pcie *hipcie)
{
reset_control_assert(hipcie->soft_reset);
......@@ -393,14 +386,6 @@ static int histb_pcie_probe(struct platform_device *pdev)
dev_err(dev, "Failed to get MSI IRQ\n");
return pp->msi_irq;
}
ret = devm_request_irq(dev, pp->msi_irq,
histb_pcie_msi_irq_handler,
IRQF_SHARED, "histb-pcie-msi", pp);
if (ret) {
dev_err(dev, "cannot request MSI IRQ\n");
return ret;
}
}
hipcie->phy = devm_phy_get(dev, "phy");
......
......@@ -180,13 +180,6 @@ static void qcom_ep_reset_deassert(struct qcom_pcie *pcie)
usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500);
}
static irqreturn_t qcom_pcie_msi_irq_handler(int irq, void *arg)
{
struct pcie_port *pp = arg;
return dw_handle_msi_irq(pp);
}
static int qcom_pcie_establish_link(struct qcom_pcie *pcie)
{
struct dw_pcie *pci = pcie->pci;
......@@ -1262,15 +1255,6 @@ static int qcom_pcie_probe(struct platform_device *pdev)
pp->msi_irq = platform_get_irq_byname(pdev, "msi");
if (pp->msi_irq < 0)
return pp->msi_irq;
ret = devm_request_irq(dev, pp->msi_irq,
qcom_pcie_msi_irq_handler,
IRQF_SHARED | IRQF_NO_THREAD,
"qcom-pcie-msi", pp);
if (ret) {
dev_err(dev, "cannot request msi irq\n");
return ret;
}
}
ret = phy_init(pcie->phy);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment