From patchwork Mon Apr 27 06:05:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxun Yang X-Patchwork-Id: 201466 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DFEA9C54FD0 for ; Mon, 27 Apr 2020 06:06:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AE2042080C for ; Mon, 27 Apr 2020 06:06:16 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=flygoat.com header.i=@flygoat.com header.b="GH9RTTnj" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726504AbgD0GGQ (ORCPT ); Mon, 27 Apr 2020 02:06:16 -0400 Received: from vultr.net.flygoat.com ([149.28.68.211]:60110 "EHLO vultr.net.flygoat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726221AbgD0GGP (ORCPT ); Mon, 27 Apr 2020 02:06:15 -0400 Received: from localhost.localdomain (unknown [IPv6:2001:da8:20f:4430:250:56ff:fe9a:7470]) by vultr.net.flygoat.com (Postfix) with ESMTPSA id 7D17320CF4; Mon, 27 Apr 2020 06:06:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=flygoat.com; s=vultr; t=1587967574; bh=NE5sCt6ssdL9diqa/uHtsH6X8dScz66rvMdDwvKjb94=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GH9RTTnjT/o2eJFEMiy55OMLVbHnBAORssZ+EwGSmFuDvo39o95+Xj36jaNyquAHR +pWlRkIWo2KR2pI2AJjYqXByWV84UvRqd9mkNw8ZqbOZdyhc3P4RSyxVoixVWWO/b7 vgXaDdEXQigrs8ueWeBchOd6NZmlM0SAZePvVmrqmJZRTvQlhMHvD+g0rzvBj1rsSQ cQNRFiD8mGpg928rW7RUdtin0ZTBs7Ku3eltiACFOP4kMxhxiqH0yP2d5WO72y8coa jwIObL/ubGQ63+wACFqu/lg1fKOsxU/j+W3LGbMaVRvfaktJoXIZj5GNxnzUIEf3Ww QSrzVhsKvUi8Q== From: Jiaxun Yang To: linux-mips@vger.kernel.org Cc: Jiaxun Yang , Bjorn Helgaas , Rob Herring , Thomas Bogendoerfer , Huacai Chen , Lorenzo Pieralisi , Paul Burton , linux-pci@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v6 1/5] PCI: Don't disable decoding when mmio_always_on is set Date: Mon, 27 Apr 2020 14:05:38 +0800 Message-Id: <20200427060551.1372591-2-jiaxun.yang@flygoat.com> X-Mailer: git-send-email 2.26.0.rc2 In-Reply-To: <20200427060551.1372591-1-jiaxun.yang@flygoat.com> References: <20200427060551.1372591-1-jiaxun.yang@flygoat.com> MIME-Version: 1.0 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Don't disable MEM/IO decoing when a device have both non_compliant_bars and mmio_always_on. That would allow us quirk devices with junk in BARs but can't disable their decoding. Signed-off-by: Jiaxun Yang --- drivers/pci/probe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 77b8a145c39b..d9c2c3301a8a 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1822,7 +1822,7 @@ int pci_setup_device(struct pci_dev *dev) /* Device class may be changed after fixup */ class = dev->class >> 8; - if (dev->non_compliant_bars) { + if (dev->non_compliant_bars && !dev->mmio_always_on) { pci_read_config_word(dev, PCI_COMMAND, &cmd); if (cmd & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { pci_info(dev, "device has non-compliant BARs; disabling IO/MEM decoding\n"); From patchwork Tue May 26 09:21:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxun Yang X-Patchwork-Id: 200047 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 24597C433DF for ; Tue, 26 May 2020 09:22:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F2E70207CB for ; Tue, 26 May 2020 09:22:41 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=flygoat.com header.i=@flygoat.com header.b="rMUpl24I" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388528AbgEZJWi (ORCPT ); Tue, 26 May 2020 05:22:38 -0400 Received: from vultr.net.flygoat.com ([149.28.68.211]:34270 "EHLO vultr.net.flygoat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388425AbgEZJWi (ORCPT ); Tue, 26 May 2020 05:22:38 -0400 Received: from localhost.localdomain (unknown [142.147.94.151]) by vultr.net.flygoat.com (Postfix) with ESMTPSA id 60E4520CF0; Tue, 26 May 2020 09:22:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=flygoat.com; s=vultr; t=1590484957; bh=Ke6cPvHXKiPrY2g75japQ2FrKO93C44dRXKjeYxEPWg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rMUpl24If/+8mkwsrw/bpSV6FPS+dZVqxHXbXIXR0OGzseXXu/Ll66WOTRfSdDg4F BuLLdFhK0/oYr7mHwSh62zBUfD14DMczkU1MeKgivX/atv1H03P/HNXp/ZfO4aDqZ5 y/Fe0yA44osE4+WlhaWRIm15c0wdPH2EqTShad60FL21seQGat+SR+ivda4AsUvbya GJAv2k8nOSKW1C/ekrNYJN79fPoOyRH00xhmQqK+Pa/WPGNNGkFKy20QdGDwhNsyWL CIrkHAhYkodQ/A1k9gzbHDL0C1VDGKXI/dtbDub0WXl445INtnJCJFIvSxwDIoM85/ piu33YpZl5Glw== From: Jiaxun Yang To: linux-pci@vger.kernel.org Cc: Jiaxun Yang , Rob Herring , Bjorn Helgaas , Rob Herring , Thomas Bogendoerfer , Huacai Chen , Lorenzo Pieralisi , Paul Burton , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mips@vger.kernel.org Subject: [PATCH v11 3/5] dt-bindings: Document Loongson PCI Host Controller Date: Tue, 26 May 2020 17:21:14 +0800 Message-Id: <20200526092130.145550-4-jiaxun.yang@flygoat.com> X-Mailer: git-send-email 2.27.0.rc0 In-Reply-To: <20200526092130.145550-1-jiaxun.yang@flygoat.com> References: <20200427060551.1372591-1-jiaxun.yang@flygoat.com> <20200526092130.145550-1-jiaxun.yang@flygoat.com> MIME-Version: 1.0 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org PCI host controller found on Loongson PCHs and SoCs. Signed-off-by: Jiaxun Yang Reviewed-by: Rob Herring --- .../devicetree/bindings/pci/loongson.yaml | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/loongson.yaml diff --git a/Documentation/devicetree/bindings/pci/loongson.yaml b/Documentation/devicetree/bindings/pci/loongson.yaml new file mode 100644 index 000000000000..30e7cf1aeb87 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/loongson.yaml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pci/loongson.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Loongson PCI Host Controller + +maintainers: + - Jiaxun Yang + +description: |+ + PCI host controller found on Loongson PCHs and SoCs. + +allOf: + - $ref: /schemas/pci/pci-bus.yaml# + +properties: + compatible: + oneOf: + - const: loongson,ls2k-pci + - const: loongson,ls7a-pci + - const: loongson,rs780e-pci + + reg: + minItems: 1 + maxItems: 2 + items: + - description: CFG0 standard config space register + - description: CFG1 extended config space register + + ranges: + minItems: 1 + maxItems: 3 + + +required: + - compatible + - reg + - ranges + +examples: + - | + + bus { + #address-cells = <2>; + #size-cells = <2>; + pcie@1a000000 { + compatible = "loongson,rs780e-pci"; + device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; + + // CPU_PHYSICAL(2) SIZE(2) + reg = <0x0 0x1a000000 0x0 0x2000000>; + + // BUS_ADDRESS(3) CPU_PHYSICAL(2) SIZE(2) + ranges = <0x01000000 0x0 0x00004000 0x0 0x00004000 0x0 0x00004000>, + <0x02000000 0x0 0x40000000 0x0 0x40000000 0x0 0x40000000>; + }; + }; +... From patchwork Sat May 16 08:29:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxun Yang X-Patchwork-Id: 200449 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5B069C433DF for ; Sat, 16 May 2020 08:30:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 39B45207D4 for ; Sat, 16 May 2020 08:30:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=flygoat.com header.i=@flygoat.com header.b="b3IyN0YB" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727010AbgEPIaC (ORCPT ); Sat, 16 May 2020 04:30:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35522 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725934AbgEPIaC (ORCPT ); Sat, 16 May 2020 04:30:02 -0400 Received: from vultr.net.flygoat.com (vultr.net.flygoat.com [IPv6:2001:19f0:6001:3633:5400:2ff:fe8c:553]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 225C7C061A0C; Sat, 16 May 2020 01:30:02 -0700 (PDT) Received: from localhost.localdomain (unknown [142.147.94.151]) by vultr.net.flygoat.com (Postfix) with ESMTPSA id 0727B21017; Sat, 16 May 2020 08:29:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=flygoat.com; s=vultr; t=1589617801; bh=aOKK1vpvGOOvQ6WE81hKjYraONAeT894AQe6gcAbybI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=b3IyN0YB2WG4UfuDEDFKpBaEVzyTltLPHQoQUWTkrIjCB8sukU5dxyF703jYWExTx 3dQZY+zEBUpeZy1fzO5K2yFPuKBL6FSyqtDgDZnFEshfA82hLGCqsg6dbF7QddTf59 XyN4US1UGD2+kCdPrM7FDyTefRtHKoOzFZxLZNaLSA5zWMiqaul7nyP7LcLXmdu6I/ KSkRJZbusJmsB642fbxa6+tdFF/keb7gk/wV6Fb4cYhPkOmqRpR/bLZrT3IiJzVr2/ HkJvALwZqUFrkERYGJQ55ylN1WtzCk2Umz8PiE/0mFyHO/b7ZcSz6dyoJk4lpCeb+S AiTK7sJ26Aj1Q== From: Jiaxun Yang To: maz@kernel.org Cc: Jiaxun Yang , Thomas Gleixner , Jason Cooper , Rob Herring , Huacai Chen , linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-mips@vger.kernel.org Subject: [PATCH v4 5/6] irqchip: Add Loongson PCH MSI controller Date: Sat, 16 May 2020 16:29:05 +0800 Message-Id: <20200516082912.3673033-5-jiaxun.yang@flygoat.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200516082912.3673033-1-jiaxun.yang@flygoat.com> References: <20200427060551.1372591-1-jiaxun.yang@flygoat.com> <20200516082912.3673033-1-jiaxun.yang@flygoat.com> MIME-Version: 1.0 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This controller appears on Loongson LS7A family of PCH to transform interrupts from PCI MSI into HyperTransport vectorized interrrupts and send them to procrssor's HT vector controller. Signed-off-by: Jiaxun Yang --- v2: - Style clean-ups - Add ack callback - Use bitmap_find_free_region v3: - Style clean-ups - mutex lock instead of spin lock - correct bitmap usage v4: - Fix table layout - Make mask parent symetric --- drivers/irqchip/Kconfig | 10 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-loongson-pch-msi.c | 255 +++++++++++++++++++++++++ 3 files changed, 266 insertions(+) create mode 100644 drivers/irqchip/irq-loongson-pch-msi.c diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 5524a621638c..0b6b826dd843 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -549,4 +549,14 @@ config LOONGSON_PCH_PIC help Support for the Loongson PCH PIC Controller. +config LOONGSON_PCH_MSI + bool "Loongson PCH PIC Controller" + depends on MACH_LOONGSON64 || COMPILE_TEST + depends on PCI + default MACH_LOONGSON64 + select IRQ_DOMAIN_HIERARCHY + select PCI_MSI + help + Support for the Loongson PCH MSI Controller. + endmenu diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index acc72331cec8..3a4ce283189a 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -109,3 +109,4 @@ obj-$(CONFIG_LOONGSON_LIOINTC) += irq-loongson-liointc.o obj-$(CONFIG_LOONGSON_HTPIC) += irq-loongson-htpic.o obj-$(CONFIG_LOONGSON_HTVEC) += irq-loongson-htvec.o obj-$(CONFIG_LOONGSON_PCH_PIC) += irq-loongson-pch-pic.o +obj-$(CONFIG_LOONGSON_PCH_MSI) += irq-loongson-pch-msi.o diff --git a/drivers/irqchip/irq-loongson-pch-msi.c b/drivers/irqchip/irq-loongson-pch-msi.c new file mode 100644 index 000000000000..50becd21008c --- /dev/null +++ b/drivers/irqchip/irq-loongson-pch-msi.c @@ -0,0 +1,255 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020, Jiaxun Yang + * Loongson PCH MSI support + */ + +#define pr_fmt(fmt) "pch-msi: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +struct pch_msi_data { + struct mutex msi_map_lock; + phys_addr_t doorbell; + u32 irq_first; /* The vector number that MSIs starts */ + u32 num_irqs; /* The number of vectors for MSIs */ + unsigned long *msi_map; +}; + +static void pch_msi_mask_msi_irq(struct irq_data *d) +{ + pci_msi_mask_irq(d); + irq_chip_mask_parent(d); +} + +static void pch_msi_unmask_msi_irq(struct irq_data *d) +{ + irq_chip_unmask_parent(d); + pci_msi_unmask_irq(d); +} + +static struct irq_chip pch_msi_irq_chip = { + .name = "PCH PCI MSI", + .irq_mask = pch_msi_mask_msi_irq, + .irq_unmask = pch_msi_unmask_msi_irq, + .irq_ack = irq_chip_ack_parent, + .irq_set_affinity = irq_chip_set_affinity_parent, +}; + +static int pch_msi_allocate_hwirq(struct pch_msi_data *priv, int num_req) +{ + int first; + + mutex_lock(&priv->msi_map_lock); + + first = bitmap_find_free_region(priv->msi_map, priv->num_irqs, + get_count_order(num_req)); + if (first < 0) { + mutex_unlock(&priv->msi_map_lock); + return -ENOSPC; + } + + mutex_unlock(&priv->msi_map_lock); + + return priv->irq_first + first; +} + +static void pch_msi_free_hwirq(struct pch_msi_data *priv, + int hwirq, int num_req) +{ + int first = hwirq - priv->irq_first; + + mutex_lock(&priv->msi_map_lock); + bitmap_release_region(priv->msi_map, first, get_count_order(num_req)); + mutex_unlock(&priv->msi_map_lock); +} + +static void pch_msi_compose_msi_msg(struct irq_data *data, + struct msi_msg *msg) +{ + struct pch_msi_data *priv = irq_data_get_irq_chip_data(data); + + msg->address_hi = upper_32_bits(priv->doorbell); + msg->address_lo = lower_32_bits(priv->doorbell); + msg->data = data->hwirq; +} + +static struct msi_domain_info pch_msi_domain_info = { + .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | + MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX, + .chip = &pch_msi_irq_chip, +}; + +static struct irq_chip middle_irq_chip = { + .name = "PCH MSI", + .irq_mask = irq_chip_mask_parent, + .irq_unmask = irq_chip_unmask_parent, + .irq_ack = irq_chip_ack_parent, + .irq_set_affinity = irq_chip_set_affinity_parent, + .irq_compose_msi_msg = pch_msi_compose_msi_msg, +}; + +static int pch_msi_parent_domain_alloc(struct irq_domain *domain, + unsigned int virq, int hwirq) +{ + struct irq_fwspec fwspec; + int ret; + + fwspec.fwnode = domain->parent->fwnode; + fwspec.param_count = 1; + fwspec.param[0] = hwirq; + + ret = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec); + if (ret) + return ret; + + return 0; +} + +static int pch_msi_middle_domain_alloc(struct irq_domain *domain, + unsigned int virq, + unsigned int nr_irqs, void *args) +{ + struct pch_msi_data *priv = domain->host_data; + int hwirq, err, i; + + hwirq = pch_msi_allocate_hwirq(priv, nr_irqs); + if (hwirq < 0) + return hwirq; + + for (i = 0; i < nr_irqs; i++) { + err = pch_msi_parent_domain_alloc(domain, virq + i, hwirq + i); + if (err) + goto err_hwirq; + + irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i, + &middle_irq_chip, priv); + } + + return 0; + +err_hwirq: + pch_msi_free_hwirq(priv, hwirq, nr_irqs); + irq_domain_free_irqs_parent(domain, virq, i - 1); + + return err; +} + +static void pch_msi_middle_domain_free(struct irq_domain *domain, + unsigned int virq, + unsigned int nr_irqs) +{ + struct irq_data *d = irq_domain_get_irq_data(domain, virq); + struct pch_msi_data *priv = irq_data_get_irq_chip_data(d); + + irq_domain_free_irqs_parent(domain, virq, nr_irqs); + pch_msi_free_hwirq(priv, d->hwirq, nr_irqs); +} + +static const struct irq_domain_ops pch_msi_middle_domain_ops = { + .alloc = pch_msi_middle_domain_alloc, + .free = pch_msi_middle_domain_free, +}; + +static int pch_msi_init_domains(struct pch_msi_data *priv, + struct device_node *node, + struct irq_domain *parent) +{ + struct irq_domain *middle_domain, *msi_domain; + + middle_domain = irq_domain_create_linear(of_node_to_fwnode(node), + priv->num_irqs, + &pch_msi_middle_domain_ops, + priv); + if (!middle_domain) { + pr_err("Failed to create the MSI middle domain\n"); + return -ENOMEM; + } + + middle_domain->parent = parent; + irq_domain_update_bus_token(middle_domain, DOMAIN_BUS_NEXUS); + + msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node), + &pch_msi_domain_info, + middle_domain); + if (!msi_domain) { + pr_err("Failed to create PCI MSI domain\n"); + irq_domain_remove(middle_domain); + return -ENOMEM; + } + + return 0; +} + +static int pch_msi_init(struct device_node *node, + struct device_node *parent) +{ + struct pch_msi_data *priv; + struct irq_domain *parent_domain; + struct resource res; + int ret; + + parent_domain = irq_find_host(parent); + if (!parent_domain) { + pr_err("Failed to find the parent domain\n"); + return -ENXIO; + } + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + mutex_init(&priv->msi_map_lock); + + ret = of_address_to_resource(node, 0, &res); + if (ret) { + pr_err("Failed to allocate resource\n"); + goto err_priv; + } + + priv->doorbell = res.start; + + if (of_property_read_u32(node, "loongson,msi-base-vec", + &priv->irq_first)) { + pr_err("Unable to parse MSI vec base\n"); + ret = -EINVAL; + goto err_priv; + } + + if (of_property_read_u32(node, "loongson,msi-num-vecs", + &priv->num_irqs)) { + pr_err("Unable to parse MSI vec number\n"); + ret = -EINVAL; + goto err_priv; + } + + priv->msi_map = bitmap_alloc(priv->num_irqs, GFP_KERNEL); + if (!priv->msi_map) { + ret = -ENOMEM; + goto err_priv; + } + + pr_debug("Registering %d MSIs, starting at %d\n", + priv->num_irqs, priv->irq_first); + + ret = pch_msi_init_domains(priv, node, parent_domain); + if (ret) + goto err_map; + + return 0; + +err_map: + kfree(priv->msi_map); +err_priv: + kfree(priv); + return ret; +} + +IRQCHIP_DECLARE(pch_msi, "loongson,pch-msi-1.0", pch_msi_init);