From patchwork Fri Mar 10 02:46:15 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brian Norris X-Patchwork-Id: 737236 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3vfWsk3qslz9s7v for ; Fri, 10 Mar 2017 13:48:26 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="oYB6SnMS"; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754520AbdCJCre (ORCPT ); Thu, 9 Mar 2017 21:47:34 -0500 Received: from mail-pg0-f53.google.com ([74.125.83.53]:33006 "EHLO mail-pg0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753120AbdCJCrR (ORCPT ); Thu, 9 Mar 2017 21:47:17 -0500 Received: by mail-pg0-f53.google.com with SMTP id 25so33442772pgy.0 for ; Thu, 09 Mar 2017 18:46:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=m59oQ9n5gDPwQ8O5RM1WRx+FPSUTLdNRVBTjODnQkuc=; b=oYB6SnMShp+6Atlu+jgd3lfYOzAnRoJO64QByLS/46+1vg00RPr1ZGOgPb8EgEgcXU wVbkMVJqxAS01dSgiaoPZph4t+NtLuGxiknv/N3p/ZHH5pVj4d61zR4EdLSsG70sDD/Q 4XEmh2IqI5jxsZmApOQAzYN1UE5La9kVVkChE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=m59oQ9n5gDPwQ8O5RM1WRx+FPSUTLdNRVBTjODnQkuc=; b=ke788h5rjpkphISoEbZx1fA+S4Tnfw+7GwfEDGZ94l86L9rPwF+YrNdEh3LZHhlax4 PoMcqQWLL5cUWRtt/hSdt39zyrUEwzu1TLQ8NlGKgImTzVWUhc4Ix2eJV5pKkv+yQYiz kJ0LQErFbrIKIUbF10isIwVvIR0w7xPnxS+8/uiswm/KtMvr3IR4y6yNVetqg3JaIKps qPOqz1q3wZQ+H5+5Q/qrBBPhb3/IJCltsU873lfoMsXsxZjraTRWHkGXQFklAyCNm/co KogSS+kU9hKuxhFhFX79UbtgBrn3TeudSlvtq5uqtYqM7p0Z/N71weoxpJcK4LXph5Pu zvdQ== X-Gm-Message-State: AMke39lbZgj/EdIJrdbTOHOPrEAKR+ByogxnB2SOMnCCBYxOnmB2q1yTXoaU28IjCvnNY6vn X-Received: by 10.84.228.208 with SMTP id y16mr21746331pli.168.1489113990720; Thu, 09 Mar 2017 18:46:30 -0800 (PST) Received: from ban.mtv.corp.google.com ([172.22.64.120]) by smtp.gmail.com with ESMTPSA id w29sm14830573pfi.131.2017.03.09.18.46.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 09 Mar 2017 18:46:30 -0800 (PST) From: Brian Norris To: Bjorn Helgaas Cc: , Shawn Lin , Jeffy Chen , Wenrui Li , linux-pci@vger.kernel.org, linux-rockchip@lists.infradead.org, Brian Norris Subject: [PATCH v2 3/5] PCI: rockchip: add remove() support Date: Thu, 9 Mar 2017 18:46:15 -0800 Message-Id: <20170310024617.67303-3-briannorris@chromium.org> X-Mailer: git-send-email 2.12.0.246.ga2ecc84866-goog In-Reply-To: <20170310024617.67303-1-briannorris@chromium.org> References: <20170310024617.67303-1-briannorris@chromium.org> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Currently, if we try to unbind the platform device, the remove will succeed, but the removal won't undo most of the registration, leaving partially-configured PCI devices in the system. This allows, for example, a simple 'lspci' to crash the system, as it will try to touch the freed (via devm_*) driver structures. So let's implement device remove(). Signed-off-by: Brian Norris --- v2: * unmap IO space with pci_unmap_iospace() * remove IRQ domain --- drivers/pci/host/pcie-rockchip.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c index 5d7b27b1e941..d2e5078ae331 100644 --- a/drivers/pci/host/pcie-rockchip.c +++ b/drivers/pci/host/pcie-rockchip.c @@ -223,9 +223,11 @@ struct rockchip_pcie { int link_gen; struct device *dev; struct irq_domain *irq_domain; - u32 io_size; int offset; + struct pci_bus *root_bus; + struct resource *io; phys_addr_t io_bus_addr; + u32 io_size; void __iomem *msg_region; u32 mem_size; phys_addr_t msg_bus_addr; @@ -1360,6 +1362,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev) err, io); continue; } + rockchip->io = io; break; case IORESOURCE_MEM: mem = win->res; @@ -1391,6 +1394,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev) err = -ENOMEM; goto err_free_res; } + rockchip->root_bus = bus; pci_bus_size_bridges(bus); pci_bus_assign_resources(bus); @@ -1421,6 +1425,34 @@ static int rockchip_pcie_probe(struct platform_device *pdev) return err; } +static int rockchip_pcie_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct rockchip_pcie *rockchip = dev_get_drvdata(dev); + + pci_stop_root_bus(rockchip->root_bus); + pci_remove_root_bus(rockchip->root_bus); + pci_unmap_iospace(rockchip->io); + irq_domain_remove(rockchip->irq_domain); + + phy_power_off(rockchip->phy); + phy_exit(rockchip->phy); + + clk_disable_unprepare(rockchip->clk_pcie_pm); + clk_disable_unprepare(rockchip->hclk_pcie); + clk_disable_unprepare(rockchip->aclk_perf_pcie); + clk_disable_unprepare(rockchip->aclk_pcie); + + if (!IS_ERR(rockchip->vpcie3v3)) + regulator_disable(rockchip->vpcie3v3); + if (!IS_ERR(rockchip->vpcie1v8)) + regulator_disable(rockchip->vpcie1v8); + if (!IS_ERR(rockchip->vpcie0v9)) + regulator_disable(rockchip->vpcie0v9); + + return 0; +} + static const struct dev_pm_ops rockchip_pcie_pm_ops = { SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(rockchip_pcie_suspend_noirq, rockchip_pcie_resume_noirq) @@ -1438,6 +1470,6 @@ static struct platform_driver rockchip_pcie_driver = { .pm = &rockchip_pcie_pm_ops, }, .probe = rockchip_pcie_probe, - + .remove = rockchip_pcie_remove, }; builtin_platform_driver(rockchip_pcie_driver);