From nobody Tue Dec 16 16:37:06 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D0439C07E97 for ; Fri, 1 Dec 2023 12:17:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1378785AbjLAMQw (ORCPT ); Fri, 1 Dec 2023 07:16:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41804 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1378763AbjLAMQt (ORCPT ); Fri, 1 Dec 2023 07:16:49 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5C873D48 for ; Fri, 1 Dec 2023 04:16:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1701433014; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=b29/c8il4IwH3mmZXi9Lko6mOop1IfhpXMh6iHVA43k=; b=gCRHXEQJ3tqRsmOP+jz+hkkiDndDKWvlot1LubcaRBbt8LG9PaDL1avu6dA6eZpvRk+1y8 UFooqaKCAcmJt7K9+oK7QH8MgM6f4F1MV6ji8hXH5WxCKAJ97zfrY8TAEXkX35MF326Iw5 q3klQmLbXslAHZ57cn9WxzjEgDhqOPo= Received: from mail-qv1-f72.google.com (mail-qv1-f72.google.com [209.85.219.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-626-KJzKkNISPyaGyBCq8hzGzg-1; Fri, 01 Dec 2023 07:16:53 -0500 X-MC-Unique: KJzKkNISPyaGyBCq8hzGzg-1 Received: by mail-qv1-f72.google.com with SMTP id 6a1803df08f44-67a1f38b735so4549146d6.0 for ; Fri, 01 Dec 2023 04:16:53 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701433013; x=1702037813; 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=b29/c8il4IwH3mmZXi9Lko6mOop1IfhpXMh6iHVA43k=; b=WWV+Pw7nuqbq8QDrraZJush92tRQ4bH9smIEu9sf7GSNr7fqxY3BMuI6DgkdrrNFnH g2enT5NwBYYZ1PI24t5WBa1wa3aL6eJXTM70GbnvcuBiBUWtzn59lef1G90BRjtjPSxI K8D2uFheZfIwcCcZZnmdDn6owJ6jFaFpAHqTvno0IYT39mtCfd64I0hXOMxi6kMcIx00 +QUvl+jTOrkQtpIjBeMSrx13nuwGCYwEpx4cJAvGBVwraNa2av6vkb8AyZE5bJVHj867 fYZcHbZCO4CXI6b3hFTVtglxxwEiqigsRt3HbYDM6iuxjvbzDGp+qqiEcG0G7cen1GE1 Phqw== X-Gm-Message-State: AOJu0Ywiuary+on1M2jglaEmUUKZeVVPrhPsKJ7G5hPL9VEVcGLzHVEF 0xtGpXVAz4Ke1tYIx352t8bk5GJKLoz62FYS80nS0Odngll6HKEcL4EofvAenZDrIhD2aK4yQ1m JrGBfFwakmHOmZ5ZIOxn1Y8G3 X-Received: by 2002:a05:6214:94b:b0:67a:94bd:f7ee with SMTP id dn11-20020a056214094b00b0067a94bdf7eemr1924507qvb.2.1701433012797; Fri, 01 Dec 2023 04:16:52 -0800 (PST) X-Google-Smtp-Source: AGHT+IFgUY4BSPRWVUPKwtDbEVuFrDGCCa51av9V5itSH44J3lXA2d6YMliye6elq/GTnMqmREYwyw== X-Received: by 2002:a05:6214:94b:b0:67a:94bd:f7ee with SMTP id dn11-20020a056214094b00b0067a94bdf7eemr1924479qvb.2.1701433012534; Fri, 01 Dec 2023 04:16:52 -0800 (PST) Received: from pstanner-thinkpadt14sgen1.remote.csb ([2001:9e8:32e2:4e00:227b:d2ff:fe26:2a7a]) by smtp.gmail.com with ESMTPSA id b19-20020ac87553000000b00423b8a53641sm1426528qtr.29.2023.12.01.04.16.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 04:16:52 -0800 (PST) From: Philipp Stanner To: Bjorn Helgaas , Arnd Bergmann , Andrew Morton , Dan Williams , Jonathan Cameron , Jakub Kicinski , Dave Jiang , Uladzislau Koshchanka , NeilBrown , Niklas Schnelle , John Sanpe , Kent Overstreet , Philipp Stanner , "Masami Hiramatsu (Google)" , Kees Cook , David Gow , Yury Norov , "wuqiang.matt" , Jason Baron , Kefeng Wang , Ben Dooks , dakr@redhat.com Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-arch@vger.kernel.org Subject: [PATCH v2 1/4] lib: move pci_iomap.c to drivers/pci/ Date: Fri, 1 Dec 2023 13:16:19 +0100 Message-ID: <20231201121622.16343-2-pstanner@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201121622.16343-1-pstanner@redhat.com> References: <20231201121622.16343-1-pstanner@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" This file is guarded by an #ifdef CONFIG_PCI. It, consequently, does not belong to lib/ because it is not generic infrastructure. Move the file to drivers/pci/ and implement the necessary changes to Makefiles and Kconfigs. Suggested-by: Danilo Krummrich Signed-off-by: Philipp Stanner --- drivers/pci/Kconfig | 5 +++++ drivers/pci/Makefile | 1 + lib/pci_iomap.c =3D> drivers/pci/iomap.c | 3 --- lib/Kconfig | 3 --- lib/Makefile | 1 - 5 files changed, 6 insertions(+), 7 deletions(-) rename lib/pci_iomap.c =3D> drivers/pci/iomap.c (99%) diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 74147262625b..d35001589d88 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -13,6 +13,11 @@ config FORCE_PCI select HAVE_PCI select PCI =20 +# select this to provide a generic PCI iomap, +# without PCI itself having to be defined +config GENERIC_PCI_IOMAP + bool + menuconfig PCI bool "PCI support" depends on HAVE_PCI diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index cc8b4e01e29d..64dcedccfc87 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -14,6 +14,7 @@ ifdef CONFIG_PCI obj-$(CONFIG_PROC_FS) +=3D proc.o obj-$(CONFIG_SYSFS) +=3D slot.o obj-$(CONFIG_ACPI) +=3D pci-acpi.o +obj-$(CONFIG_GENERIC_PCI_IOMAP) +=3D iomap.o endif =20 obj-$(CONFIG_OF) +=3D of.o diff --git a/lib/pci_iomap.c b/drivers/pci/iomap.c similarity index 99% rename from lib/pci_iomap.c rename to drivers/pci/iomap.c index ce39ce9f3526..0a9d503ba533 100644 --- a/lib/pci_iomap.c +++ b/drivers/pci/iomap.c @@ -9,7 +9,6 @@ =20 #include =20 -#ifdef CONFIG_PCI /** * pci_iomap_range - create a virtual mapping cookie for a PCI BAR * @dev: PCI device that owns the BAR @@ -176,5 +175,3 @@ void pci_iounmap(struct pci_dev *dev, void __iomem *p) EXPORT_SYMBOL(pci_iounmap); =20 #endif /* ARCH_WANTS_GENERIC_PCI_IOUNMAP */ - -#endif /* CONFIG_PCI */ diff --git a/lib/Kconfig b/lib/Kconfig index 3ea1c830efab..1bf859166ac7 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -70,9 +70,6 @@ source "lib/math/Kconfig" config NO_GENERIC_PCI_IOPORT_MAP bool =20 -config GENERIC_PCI_IOMAP - bool - config GENERIC_IOMAP bool select GENERIC_PCI_IOMAP diff --git a/lib/Makefile b/lib/Makefile index 6b09731d8e61..0800289ec6c5 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -153,7 +153,6 @@ CFLAGS_debug_info.o +=3D $(call cc-option, -femit-struc= t-debug-detailed=3Dany) obj-y +=3D math/ crypto/ =20 obj-$(CONFIG_GENERIC_IOMAP) +=3D iomap.o -obj-$(CONFIG_GENERIC_PCI_IOMAP) +=3D pci_iomap.o obj-$(CONFIG_HAS_IOMEM) +=3D iomap_copy.o devres.o obj-$(CONFIG_CHECK_SIGNATURE) +=3D check_signature.o obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) +=3D locking-selftest.o --=20 2.43.0 From nobody Tue Dec 16 16:37:06 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8EC48C4167B for ; Fri, 1 Dec 2023 12:17:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1378812AbjLAMRA (ORCPT ); Fri, 1 Dec 2023 07:17:00 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32962 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1378786AbjLAMQx (ORCPT ); Fri, 1 Dec 2023 07:16:53 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1798C103 for ; Fri, 1 Dec 2023 04:16:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1701433018; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4EfRzkqO1aZ81ioSW+ft5HOgZe0RLE7oV5/ARH+xGkg=; b=D4U6i1RXEbVViQWmaOrNXX7QqGYmhkp2dZ2j5S4kcyiefZFMBZoZP6/gtpJkBOWw4UOXPA QGhUiQYp/IsF/vfQkoCtyUTywRMD4PiFKwVSbt1cRcFka4sLLGBCotNu/bGfMjUr7BaOs5 /kqe63/Zcp1PL50Erh0M7jz84DeiAoY= Received: from mail-qt1-f200.google.com (mail-qt1-f200.google.com [209.85.160.200]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-531-JBGCBAR4O8Wfh3mN2WNlfQ-1; Fri, 01 Dec 2023 07:16:57 -0500 X-MC-Unique: JBGCBAR4O8Wfh3mN2WNlfQ-1 Received: by mail-qt1-f200.google.com with SMTP id d75a77b69052e-4239f7f5304so5631021cf.0 for ; Fri, 01 Dec 2023 04:16:57 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701433016; x=1702037816; 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=4EfRzkqO1aZ81ioSW+ft5HOgZe0RLE7oV5/ARH+xGkg=; b=VERm9CuHNcHih23mbFScaTdtuQf3S6LvGYHUXPu+rbGt9ueakyq7wzWkKxyzWtF0M4 F6AF1dzIGZScj/FcV5btBrboDXhTLZh0eDcSb95eeXbTZhv2x9seXKyk2e9LfzzT8NBF xKr2f05B2WUsi2N0rxjLr+TUlgoEtreZyDL2E1C5X1JbzPJGM3HnBM9tu1uRS0k+wKa8 AliwacTy57uuyF0+2N9wlsUEcDm8trhXCZhkg+irxA3RVJfEuKZI7d0ncINDBYU8iscd MNpweHtsKFRqghxfxEuLrxGedvOJzvPIJu3W1nC+WUk2kFkYW7Xe3YDdF1rvxFG4uRXZ OPLw== X-Gm-Message-State: AOJu0YyDcQ/HPNowCpey8iChGdBhtK2v6DIper6xbysJmj1tcXeTXIrk wwBpy7ldR/ZyCcrAiBLVm50J11+pQxq4hHv9DB4lAd40h8GUiy2UygUUV7Esb3xs2ReE5bYgLnX RzQJ+1kOLXJfP3Mjrw/TbU6pB X-Received: by 2002:ac8:78d:0:b0:415:141e:fa21 with SMTP id l13-20020ac8078d000000b00415141efa21mr4745752qth.6.1701433016425; Fri, 01 Dec 2023 04:16:56 -0800 (PST) X-Google-Smtp-Source: AGHT+IGFmZJypRQ8ZHOHDscqr2RObCwTZVnQwO5c/ogqCaotObZaqVe4SbOzBArDdccHeYNc2uDvhg== X-Received: by 2002:ac8:78d:0:b0:415:141e:fa21 with SMTP id l13-20020ac8078d000000b00415141efa21mr4745716qth.6.1701433016025; Fri, 01 Dec 2023 04:16:56 -0800 (PST) Received: from pstanner-thinkpadt14sgen1.remote.csb ([2001:9e8:32e2:4e00:227b:d2ff:fe26:2a7a]) by smtp.gmail.com with ESMTPSA id b19-20020ac87553000000b00423b8a53641sm1426528qtr.29.2023.12.01.04.16.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 04:16:55 -0800 (PST) From: Philipp Stanner To: Bjorn Helgaas , Arnd Bergmann , Andrew Morton , Dan Williams , Jonathan Cameron , Jakub Kicinski , Dave Jiang , Uladzislau Koshchanka , NeilBrown , Niklas Schnelle , John Sanpe , Kent Overstreet , Philipp Stanner , "Masami Hiramatsu (Google)" , Kees Cook , David Gow , Yury Norov , "wuqiang.matt" , Jason Baron , Kefeng Wang , Ben Dooks , dakr@redhat.com Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-arch@vger.kernel.org Subject: [PATCH v2 2/4] lib: move pci-specific devres code to drivers/pci/ Date: Fri, 1 Dec 2023 13:16:20 +0100 Message-ID: <20231201121622.16343-3-pstanner@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201121622.16343-1-pstanner@redhat.com> References: <20231201121622.16343-1-pstanner@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The pcim_*() functions in lib/devres.c are guarded by an #ifdef CONFIG_PCI and, thus, don't belong to this file. They are only ever used for pci and are not generic infrastructure. Move all pcim_*() functions in lib/devres.c to drivers/pci/devres.c. Adjust the Makefile. Suggested-by: Danilo Krummrich Signed-off-by: Philipp Stanner --- drivers/pci/Makefile | 2 +- drivers/pci/devres.c | 207 ++++++++++++++++++++++++++++++++++++++++++ lib/devres.c | 208 +------------------------------------------ 3 files changed, 209 insertions(+), 208 deletions(-) create mode 100644 drivers/pci/devres.c diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 64dcedccfc87..ed65299b42b5 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_PCI) +=3D access.o bus.o probe.o host-bridge.o \ remove.o pci.o pci-driver.o search.o \ pci-sysfs.o rom.o setup-res.o irq.o vpd.o \ - setup-bus.o vc.o mmap.o setup-irq.o + setup-bus.o vc.o mmap.o setup-irq.o devres.o =20 obj-$(CONFIG_PCI) +=3D msi/ obj-$(CONFIG_PCI) +=3D pcie/ diff --git a/drivers/pci/devres.c b/drivers/pci/devres.c new file mode 100644 index 000000000000..a3fd0d65cef1 --- /dev/null +++ b/drivers/pci/devres.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include "pci.h" + +/* + * PCI iomap devres + */ +#define PCIM_IOMAP_MAX PCI_STD_NUM_BARS + +struct pcim_iomap_devres { + void __iomem *table[PCIM_IOMAP_MAX]; +}; + +static void pcim_iomap_release(struct device *gendev, void *res) +{ + struct pci_dev *dev =3D to_pci_dev(gendev); + struct pcim_iomap_devres *this =3D res; + int i; + + for (i =3D 0; i < PCIM_IOMAP_MAX; i++) + if (this->table[i]) + pci_iounmap(dev, this->table[i]); +} + +/** + * pcim_iomap_table - access iomap allocation table + * @pdev: PCI device to access iomap table for + * + * Access iomap allocation table for @dev. If iomap table doesn't + * exist and @pdev is managed, it will be allocated. All iomaps + * recorded in the iomap table are automatically unmapped on driver + * detach. + * + * This function might sleep when the table is first allocated but can + * be safely called without context and guaranteed to succeed once + * allocated. + */ +void __iomem * const *pcim_iomap_table(struct pci_dev *pdev) +{ + struct pcim_iomap_devres *dr, *new_dr; + + dr =3D devres_find(&pdev->dev, pcim_iomap_release, NULL, NULL); + if (dr) + return dr->table; + + new_dr =3D devres_alloc_node(pcim_iomap_release, sizeof(*new_dr), GFP_KER= NEL, + dev_to_node(&pdev->dev)); + if (!new_dr) + return NULL; + dr =3D devres_get(&pdev->dev, new_dr, NULL, NULL); + return dr->table; +} +EXPORT_SYMBOL(pcim_iomap_table); + +/** + * pcim_iomap - Managed pcim_iomap() + * @pdev: PCI device to iomap for + * @bar: BAR to iomap + * @maxlen: Maximum length of iomap + * + * Managed pci_iomap(). Map is automatically unmapped on driver + * detach. + */ +void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxl= en) +{ + void __iomem **tbl; + + BUG_ON(bar >=3D PCIM_IOMAP_MAX); + + tbl =3D (void __iomem **)pcim_iomap_table(pdev); + if (!tbl || tbl[bar]) /* duplicate mappings not allowed */ + return NULL; + + tbl[bar] =3D pci_iomap(pdev, bar, maxlen); + return tbl[bar]; +} +EXPORT_SYMBOL(pcim_iomap); + +/** + * pcim_iounmap - Managed pci_iounmap() + * @pdev: PCI device to iounmap for + * @addr: Address to unmap + * + * Managed pci_iounmap(). @addr must have been mapped using pcim_iomap(). + */ +void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr) +{ + void __iomem **tbl; + int i; + + pci_iounmap(pdev, addr); + + tbl =3D (void __iomem **)pcim_iomap_table(pdev); + BUG_ON(!tbl); + + for (i =3D 0; i < PCIM_IOMAP_MAX; i++) + if (tbl[i] =3D=3D addr) { + tbl[i] =3D NULL; + return; + } + WARN_ON(1); +} +EXPORT_SYMBOL(pcim_iounmap); + +/** + * pcim_iomap_regions - Request and iomap PCI BARs + * @pdev: PCI device to map IO resources for + * @mask: Mask of BARs to request and iomap + * @name: Name used when requesting regions + * + * Request and iomap regions specified by @mask. + */ +int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name) +{ + void __iomem * const *iomap; + int i, rc; + + iomap =3D pcim_iomap_table(pdev); + if (!iomap) + return -ENOMEM; + + for (i =3D 0; i < DEVICE_COUNT_RESOURCE; i++) { + unsigned long len; + + if (!(mask & (1 << i))) + continue; + + rc =3D -EINVAL; + len =3D pci_resource_len(pdev, i); + if (!len) + goto err_inval; + + rc =3D pci_request_region(pdev, i, name); + if (rc) + goto err_inval; + + rc =3D -ENOMEM; + if (!pcim_iomap(pdev, i, 0)) + goto err_region; + } + + return 0; + + err_region: + pci_release_region(pdev, i); + err_inval: + while (--i >=3D 0) { + if (!(mask & (1 << i))) + continue; + pcim_iounmap(pdev, iomap[i]); + pci_release_region(pdev, i); + } + + return rc; +} +EXPORT_SYMBOL(pcim_iomap_regions); + +/** + * pcim_iomap_regions_request_all - Request all BARs and iomap specified o= nes + * @pdev: PCI device to map IO resources for + * @mask: Mask of BARs to iomap + * @name: Name used when requesting regions + * + * Request all PCI BARs and iomap regions specified by @mask. + */ +int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask, + const char *name) +{ + int request_mask =3D ((1 << 6) - 1) & ~mask; + int rc; + + rc =3D pci_request_selected_regions(pdev, request_mask, name); + if (rc) + return rc; + + rc =3D pcim_iomap_regions(pdev, mask, name); + if (rc) + pci_release_selected_regions(pdev, request_mask); + return rc; +} +EXPORT_SYMBOL(pcim_iomap_regions_request_all); + +/** + * pcim_iounmap_regions - Unmap and release PCI BARs + * @pdev: PCI device to map IO resources for + * @mask: Mask of BARs to unmap and release + * + * Unmap and release regions specified by @mask. + */ +void pcim_iounmap_regions(struct pci_dev *pdev, int mask) +{ + void __iomem * const *iomap; + int i; + + iomap =3D pcim_iomap_table(pdev); + if (!iomap) + return; + + for (i =3D 0; i < PCIM_IOMAP_MAX; i++) { + if (!(mask & (1 << i))) + continue; + + pcim_iounmap(pdev, iomap[i]); + pci_release_region(pdev, i); + } +} +EXPORT_SYMBOL(pcim_iounmap_regions); diff --git a/lib/devres.c b/lib/devres.c index c44f104b58d5..fe0c63caeb68 100644 --- a/lib/devres.c +++ b/lib/devres.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include -#include #include #include #include @@ -311,212 +311,6 @@ void devm_ioport_unmap(struct device *dev, void __iom= em *addr) EXPORT_SYMBOL(devm_ioport_unmap); #endif /* CONFIG_HAS_IOPORT_MAP */ =20 -#ifdef CONFIG_PCI -/* - * PCI iomap devres - */ -#define PCIM_IOMAP_MAX PCI_STD_NUM_BARS - -struct pcim_iomap_devres { - void __iomem *table[PCIM_IOMAP_MAX]; -}; - -static void pcim_iomap_release(struct device *gendev, void *res) -{ - struct pci_dev *dev =3D to_pci_dev(gendev); - struct pcim_iomap_devres *this =3D res; - int i; - - for (i =3D 0; i < PCIM_IOMAP_MAX; i++) - if (this->table[i]) - pci_iounmap(dev, this->table[i]); -} - -/** - * pcim_iomap_table - access iomap allocation table - * @pdev: PCI device to access iomap table for - * - * Access iomap allocation table for @dev. If iomap table doesn't - * exist and @pdev is managed, it will be allocated. All iomaps - * recorded in the iomap table are automatically unmapped on driver - * detach. - * - * This function might sleep when the table is first allocated but can - * be safely called without context and guaranteed to succeed once - * allocated. - */ -void __iomem * const *pcim_iomap_table(struct pci_dev *pdev) -{ - struct pcim_iomap_devres *dr, *new_dr; - - dr =3D devres_find(&pdev->dev, pcim_iomap_release, NULL, NULL); - if (dr) - return dr->table; - - new_dr =3D devres_alloc_node(pcim_iomap_release, sizeof(*new_dr), GFP_KER= NEL, - dev_to_node(&pdev->dev)); - if (!new_dr) - return NULL; - dr =3D devres_get(&pdev->dev, new_dr, NULL, NULL); - return dr->table; -} -EXPORT_SYMBOL(pcim_iomap_table); - -/** - * pcim_iomap - Managed pcim_iomap() - * @pdev: PCI device to iomap for - * @bar: BAR to iomap - * @maxlen: Maximum length of iomap - * - * Managed pci_iomap(). Map is automatically unmapped on driver - * detach. - */ -void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxl= en) -{ - void __iomem **tbl; - - BUG_ON(bar >=3D PCIM_IOMAP_MAX); - - tbl =3D (void __iomem **)pcim_iomap_table(pdev); - if (!tbl || tbl[bar]) /* duplicate mappings not allowed */ - return NULL; - - tbl[bar] =3D pci_iomap(pdev, bar, maxlen); - return tbl[bar]; -} -EXPORT_SYMBOL(pcim_iomap); - -/** - * pcim_iounmap - Managed pci_iounmap() - * @pdev: PCI device to iounmap for - * @addr: Address to unmap - * - * Managed pci_iounmap(). @addr must have been mapped using pcim_iomap(). - */ -void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr) -{ - void __iomem **tbl; - int i; - - pci_iounmap(pdev, addr); - - tbl =3D (void __iomem **)pcim_iomap_table(pdev); - BUG_ON(!tbl); - - for (i =3D 0; i < PCIM_IOMAP_MAX; i++) - if (tbl[i] =3D=3D addr) { - tbl[i] =3D NULL; - return; - } - WARN_ON(1); -} -EXPORT_SYMBOL(pcim_iounmap); - -/** - * pcim_iomap_regions - Request and iomap PCI BARs - * @pdev: PCI device to map IO resources for - * @mask: Mask of BARs to request and iomap - * @name: Name used when requesting regions - * - * Request and iomap regions specified by @mask. - */ -int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name) -{ - void __iomem * const *iomap; - int i, rc; - - iomap =3D pcim_iomap_table(pdev); - if (!iomap) - return -ENOMEM; - - for (i =3D 0; i < DEVICE_COUNT_RESOURCE; i++) { - unsigned long len; - - if (!(mask & (1 << i))) - continue; - - rc =3D -EINVAL; - len =3D pci_resource_len(pdev, i); - if (!len) - goto err_inval; - - rc =3D pci_request_region(pdev, i, name); - if (rc) - goto err_inval; - - rc =3D -ENOMEM; - if (!pcim_iomap(pdev, i, 0)) - goto err_region; - } - - return 0; - - err_region: - pci_release_region(pdev, i); - err_inval: - while (--i >=3D 0) { - if (!(mask & (1 << i))) - continue; - pcim_iounmap(pdev, iomap[i]); - pci_release_region(pdev, i); - } - - return rc; -} -EXPORT_SYMBOL(pcim_iomap_regions); - -/** - * pcim_iomap_regions_request_all - Request all BARs and iomap specified o= nes - * @pdev: PCI device to map IO resources for - * @mask: Mask of BARs to iomap - * @name: Name used when requesting regions - * - * Request all PCI BARs and iomap regions specified by @mask. - */ -int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask, - const char *name) -{ - int request_mask =3D ((1 << 6) - 1) & ~mask; - int rc; - - rc =3D pci_request_selected_regions(pdev, request_mask, name); - if (rc) - return rc; - - rc =3D pcim_iomap_regions(pdev, mask, name); - if (rc) - pci_release_selected_regions(pdev, request_mask); - return rc; -} -EXPORT_SYMBOL(pcim_iomap_regions_request_all); - -/** - * pcim_iounmap_regions - Unmap and release PCI BARs - * @pdev: PCI device to map IO resources for - * @mask: Mask of BARs to unmap and release - * - * Unmap and release regions specified by @mask. - */ -void pcim_iounmap_regions(struct pci_dev *pdev, int mask) -{ - void __iomem * const *iomap; - int i; - - iomap =3D pcim_iomap_table(pdev); - if (!iomap) - return; - - for (i =3D 0; i < PCIM_IOMAP_MAX; i++) { - if (!(mask & (1 << i))) - continue; - - pcim_iounmap(pdev, iomap[i]); - pci_release_region(pdev, i); - } -} -EXPORT_SYMBOL(pcim_iounmap_regions); -#endif /* CONFIG_PCI */ - static void devm_arch_phys_ac_add_release(struct device *dev, void *res) { arch_phys_wc_del(*((int *)res)); --=20 2.43.0 From nobody Tue Dec 16 16:37:06 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A70BCC4167B for ; Fri, 1 Dec 2023 12:17:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1378823AbjLAMRE (ORCPT ); Fri, 1 Dec 2023 07:17:04 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33068 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1378794AbjLAMQ6 (ORCPT ); Fri, 1 Dec 2023 07:16:58 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 233D81721 for ; Fri, 1 Dec 2023 04:17:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1701433022; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=D9lSBUfUwPiPxVYyMJ+3p0394qI/+OviCW4Ee5BgOjc=; b=ODIO25RYZxgcVRjLvOoldMmasysRGeaE1P4YGEfLKANPcViVbkNngAK3heRLhje7ttn8B2 X9EZm1FrQdAYjIgsdzJsvEry2VTMG6hou8imJvlnYFOvfN7pMNojWh/4zNBU+wdGRuhMkd iHPNmM4BxXsBtSwmRvAIbkXFUoTDgTg= Received: from mail-oo1-f71.google.com (mail-oo1-f71.google.com [209.85.161.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-500-X2GFF2wGMBmT_YrXIUjzAw-1; Fri, 01 Dec 2023 07:17:01 -0500 X-MC-Unique: X2GFF2wGMBmT_YrXIUjzAw-1 Received: by mail-oo1-f71.google.com with SMTP id 006d021491bc7-58d7fcec894so480995eaf.1 for ; Fri, 01 Dec 2023 04:17:01 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701433020; x=1702037820; 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=D9lSBUfUwPiPxVYyMJ+3p0394qI/+OviCW4Ee5BgOjc=; b=l6+S4bQOs0klwmAXlui9xgOthDYKilhsZY9o5Mi4zr2Og1erPGNN5kOcZ+fNNE2+Fa PmvdbgXOy5R6urzVmaC9bCIVrASpV/8vEg4qO0Mtzx9MtmR6LunvxAiYK4OoCcjwOxwk tzSpqID+o9t9pBQ5txiq3fmg5wVNo5G2kYIKiXjuGA6C7HwjDAjszGjFBZ7eiCJRXUkb H8d2wqkVMFKxfcq66JXl9owr7UBxG0s7UgjvsPCaqotgkmEmmgPWjHKQeThI3F2q1SNs S7pToihlx6O2G7ctvOPlfTPwNqse0qFn/LKksQD2H5zgfo9g2y18fQHjZuEzoMZSIixL f8SQ== X-Gm-Message-State: AOJu0Yx37GbziNB2KyYpxLJzDp85mlW3Aopfc/H98gO/5tlvFwZPnlIS ndJ3TrtU02zbl73pTG7qBLeNJ9yrSr0JXLoObQsvipqXWXfQjYnb5SuHEhvvj+1ZfU62ZbglfiO 5P3d9RxZPJuiKE7VnzmPQMfTT X-Received: by 2002:a05:6358:3102:b0:16b:96fa:2cd4 with SMTP id c2-20020a056358310200b0016b96fa2cd4mr24879946rwe.1.1701433020051; Fri, 01 Dec 2023 04:17:00 -0800 (PST) X-Google-Smtp-Source: AGHT+IEp55yajo0zJ0191ERp3bs7c0y39G0TSxpW58Am/WoTdopmVpjihhQ8EPqfr1qly4f6j8j2Ag== X-Received: by 2002:a05:6358:3102:b0:16b:96fa:2cd4 with SMTP id c2-20020a056358310200b0016b96fa2cd4mr24879910rwe.1.1701433019568; Fri, 01 Dec 2023 04:16:59 -0800 (PST) Received: from pstanner-thinkpadt14sgen1.remote.csb ([2001:9e8:32e2:4e00:227b:d2ff:fe26:2a7a]) by smtp.gmail.com with ESMTPSA id b19-20020ac87553000000b00423b8a53641sm1426528qtr.29.2023.12.01.04.16.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 04:16:59 -0800 (PST) From: Philipp Stanner To: Bjorn Helgaas , Arnd Bergmann , Andrew Morton , Dan Williams , Jonathan Cameron , Jakub Kicinski , Dave Jiang , Uladzislau Koshchanka , NeilBrown , Niklas Schnelle , John Sanpe , Kent Overstreet , Philipp Stanner , "Masami Hiramatsu (Google)" , Kees Cook , David Gow , Yury Norov , "wuqiang.matt" , Jason Baron , Kefeng Wang , Ben Dooks , dakr@redhat.com Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-arch@vger.kernel.org Subject: [PATCH v2 3/4] pci: move devres code from pci.c to devres.c Date: Fri, 1 Dec 2023 13:16:21 +0100 Message-ID: <20231201121622.16343-4-pstanner@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201121622.16343-1-pstanner@redhat.com> References: <20231201121622.16343-1-pstanner@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The file pci.c is very large and contains a number of devres-functions. These functions should now reside in devres.c There are a few callers left in pci.c that do devres operations. These should be ported in the future. Corresponding TODOs are added by this commit. The reason they are not moved right now in this commit is that pci's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c Moving the functions would require changes to pci's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch-series that will cleanly separate the PCI's managed and unmanaged API. Move as much devres-specific code from pci.c to devres.c as possible. Suggested-by: Danilo Krummrich Signed-off-by: Philipp Stanner --- As it turns out, this move is actually necessary because the iomap-functions have previously not been compiled as they were guarded by #ifdef PCI in lib/iomap.c when GENERIC_IOMAP was set. Additionally, it's still desirable (to me) because I want to add devres functions later that do not actually map anything. --- drivers/pci/devres.c | 243 +++++++++++++++++++++++++++++++++++++++++ drivers/pci/pci.c | 249 ------------------------------------------- drivers/pci/pci.h | 24 +++++ 3 files changed, 267 insertions(+), 249 deletions(-) diff --git a/drivers/pci/devres.c b/drivers/pci/devres.c index a3fd0d65cef1..55f76a2c3748 100644 --- a/drivers/pci/devres.c +++ b/drivers/pci/devres.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include #include "pci.h" =20 @@ -11,6 +12,248 @@ struct pcim_iomap_devres { void __iomem *table[PCIM_IOMAP_MAX]; }; =20 + +static void devm_pci_unmap_iospace(struct device *dev, void *ptr) +{ + struct resource **res =3D ptr; + + pci_unmap_iospace(*res); +} + +/** + * devm_pci_remap_iospace - Managed pci_remap_iospace() + * @dev: Generic device to remap IO address for + * @res: Resource describing the I/O space + * @phys_addr: physical address of range to be mapped + * + * Managed pci_remap_iospace(). Map is automatically unmapped on driver + * detach. + */ +int devm_pci_remap_iospace(struct device *dev, const struct resource *res, + phys_addr_t phys_addr) +{ + const struct resource **ptr; + int error; + + ptr =3D devres_alloc(devm_pci_unmap_iospace, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + error =3D pci_remap_iospace(res, phys_addr); + if (error) { + devres_free(ptr); + } else { + *ptr =3D res; + devres_add(dev, ptr); + } + + return error; +} +EXPORT_SYMBOL(devm_pci_remap_iospace); + +/** + * devm_pci_remap_cfgspace - Managed pci_remap_cfgspace() + * @dev: Generic device to remap IO address for + * @offset: Resource address to map + * @size: Size of map + * + * Managed pci_remap_cfgspace(). Map is automatically unmapped on driver + * detach. + */ +void __iomem *devm_pci_remap_cfgspace(struct device *dev, + resource_size_t offset, + resource_size_t size) +{ + void __iomem **ptr, *addr; + + ptr =3D devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return NULL; + + addr =3D pci_remap_cfgspace(offset, size); + if (addr) { + *ptr =3D addr; + devres_add(dev, ptr); + } else + devres_free(ptr); + + return addr; +} +EXPORT_SYMBOL(devm_pci_remap_cfgspace); + +/** + * devm_pci_remap_cfg_resource - check, request region and ioremap cfg res= ource + * @dev: generic device to handle the resource for + * @res: configuration space resource to be handled + * + * Checks that a resource is a valid memory region, requests the memory + * region and ioremaps with pci_remap_cfgspace() API that ensures the + * proper PCI configuration space memory attributes are guaranteed. + * + * All operations are managed and will be undone on driver detach. + * + * Returns a pointer to the remapped memory or an ERR_PTR() encoded error = code + * on failure. Usage example:: + * + * res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0); + * base =3D devm_pci_remap_cfg_resource(&pdev->dev, res); + * if (IS_ERR(base)) + * return PTR_ERR(base); + */ +void __iomem *devm_pci_remap_cfg_resource(struct device *dev, + struct resource *res) +{ + resource_size_t size; + const char *name; + void __iomem *dest_ptr; + + BUG_ON(!dev); + + if (!res || resource_type(res) !=3D IORESOURCE_MEM) { + dev_err(dev, "invalid resource\n"); + return IOMEM_ERR_PTR(-EINVAL); + } + + size =3D resource_size(res); + + if (res->name) + name =3D devm_kasprintf(dev, GFP_KERNEL, "%s %s", dev_name(dev), + res->name); + else + name =3D devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); + if (!name) + return IOMEM_ERR_PTR(-ENOMEM); + + if (!devm_request_mem_region(dev, res->start, size, name)) { + dev_err(dev, "can't request region for resource %pR\n", res); + return IOMEM_ERR_PTR(-EBUSY); + } + + dest_ptr =3D devm_pci_remap_cfgspace(dev, res->start, size); + if (!dest_ptr) { + dev_err(dev, "ioremap failed for resource %pR\n", res); + devm_release_mem_region(dev, res->start, size); + dest_ptr =3D IOMEM_ERR_PTR(-ENOMEM); + } + + return dest_ptr; +} +EXPORT_SYMBOL(devm_pci_remap_cfg_resource); + +/** + * pcim_set_mwi - a device-managed pci_set_mwi() + * @dev: the PCI device for which MWI is enabled + * + * Managed pci_set_mwi(). + * + * RETURNS: An appropriate -ERRNO error value on error, or zero for succes= s. + */ +int pcim_set_mwi(struct pci_dev *dev) +{ + struct pci_devres *dr; + + dr =3D find_pci_dr(dev); + if (!dr) + return -ENOMEM; + + dr->mwi =3D 1; + return pci_set_mwi(dev); +} +EXPORT_SYMBOL(pcim_set_mwi); + + +static void pcim_release(struct device *gendev, void *res) +{ + struct pci_dev *dev =3D to_pci_dev(gendev); + struct pci_devres *this =3D res; + int i; + + for (i =3D 0; i < DEVICE_COUNT_RESOURCE; i++) + if (this->region_mask & (1 << i)) + pci_release_region(dev, i); + + if (this->mwi) + pci_clear_mwi(dev); + + if (this->restore_intx) + pci_intx(dev, this->orig_intx); + + if (this->enabled && !this->pinned) + pci_disable_device(dev); +} + +/* + * TODO: + * Once the last four callers in pci.c are ported, this function here need= s to + * be made static again. + */ +struct pci_devres *find_pci_dr(struct pci_dev *pdev) +{ + if (pci_is_managed(pdev)) + return devres_find(&pdev->dev, pcim_release, NULL, NULL); + return NULL; +} +EXPORT_SYMBOL(find_pci_dr); // TODO do we need this? + +static struct pci_devres *get_pci_dr(struct pci_dev *pdev) +{ + struct pci_devres *dr, *new_dr; + + dr =3D devres_find(&pdev->dev, pcim_release, NULL, NULL); + if (dr) + return dr; + + new_dr =3D devres_alloc(pcim_release, sizeof(*new_dr), GFP_KERNEL); + if (!new_dr) + return NULL; + return devres_get(&pdev->dev, new_dr, NULL, NULL); +} + +/** + * pcim_enable_device - Managed pci_enable_device() + * @pdev: PCI device to be initialized + * + * Managed pci_enable_device(). + */ +int pcim_enable_device(struct pci_dev *pdev) +{ + struct pci_devres *dr; + int rc; + + dr =3D get_pci_dr(pdev); + if (unlikely(!dr)) + return -ENOMEM; + if (dr->enabled) + return 0; + + rc =3D pci_enable_device(pdev); + if (!rc) { + pdev->is_managed =3D 1; + dr->enabled =3D 1; + } + return rc; +} +EXPORT_SYMBOL(pcim_enable_device); + +/** + * pcim_pin_device - Pin managed PCI device + * @pdev: PCI device to pin + * + * Pin managed PCI device @pdev. Pinned device won't be disabled on + * driver detach. @pdev must have been enabled with + * pcim_enable_device(). + */ +void pcim_pin_device(struct pci_dev *pdev) +{ + struct pci_devres *dr; + + dr =3D find_pci_dr(pdev); + WARN_ON(!dr || !dr->enabled); + if (dr) + dr->pinned =3D 1; +} +EXPORT_SYMBOL(pcim_pin_device); + static void pcim_iomap_release(struct device *gendev, void *res) { struct pci_dev *dev =3D to_pci_dev(gendev); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 55bc3576a985..742b0a6545b6 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2088,107 +2088,6 @@ int pci_enable_device(struct pci_dev *dev) } EXPORT_SYMBOL(pci_enable_device); =20 -/* - * Managed PCI resources. This manages device on/off, INTx/MSI/MSI-X - * on/off and BAR regions. pci_dev itself records MSI/MSI-X status, so - * there's no need to track it separately. pci_devres is initialized - * when a device is enabled using managed PCI device enable interface. - */ -struct pci_devres { - unsigned int enabled:1; - unsigned int pinned:1; - unsigned int orig_intx:1; - unsigned int restore_intx:1; - unsigned int mwi:1; - u32 region_mask; -}; - -static void pcim_release(struct device *gendev, void *res) -{ - struct pci_dev *dev =3D to_pci_dev(gendev); - struct pci_devres *this =3D res; - int i; - - for (i =3D 0; i < DEVICE_COUNT_RESOURCE; i++) - if (this->region_mask & (1 << i)) - pci_release_region(dev, i); - - if (this->mwi) - pci_clear_mwi(dev); - - if (this->restore_intx) - pci_intx(dev, this->orig_intx); - - if (this->enabled && !this->pinned) - pci_disable_device(dev); -} - -static struct pci_devres *get_pci_dr(struct pci_dev *pdev) -{ - struct pci_devres *dr, *new_dr; - - dr =3D devres_find(&pdev->dev, pcim_release, NULL, NULL); - if (dr) - return dr; - - new_dr =3D devres_alloc(pcim_release, sizeof(*new_dr), GFP_KERNEL); - if (!new_dr) - return NULL; - return devres_get(&pdev->dev, new_dr, NULL, NULL); -} - -static struct pci_devres *find_pci_dr(struct pci_dev *pdev) -{ - if (pci_is_managed(pdev)) - return devres_find(&pdev->dev, pcim_release, NULL, NULL); - return NULL; -} - -/** - * pcim_enable_device - Managed pci_enable_device() - * @pdev: PCI device to be initialized - * - * Managed pci_enable_device(). - */ -int pcim_enable_device(struct pci_dev *pdev) -{ - struct pci_devres *dr; - int rc; - - dr =3D get_pci_dr(pdev); - if (unlikely(!dr)) - return -ENOMEM; - if (dr->enabled) - return 0; - - rc =3D pci_enable_device(pdev); - if (!rc) { - pdev->is_managed =3D 1; - dr->enabled =3D 1; - } - return rc; -} -EXPORT_SYMBOL(pcim_enable_device); - -/** - * pcim_pin_device - Pin managed PCI device - * @pdev: PCI device to pin - * - * Pin managed PCI device @pdev. Pinned device won't be disabled on - * driver detach. @pdev must have been enabled with - * pcim_enable_device(). - */ -void pcim_pin_device(struct pci_dev *pdev) -{ - struct pci_devres *dr; - - dr =3D find_pci_dr(pdev); - WARN_ON(!dr || !dr->enabled); - if (dr) - dr->pinned =3D 1; -} -EXPORT_SYMBOL(pcim_pin_device); - /* * pcibios_device_add - provide arch specific hooks when adding device dev * @dev: the PCI device being added @@ -4281,133 +4180,6 @@ void pci_unmap_iospace(struct resource *res) } EXPORT_SYMBOL(pci_unmap_iospace); =20 -static void devm_pci_unmap_iospace(struct device *dev, void *ptr) -{ - struct resource **res =3D ptr; - - pci_unmap_iospace(*res); -} - -/** - * devm_pci_remap_iospace - Managed pci_remap_iospace() - * @dev: Generic device to remap IO address for - * @res: Resource describing the I/O space - * @phys_addr: physical address of range to be mapped - * - * Managed pci_remap_iospace(). Map is automatically unmapped on driver - * detach. - */ -int devm_pci_remap_iospace(struct device *dev, const struct resource *res, - phys_addr_t phys_addr) -{ - const struct resource **ptr; - int error; - - ptr =3D devres_alloc(devm_pci_unmap_iospace, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return -ENOMEM; - - error =3D pci_remap_iospace(res, phys_addr); - if (error) { - devres_free(ptr); - } else { - *ptr =3D res; - devres_add(dev, ptr); - } - - return error; -} -EXPORT_SYMBOL(devm_pci_remap_iospace); - -/** - * devm_pci_remap_cfgspace - Managed pci_remap_cfgspace() - * @dev: Generic device to remap IO address for - * @offset: Resource address to map - * @size: Size of map - * - * Managed pci_remap_cfgspace(). Map is automatically unmapped on driver - * detach. - */ -void __iomem *devm_pci_remap_cfgspace(struct device *dev, - resource_size_t offset, - resource_size_t size) -{ - void __iomem **ptr, *addr; - - ptr =3D devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return NULL; - - addr =3D pci_remap_cfgspace(offset, size); - if (addr) { - *ptr =3D addr; - devres_add(dev, ptr); - } else - devres_free(ptr); - - return addr; -} -EXPORT_SYMBOL(devm_pci_remap_cfgspace); - -/** - * devm_pci_remap_cfg_resource - check, request region and ioremap cfg res= ource - * @dev: generic device to handle the resource for - * @res: configuration space resource to be handled - * - * Checks that a resource is a valid memory region, requests the memory - * region and ioremaps with pci_remap_cfgspace() API that ensures the - * proper PCI configuration space memory attributes are guaranteed. - * - * All operations are managed and will be undone on driver detach. - * - * Returns a pointer to the remapped memory or an ERR_PTR() encoded error = code - * on failure. Usage example:: - * - * res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0); - * base =3D devm_pci_remap_cfg_resource(&pdev->dev, res); - * if (IS_ERR(base)) - * return PTR_ERR(base); - */ -void __iomem *devm_pci_remap_cfg_resource(struct device *dev, - struct resource *res) -{ - resource_size_t size; - const char *name; - void __iomem *dest_ptr; - - BUG_ON(!dev); - - if (!res || resource_type(res) !=3D IORESOURCE_MEM) { - dev_err(dev, "invalid resource\n"); - return IOMEM_ERR_PTR(-EINVAL); - } - - size =3D resource_size(res); - - if (res->name) - name =3D devm_kasprintf(dev, GFP_KERNEL, "%s %s", dev_name(dev), - res->name); - else - name =3D devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); - if (!name) - return IOMEM_ERR_PTR(-ENOMEM); - - if (!devm_request_mem_region(dev, res->start, size, name)) { - dev_err(dev, "can't request region for resource %pR\n", res); - return IOMEM_ERR_PTR(-EBUSY); - } - - dest_ptr =3D devm_pci_remap_cfgspace(dev, res->start, size); - if (!dest_ptr) { - dev_err(dev, "ioremap failed for resource %pR\n", res); - devm_release_mem_region(dev, res->start, size); - dest_ptr =3D IOMEM_ERR_PTR(-ENOMEM); - } - - return dest_ptr; -} -EXPORT_SYMBOL(devm_pci_remap_cfg_resource); - static void __pci_set_master(struct pci_dev *dev, bool enable) { u16 old_cmd, cmd; @@ -4557,27 +4329,6 @@ int pci_set_mwi(struct pci_dev *dev) } EXPORT_SYMBOL(pci_set_mwi); =20 -/** - * pcim_set_mwi - a device-managed pci_set_mwi() - * @dev: the PCI device for which MWI is enabled - * - * Managed pci_set_mwi(). - * - * RETURNS: An appropriate -ERRNO error value on error, or zero for succes= s. - */ -int pcim_set_mwi(struct pci_dev *dev) -{ - struct pci_devres *dr; - - dr =3D find_pci_dr(dev); - if (!dr) - return -ENOMEM; - - dr->mwi =3D 1; - return pci_set_mwi(dev); -} -EXPORT_SYMBOL(pcim_set_mwi); - /** * pci_try_set_mwi - enables memory-write-invalidate PCI transaction * @dev: the PCI device for which MWI is enabled diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 5ecbcf041179..69052059dbd2 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -793,6 +793,30 @@ static inline pci_power_t mid_pci_get_power_state(stru= ct pci_dev *pdev) } #endif =20 +/* + * TODO: + * The following two components wouldn't need to be here if they weren't u= sed at + * four last places in pci.c + * Port or move these functions to devres.c and then remove the + * pci_devres-components from this header file here. + */ +/* + * Managed PCI resources. This manages device on/off, INTx/MSI/MSI-X + * on/off and BAR regions. pci_dev itself records MSI/MSI-X status, so + * there's no need to track it separately. pci_devres is initialized + * when a device is enabled using managed PCI device enable interface. + */ +struct pci_devres { + unsigned int enabled:1; + unsigned int pinned:1; + unsigned int orig_intx:1; + unsigned int restore_intx:1; + unsigned int mwi:1; + u32 region_mask; +}; + +struct pci_devres *find_pci_dr(struct pci_dev *pdev); + /* * Config Address for PCI Configuration Mechanism #1 * --=20 2.43.0 From nobody Tue Dec 16 16:37:06 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 54DE9C4167B for ; Fri, 1 Dec 2023 12:17:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1378835AbjLAMRO (ORCPT ); Fri, 1 Dec 2023 07:17:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33022 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1378807AbjLAMRD (ORCPT ); Fri, 1 Dec 2023 07:17:03 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DCCC91715 for ; Fri, 1 Dec 2023 04:17:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1701433026; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=aIU4mh01NIo3J+0bv0Z7Ok8zfrU9Sy5KFoYboE67XEg=; b=WKX3NhC8/gJn8CmP6fzH9EOMlC7PCUwBGiE3+48PKDyNzjQgkNAzfv0rDZ3dqBdkOViquV P1v7pWnO4njyddN0SN/3m471ZQnDlUQ/gTuhE5Hyj7xpH8+32WOq92bhfe9heivBuEayQt CLN77ESdyu8yFcpZyTrVa2Yi45CMvdE= Received: from mail-qt1-f200.google.com (mail-qt1-f200.google.com [209.85.160.200]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-99-tplWXAJEPkqnPXDqWRFaJA-1; Fri, 01 Dec 2023 07:17:04 -0500 X-MC-Unique: tplWXAJEPkqnPXDqWRFaJA-1 Received: by mail-qt1-f200.google.com with SMTP id d75a77b69052e-423f2ad71c9so5378081cf.0 for ; Fri, 01 Dec 2023 04:17:04 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701433023; x=1702037823; 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=aIU4mh01NIo3J+0bv0Z7Ok8zfrU9Sy5KFoYboE67XEg=; b=RLQl7NPbdGe/0b8gNc5vTeDkvXwzab3ymmmpz+YdeVUx4DGU4IHKe0TEDnI/EnBMtZ Hc/ebWCDbXfQi9lxDKUAZnBU7I6KYQmsaWEXDvre2GXiPzUe1hbfvHLFMdGNU2YxbLzX 3JewRWtL/km+s6nl0+wIlFBT+NgpQOZuSxDrmnfo+U9L8FGdX1jSiUtLC95tOXNbU3Wn D6c27tFYBbOlwh7+hyCaCG1D5pX2zLqyfmQQMPr5q9PL9P7+cdUDBP4rPWDy/ADE6LTd rGEyuMtpaJ1pQCVQPz4/41RSB0eVN/aFUuAulEK2sq1cL/xMxArXDKasp075LMCax0s9 HI0g== X-Gm-Message-State: AOJu0Yx2+dlVfz+xicdU+SIxqA0/38bSvm1WwBiEfiG2+GbwdKktWOds nlkqtTRtCsLfiBqUFW0bW5bpgzAPuQvgI8PQwlZMZjc3J6kyPL0z9GkEZlA4IArf0W13MvUuYw2 wMry4MbJrzMMo1CUzAaGXIV1P X-Received: by 2002:a05:622a:5505:b0:423:a6c8:7db9 with SMTP id fj5-20020a05622a550500b00423a6c87db9mr24035871qtb.6.1701433023437; Fri, 01 Dec 2023 04:17:03 -0800 (PST) X-Google-Smtp-Source: AGHT+IFQfSS2UW2A54VtKLLtAF4bxHgHalN5nM46dpZI44qbzDLU3S4OQPiukfxEaRXrK+nRrdI9pQ== X-Received: by 2002:a05:622a:5505:b0:423:a6c8:7db9 with SMTP id fj5-20020a05622a550500b00423a6c87db9mr24035847qtb.6.1701433023157; Fri, 01 Dec 2023 04:17:03 -0800 (PST) Received: from pstanner-thinkpadt14sgen1.remote.csb ([2001:9e8:32e2:4e00:227b:d2ff:fe26:2a7a]) by smtp.gmail.com with ESMTPSA id b19-20020ac87553000000b00423b8a53641sm1426528qtr.29.2023.12.01.04.16.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 04:17:02 -0800 (PST) From: Philipp Stanner To: Bjorn Helgaas , Arnd Bergmann , Andrew Morton , Dan Williams , Jonathan Cameron , Jakub Kicinski , Dave Jiang , Uladzislau Koshchanka , NeilBrown , Niklas Schnelle , John Sanpe , Kent Overstreet , Philipp Stanner , "Masami Hiramatsu (Google)" , Kees Cook , David Gow , Yury Norov , "wuqiang.matt" , Jason Baron , Kefeng Wang , Ben Dooks , dakr@redhat.com Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-arch@vger.kernel.org, Arnd Bergmann Subject: [PATCH v2 4/4] lib, pci: unify generic pci_iounmap() Date: Fri, 1 Dec 2023 13:16:22 +0100 Message-ID: <20231201121622.16343-5-pstanner@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231201121622.16343-1-pstanner@redhat.com> References: <20231201121622.16343-1-pstanner@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The implementation of pci_iounmap() is currently scattered over two files, drivers/pci/iounmap.c and lib/iomap.c. Additionally, architectures can define their own version. Besides one unified version being desirable in the first place, the old version in drivers/pci/iounmap.c contained a bug and could leak memory mappings. The bug was that #ifdef ARCH_HAS_GENERIC_IOPORT_MAP should not have guarded iounmap(p); in addition to the preceding code. To have only one version, it's necessary to create a helper function, iomem_is_ioport(), that tells pci_iounmap() whether the passed address points to an ioport or normal memory. iomem_is_ioport() can be provided through three different ways: 1. The architecture itself provides it. 2. As a default version in include/asm-generic/io.h for those architectures that don't use CONFIG_GENERIC_IOMAP, but also don't provide their own version of iomem_is_ioport(). 3. As a default version in lib/iomap.c for those architectures that define and use CONFIG_GENERIC_IOMAP (currently, only x86 really uses the functions in lib/iomap.c) Create a unified version of pci_iounmap() in drivers/pci/iomap.c. Provide the function iomem_is_ioport() in include/asm-generic/io.h and lib/iomap.c. Remove the CONFIG_GENERIC_IOMAP guard around ARCH_WANTS_GENERIC_PCI_IOUNMAP so that configs that set CONFIG_GENERIC_PCI_IOMAP without CONFIG_GENERIC_IOMAP still get the function. Fixes: 316e8d79a095 ("pci_iounmap'2: Electric Boogaloo: try to make sense o= f it all") Suggested-by: Arnd Bergmann Signed-off-by: Philipp Stanner --- drivers/pci/iomap.c | 40 +++++++++++----------------------------- include/asm-generic/io.h | 37 ++++++++++++++++++++++++++++++++++--- lib/iomap.c | 16 +++++++++------- 3 files changed, 54 insertions(+), 39 deletions(-) diff --git a/drivers/pci/iomap.c b/drivers/pci/iomap.c index 0a9d503ba533..cb7f86371b7d 100644 --- a/drivers/pci/iomap.c +++ b/drivers/pci/iomap.c @@ -135,42 +135,24 @@ void __iomem *pci_iomap_wc(struct pci_dev *dev, int b= ar, unsigned long maxlen) EXPORT_SYMBOL_GPL(pci_iomap_wc); =20 /* - * pci_iounmap() somewhat illogically comes from lib/iomap.c for the - * CONFIG_GENERIC_IOMAP case, because that's the code that knows about - * the different IOMAP ranges. + * Generic version of pci_iounmap() that is used if the architecture does = not + * provide its own version. * - * But if the architecture does not use the generic iomap code, and if - * it has _not_ defined it's own private pci_iounmap function, we define - * it here. - * - * NOTE! This default implementation assumes that if the architecture - * support ioport mapping (HAS_IOPORT_MAP), the ioport mapping will - * be fixed to the range [ PCI_IOBASE, PCI_IOBASE+IO_SPACE_LIMIT [, - * and does not need unmapping with 'ioport_unmap()'. - * - * If you have different rules for your architecture, you need to - * implement your own pci_iounmap() that knows the rules for where - * and how IO vs MEM get mapped. - * - * This code is odd, and the ARCH_HAS/ARCH_WANTS #define logic comes - * from legacy header file behavior. In particular, - * it would seem to make sense to do the iounmap(p) for the non-IO-space - * case here regardless, but that's not what the old header file code - * did. Probably incorrectly, but this is meant to be bug-for-bug - * compatible. + * If you have special rules for your architecture, you need to implement = your + * own pci_iounmap() in ARCH/asm/io.h that knows the rules for where and h= ow IO + * vs MEM get mapped. */ #if defined(ARCH_WANTS_GENERIC_PCI_IOUNMAP) =20 -void pci_iounmap(struct pci_dev *dev, void __iomem *p) +void pci_iounmap(struct pci_dev *dev, void __iomem *addr) { -#ifdef ARCH_HAS_GENERIC_IOPORT_MAP - uintptr_t start =3D (uintptr_t) PCI_IOBASE; - uintptr_t addr =3D (uintptr_t) p; - - if (addr >=3D start && addr < start + IO_SPACE_LIMIT) +#ifdef CONFIG_HAS_IOPORT + if (iomem_is_ioport(addr)) { + ioport_unmap(addr); return; - iounmap(p); + } #endif + iounmap(addr); } EXPORT_SYMBOL(pci_iounmap); =20 diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h index bac63e874c7b..4177d6b97e0b 100644 --- a/include/asm-generic/io.h +++ b/include/asm-generic/io.h @@ -1129,11 +1129,42 @@ extern void ioport_unmap(void __iomem *p); #endif /* CONFIG_GENERIC_IOMAP */ #endif /* CONFIG_HAS_IOPORT_MAP */ =20 -#ifndef CONFIG_GENERIC_IOMAP #ifndef pci_iounmap +#define pci_iounmap pci_iounmap #define ARCH_WANTS_GENERIC_PCI_IOUNMAP -#endif -#endif +#endif /* pci_iounmap */ + + +/* + * This function is a helper only needed for the generic pci_iounmap(). + * It's provided here if the architecture does not select GENERIC_IOMAP an= d does + * not provide its own version. + */ +#ifdef CONFIG_HAS_IOPORT +#ifndef iomem_is_ioport /* i.e., if the architecture hasn't defined its ow= n. */ +#define iomem_is_ioport iomem_is_ioport + +#ifndef CONFIG_GENERIC_IOMAP +static inline bool iomem_is_ioport(void __iomem *addr) +{ + unsigned long port =3D (unsigned long __force)addr; + + // TODO: do we have to take IO_SPACE_LIMIT and PCI_IOBASE into account + // similar as in ioport_map() ? + + if (port > MMIO_UPPER_LIMIT) + return false; + + return true; +} +#else /* CONFIG_GENERIC_IOMAP. Version from lib/iomap.c will be used. */ +bool iomem_is_ioport(void __iomem *addr); +#define ARCH_WANTS_GENERIC_IOMEM_IS_IOPORT +#endif /* CONFIG_GENERIC_IOMAP */ + +#endif /* iomem_is_ioport */ +#endif /* CONFIG_HAS_IOPORT */ + =20 #ifndef xlate_dev_mem_ptr #define xlate_dev_mem_ptr xlate_dev_mem_ptr diff --git a/lib/iomap.c b/lib/iomap.c index 4f8b31baa575..adaf6246f892 100644 --- a/lib/iomap.c +++ b/lib/iomap.c @@ -418,12 +418,14 @@ EXPORT_SYMBOL(ioport_map); EXPORT_SYMBOL(ioport_unmap); #endif /* CONFIG_HAS_IOPORT_MAP */ =20 -#ifdef CONFIG_PCI -/* Hide the details if this is a MMIO or PIO address space and just do what - * you expect in the correct way. */ -void pci_iounmap(struct pci_dev *dev, void __iomem * addr) +#if defined(ARCH_WANTS_GENERIC_IOMEM_IS_IOPORT) +bool iomem_is_ioport(void __iomem *addr) { - IO_COND(addr, /* nothing */, iounmap(addr)); + unsigned long port =3D (unsigned long __force)addr; + + if (port > PIO_OFFSET && port < PIO_RESERVED) + return true; + + return false; } -EXPORT_SYMBOL(pci_iounmap); -#endif /* CONFIG_PCI */ +#endif /* ARCH_WANTS_GENERIC_IOMEM_IS_IOPORT */ --=20 2.43.0