From patchwork Fri Feb 21 17:23:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Manivannan Sadhasivam X-Patchwork-Id: 13986092 X-Patchwork-Delegate: kw@linux.com Received: from mail-pl1-f175.google.com (mail-pl1-f175.google.com [209.85.214.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1809D2500CF for ; Fri, 21 Feb 2025 17:23:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740158604; cv=none; b=fNDIQRtxCiQiOCB4WU5uepwjk3R0fFHPtofzpiC9uVdBLpPkuAKc40KeTS7HJEHoBFlffZT+nRvdlZMi00iKl1VcrKOEHw4DZi9A+4zbULjW/nwJfWOE9DzJR2dqEkcGpk/nhFaV1aupJGxauDc3u1UPFpe5wCFOk+wVIjHODxc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740158604; c=relaxed/simple; bh=TvvuaEdFtU9UqfsZC6JoSCudSB2FfcZqsrRdClTssfQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Z6RjuANmVugDsIF3fOeA+wCNpN2WhZWandur7tVea+XK4C6s7PyQTDHKTOVgUAQPENX4JRztiQ71z9yL+xFQU2aZOh8Rqb1K/gbo7mw4u/mLWxrEgFqGTu2kKvF1ScVubdiYaZYyNsG1DPLxTn3dL3cutUjxI/A1rx++fwwcArY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=P+K7QubG; arc=none smtp.client-ip=209.85.214.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="P+K7QubG" Received: by mail-pl1-f175.google.com with SMTP id d9443c01a7336-22128b7d587so47785615ad.3 for ; Fri, 21 Feb 2025 09:23:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1740158602; x=1740763402; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Ob+IAIS3PcMsuG9oa1uTykNVP/mdisbkDjZEDx6eRLA=; b=P+K7QubGh6OsSxzeCkvWAJZSp/HffcG1JJSkpNWSJ+NP1AObC42IkEc50p4O7o23Fv 1Un+21FJHXOopihnDlEVCgGTxLDv6yFiSIrV43zFYfSQ9h5l7QxkJiMR8437V7OsfViI u1RvSxKsDtj5RjlmT7XuSmRsy7Uab0sx3ZDjdSkfZgbhO5nHvRGXWX2ZeL1YgHc/79J5 cmb6QFSdmT5q5v6JDbhJLrXKgmyQ1yEYlHIC8VBbpBJbYEvEWVn+NX/48DC12YHeWepz cdWio32VJ8SRFl+YsS7RMmVAi2EIgbqwOVETKfI1jtw6BUwaTDKhulGk+fcQly+ewci1 8XjA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1740158602; x=1740763402; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Ob+IAIS3PcMsuG9oa1uTykNVP/mdisbkDjZEDx6eRLA=; b=JESauU4qaCjwxavXLcibMz1YeURqqS9szM0fRas0c0yFwJZIe5H6egYyMNhAfKDl3d 2/7wb4t1IaDqK35Oo7E5J0I7dz8nCiGIvvxc+VZMv7KnSfvUEIO3O0EVeTYiZ65vB1L7 7bPveBJ5u5BqqmJ6cJ9xfypZv+fSLtp2Kenoezz+1lNtRvgwyDqMxNcWXjBrC9KH/L0v ER63sMPseg1jGeaziZnZPB+GGBG3Ojq4YHY03Qk3GSURv5PpwFWDREjLUEGPaLtYtwEF KVqa+161x/Uwj7k6wUI7PV7HGoK8WXj5HnGCwuuuwy3QkaSmOvEcp2djtafle/SIlX8r kDlw== X-Gm-Message-State: AOJu0YxT9pz2jJmShNr7K9x4kz1rwEBCgjsJTLFf7w+DxM8VCNqUqulA WUOkQQwNazyWsIfxtl8YqkvFiy0IrRYhbcbyOvEKn+1eSgJQ9uzNW49TIZGdOA== X-Gm-Gg: ASbGncsxf2cYiMma55yCdIYuKvtSqlo2q+FT3nGl2SQFZHYXh6hEJUdYhZMRR9n76Cx 0K1bW8Wo1md+sxX0FwrbGkJ0B5ysPVofX0IeShMxu3aiakVyQhYdeiuWYeKr6Ib3LuxzAvDMuWE YwOTE03509+Vc7ZhPOncrMs8ROuoRN0ADDJI062+qbEuixAsl5u9TY7bMq8e/07Wr0bWaFvLGFH xcjANFYFyK+uyyYvI7U0nQWbdgbRIkyGneX1tNEa0n2OBt9EBMqAryOgLcTWS8R+J83JgHaY1Rc V7XnZjpsBE5baxg4pVOXk17Qx8TJE73tz/jh0o8VeyCVyMz8k1Io X-Google-Smtp-Source: AGHT+IGzsgGWotdM0GJDHccBXJBXwgMMkAjpIS/G4maCwqsIVpwHx6wNGdibYi4vAESSIt/Gd8cCYQ== X-Received: by 2002:a17:902:f712:b0:221:7e36:b13e with SMTP id d9443c01a7336-2219ff50d62mr80161515ad.12.1740158602264; Fri, 21 Feb 2025 09:23:22 -0800 (PST) Received: from localhost.localdomain ([120.60.73.12]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-220d545c814sm141243405ad.148.2025.02.21.09.23.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 Feb 2025 09:23:21 -0800 (PST) From: Manivannan Sadhasivam To: lpieralisi@kernel.org, kw@linux.com, bhelgaas@google.com Cc: linux-pci@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, dingwei@marvell.com, cassel@kernel.org, Manivannan Sadhasivam Subject: [PATCH 1/2] PCI: Add pci_host_bridge_handle_link_down() API to handle the PCI link down event Date: Fri, 21 Feb 2025 22:53:08 +0530 Message-Id: <20250221172309.120009-2-manivannan.sadhasivam@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250221172309.120009-1-manivannan.sadhasivam@linaro.org> References: <20250221172309.120009-1-manivannan.sadhasivam@linaro.org> Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The PCI link, when down, needs to be retrained to bring it back. But that cannot be done in a generic way as link retrain procedure is specific to host bridges. So add a new API pci_host_bridge_handle_link_down() that could be called by the host bridge drivers when the link goes down. The API will remove all the devices from the root bus since there is no way the PCI core/drivers can access them and then calls the bus specific 'retrain_link()' callback if available. This callback is supposed to be implemented by the host bridge drivers to retrain the link in a platform specific way. Once that succeeds, the API will rescan the bus to bring the devices back. Signed-off-by: Manivannan Sadhasivam --- drivers/pci/probe.c | 34 ++++++++++++++++++++++++++++++++++ include/linux/pci.h | 2 ++ 2 files changed, 36 insertions(+) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index b6536ed599c3..36ffcd2a44a5 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -706,6 +706,40 @@ void pci_free_host_bridge(struct pci_host_bridge *bridge) } EXPORT_SYMBOL(pci_free_host_bridge); +void pci_host_bridge_handle_link_down(struct pci_host_bridge *bridge) +{ + struct pci_bus *bus = bridge->bus; + struct device *dev = &bridge->dev; + struct pci_dev *child, *tmp; + int ret; + + pci_lock_rescan_remove(); + + /* Knock the devices off root bus since we cannot access them */ + dev_warn(dev, "Removing devices from root bus due to link down\n"); + list_for_each_entry_safe(child, tmp, &bus->devices, bus_list) + pci_stop_and_remove_bus_device(child); + + /* Now retrain the link in a vendor specific way to bring it back */ + if (bus->ops->retrain_link) { + dev_info(dev, "Starting link retraining\n"); + ret = bus->ops->retrain_link(bus); + if (ret) { + dev_err(dev, "Failed to retrain the link\n"); + pci_unlock_rescan_remove(); + return; + } + dev_info(dev, "Link retraining completed\n"); + } else { + dev_warn(dev, "retrain_link() callback not implemented!\n"); + } + + /* Finally, rescan the bus to bring the devices back */ + pci_rescan_bus(bus); + pci_unlock_rescan_remove(); +} +EXPORT_SYMBOL(pci_host_bridge_handle_link_down); + /* Indexed by PCI_X_SSTATUS_FREQ (secondary bus mode and frequency) */ static const unsigned char pcix_bus_speed[] = { PCI_SPEED_UNKNOWN, /* 0 */ diff --git a/include/linux/pci.h b/include/linux/pci.h index 47b31ad724fa..1c6f18a51bdd 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -637,6 +637,7 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv); struct pci_host_bridge *devm_pci_alloc_host_bridge(struct device *dev, size_t priv); void pci_free_host_bridge(struct pci_host_bridge *bridge); +void pci_host_bridge_handle_link_down(struct pci_host_bridge *bridge); struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus); void pci_set_host_bridge_release(struct pci_host_bridge *bridge, @@ -804,6 +805,7 @@ struct pci_ops { void __iomem *(*map_bus)(struct pci_bus *bus, unsigned int devfn, int where); int (*read)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val); int (*write)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val); + int (*retrain_link)(struct pci_bus *bus); }; /* From patchwork Fri Feb 21 17:23:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Manivannan Sadhasivam X-Patchwork-Id: 13986093 X-Patchwork-Delegate: kw@linux.com Received: from mail-pl1-f178.google.com (mail-pl1-f178.google.com [209.85.214.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DBA3E2505CE for ; Fri, 21 Feb 2025 17:23:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740158609; cv=none; b=fZvzsWgSTPahq8n2fmqX50yNI5qyCCIlBno4v4aid+b48ib+v4jKx+yAaHzQlMuD4XUPsSgWPYbhoU5cQicNFRCm5yrSQ1wFj5pgzFwounjOSlUk4j37ZrtYOW94Q0cwR4NeFt2ElDNGhqpSHwVJv6chljPWKEigpjQrdJoU/hI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740158609; c=relaxed/simple; bh=432o3LdSfGr+97dz21dol2E2CpCbQLWX6ldZdo4avtw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=sPV+Wh5Y/EJCNqPTv1yijzuTtbHClQcsuoHsQ423pIuP9M2vIk+EfMmPueylZ/vCEEnqDgS334fJY/i5s3cyKcaQM8fl5NM7TVk4K5Uo7CFOwymNbmpYnkIm8s6ROMFYSXE8JPTereZK7BrC1ImuHpBtyMAlSz0brPs6FP4DIk8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=ewkQ1nnX; arc=none smtp.client-ip=209.85.214.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="ewkQ1nnX" Received: by mail-pl1-f178.google.com with SMTP id d9443c01a7336-220ec47991aso33566415ad.1 for ; Fri, 21 Feb 2025 09:23:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1740158607; x=1740763407; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=H4hJLC9ezjmzckiqXS2j2AvB+5mvndIMa9rBZc/aOjo=; b=ewkQ1nnXlyFvB5zHIFJ3t2AhzjOOJD7JfijAw1ZaYFA9RbjwVBT/Bq5dX6GfP+oZ17 KmHWDOXfxzY3RZbpyvC6948sd54K9LPznvGYUazLVujEtSWiZX4i3pnwGw+TdsqzCgI3 yoOirIIsWGUUGm3X4s+qL7VA9DITv4ArA6DKuUkjdH18nObD7ZErc18Pm6EWVAIWpMS9 zsrKOqxJQvqKXSS/n/uEPsGtHPrrBnjJ8hsMy7DV9VJPI/X6OoOyeVM1no2kIidX55nV EeQEyFPrPL4gDqlT+Tz/ncXO6+hMp7uEiyQ+BPar4jTZw2D+/8rBTJvCXhz/Nwy98De5 ZOzA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1740158607; x=1740763407; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=H4hJLC9ezjmzckiqXS2j2AvB+5mvndIMa9rBZc/aOjo=; b=JLCnyr+lmVei3/6DmgiiXCBNP6lDWbzkgNTjKZq0IEIJpKEmbW/NRUkrVtHpiBVLCb TLz9R9Camh7WgxSIvlhzdMUxkD4wOCmX052iap10lmw+HT4M6iakyygK/LG1gc3BFeLL t45EMprj5FudVe5aY8sRK5C0oW4tgH4CiY9TH//a8UW5Sc1P1WrERfKmpk7UEECWJkvr ELURc1G7WzW05j7XfMbKsXF670TIIh8bmVSWh4ec0SDAd6rmJc2U3bapUT+o4XYc/xSL eRu4kRjGBpxeXxiuARd7/+k8uut6tMR6SK75hm/VI9NZQflXuOkBDlMoN41PnAYtylVD yEog== X-Gm-Message-State: AOJu0YwZLxGkGWFObX1onuDmpkXcmvzAWieB7rIf7rNH3ybWlKwNcQR2 DkyqsdAN4QQa5cF3YqRSiGgmx2dfiPOZjGXBqlD9GC824deM2JkjnycoRBuH1A== X-Gm-Gg: ASbGncuFPqSOHc6qCtiVpVaBClT+odDLP3+Ehv9umWVe/N7btKbjb/9Dsz64evyo1Nn zsQdKXgVjcfJxcZhyAFXKeICnWcD0q1b3yDp0i+KGCyUv7d0BliG0DP9rM2lw2wGbeVrQY8EEqp 4ewRA3nvlQ8lHc9FENKgDEj42wOa0o91jelqJwF9zofNcZRKDtfNBW9chhF2TcR44TPAqWjPHWx 8kVZuPSU070R2evu4lkTijzqKXKTM386rH8cE0nXG0sIOKKzXtX0IsQXzPvslKejgR/sqxpFt83 qLuNFOfBjBDDSLzzPL/rPapss6hgaIVspwrBCFtga46/6SH9ABsL X-Google-Smtp-Source: AGHT+IFFxw0nkRkM5smllKdWbGW6yYHFF8V3927Y2RR95VX56SRlzaDxW8xBfx5wbngEvMWxjPsqAA== X-Received: by 2002:a17:903:2349:b0:220:ec62:7dc8 with SMTP id d9443c01a7336-2219ff28ef8mr66227175ad.2.1740158605605; Fri, 21 Feb 2025 09:23:25 -0800 (PST) Received: from localhost.localdomain ([120.60.73.12]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-220d545c814sm141243405ad.148.2025.02.21.09.23.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 Feb 2025 09:23:25 -0800 (PST) From: Manivannan Sadhasivam To: lpieralisi@kernel.org, kw@linux.com, bhelgaas@google.com Cc: linux-pci@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, dingwei@marvell.com, cassel@kernel.org, Manivannan Sadhasivam Subject: [PATCH 2/2] PCI: qcom: Add support for retraining the link due to link down event Date: Fri, 21 Feb 2025 22:53:09 +0530 Message-Id: <20250221172309.120009-3-manivannan.sadhasivam@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250221172309.120009-1-manivannan.sadhasivam@linaro.org> References: <20250221172309.120009-1-manivannan.sadhasivam@linaro.org> Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The PCIe link can go down under circumstances such as the device removed from the bus, reset condition, etc... When that happens, the link needs to be retrained back to make it operational again. Currently, the driver is not handling the link down event, due to which the users have to restart the machine to make PCIe link operational again. So fix it by detecting the link down event and adding support to retraining the link. Since the Qcom PCIe controllers report the link down event through the 'global' IRQ, enable the link down event by setting PARF_INT_ALL_LINK_DOWN bit in PARF_INT_ALL_MASK register. Then in the case of the event, call pci_host_bridge_handle_link_down() API in the handler to let the PCI core handle the link down condition. The API will internally call, 'pci_ops::retrain_link()' callback to retrain the link in a platform specific way. So implement the callback to retrain the link by first resetting the PCIe core, followed by reinitializing the resources and then finally starting the link again. The PCI core will finally rescan the bus to enumerate the devices. Signed-off-by: Manivannan Sadhasivam --- drivers/pci/controller/dwc/pcie-qcom.c | 90 +++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index e4d3366ead1f..ebc58e88161e 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -55,6 +55,7 @@ #define PARF_INT_ALL_STATUS 0x224 #define PARF_INT_ALL_CLEAR 0x228 #define PARF_INT_ALL_MASK 0x22c +#define PARF_STATUS 0x230 #define PARF_SID_OFFSET 0x234 #define PARF_BDF_TRANSLATE_CFG 0x24c #define PARF_DBI_BASE_ADDR_V2 0x350 @@ -130,8 +131,11 @@ /* PARF_LTSSM register fields */ #define LTSSM_EN BIT(8) +#define SW_CLEAR_FLUSH_MODE BIT(10) +#define FLUSH_MODE BIT(11) /* PARF_INT_ALL_{STATUS/CLEAR/MASK} register fields */ +#define PARF_INT_ALL_LINK_DOWN BIT(1) #define PARF_INT_ALL_LINK_UP BIT(13) #define PARF_INT_MSI_DEV_0_7 GENMASK(30, 23) @@ -145,6 +149,9 @@ /* PARF_BDF_TO_SID_CFG fields */ #define BDF_TO_SID_BYPASS BIT(0) +/* PARF_STATUS fields */ +#define FLUSH_COMPLETED BIT(8) + /* ELBI_SYS_CTRL register fields */ #define ELBI_SYS_CTRL_LT_ENABLE BIT(0) @@ -169,6 +176,7 @@ PCIE_CAP_SLOT_POWER_LIMIT_SCALE) #define PERST_DELAY_US 1000 +#define FLUSH_TIMEOUT_US 100 #define QCOM_PCIE_CRC8_POLYNOMIAL (BIT(2) | BIT(1) | BIT(0)) @@ -239,6 +247,7 @@ union qcom_pcie_resources { }; struct qcom_pcie; +static struct pci_ops qcom_pcie_bridge_ops; struct qcom_pcie_ops { int (*get_resources)(struct qcom_pcie *pcie); @@ -274,6 +283,7 @@ struct qcom_pcie { struct icc_path *icc_cpu; const struct qcom_pcie_cfg *cfg; struct dentry *debugfs; + int global_irq; bool suspended; bool use_pm_opp; }; @@ -1263,6 +1273,8 @@ static int qcom_pcie_host_init(struct dw_pcie_rp *pp) goto err_assert_reset; } + pp->bridge->ops = &qcom_pcie_bridge_ops; + return 0; err_assert_reset: @@ -1300,6 +1312,75 @@ static const struct dw_pcie_host_ops qcom_pcie_dw_ops = { .post_init = qcom_pcie_host_post_init, }; +static int qcom_pcie_retrain_link(struct pci_bus *bus) +{ + struct dw_pcie_rp *pp = bus->sysdata; + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct qcom_pcie *pcie = to_qcom_pcie(pci); + struct device *dev = pcie->pci->dev; + u32 val; + int ret; + + /* Wait for the pending transactions to be completed */ + ret = readl_relaxed_poll_timeout(pcie->parf + PARF_STATUS, val, + val & FLUSH_COMPLETED, 10, + FLUSH_TIMEOUT_US); + if (ret) { + dev_err(dev, "Flush completion failed: %d\n", ret); + goto err_host_deinit; + } + + /* Clear the FLUSH_MODE to allow the core to be reset */ + val = readl(pcie->parf + PARF_LTSSM); + val |= SW_CLEAR_FLUSH_MODE; + writel(val, pcie->parf + PARF_LTSSM); + + /* Wait for the FLUSH_MODE to clear */ + ret = readl_relaxed_poll_timeout(pcie->parf + PARF_LTSSM, val, + !(val & FLUSH_MODE), 10, + FLUSH_TIMEOUT_US); + if (ret) { + dev_err(dev, "Flush mode clear failed: %d\n", ret); + goto err_host_deinit; + } + + qcom_pcie_host_deinit(pp); + + ret = qcom_pcie_host_init(pp); + if (ret) { + dev_err(dev, "Host init failed\n"); + return ret; + } + + ret = dw_pcie_setup_rc(pp); + if (ret) + goto err_host_deinit; + + /* + * Re-enable global IRQ events as the PARF_INT_ALL_MASK register is + * non-sticky. + */ + if (pcie->global_irq) + writel_relaxed(PARF_INT_ALL_LINK_UP | PARF_INT_ALL_LINK_DOWN | + PARF_INT_MSI_DEV_0_7, pcie->parf + PARF_INT_ALL_MASK); + + qcom_pcie_start_link(pci); + + return 0; + +err_host_deinit: + qcom_pcie_host_deinit(pp); + + return ret; +} + +static struct pci_ops qcom_pcie_bridge_ops = { + .map_bus = dw_pcie_own_conf_map_bus, + .read = pci_generic_config_read, + .write = pci_generic_config_write, + .retrain_link = qcom_pcie_retrain_link, +}; + /* Qcom IP rev.: 2.1.0 Synopsys IP rev.: 4.01a */ static const struct qcom_pcie_ops ops_2_1_0 = { .get_resources = qcom_pcie_get_resources_2_1_0, @@ -1571,6 +1652,9 @@ static irqreturn_t qcom_pcie_global_irq_thread(int irq, void *data) pci_unlock_rescan_remove(); qcom_pcie_icc_opp_update(pcie); + } else if (FIELD_GET(PARF_INT_ALL_LINK_DOWN, status)) { + dev_dbg(dev, "Received Link down event\n"); + pci_host_bridge_handle_link_down(pp->bridge); } else { dev_WARN_ONCE(dev, 1, "Received unknown event. INT_STATUS: 0x%08x\n", status); @@ -1732,8 +1816,10 @@ static int qcom_pcie_probe(struct platform_device *pdev) goto err_host_deinit; } - writel_relaxed(PARF_INT_ALL_LINK_UP | PARF_INT_MSI_DEV_0_7, - pcie->parf + PARF_INT_ALL_MASK); + writel_relaxed(PARF_INT_ALL_LINK_UP | PARF_INT_ALL_LINK_DOWN | + PARF_INT_MSI_DEV_0_7, pcie->parf + PARF_INT_ALL_MASK); + + pcie->global_irq = irq; } qcom_pcie_icc_opp_update(pcie);