From mboxrd@z Thu Jan 1 00:00:00 1970 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=-16.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_SANE_1 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 A5CDAC636C9 for ; Sun, 18 Jul 2021 00:28:25 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 618B261153 for ; Sun, 18 Jul 2021 00:28:25 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 618B261153 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:References: Message-ID:Subject:Cc:To:From:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=AxHTi5DtF3L7pt3Xfd67KFcqNCN5HeZQL4xSV1o/mwA=; b=Z5XfPfNM3w6pDY gd43mMGB23k7Np1AWYSXm6BTV5RykOurhF4IA+3AH+9iPCQadvHDY9+gRynYf1WpXoTqQRlWzV2/5 hAx4ovt601CYjB0mAeqy4Y5U/hhyWucbPLG4uh4fNnKcxutPAe7V/AgB39r/e1B4P0S2SJAQyTS+g JF4IK/PwFTZSvpmcBo06N04FsgOq3VkPZUm2pWjQ39CxU1EHBnKVg+A6e/JftiZB/HJpa2Cei5xla G8ZgoDZVl8+FxmDRmVTkMnpZo4jgLjlcXdPZc73zFG7zuapC40LEg2RL0LusNngEas928FQrkdJ+E oJ82sU7F+0kD4uIy6yZQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1m4udT-007Dhe-3n; Sun, 18 Jul 2021 00:26:23 +0000 Received: from mail.kernel.org ([198.145.29.99]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1m4udO-007DhJ-KO for linux-arm-kernel@lists.infradead.org; Sun, 18 Jul 2021 00:26:20 +0000 Received: by mail.kernel.org (Postfix) with ESMTPSA id BB6FD61153; Sun, 18 Jul 2021 00:26:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1626567978; bh=URoambk1xvFO2WPF6LufgHf8T3Y30E5lldB6rMC0Gxw=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=MRhAQ4RYE9+YNKwm6uB4bxR+Ioh6atTI8BXom7t3jQeFqq6T30INZAuU4tF/c6JAS SohO3UvdZqD0aPeKpeben0kxtxuaKzLcaG4GTf6lh+EYLngTIYkswC8nOFSRanurBy aLbash0ENbyn0ELvB2I1TRMLYUwXYzgLN/8MDiiCbYwkSntmXvXrvWbCp8k8l5bisa 2VBmiM1FKa7+osCHDRY5uFY9R63d5Xhtrj7dygthh27uVeURklHVrueiPlWQP2TWlK KhwDddmNwdR+9v9Rqy1QTXyQe2AABGrUCYuGsX9dCFTEPFnqyfoUnwU1+wczjf/Pfg 814jiwHDBAy9Q== Received: by pali.im (Postfix) id 0772795D; Sun, 18 Jul 2021 02:26:14 +0200 (CEST) Date: Sun, 18 Jul 2021 02:26:14 +0200 From: Pali =?utf-8?B?Um9ow6Fy?= To: Kunihiko Hayashi Cc: Bjorn Helgaas , Rob Herring , Lorenzo Pieralisi , Jingoo Han , Gustavo Pimentel , Marc Zyngier , linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Jassi Brar , Masami Hiramatsu Subject: Re: [PATCH v11 3/3] PCI: uniphier: Add misc interrupt handler to invoke PME and AER Message-ID: <20210718002614.3l74hlondwgthuby@pali> References: <1619111097-10232-1-git-send-email-hayashi.kunihiko@socionext.com> <1619111097-10232-4-git-send-email-hayashi.kunihiko@socionext.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <1619111097-10232-4-git-send-email-hayashi.kunihiko@socionext.com> User-Agent: NeoMutt/20180716 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210717_172618_760833_AD647E46 X-CRM114-Status: GOOD ( 37.32 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Hello Kunihiko! On Friday 23 April 2021 02:04:57 Kunihiko Hayashi wrote: > This patch adds misc interrupt handler to detect and invoke PME/AER event. > > In UniPhier PCIe controller, PME/AER signals are assigned to the same > signal as MSI by the internal logic. These signals should be detected by > the internal register, however, DWC MSI handler can't handle these signals. > > DWC MSI handler calls .msi_host_isr() callback function, that detects > PME/AER signals using the internal register and invokes the interrupt > with PME/AER IRQ numbers. > > These IRQ numbers is obtained by uniphier_pcie_port_get_irq() function, > that finds the device that matches PME/AER from the devices associated > with Root Port, and returns its IRQ number. If I understood this issue correctly, it means that your PCIe controller does not issue regular MSI interrupt for PME and AER events, but rather it issue controller specific interrupt and you need to figure out what kind of controller-specific event happened (e.g. PME or AER or something else). But if your controller supports PME or AER then it expose in its PCIe Root Port capabilities register MSI number for these PME and AER events. Kernel PCIe PME and AER drivers read from capabilities register these numbers and register irq functions to be called when interrupt happens. So it means that you do not need to implement uniphier_pcie_port_get_irq function via this "ugly" foreach and call pcie_port_service_get_irq. But you can read this MSI interrupt number directly from your controller in this pcie-uniphier.c driver and then use irq_find_mapping() to convert hw MSI number to kernel's virq (used in generic_handle_irq()). Because currently you use in pcie-uniphier.c call to function pcie_port_service_get_irq() which returns cached interrupt number value which was read from PCIe Root Port capability register by PCI subsystem callbacked back to the pcie-uniphier.c driver. For me this looks like "ugly" if you need to do something in "complicated" way and add dependency e.g. on compile options like "if (!IS_ENABLED(CONFIG_PCIEAER) && !IS_ENABLED(CONFIG_PCIE_PME))" if it can be easily avoided. I'm writing this because I was solving exactly same problem for aardvark PCIe controller with PME, AER and HP interrupts (patches are on ML). So I think that this pcie-uniphier.c implementation can be simplified without need to use checks for CONFIG_* options and calling pcie_port_service_get_irq() in list_for_each_entry loop. Could you please post output of 'lspci -nn -vv'? In my opinion MSI numbers for AER and PME in Root Port could be constant so it may simplify implementation even more. (Just to note that in my case aardvark returns zero as MSI number and it is also documented in spec). > Cc: Marc Zyngier > Cc: Jingoo Han > Cc: Gustavo Pimentel > Cc: Lorenzo Pieralisi > Signed-off-by: Kunihiko Hayashi > Reviewed-by: Rob Herring > --- > drivers/pci/controller/dwc/pcie-uniphier.c | 105 +++++++++++++++++++++++++---- > 1 file changed, 91 insertions(+), 14 deletions(-) > > diff --git a/drivers/pci/controller/dwc/pcie-uniphier.c b/drivers/pci/controller/dwc/pcie-uniphier.c > index 7e8bad3..dcd8fa8 100644 > --- a/drivers/pci/controller/dwc/pcie-uniphier.c > +++ b/drivers/pci/controller/dwc/pcie-uniphier.c > @@ -21,6 +21,7 @@ > #include > > #include "pcie-designware.h" > +#include "../../pcie/portdrv.h" > > #define PCL_PINCTRL0 0x002c > #define PCL_PERST_PLDN_REGEN BIT(12) > @@ -44,7 +45,9 @@ > #define PCL_SYS_AUX_PWR_DET BIT(8) > > #define PCL_RCV_INT 0x8108 > +#define PCL_RCV_INT_ALL_INT_MASK GENMASK(28, 25) > #define PCL_RCV_INT_ALL_ENABLE GENMASK(20, 17) > +#define PCL_RCV_INT_ALL_MSI_MASK GENMASK(12, 9) > #define PCL_CFG_BW_MGT_STATUS BIT(4) > #define PCL_CFG_LINK_AUTO_BW_STATUS BIT(3) > #define PCL_CFG_AER_RC_ERR_MSI_STATUS BIT(2) > @@ -68,6 +71,8 @@ struct uniphier_pcie_priv { > struct reset_control *rst; > struct phy *phy; > struct irq_domain *legacy_irq_domain; > + int aer_irq; > + int pme_irq; > }; > > #define to_uniphier_pcie(x) dev_get_drvdata((x)->dev) > @@ -164,7 +169,15 @@ static void uniphier_pcie_stop_link(struct dw_pcie *pci) > > static void uniphier_pcie_irq_enable(struct uniphier_pcie_priv *priv) > { > - writel(PCL_RCV_INT_ALL_ENABLE, priv->base + PCL_RCV_INT); > + u32 val; > + > + val = PCL_RCV_INT_ALL_ENABLE; > + if (pci_msi_enabled()) > + val |= PCL_RCV_INT_ALL_INT_MASK; > + else > + val |= PCL_RCV_INT_ALL_MSI_MASK; > + > + writel(val, priv->base + PCL_RCV_INT); > writel(PCL_RCV_INTX_ALL_ENABLE, priv->base + PCL_RCV_INTX); > } > > @@ -228,28 +241,51 @@ static const struct irq_domain_ops uniphier_intx_domain_ops = { > .map = uniphier_pcie_intx_map, > }; > > -static void uniphier_pcie_irq_handler(struct irq_desc *desc) > +static void uniphier_pcie_misc_isr(struct pcie_port *pp, bool is_msi) > { > - struct pcie_port *pp = irq_desc_get_handler_data(desc); > struct dw_pcie *pci = to_dw_pcie_from_pp(pp); > struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci); > - struct irq_chip *chip = irq_desc_get_chip(desc); > - unsigned long reg; > - u32 val, bit, virq; > + u32 val; > > - /* INT for debug */ > val = readl(priv->base + PCL_RCV_INT); > > if (val & PCL_CFG_BW_MGT_STATUS) > dev_dbg(pci->dev, "Link Bandwidth Management Event\n"); > if (val & PCL_CFG_LINK_AUTO_BW_STATUS) > dev_dbg(pci->dev, "Link Autonomous Bandwidth Event\n"); > - if (val & PCL_CFG_AER_RC_ERR_MSI_STATUS) > - dev_dbg(pci->dev, "Root Error\n"); > - if (val & PCL_CFG_PME_MSI_STATUS) > - dev_dbg(pci->dev, "PME Interrupt\n"); > + > + if (is_msi) { > + if (val & PCL_CFG_AER_RC_ERR_MSI_STATUS) { > + dev_dbg(pci->dev, "Root Error Status\n"); > + if (priv->aer_irq) > + generic_handle_irq(priv->aer_irq); > + } > + > + if (val & PCL_CFG_PME_MSI_STATUS) { > + dev_dbg(pci->dev, "PME Interrupt\n"); > + if (priv->pme_irq) > + generic_handle_irq(priv->pme_irq); > + } > + } > > writel(val, priv->base + PCL_RCV_INT); > +} > + > +static void uniphier_pcie_msi_host_isr(struct pcie_port *pp) > +{ > + uniphier_pcie_misc_isr(pp, true); > +} > + > +static void uniphier_pcie_irq_handler(struct irq_desc *desc) > +{ > + struct pcie_port *pp = irq_desc_get_handler_data(desc); > + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); > + struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci); > + struct irq_chip *chip = irq_desc_get_chip(desc); > + unsigned long reg; > + u32 val, bit, irq; > + > + uniphier_pcie_misc_isr(pp, false); > > /* INTx */ > chained_irq_enter(chip, desc); > @@ -258,8 +294,8 @@ static void uniphier_pcie_irq_handler(struct irq_desc *desc) > reg = FIELD_GET(PCL_RCV_INTX_ALL_STATUS, val); > > for_each_set_bit(bit, ®, PCI_NUM_INTX) { > - virq = irq_linear_revmap(priv->legacy_irq_domain, bit); > - generic_handle_irq(virq); > + irq = irq_linear_revmap(priv->legacy_irq_domain, bit); > + generic_handle_irq(irq); > } > > chained_irq_exit(chip, desc); > @@ -317,8 +353,45 @@ static int uniphier_pcie_host_init(struct pcie_port *pp) > return 0; > } > > +static int uniphier_pcie_port_get_irq(struct pcie_port *pp, u32 service) > +{ > + struct pci_dev *pcidev; > + int irq = 0; > + > + if (!IS_ENABLED(CONFIG_PCIEAER) && !IS_ENABLED(CONFIG_PCIE_PME)) > + return 0; > + > + /* > + * Finds the device that matches 'service' from the devices > + * associated with Root Port, and returns its IRQ number. > + */ > + list_for_each_entry(pcidev, &pp->bridge->bus->devices, bus_list) { > + irq = pcie_port_service_get_irq(pcidev, service); > + if (irq) > + break; > + } > + > + return irq; > +} > + > +static int uniphier_pcie_host_init_complete(struct pcie_port *pp) > +{ > + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); > + struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci); > + > + if (IS_ENABLED(CONFIG_PCIE_PME)) > + priv->pme_irq = > + uniphier_pcie_port_get_irq(pp, PCIE_PORT_SERVICE_PME); > + if (IS_ENABLED(CONFIG_PCIEAER)) > + priv->aer_irq = > + uniphier_pcie_port_get_irq(pp, PCIE_PORT_SERVICE_AER); > + > + return 0; > +} > + > static const struct dw_pcie_host_ops uniphier_pcie_host_ops = { > .host_init = uniphier_pcie_host_init, > + .msi_host_isr = uniphier_pcie_msi_host_isr, > }; > > static int uniphier_pcie_host_enable(struct uniphier_pcie_priv *priv) > @@ -398,7 +471,11 @@ static int uniphier_pcie_probe(struct platform_device *pdev) > > priv->pci.pp.ops = &uniphier_pcie_host_ops; > > - return dw_pcie_host_init(&priv->pci.pp); > + ret = dw_pcie_host_init(&priv->pci.pp); > + if (ret) > + return ret; > + > + return uniphier_pcie_host_init_complete(&priv->pci.pp); > } > > static const struct of_device_id uniphier_pcie_match[] = { > -- > 2.7.4 > _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel