From patchwork Mon Jan 15 14:46:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Stanner X-Patchwork-Id: 13519729 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 52319C3DA79 for ; Mon, 15 Jan 2024 14:47:19 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id AAF8F10E2E2; Mon, 15 Jan 2024 14:47:18 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by gabe.freedesktop.org (Postfix) with ESMTPS id 50CEC10E2E2 for ; Mon, 15 Jan 2024 14:47:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705330036; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=wbybY9iQcnkB73xM1yKkpppr/vxHnl4OLedIb79V9wo=; b=dLGeCd6kQKKPn6i5gT08Q7HOwvrJ6G6NADkfRfkbGNziuJL97mELvmRlCtEFi8UYG6hlPp ghBb3e9487EVzUHpQiXCe6SrJCxEmFu6YYGilGSvq3fdRWwHhz1zAiS7ZUGk6UmyCHQJTQ HGfecK8yKfzQyMlHu+pIwPCeq1JYX1w= Received: from mail-qv1-f71.google.com (mail-qv1-f71.google.com [209.85.219.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-554-cDIFvwy1N3uS7D1yWAgGXw-1; Mon, 15 Jan 2024 09:47:15 -0500 X-MC-Unique: cDIFvwy1N3uS7D1yWAgGXw-1 Received: by mail-qv1-f71.google.com with SMTP id 6a1803df08f44-680fce72f68so25067486d6.0 for ; Mon, 15 Jan 2024 06:47:15 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705330034; x=1705934834; 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=wbybY9iQcnkB73xM1yKkpppr/vxHnl4OLedIb79V9wo=; b=SHbXMHiXN4N2j7R3JG+xQ/r0zo2Tvs7PuZfXr0nAsQAWAHjdLcaqVmRdbM5nSLeLo3 mAA7Ki+C1R0VU21SgzKji2b/jT84N0zeybvO/sHoEF5mOJycMCRrISlnsVtjG7i/xJTY w13jZo+uDvNSVhDtoZd6UfOrMBR/IvsB8mImCrS7Lvh1D5IphIn0sPTxr+7QzaVXPHHd GqRdA8tYgJf3V0BmN3CZfSQuYp80CCRmWKWKDDW61smCM9fZhavar0WebUQVmSsPcjzf 0NjiTk6PB+KQTNM7Gu7JH5kgl3ITk7xxmB24ng4d1cQlMuwzWsrsihPN/DTKwC9UqmqO uGRw== X-Gm-Message-State: AOJu0YzQUt1kdU1K9k+zHK0m+O0Ki2DnNvimeKdPZDbIkqF/QHFPj/UQ RAn80Utsvyi4sMKXBGkrluuzsPBAoCLnxarTsEim+bK0un8gu157mlsbJYmDUZ/EivwxdWRXrDa /Bwc+AqLAgYv8Tgb1tpI1jwrh44Da9YMbgzdg X-Received: by 2002:a05:6214:1c45:b0:681:554a:a94b with SMTP id if5-20020a0562141c4500b00681554aa94bmr6344628qvb.4.1705330034305; Mon, 15 Jan 2024 06:47:14 -0800 (PST) X-Google-Smtp-Source: AGHT+IFp3HxThPTri3utY9IJvRlcM6dRy9DG1DBfIgbFThv8dyL1vLRK4mkJab5Ju7PxXxoqgvW/fA== X-Received: by 2002:a05:6214:1c45:b0:681:554a:a94b with SMTP id if5-20020a0562141c4500b00681554aa94bmr6344602qvb.4.1705330033916; Mon, 15 Jan 2024 06:47:13 -0800 (PST) Received: from pstanner-thinkpadt14sgen1.muc.redhat.com (nat-pool-muc-t.redhat.com. [149.14.88.26]) by smtp.gmail.com with ESMTPSA id ne13-20020a056214424d00b006815cf9a644sm1020720qvb.55.2024.01.15.06.47.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Jan 2024 06:47:13 -0800 (PST) From: Philipp Stanner To: Jonathan Corbet , Hans de Goede , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Daniel Vetter , Bjorn Helgaas , Philipp Stanner , Sam Ravnborg , dakr@redhat.com Subject: [PATCH 01/10] pci: add new set of devres functions Date: Mon, 15 Jan 2024 15:46:12 +0100 Message-ID: <20240115144655.32046-3-pstanner@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240115144655.32046-2-pstanner@redhat.com> References: <20240115144655.32046-2-pstanner@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" PCI's devres API is not extensible to ranged mappings and has bug-provoking features. Improve that by providing better alternatives. When the original devres API for PCI was implemented, priority was given to the creation of a set of "pural functions" such as pcim_request_regions(). These functions have bit masks as parameters to specify which BARs shall get mapped. Most users, however, only use those to mapp 1-3 BARs. A complete set of "singular functions" does not exist. As functions mapping / requesting multiple BARs at once have (almost) no mechanism in C to return the resources to the caller of the plural function, the devres API utilizes the iomap-table administrated by the function pcim_iomap_table(). The entire PCI devres implementation was strongly tied to that table which only allows for mapping whole, complete BARs, as the BAR's index is used as table index. Consequently, it's not possible to, e.g., have a pcim_iomap_range() function with that mechanism. An additional problem is that pci-devres has been ipmlemented in a sort of "hybrid-mode": Some unmanaged functions have managed counterparts (e.g.: pci_iomap() <-> pcim_iomap()), making their managed nature obvious to the programmer. However, the region-request functions in pci.c, prefixed with pci_, behave either managed or unmanaged, depending on whether pci_enable_device() or pcim_enable_device() has been called in advance. This hybrid API is confusing and should be more cleanly separated by providing always-managed functions prefixed with pcim_. Thus, the existing devres API is not desirable because: a) The vast majority of the users of the plural functions only ever sets a single bit in the bit mask, consequently making them singular functions anyways. b) There is no mechanism to request / iomap only part of a BAR. c) The iomap-table mechanism is over-engineered, complicated and can by definition not perform bounds checks, thus, provoking memory faults: pcim_iomap_table(pdev)[42] d) region-request functions being sometimes managed and sometimes not is bug-provoking. Implement a set of singular pcim_ functions that use devres directly and bypass the legacy iomap table mechanism. Add devres.c to driver-api documentation. Signed-off-by: Philipp Stanner --- Documentation/driver-api/pci/pci.rst | 3 + drivers/pci/devres.c | 481 ++++++++++++++++++++++++++- include/linux/pci.h | 11 + 3 files changed, 490 insertions(+), 5 deletions(-) diff --git a/Documentation/driver-api/pci/pci.rst b/Documentation/driver-api/pci/pci.rst index 4843cfad4f60..92b11775344e 100644 --- a/Documentation/driver-api/pci/pci.rst +++ b/Documentation/driver-api/pci/pci.rst @@ -4,6 +4,9 @@ PCI Support Library .. kernel-doc:: drivers/pci/pci.c :export: +.. kernel-doc:: drivers/pci/devres.c + :export: + .. kernel-doc:: drivers/pci/pci-driver.c :export: diff --git a/drivers/pci/devres.c b/drivers/pci/devres.c index 4bd1e125bca1..cc8c1501eb13 100644 --- a/drivers/pci/devres.c +++ b/drivers/pci/devres.c @@ -8,10 +8,223 @@ */ #define PCIM_IOMAP_MAX PCI_STD_NUM_BARS +/* + * Legacy struct storing addresses to whole mapped bars. + */ struct pcim_iomap_devres { void __iomem *table[PCIM_IOMAP_MAX]; }; +enum pcim_addr_devres_type { + /* Default initializer. */ + PCIM_ADDR_DEVRES_TYPE_INVALID, + + /* A region spaning an entire bar. */ + PCIM_ADDR_DEVRES_TYPE_REGION, + + /* A region spaning an entire bar, and a mapping for that whole bar. */ + PCIM_ADDR_DEVRES_TYPE_REGION_MAPPING, + + /* + * A mapping within a bar, either spaning the whole bar or just a range. + * Without a requested region. + */ + PCIM_ADDR_DEVRES_TYPE_MAPPING, + + /* A ranged region within a bar, with a mapping spaning that range. */ + PCIM_ADDR_DEVRES_TYPE_REGION_RANGE_MAPPING +}; + +/* + * This struct envelopes IO or MEM addresses, that means mappings and region + * requests, because those are very frequently requested and released together. + */ +struct pcim_addr_devres { + enum pcim_addr_devres_type type; + void __iomem *baseaddr; + unsigned long offset; + unsigned long len; + short bar; +}; + +static inline void pcim_addr_devres_clear(struct pcim_addr_devres *res) +{ + res->type = PCIM_ADDR_DEVRES_TYPE_INVALID; + res->bar = -1; + res->baseaddr = NULL; + res->offset = 0; + res->len = 0; +} + +/* + * The following functions, __pcim_*_region*, exist as counterparts to the + * versions from pci.c - which, unfortunately, can be in "hybrid mode", i.e., + * sometimes managed, sometimes not. + * + * To separate the APIs cleanly, we define our own, simplified versions here. + */ + +/** + * __pcim_request_region_range - Request a ranged region + * @pdev: PCI device the region belongs to + * @bar: The BAR the region is within + * @offset: offset from the BAR's start address + * @maxlen: length in bytes, beginning at @offset + * @name: name associated with the request + * @exclusive: whether the mapping shall be exclusively for kernelspace + * + * Returns: 0 on success, a negative error code on failure. + * + * Request a ranged region within a device's PCI BAR. This function performs + * sanity checks on the input. + */ +static int __pcim_request_region_range(struct pci_dev *pdev, int bar, + unsigned long offset, unsigned long maxlen, + const char *name, int exclusive) +{ + resource_size_t start = pci_resource_start(pdev, bar); + resource_size_t len = pci_resource_len(pdev, bar); + unsigned long flags = pci_resource_flags(pdev, bar); + + if (start == 0 || len == 0) /* that's an unused BAR. */ + return 0; + if (len <= offset) + return -EINVAL; + + start += offset; + len -= offset; + + if (len > maxlen && maxlen != 0) + len = maxlen; + + if (flags & IORESOURCE_IO) { + if (!request_region(start, len, name)) + return -EBUSY; + } else if (flags & IORESOURCE_MEM) { + if (!__request_mem_region(start, len, name, exclusive)) + return -EBUSY; + } else { + /* That's not a device we can request anything on. */ + return -ENODEV; + } + + return 0; +} + +static void __pcim_release_region_range(struct pci_dev *pdev, int bar, + unsigned long offset, unsigned long maxlen) +{ + resource_size_t start = pci_resource_start(pdev, bar); + resource_size_t len = pci_resource_len(pdev, bar); + unsigned long flags = pci_resource_flags(pdev, bar); + + if (len <= offset || start == 0) + return; + + if (len == 0 || maxlen == 0) /* This an unused BAR. Do nothing. */ + return; + + start += offset; + len -= offset; + + if (len > maxlen) + len = maxlen; + + if (flags & IORESOURCE_IO) + release_region(start, len); + else if (flags & IORESOURCE_MEM) + release_mem_region(start, len); +} + +static int __pcim_request_region(struct pci_dev *pdev, int bar, + const char *name, int exclusive) +{ + const unsigned long offset = 0; + const unsigned long len = pci_resource_len(pdev, bar); + + return __pcim_request_region_range(pdev, bar, offset, len, name, exclusive); +} + +static void __pcim_release_region(struct pci_dev *pdev, int bar) +{ + const unsigned long offset = 0; + const unsigned long len = pci_resource_len(pdev, bar); + + __pcim_release_region_range(pdev, bar, offset, len); +} + +static void pcim_addr_resource_release(struct device *dev, void *resource_raw) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct pcim_addr_devres *res = resource_raw; + + switch (res->type) { + case PCIM_ADDR_DEVRES_TYPE_REGION: + __pcim_release_region(pdev, res->bar); + break; + case PCIM_ADDR_DEVRES_TYPE_REGION_MAPPING: + pci_iounmap(pdev, res->baseaddr); + __pcim_release_region(pdev, res->bar); + break; + case PCIM_ADDR_DEVRES_TYPE_MAPPING: + pci_iounmap(pdev, res->baseaddr); + break; + case PCIM_ADDR_DEVRES_TYPE_REGION_RANGE_MAPPING: + pci_iounmap(pdev, res->baseaddr); + __pcim_release_region_range(pdev, res->bar, res->offset, res->len); + break; + default: + break; + } +} + +static struct pcim_addr_devres *pcim_addr_devres_alloc(struct pci_dev *pdev) +{ + struct pcim_addr_devres *res; + + res = devres_alloc_node(pcim_addr_resource_release, sizeof(*res), + GFP_KERNEL, dev_to_node(&pdev->dev)); + if (res) + pcim_addr_devres_clear(res); + return res; +} + +/* Just for consistency and readability. */ +static inline void pcim_addr_devres_free(struct pcim_addr_devres *res) +{ + devres_free(res); +} + +/* + * Used to identify a resource in devres_*() functions. + */ +static int pcim_addr_resources_match(struct device *dev, void *a_raw, void *b_raw) +{ + struct pcim_addr_devres *a, *b; + + a = a_raw; + b = b_raw; + + (void)dev; /* unused. */ + + if (a->type != b->type) + return 0; + + switch (a->type) { + case PCIM_ADDR_DEVRES_TYPE_REGION: + case PCIM_ADDR_DEVRES_TYPE_REGION_MAPPING: + return a->bar == b->bar; + case PCIM_ADDR_DEVRES_TYPE_MAPPING: + return a->baseaddr == b->baseaddr; + case PCIM_ADDR_DEVRES_TYPE_REGION_RANGE_MAPPING: + return a->bar == b->bar && + a->offset == b->offset && a->len == b->len; + default: + break; + } + + return 0; +} static void devm_pci_unmap_iospace(struct device *dev, void *ptr) { @@ -92,8 +305,8 @@ EXPORT_SYMBOL(devm_pci_remap_cfgspace); * * 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:: + * Returns a pointer to the remapped memory or an IOMEM_ERR_PTR() encoded error + * code on failure. Usage example:: * * res = platform_get_resource(pdev, IORESOURCE_MEM, 0); * base = devm_pci_remap_cfg_resource(&pdev->dev, res); @@ -341,15 +554,80 @@ void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr) tbl[i] = NULL; return; } - WARN_ON(1); } EXPORT_SYMBOL(pcim_iounmap); +/** + * pcim_iomap_region - Request and iomap a PCI BAR + * @pdev: PCI device to map IO resources for + * @bar: Index of a BAR to map + * @name: Name associated with the request + * + * Returns __iomem pointer on success, an IOMEM_ERR_PTR on failure. + * + * Mapping and region will get automatically released on driver detach. If + * desired, release manually only with pcim_iounmap_region(). + */ +void __iomem *pcim_iomap_region(struct pci_dev *pdev, int bar, const char *name) +{ + int ret = 0; + struct pcim_addr_devres *res; + + res = pcim_addr_devres_alloc(pdev); + if (!res) + return IOMEM_ERR_PTR(-ENOMEM); + + res->type = PCIM_ADDR_DEVRES_TYPE_REGION_MAPPING; + res->bar = bar; + + ret = __pcim_request_region(pdev, bar, name, 0); + if (ret != 0) + goto err_region; + + res->baseaddr = pci_iomap(pdev, bar, 0); + if (!res->baseaddr) { + ret = -EINVAL; + goto err_iomap; + } + + devres_add(&pdev->dev, res); + return res->baseaddr; + +err_iomap: + __pcim_release_region(pdev, bar); +err_region: + pcim_addr_devres_free(res); + + return IOMEM_ERR_PTR(ret); +} +EXPORT_SYMBOL(pcim_iomap_region); + +/** + * pcim_iounmap_region - Unmap and release a PCI BAR + * @pdev: PCI device to operate on + * @bar: Index of BAR to unmap and release + * + * Unmap a BAR and release its region manually. Only pass BARs that were + * previously mapped by pcim_iomap_region(). + */ +void pcim_iounmap_region(struct pci_dev *pdev, int bar) +{ + struct pcim_addr_devres res_searched; + + pcim_addr_devres_clear(&res_searched); + res_searched.type = PCIM_ADDR_DEVRES_TYPE_REGION_MAPPING; + res_searched.bar = bar; + + devres_release(&pdev->dev, pcim_addr_resource_release, + pcim_addr_resources_match, &res_searched); +} +EXPORT_SYMBOL(pcim_iounmap_region); + /** * 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 + * @name: Name associated with the requests * * Request and iomap regions specified by @mask. */ @@ -402,7 +680,7 @@ EXPORT_SYMBOL(pcim_iomap_regions); * pcim_iomap_regions_request_all - Request all BARs and iomap specified ones * @pdev: PCI device to map IO resources for * @mask: Mask of BARs to iomap - * @name: Name used when requesting regions + * @name: Name associated with the requests * * Request all PCI BARs and iomap regions specified by @mask. */ @@ -448,3 +726,196 @@ void pcim_iounmap_regions(struct pci_dev *pdev, int mask) } } EXPORT_SYMBOL(pcim_iounmap_regions); + +static int _pcim_request_region(struct pci_dev *pdev, int bar, const char *name, + int request_flags) +{ + int ret = 0; + struct pcim_addr_devres *res; + + res = pcim_addr_devres_alloc(pdev); + if (!res) + return -ENOMEM; + res->type = PCIM_ADDR_DEVRES_TYPE_REGION; + res->bar = bar; + + ret = __pcim_request_region(pdev, bar, name, request_flags); + if (ret != 0) { + pcim_addr_devres_free(res); + return ret; + } + + devres_add(&pdev->dev, res); + return 0; +} + +/** + * pcim_request_region - Request a PCI BAR + * @pdev: PCI device to requestion region for + * @bar: Index of BAR to request + * @name: Name associated with the request + * + * Returns: 0 on success, a negative error code on failure. + * + * Request region specified by @bar. + * + * The region will automatically be released on driver detach. If desired, + * release manually only with pcim_release_region(). + */ +int pcim_request_region(struct pci_dev *pdev, int bar, const char *name) +{ + return _pcim_request_region(pdev, bar, name, 0); +} +EXPORT_SYMBOL(pcim_request_region); + +/** + * pcim_release_region - Release a PCI BAR + * @pdev: PCI device to operate on + * @bar: Index of BAR to release + * + * Release a region manually that was previously requested by + * pcim_request_region(). + */ +void pcim_release_region(struct pci_dev *pdev, int bar) +{ + struct pcim_addr_devres res_searched; + + pcim_addr_devres_clear(&res_searched); + res_searched.type = PCIM_ADDR_DEVRES_TYPE_REGION; + res_searched.bar = bar; + + devres_release(&pdev->dev, pcim_addr_resource_release, + pcim_addr_resources_match, &res_searched); +} +EXPORT_SYMBOL(pcim_release_region); + +/** + * pcim_iomap_range - Create a ranged __iomap mapping within a PCI BAR + * @pdev: PCI device to map IO resources for + * @bar: Index of the BAR + * @offset: Offset from the begin of the BAR + * @len: Length in bytes for the mapping + * + * Returns: __iomem pointer on success, an IOMEM_ERR_PTR on failure. + * + * Creates a new IO-Mapping within the specified @bar, ranging from @offset to + * @offset + @len. + * + * The mapping will automatically get unmapped on driver detach. If desired, + * release manually only with pcim_iounmap(). + */ +void __iomem *pcim_iomap_range(struct pci_dev *pdev, int bar, + unsigned long offset, unsigned long len) +{ + void __iomem *mapping; + struct pcim_addr_devres *res; + + res = pcim_addr_devres_alloc(pdev); + if (!res) + return IOMEM_ERR_PTR(-ENOMEM); + + mapping = pci_iomap_range(pdev, bar, offset, len); + if (!mapping) { + pcim_addr_devres_free(res); + return IOMEM_ERR_PTR(-EINVAL); + } + + res->type = PCIM_ADDR_DEVRES_TYPE_MAPPING; + res->baseaddr = mapping; + + /* + * Ranged mappings don't get added to the legacy-table, since the table + * only ever keeps track of whole BARs. + */ + + devres_add(&pdev->dev, res); + return mapping; +} +EXPORT_SYMBOL(pcim_iomap_range); + +/** + * pcim_iomap_region_range - Request and map a range within a PCI BAR + * @pdev: PCI device to map IO resources for + * @bar: Index of BAR to request within + * @offset: Offset from the begin of the BAR + * @len: Length in bytes for the mapping + * @name: Name associated with the request + * + * Returns: __iomem pointer on success, an IOMEM_ERR_PTR on failure. + * + * Request region with a range specified by @offset and @len within @bar and + * iomap it. + * + * The region will automatically be released and the mapping be unmapped on + * driver detach. If desired, release manually only with + * pcim_iounmap_region_range(). + * + * You probably should only use this function if you explicitly do not want to + * request the entire BAR. For most use-cases, combining pcim_request_region() + * and pcim_iomap_range() should be sufficient. + */ +void __iomem *pcim_iomap_region_range(struct pci_dev *pdev, int bar, + unsigned long offset, unsigned long len, const char *name) +{ + int ret = 0; + struct pcim_addr_devres *res; + + res = pcim_addr_devres_alloc(pdev); + if (!res) + return IOMEM_ERR_PTR(-ENOMEM); + + res->type = PCIM_ADDR_DEVRES_TYPE_REGION_RANGE_MAPPING; + res->bar = bar; + res->offset = offset; + res->len = len; + + ret = __pcim_request_region_range(pdev, bar, offset, len, name, 0); + if (ret != 0) + goto err_region; + + res->baseaddr = pci_iomap_range(pdev, bar, offset, len); + if (!res->baseaddr) { + ret = -EINVAL; + goto err_iomap; + } + + devres_add(&pdev->dev, res); + return res->baseaddr; + +err_iomap: + __pcim_release_region_range(pdev, bar, offset, len); +err_region: + pcim_addr_devres_free(res); + + return IOMEM_ERR_PTR(ret); +} +EXPORT_SYMBOL(pcim_iomap_region_range); + +/** + * pcim_iounmap_region_range - Unmap and release a range within a PCI BAR + * @pdev: PCI device to operate on + * @bar: Index of BAR containing the range + * @offset: Offset from the begin of the BAR + * @len: Length in bytes for the mapping + * + * Unmaps and releases a memory area within the specified PCI BAR. + * + * This function may not be used to free only part of a range. Only use this + * function with the exact parameters you previously used successfully in + * pcim_iomap_region_range(). + */ +void pcim_iounmap_region_range(struct pci_dev *pdev, int bar, + unsigned long offset, unsigned long len) +{ + struct pcim_addr_devres res_searched; + pcim_addr_devres_clear(&res_searched); + + res_searched.type = PCIM_ADDR_DEVRES_TYPE_REGION_RANGE_MAPPING; + res_searched.bar = bar; + res_searched.offset = offset; + res_searched.len = len; + + devres_release(&pdev->dev, pcim_addr_resource_release, + pcim_addr_resources_match, &res_searched); +} +EXPORT_SYMBOL(pcim_iounmap_region_range); diff --git a/include/linux/pci.h b/include/linux/pci.h index 58a4c976c39b..1b45a4888703 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -2314,10 +2314,21 @@ static inline void pci_fixup_device(enum pci_fixup_pass pass, void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen); void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr); void __iomem * const *pcim_iomap_table(struct pci_dev *pdev); +void __iomem *pcim_iomap_region(struct pci_dev *pdev, int bar, const char *name); +void pcim_iounmap_region(struct pci_dev *pdev, int bar); int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name); int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask, const char *name); void pcim_iounmap_regions(struct pci_dev *pdev, int mask); +int pcim_request_region(struct pci_dev *pdev, int bar, const char *res_name); +void pcim_release_region(struct pci_dev *pdev, int bar); +void __iomem *pcim_iomap_range(struct pci_dev *pdev, int bar, + unsigned long offset, unsigned long len); +void __iomem *pcim_iomap_region_range(struct pci_dev *pdev, int bar, + unsigned long offset, unsigned long len, + const char *res_name); +void pcim_iounmap_region_range(struct pci_dev *pdev, int bar, + unsigned long offset, unsigned long len); extern int pci_pci_problems; #define PCIPCI_FAIL 1 /* No PCI PCI DMA */ From patchwork Mon Jan 15 14:46:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Stanner X-Patchwork-Id: 13519731 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6B22DC3DA79 for ; Mon, 15 Jan 2024 14:47:27 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C08D110E2F6; Mon, 15 Jan 2024 14:47:26 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by gabe.freedesktop.org (Postfix) with ESMTPS id 6DF9610E2F3 for ; Mon, 15 Jan 2024 14:47:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705330043; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=O/4sb7EtZnZXDAXsZ1TnbdCzfHG1Mac4zhgSYFspvX4=; b=N7QWPmfqscMdKseHlsZzZujL3UJ8p45Ldm6XJmSjSFurmxtMWhb9o3zRDVCXfhhVVcKuJM rQXn5GN5eiP2bzxVBPKW7jER1p4cSUAU5agW4tLsSUS5Js5KBBNqgUaKX0UU8p4pInEnoa qUFlsiYAGv52t1K/Cg3E3ncbxATAPXg= Received: from mail-yw1-f197.google.com (mail-yw1-f197.google.com [209.85.128.197]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-576-pjPhRWCvPLSkUGc3NXfYOw-1; Mon, 15 Jan 2024 09:47:17 -0500 X-MC-Unique: pjPhRWCvPLSkUGc3NXfYOw-1 Received: by mail-yw1-f197.google.com with SMTP id 00721157ae682-5ff4218b906so510097b3.1 for ; Mon, 15 Jan 2024 06:47:17 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705330037; x=1705934837; 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=O/4sb7EtZnZXDAXsZ1TnbdCzfHG1Mac4zhgSYFspvX4=; b=LnCPO5pwgq3Z42qXISx2Fook7Z+5iEI31nObHiG83KFyY6BuHvBocAe9sqlSk2tDOl NYO9SVUXxt1pUghcX2irUl8YzlabDXpeA6XPjFyYT6FbA7iMShvUi2EUUsCsTZ84SXUd 9VZ0b3/952K/J4yWR+qz0qqdfjPs6WOWHRUv3nfWbdzYOZ1rlfSSyk+sZrA3/aik4dkV mUp8MP2WDpHVR9tjP8HDHpc6ioOPAQ0xrvJG7W3ljZzrrJf2OOkhZuZpPR+jgipBm/+e mhupfMB6rTC5l0+c94spTpzqqmgRv3GvHXsEu7hrymTzlzE6eV0C7Zh7+ne4w0Ur0PRb 4nHA== X-Gm-Message-State: AOJu0YzGvnrJ8KQCVu3X1nnuolnS5V1G4AhzfLjx8FZx4AODoxS07tlM 6QS84deXaH4n+olBfURPOi2iVDDQC5A5bM3nk/iledZjgbHjbgM1SOxsxLulAo+1F5YI7XgOFWX fGage/wMkjzqyErBmO8+DBCUESs8umiJxDFvU X-Received: by 2002:a81:48d1:0:b0:5ed:95b2:ca48 with SMTP id v200-20020a8148d1000000b005ed95b2ca48mr4529244ywa.5.1705330036599; Mon, 15 Jan 2024 06:47:16 -0800 (PST) X-Google-Smtp-Source: AGHT+IEFikiSFust9uxkTlR/9heFIFjf1A0XIIogDr1MtKcQAB8Xk4Knp3bRyPE3d8Lwwogh0DxVXg== X-Received: by 2002:a81:48d1:0:b0:5ed:95b2:ca48 with SMTP id v200-20020a8148d1000000b005ed95b2ca48mr4529224ywa.5.1705330036207; Mon, 15 Jan 2024 06:47:16 -0800 (PST) Received: from pstanner-thinkpadt14sgen1.muc.redhat.com (nat-pool-muc-t.redhat.com. [149.14.88.26]) by smtp.gmail.com with ESMTPSA id ne13-20020a056214424d00b006815cf9a644sm1020720qvb.55.2024.01.15.06.47.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Jan 2024 06:47:15 -0800 (PST) From: Philipp Stanner To: Jonathan Corbet , Hans de Goede , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Daniel Vetter , Bjorn Helgaas , Philipp Stanner , Sam Ravnborg , dakr@redhat.com Subject: [PATCH 02/10] pci: deprecate iomap-table functions Date: Mon, 15 Jan 2024 15:46:13 +0100 Message-ID: <20240115144655.32046-4-pstanner@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240115144655.32046-2-pstanner@redhat.com> References: <20240115144655.32046-2-pstanner@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The old plural devres functions tie PCI's devres implementation to the iomap-table mechanism which unfortunately is not extensible. As the purlal functions are almost never used with more than one bit set in their bit-mask, deprecating them and encouraging users to use the new singular functions instead is reasonable. Furthermore, to make the implementation more consistent and extensible, the plural functions should use the singular functions. Add new wrapper to request / release all BARs. Make the plural functions call into the singular functions. Mark the plural functions as deprecated. Remove as much of the iomap-table-mechanism as possible. Add comments describing the path towards a cleaned-up API. Signed-off-by: Philipp Stanner --- drivers/pci/devres.c | 369 +++++++++++++++++++++++++++++++++---------- drivers/pci/pci.c | 20 +++ drivers/pci/pci.h | 5 + include/linux/pci.h | 2 + 4 files changed, 313 insertions(+), 83 deletions(-) diff --git a/drivers/pci/devres.c b/drivers/pci/devres.c index cc8c1501eb13..e221919ebbe2 100644 --- a/drivers/pci/devres.c +++ b/drivers/pci/devres.c @@ -4,15 +4,43 @@ #include "pci.h" /* - * PCI iomap devres + * On the state of PCI's devres implementation: + * + * The older devres API for PCI has two significant problems: + * + * 1. It is very strongly tied to the statically allocated mapping table in + * struct pcim_iomap_devres below. This is mostly solved in the sense of the + * pcim_ functions in this file providing things like ranged mapping by + * bypassing this table, wheras the functions that were present in the old + * API still enter the mapping addresses into the table for users of the old + * API. + * 2. The region-request-functions in pci.c do become managed IF the device has + * been enabled with pcim_enable_device() instead of pci_enable_device(). + * This resulted in the API becoming inconsistent: Some functions have an + * obviously managed counter-part (e.g., pci_iomap() <-> pcim_iomap()), + * whereas some don't and are never managed, while others don't and are + * _sometimes_ managed (e.g. pci_request_region()). + * Consequently, in the new API, region requests performed by the pcim_ + * functions are automatically cleaned up through the devres callback + * pcim_addr_resource_release(), while requests performed by + * pcim_enable_device() + pci_*region*() are automatically cleaned up + * through the for-loop in pcim_release(). + * + * TODO 1: + * Remove the legacy table entirely once all calls to pcim_iomap_table() in + * the kernel have been removed. + * + * TODO 2: + * Port everyone calling pcim_enable_device() + pci_*region*() to using the + * pcim_ functions. Then, remove all devres functionality from pci_*region*() + * functions and remove the associated cleanups described above in point #2. */ -#define PCIM_IOMAP_MAX PCI_STD_NUM_BARS /* * Legacy struct storing addresses to whole mapped bars. */ struct pcim_iomap_devres { - void __iomem *table[PCIM_IOMAP_MAX]; + void __iomem *table[PCI_STD_NUM_BARS]; }; enum pcim_addr_devres_type { @@ -381,6 +409,16 @@ static void pcim_release(struct device *gendev, void *res) struct pci_devres *this = res; int i; + /* + * This is legacy code. + * All regions requested by a pcim_ function do get released through + * pcim_addr_resource_release(). Thanks to the hybrid nature of the pci_ + * region-request functions, this for-loop has to release the regions + * if they have been requested by such a function. + * + * TODO: Remove this once all users of pcim_enable_device() PLUS + * pci-region-request-functions have been ported to pcim_ functions. + */ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) if (this->region_mask & (1 << i)) pci_release_region(dev, i); @@ -469,17 +507,16 @@ EXPORT_SYMBOL(pcim_pin_device); static void pcim_iomap_release(struct device *gendev, void *res) { - struct pci_dev *dev = to_pci_dev(gendev); - struct pcim_iomap_devres *this = res; - int i; - - for (i = 0; i < PCIM_IOMAP_MAX; i++) - if (this->table[i]) - pci_iounmap(dev, this->table[i]); + /* + * Do nothing. This is legacy code. + * + * Cleanup of the mappings is now done directly through the callbacks + * registered when creating them. + */ } /** - * pcim_iomap_table - access iomap allocation table + * pcim_iomap_table - access iomap allocation table (DEPRECATED) * @pdev: PCI device to access iomap table for * * Access iomap allocation table for @dev. If iomap table doesn't @@ -490,6 +527,11 @@ static void pcim_iomap_release(struct device *gendev, void *res) * This function might sleep when the table is first allocated but can * be safely called without context and guaranteed to succeed once * allocated. + * + * This function is DEPRECATED. Do not use it in new code. + * Instead, obtain a mapping's address directly from one of the pcim_* mapping + * functions. For example: + * void __iomem *mappy = pcim_iomap(pdev, barnr, length); */ void __iomem * const *pcim_iomap_table(struct pci_dev *pdev) { @@ -508,27 +550,109 @@ void __iomem * const *pcim_iomap_table(struct pci_dev *pdev) } EXPORT_SYMBOL(pcim_iomap_table); +/* + * Fill the legacy mapping-table, so that drivers using the old API + * can still get a BAR's mapping address through pcim_iomap_table(). + */ +static int pcim_add_mapping_to_legacy_table(struct pci_dev *pdev, + void __iomem *mapping, short bar) +{ + void __iomem **legacy_iomap_table; + + if (bar >= PCI_STD_NUM_BARS) + return -EINVAL; + + legacy_iomap_table = (void __iomem **)pcim_iomap_table(pdev); + if (!legacy_iomap_table) + return -ENOMEM; + + /* The legacy mechanism doesn't allow for duplicate mappings. */ + WARN_ON(legacy_iomap_table[bar]); + + legacy_iomap_table[bar] = mapping; + + return 0; +} + +/* + * Removes a mapping. The table only contains whole-bar-mappings, so this will + * never interfere with ranged mappings. + */ +static void pcim_remove_mapping_from_legacy_table(struct pci_dev *pdev, + void __iomem *addr) +{ + short bar; + void __iomem **legacy_iomap_table; + + legacy_iomap_table = (void __iomem **)pcim_iomap_table(pdev); + if (!legacy_iomap_table) + return; + + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { + if (legacy_iomap_table[bar] == addr) { + legacy_iomap_table[bar] = NULL; + return; + } + } +} + +/* + * The same as pcim_remove_mapping_from_legacy_table(), but identifies the + * mapping by its BAR index. + */ +static void pcim_remove_bar_from_legacy_table(struct pci_dev *pdev, short bar) +{ + void __iomem **legacy_iomap_table; + + if (bar >= PCI_STD_NUM_BARS) + return; + + legacy_iomap_table = (void __iomem **)pcim_iomap_table(pdev); + if (!legacy_iomap_table) + return; + + legacy_iomap_table[bar] = NULL; +} + /** * 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. + * Returns __iomem pointer on success, NULL on failure. + * + * Managed pci_iomap(). Map is automatically unmapped on driver detach. If + * desired, unmap manually only with pcim_iounmap(). + * + * This SHOULD only be used once per BAR. */ void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen) { - void __iomem **tbl; - - BUG_ON(bar >= PCIM_IOMAP_MAX); + void __iomem *mapping; + struct pcim_addr_devres *res; - tbl = (void __iomem **)pcim_iomap_table(pdev); - if (!tbl || tbl[bar]) /* duplicate mappings not allowed */ + res = pcim_addr_devres_alloc(pdev); + if (!res) return NULL; + res->type = PCIM_ADDR_DEVRES_TYPE_MAPPING; - tbl[bar] = pci_iomap(pdev, bar, maxlen); - return tbl[bar]; + mapping = pci_iomap(pdev, bar, maxlen); + if (!mapping) + goto err_iomap; + res->baseaddr = mapping; + + if (pcim_add_mapping_to_legacy_table(pdev, mapping, bar) != 0) + goto err_table; + + devres_add(&pdev->dev, res); + return mapping; + +err_table: + pci_iounmap(pdev, mapping); +err_iomap: + pcim_addr_devres_free(res); + return NULL; } EXPORT_SYMBOL(pcim_iomap); @@ -537,23 +661,24 @@ EXPORT_SYMBOL(pcim_iomap); * @pdev: PCI device to iounmap for * @addr: Address to unmap * - * Managed pci_iounmap(). @addr must have been mapped using pcim_iomap(). + * Managed pci_iounmap(). @addr must have been mapped using pcim_iomap() or + * pcim_iomap_range(). */ void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr) { - void __iomem **tbl; - int i; + struct pcim_addr_devres res_searched; - pci_iounmap(pdev, addr); + pcim_addr_devres_clear(&res_searched); + res_searched.type = PCIM_ADDR_DEVRES_TYPE_MAPPING; + res_searched.baseaddr = addr; - tbl = (void __iomem **)pcim_iomap_table(pdev); - BUG_ON(!tbl); + if (devres_release(&pdev->dev, pcim_addr_resource_release, + pcim_addr_resources_match, &res_searched) != 0) { + /* Doesn't exist. User passed nonsense. */ + return; + } - for (i = 0; i < PCIM_IOMAP_MAX; i++) - if (tbl[i] == addr) { - tbl[i] = NULL; - return; - } + pcim_remove_mapping_from_legacy_table(pdev, addr); } EXPORT_SYMBOL(pcim_iounmap); @@ -623,106 +748,184 @@ void pcim_iounmap_region(struct pci_dev *pdev, int bar) } EXPORT_SYMBOL(pcim_iounmap_region); +static inline bool mask_contains_bar(int mask, int bar) +{ + return mask & (1 << bar); +} + /** - * pcim_iomap_regions - Request and iomap PCI BARs + * pcim_iomap_regions - Request and iomap PCI BARs (DEPRECATED) * @pdev: PCI device to map IO resources for * @mask: Mask of BARs to request and iomap * @name: Name associated with the requests * + * Returns 0 on success, negative error code on failure. + * * Request and iomap regions specified by @mask. + * + * This function is DEPRECATED. Don't use it in new code. + * Use pcim_iomap_region() instead. */ int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name) { - void __iomem * const *iomap; - int i, rc; + int ret = -1; + short bar; + void __iomem *mapping; - iomap = pcim_iomap_table(pdev); - if (!iomap) - return -ENOMEM; + for (bar = 0; bar < DEVICE_COUNT_RESOURCE; bar++) { + if (!mask_contains_bar(mask, bar)) + continue; - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { - unsigned long len; + mapping = pcim_iomap_region(pdev, bar, name); + if (IS_ERR(mapping)) { + ret = PTR_ERR(mapping); + goto err; + } + ret = pcim_add_mapping_to_legacy_table(pdev, mapping, bar); + if (ret != 0) + goto err; + } - if (!(mask & (1 << i))) - continue; + return 0; - rc = -EINVAL; - len = pci_resource_len(pdev, i); - if (!len) - goto err_inval; + err: + while (--bar >= 0) { + pcim_iounmap_region(pdev, bar); + pcim_remove_bar_from_legacy_table(pdev, bar); + } - rc = pci_request_region(pdev, i, name); - if (rc) - goto err_inval; + return ret; +} +EXPORT_SYMBOL(pcim_iomap_regions); - rc = -ENOMEM; - if (!pcim_iomap(pdev, i, 0)) - goto err_region; +/** + * pcim_release_all_regions - Release all regions of a PCI-device + * @pdev: the PCI device + * + * Returns 0 on success, negative error code on failure. + * + * Will release all regions previously requested through pcim_request_region() + * or pcim_request_all_regions(). + * + * Can be called from any context, i.e., not necessarily as a counterpart to + * pcim_request_all_regions(). + */ +void pcim_release_all_regions(struct pci_dev *pdev) +{ + short bar; + + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) + pcim_release_region(pdev, bar); +} +EXPORT_SYMBOL(pcim_release_all_regions); + +/** + * pcim_request_all_regions - Request all regions + * @pdev: PCI device to map IO resources for + * @name: name associated with the request + * + * Requested regions will automatically be released at driver detach. If desired, + * release individual regions with pcim_release_region() or all of them at once + * with pcim_release_all_regions(). + */ +int pcim_request_all_regions(struct pci_dev *pdev, const char *name) +{ + int ret; + short bar; + + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { + ret = pcim_request_region(pdev, bar, name); + if (ret != 0) + goto err; } return 0; - err_region: - pci_release_region(pdev, i); - err_inval: - while (--i >= 0) { - if (!(mask & (1 << i))) - continue; - pcim_iounmap(pdev, iomap[i]); - pci_release_region(pdev, i); - } +err: + pcim_release_all_regions(pdev); - return rc; + return ret; } -EXPORT_SYMBOL(pcim_iomap_regions); +EXPORT_SYMBOL(pcim_request_all_regions); /** - * pcim_iomap_regions_request_all - Request all BARs and iomap specified ones + * pcim_iomap_regions_request_all - Request all BARs and iomap specified ones (DEPRECATED) * @pdev: PCI device to map IO resources for * @mask: Mask of BARs to iomap * @name: Name associated with the requests * + * Returns 0 on success, negative error code on failure. + * * Request all PCI BARs and iomap regions specified by @mask. + * + * To release these resources manually, call pcim_release_region() for the + * regions and pcim_iounmap() for the mappings. + * + * This function is DEPRECATED. Don't use it in new code. + * Use pcim_request_all_regions() + pcim_iomap*() instead. */ int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask, const char *name) { - int request_mask = ((1 << 6) - 1) & ~mask; - int rc; + short bar; + int ret = -1; + void __iomem **legacy_iomap_table; - rc = pci_request_selected_regions(pdev, request_mask, name); - if (rc) - return rc; + ret = pcim_request_all_regions(pdev, name); + if (ret != 0) + return ret; - rc = pcim_iomap_regions(pdev, mask, name); - if (rc) - pci_release_selected_regions(pdev, request_mask); - return rc; + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { + if (!mask_contains_bar(mask, bar)) + continue; + if (!pcim_iomap(pdev, bar, 0)) + goto err; + } + + return 0; + +err: + /* + * Here it gets tricky: pcim_iomap() above has most likely + * failed because it got an OOM when trying to create the + * legacy-table. + * We check here if that has happened. If not, pcim_iomap() + * must have failed because of EINVAL. + */ + legacy_iomap_table = (void __iomem **)pcim_iomap_table(pdev); + if (!legacy_iomap_table) + ret = -ENOMEM; + else + ret = -EINVAL; + + while (--bar >= 0) + pcim_iounmap(pdev, legacy_iomap_table[bar]); + + pcim_release_all_regions(pdev); + + return ret; } EXPORT_SYMBOL(pcim_iomap_regions_request_all); /** - * pcim_iounmap_regions - Unmap and release PCI BARs + * pcim_iounmap_regions - Unmap and release PCI BARs (DEPRECATED) * @pdev: PCI device to map IO resources for * @mask: Mask of BARs to unmap and release * * Unmap and release regions specified by @mask. + * + * This function is DEPRECATED. Don't use it in new code. */ void pcim_iounmap_regions(struct pci_dev *pdev, int mask) { - void __iomem * const *iomap; - int i; - - iomap = pcim_iomap_table(pdev); - if (!iomap) - return; + short bar; - for (i = 0; i < PCIM_IOMAP_MAX; i++) { - if (!(mask & (1 << i))) + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { + if (!mask_contains_bar(mask, bar)) continue; - pcim_iounmap(pdev, iomap[i]); - pci_release_region(pdev, i); + pcim_iounmap_region(pdev, bar); + pcim_remove_bar_from_legacy_table(pdev, bar); } } EXPORT_SYMBOL(pcim_iounmap_regions); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index bf5f9c3a1908..2899df77a285 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3884,6 +3884,16 @@ void pci_release_region(struct pci_dev *pdev, int bar) release_mem_region(pci_resource_start(pdev, bar), pci_resource_len(pdev, bar)); + /* + * This devres utility makes this function sometimes managed + * (when pcim_enable_device() has been called before). + * This is bad because it conflicts with the pcim_ functions being + * exclusively responsible for managed pci. Its "sometimes yes, sometimes + * no" nature can cause bugs. + * + * TODO: Remove this once all users that use pcim_enable_device() PLUS + * a region request function have been ported to using pcim_ functions. + */ dr = find_pci_dr(pdev); if (dr) dr->region_mask &= ~(1 << bar); @@ -3928,6 +3938,16 @@ static int __pci_request_region(struct pci_dev *pdev, int bar, goto err_out; } + /* + * This devres utility makes this function sometimes managed + * (when pcim_enable_device() has been called before). + * This is bad because it conflicts with the pcim_ functions being + * exclusively responsible for managed pci. Its "sometimes yes, sometimes + * no" nature can cause bugs. + * + * TODO: Remove this once all users that use pcim_enable_device() PLUS + * a region request function have been ported to using pcim_ functions. + */ dr = find_pci_dr(pdev); if (dr) dr->region_mask |= 1 << bar; diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index de6d61d1e07f..4d4bcc2d850f 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -814,6 +814,11 @@ struct pci_devres { unsigned int orig_intx:1; unsigned int restore_intx:1; unsigned int mwi:1; + + /* + * TODO: remove the region_mask once everyone calling + * pcim_enable_device() + pci_*region*() is ported to pcim_ functions. + */ u32 region_mask; }; diff --git a/include/linux/pci.h b/include/linux/pci.h index 1b45a4888703..3dcd8a5e10b5 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -2322,6 +2322,8 @@ int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask, void pcim_iounmap_regions(struct pci_dev *pdev, int mask); int pcim_request_region(struct pci_dev *pdev, int bar, const char *res_name); void pcim_release_region(struct pci_dev *pdev, int bar); +void pcim_release_all_regions(struct pci_dev *pdev); +int pcim_request_all_regions(struct pci_dev *pdev, const char *name); void __iomem *pcim_iomap_range(struct pci_dev *pdev, int bar, unsigned long offset, unsigned long len); void __iomem *pcim_iomap_region_range(struct pci_dev *pdev, int bar, From patchwork Mon Jan 15 14:46:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Stanner X-Patchwork-Id: 13519730 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id DE2B9C3DA79 for ; Mon, 15 Jan 2024 14:47:23 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 20D8D10E2F2; Mon, 15 Jan 2024 14:47:23 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by gabe.freedesktop.org (Postfix) with ESMTPS id 4EF6910E2EF for ; Mon, 15 Jan 2024 14:47:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705330040; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ppwvkSEuixS2SG0TbgxgzQKgr6fgJxktZuxIJo/ERYU=; b=GS5Ls6bafb3Oz2f4IECeL6IhLuVLUcQKWWzBTRkEF07CeYh27Sv9wWOj+BrUQKfUSsKf5M 4e4kwgrmUjfc8AfO+aJSMU8eOEdTiI+eQplvZLTKsdK9OKbkLjLw/u8p8nReg0FMRdso8I fBNg+jHsKaAt5ziatejuGggW7bRvnWY= Received: from mail-qk1-f197.google.com (mail-qk1-f197.google.com [209.85.222.197]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-175-VuEpIAX-Od2B0cmiByEtjg-1; Mon, 15 Jan 2024 09:47:19 -0500 X-MC-Unique: VuEpIAX-Od2B0cmiByEtjg-1 Received: by mail-qk1-f197.google.com with SMTP id af79cd13be357-78130939196so202114785a.1 for ; Mon, 15 Jan 2024 06:47:19 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705330039; x=1705934839; 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=ppwvkSEuixS2SG0TbgxgzQKgr6fgJxktZuxIJo/ERYU=; b=N53tN7jVGIp5/UN7jJQCDeWiYuMaEVsGc0TvFuVF5p88UcVza7fsLsBVyrM0qc75bm cI3EQeDIeEDoKaT7NwpGavDPVTRc9vGX9XgyffmBdFecy4Cw7wY0ULYZu6wwr2oc8BWU 6bazRUwxU7uu2eCKR4z39csNFNaSHs+y2Bgm+nFnh7UfSmZqGqgrfXygCXoPUFoi+B70 cxcp3ZTttcU8gg8sUyDT+pcZvtgBoZVWylkXb7r+n9yfNiPxC0OEbbrk5pZSZFYljAZ7 eP9525icZTd6Lin8ud5oxfCy+E9tfIa91h9aKlSX0UtpMSYiZUy3yYbq9zOr9BJ/iu9m sL8Q== X-Gm-Message-State: AOJu0Yzd+jSQsyLlQfd0as0ew7DZBMwCKGeoXpwK+velwsRscDduI9c6 Y9pm9HLTm2OO7p44u/5TkE6StfX5gDgbPLjSyJYKKyuLgm5myJh7DNPisV7vlkwONzAqPaec6m3 JRy9cb6H5lqT6n2oYbXZxuCPQhKnqCkbdKZR2 X-Received: by 2002:a05:6214:4109:b0:681:3016:2ca6 with SMTP id kc9-20020a056214410900b0068130162ca6mr10705061qvb.6.1705330038831; Mon, 15 Jan 2024 06:47:18 -0800 (PST) X-Google-Smtp-Source: AGHT+IHUSOs/arWl9oiDpq0rWblAC6qIoaPYTdyyYZ8nxT4UMvv5M5B4KQKyYzih3gp3DMQa57ou9A== X-Received: by 2002:a05:6214:4109:b0:681:3016:2ca6 with SMTP id kc9-20020a056214410900b0068130162ca6mr10705033qvb.6.1705330038467; Mon, 15 Jan 2024 06:47:18 -0800 (PST) Received: from pstanner-thinkpadt14sgen1.muc.redhat.com (nat-pool-muc-t.redhat.com. [149.14.88.26]) by smtp.gmail.com with ESMTPSA id ne13-20020a056214424d00b006815cf9a644sm1020720qvb.55.2024.01.15.06.47.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Jan 2024 06:47:18 -0800 (PST) From: Philipp Stanner To: Jonathan Corbet , Hans de Goede , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Daniel Vetter , Bjorn Helgaas , Philipp Stanner , Sam Ravnborg , dakr@redhat.com Subject: [PATCH 03/10] pci: warn users about complicated devres nature Date: Mon, 15 Jan 2024 15:46:14 +0100 Message-ID: <20240115144655.32046-5-pstanner@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240115144655.32046-2-pstanner@redhat.com> References: <20240115144655.32046-2-pstanner@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The PCI region-request functions become managed functions when pcim_enable_device() has been called previously instead of pci_enable_device(). This has already caused bugs by confusing users, who came to believe that all pci functions, such as pci_iomap(), suddenly are managed that way. This is not the case. Add comments to the relevant functions' docstrings that warn users about this behavior. Signed-off-by: Philipp Stanner --- drivers/pci/iomap.c | 18 ++++++++++++++ drivers/pci/pci.c | 60 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/drivers/pci/iomap.c b/drivers/pci/iomap.c index b7faf22ec8f5..0b7fcc2f7a49 100644 --- a/drivers/pci/iomap.c +++ b/drivers/pci/iomap.c @@ -23,6 +23,11 @@ * * @maxlen specifies the maximum length to map. If you want to get access to * the complete BAR from offset to the end, pass %0 here. + * + * NOTE: + * This function is never managed, even if you initialized with + * pcim_enable_device(). + * If you need automatic cleanup, use pcim_iomap_range(). * */ void __iomem *pci_iomap_range(struct pci_dev *dev, int bar, @@ -63,6 +68,10 @@ EXPORT_SYMBOL(pci_iomap_range); * * @maxlen specifies the maximum length to map. If you want to get access to * the complete BAR from offset to the end, pass %0 here. + * + * NOTE: + * This function is never managed, even if you initialized with + * pcim_enable_device(). * */ void __iomem *pci_iomap_wc_range(struct pci_dev *dev, int bar, @@ -106,6 +115,11 @@ EXPORT_SYMBOL_GPL(pci_iomap_wc_range); * * @maxlen specifies the maximum length to map. If you want to get access to * the complete BAR without checking for its length first, pass %0 here. + * + * NOTE: + * This function is never managed, even if you initialized with + * pcim_enable_device(). + * If you need automatic cleanup, use pcim_iomap(). * */ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) { @@ -127,6 +141,10 @@ EXPORT_SYMBOL(pci_iomap); * * @maxlen specifies the maximum length to map. If you want to get access to * the complete BAR without checking for its length first, pass %0 here. + * + * NOTE: + * This function is never managed, even if you initialized with + * pcim_enable_device(). * */ void __iomem *pci_iomap_wc(struct pci_dev *dev, int bar, unsigned long maxlen) { diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 2899df77a285..7ca860acf351 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3907,6 +3907,8 @@ EXPORT_SYMBOL(pci_release_region); * @res_name: Name to be associated with resource. * @exclusive: whether the region access is exclusive or not * + * Returns: 0 on success, negative error code on failure. + * * Mark the PCI region associated with PCI device @pdev BAR @bar as * being reserved by owner @res_name. Do not access any * address inside the PCI regions unless this call returns @@ -3918,6 +3920,13 @@ EXPORT_SYMBOL(pci_release_region); * * Returns 0 on success, or %EBUSY on error. A warning * message is also printed on failure. + * + * NOTE: + * This is a "hybrid" function: Its normally unmanaged, but becomes managed + * when pcim_enable_device() has been called in advance. + * This hybrid feature is DEPRECATED! If you need to implement a new pci + * function that does automatic cleanup, write a new pcim_* function that uses + * devres directly. */ static int __pci_request_region(struct pci_dev *pdev, int bar, const char *res_name, int exclusive) @@ -3966,6 +3975,8 @@ static int __pci_request_region(struct pci_dev *pdev, int bar, * @bar: BAR to be reserved * @res_name: Name to be associated with resource * + * Returns: 0 on success, negative error code on failure. + * * Mark the PCI region associated with PCI device @pdev BAR @bar as * being reserved by owner @res_name. Do not access any * address inside the PCI regions unless this call returns @@ -3973,6 +3984,12 @@ static int __pci_request_region(struct pci_dev *pdev, int bar, * * Returns 0 on success, or %EBUSY on error. A warning * message is also printed on failure. + * + * NOTE: + * This is a "hybrid" function: Its normally unmanaged, but becomes managed + * when pcim_enable_device() has been called in advance. + * This hybrid feature is DEPRECATED! If you want managed cleanup, use the + * pcim_* functions instead. */ int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name) { @@ -3998,6 +4015,13 @@ void pci_release_selected_regions(struct pci_dev *pdev, int bars) } EXPORT_SYMBOL(pci_release_selected_regions); +/* + * NOTE: + * This is a "hybrid" function: Its normally unmanaged, but becomes managed + * when pcim_enable_device() has been called in advance. + * This hybrid feature is DEPRECATED! If you want managed cleanup, use the + * pcim_* functions instead. + */ static int __pci_request_selected_regions(struct pci_dev *pdev, int bars, const char *res_name, int excl) { @@ -4023,6 +4047,14 @@ static int __pci_request_selected_regions(struct pci_dev *pdev, int bars, * @pdev: PCI device whose resources are to be reserved * @bars: Bitmask of BARs to be requested * @res_name: Name to be associated with resource + * + * Returns: 0 on success, negative error code on failure. + * + * NOTE: + * This is a "hybrid" function: Its normally unmanaged, but becomes managed + * when pcim_enable_device() has been called in advance. + * This hybrid feature is DEPRECATED! If you want managed cleanup, use the + * pcim_* functions instead. */ int pci_request_selected_regions(struct pci_dev *pdev, int bars, const char *res_name) @@ -4031,6 +4063,20 @@ int pci_request_selected_regions(struct pci_dev *pdev, int bars, } EXPORT_SYMBOL(pci_request_selected_regions); +/** + * pci_request_selected_regions_exclusive - Request regions exclusively + * @pdev: PCI device to request regions from + * @bars: bit mask of bars to request + * @res_name: name to be associated with the requests + * + * Returns: 0 on success, negative error code on failure. + * + * NOTE: + * This is a "hybrid" function: Its normally unmanaged, but becomes managed + * when pcim_enable_device() has been called in advance. + * This hybrid feature is DEPRECATED! If you want managed cleanup, use the + * pcim_* functions instead. + */ int pci_request_selected_regions_exclusive(struct pci_dev *pdev, int bars, const char *res_name) { @@ -4048,7 +4094,6 @@ EXPORT_SYMBOL(pci_request_selected_regions_exclusive); * successful call to pci_request_regions(). Call this function only * after all use of the PCI regions has ceased. */ - void pci_release_regions(struct pci_dev *pdev) { pci_release_selected_regions(pdev, (1 << PCI_STD_NUM_BARS) - 1); @@ -4080,6 +4125,8 @@ EXPORT_SYMBOL(pci_request_regions); * @pdev: PCI device whose resources are to be reserved * @res_name: Name to be associated with resource. * + * Returns: 0 on success, negative error code on failure. + * * Mark all PCI regions associated with PCI device @pdev as being reserved * by owner @res_name. Do not access any address inside the PCI regions * unless this call returns successfully. @@ -4089,6 +4136,12 @@ EXPORT_SYMBOL(pci_request_regions); * * Returns 0 on success, or %EBUSY on error. A warning message is also * printed on failure. + * + * NOTE: + * This is a "hybrid" function: Its normally unmanaged, but becomes managed + * when pcim_enable_device() has been called in advance. + * This hybrid feature is DEPRECATED! If you want managed cleanup, use the + * pcim_* functions instead. */ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name) { @@ -4420,6 +4473,11 @@ void pci_disable_parity(struct pci_dev *dev) * @enable: boolean: whether to enable or disable PCI INTx * * Enables/disables PCI INTx for device @pdev + * + * NOTE: + * This is a "hybrid" function: Its normally unmanaged, but becomes managed + * when pcim_enable_device() has been called in advance. + * This hybrid feature is DEPRECATED! */ void pci_intx(struct pci_dev *pdev, int enable) { From patchwork Mon Jan 15 14:46:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Stanner X-Patchwork-Id: 13519732 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D8A55C4707B for ; Mon, 15 Jan 2024 14:47:28 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D4A6310E2F4; Mon, 15 Jan 2024 14:47:26 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by gabe.freedesktop.org (Postfix) with ESMTPS id CAB3410E2F3 for ; Mon, 15 Jan 2024 14:47:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705330043; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=GuPy6o0xdtswTFzGt//PWEkxlEqwBN5Ui7YfUNE5A+E=; b=HrBqZFtSn3k49PzGLQRNR3A7eL5g7Ils2gB0TJH2JaKi+3MFKfsp1uXbyva+4pInFiO14j IlfvnJUqrYYtXiJiUS/5DhaqLT1px5+19Em1fi8hUuRaqZ0cVLlut8t7U3uFV1CDnNt/Gk yZHdy74Ud66bquI/afvqb5Yhpwi4smo= Received: from mail-vk1-f198.google.com (mail-vk1-f198.google.com [209.85.221.198]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-377-BdHxRmkxNEq1dzUWWKbFPw-1; Mon, 15 Jan 2024 09:47:21 -0500 X-MC-Unique: BdHxRmkxNEq1dzUWWKbFPw-1 Received: by mail-vk1-f198.google.com with SMTP id 71dfb90a1353d-4b721a956cdso200375e0c.1 for ; Mon, 15 Jan 2024 06:47:21 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705330041; x=1705934841; 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=GuPy6o0xdtswTFzGt//PWEkxlEqwBN5Ui7YfUNE5A+E=; b=Y4+IwvhKxFw+6rKWNd+mjY9pxOk4AZrqnbpc4F/wdjPZ7oKM3elpD4b9sSl3PdIy1W oYBWCOl6bsd/Fg6WVBFGOzlaVyCIvTs927/o6LO2bXTIJCMZVaT7k5KrW3TYWvtJ/fXy eE8N3qwAmaGnYiWtMBZBMRVE1A5tK/ehppIid0K5aqjVYreeHIzUBwN8YluYh14kB1Fd 8kZOKyCmt2BcVRR/+8d0mg4LDSusJVnQbPx0jzSbKoscMMYthuQ4IhDAi11I0I+YoaGF sBVew8JpT85AriIv2HqXNq0RS39cc6agGO14qwyi+aJg6NOFaUW6KtG/3JdjqEZBId3N xGEQ== X-Gm-Message-State: AOJu0Yx14i5DrDfVpOfG9oP5P0Ta6gx9Z27y4B/DsSf6bR+IZb02aH1d PKF7KGlOa72GwJqVR5rlOA7WCcEwL7VTXiM40VJaGfkovJPIdz8kqO4qDAnud4B4M36UnvQZbBZ u25gbeEoFR7hh7H8SPCHWv4yGtcWBWMRT8ftc X-Received: by 2002:a05:6122:200a:b0:4b6:e3fa:7599 with SMTP id l10-20020a056122200a00b004b6e3fa7599mr4678904vkd.0.1705330041173; Mon, 15 Jan 2024 06:47:21 -0800 (PST) X-Google-Smtp-Source: AGHT+IHCsY0ZuDYFJr87bladWt7s6eCEJzNh1RKNCl6gfgHXUBWkBCjqEMu+F8KwMd/Grf0wk26qBg== X-Received: by 2002:a05:6122:200a:b0:4b6:e3fa:7599 with SMTP id l10-20020a056122200a00b004b6e3fa7599mr4678878vkd.0.1705330040810; Mon, 15 Jan 2024 06:47:20 -0800 (PST) Received: from pstanner-thinkpadt14sgen1.muc.redhat.com (nat-pool-muc-t.redhat.com. [149.14.88.26]) by smtp.gmail.com with ESMTPSA id ne13-20020a056214424d00b006815cf9a644sm1020720qvb.55.2024.01.15.06.47.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Jan 2024 06:47:20 -0800 (PST) From: Philipp Stanner To: Jonathan Corbet , Hans de Goede , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Daniel Vetter , Bjorn Helgaas , Philipp Stanner , Sam Ravnborg , dakr@redhat.com Subject: [PATCH 04/10] pci: devres: make devres region requests consistent Date: Mon, 15 Jan 2024 15:46:15 +0100 Message-ID: <20240115144655.32046-6-pstanner@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240115144655.32046-2-pstanner@redhat.com> References: <20240115144655.32046-2-pstanner@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Now that pure managed region request functions are available, the implementation of the hybrid-functions which are only sometimes managed can be made more consistent and readable by wrapping those always-managed functions. Implement a new pcim_ function for exclusively requested regions. Have the pci_request / release functions call their pcim_ counterparts. Remove the now surplus region_mask from the devres struct. Signed-off-by: Philipp Stanner --- drivers/pci/devres.c | 49 ++++++++++++++++++++++--------------------- drivers/pci/pci.c | 50 +++++++++++++++----------------------------- drivers/pci/pci.h | 6 ------ include/linux/pci.h | 1 + 4 files changed, 43 insertions(+), 63 deletions(-) diff --git a/drivers/pci/devres.c b/drivers/pci/devres.c index e221919ebbe2..1e5cf950775d 100644 --- a/drivers/pci/devres.c +++ b/drivers/pci/devres.c @@ -22,18 +22,15 @@ * _sometimes_ managed (e.g. pci_request_region()). * Consequently, in the new API, region requests performed by the pcim_ * functions are automatically cleaned up through the devres callback - * pcim_addr_resource_release(), while requests performed by - * pcim_enable_device() + pci_*region*() are automatically cleaned up - * through the for-loop in pcim_release(). + * pcim_addr_resource_release(). + * Users utilizing pcim_enable_device() + pci_*region*() are redirected in + * pci.c to the managed functions here in this file. This isn't exactly + * perfect, but the only alternative way would be to port ALL drivers using + * said combination to pcim_ functions. * - * TODO 1: + * TODO: * Remove the legacy table entirely once all calls to pcim_iomap_table() in * the kernel have been removed. - * - * TODO 2: - * Port everyone calling pcim_enable_device() + pci_*region*() to using the - * pcim_ functions. Then, remove all devres functionality from pci_*region*() - * functions and remove the associated cleanups described above in point #2. */ /* @@ -407,21 +404,6 @@ static void pcim_release(struct device *gendev, void *res) { struct pci_dev *dev = to_pci_dev(gendev); struct pci_devres *this = res; - int i; - - /* - * This is legacy code. - * All regions requested by a pcim_ function do get released through - * pcim_addr_resource_release(). Thanks to the hybrid nature of the pci_ - * region-request functions, this for-loop has to release the regions - * if they have been requested by such a function. - * - * TODO: Remove this once all users of pcim_enable_device() PLUS - * pci-region-request-functions have been ported to pcim_ functions. - */ - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) - if (this->region_mask & (1 << i)) - pci_release_region(dev, i); if (this->mwi) pci_clear_mwi(dev); @@ -971,6 +953,25 @@ int pcim_request_region(struct pci_dev *pdev, int bar, const char *name) } EXPORT_SYMBOL(pcim_request_region); +/** + * pcim_request_region_exclusive - Request a PCI BAR exclusively + * @pdev: PCI device to requestion region for + * @bar: Index of BAR to request + * @name: Name associated with the request + * + * Returns: 0 on success, a negative error code on failure. + * + * Request region specified by @bar exclusively. + * + * The region will automatically be released on driver detach. If desired, + * release manually only with pcim_release_region(). + */ +int pcim_request_region_exclusive(struct pci_dev *pdev, int bar, const char *name) +{ + return _pcim_request_region(pdev, bar, name, IORESOURCE_EXCLUSIVE); +} +EXPORT_SYMBOL(pcim_request_region_exclusive); + /** * pcim_release_region - Release a PCI BAR * @pdev: PCI device to operate on diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 7ca860acf351..66639dd754c7 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3873,7 +3873,15 @@ EXPORT_SYMBOL_GPL(pci_common_swizzle); */ void pci_release_region(struct pci_dev *pdev, int bar) { - struct pci_devres *dr; + /* + * This is done for backwards compatibility, because the old pci-devres + * API had a mode in which the function became managed if it had been + * enabled with pcim_enable_device() instead of pci_enable_device(). + */ + if (pci_is_managed(pdev)) { + pcim_release_region(pdev, bar); + return; + } if (pci_resource_len(pdev, bar) == 0) return; @@ -3883,20 +3891,6 @@ void pci_release_region(struct pci_dev *pdev, int bar) else if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) release_mem_region(pci_resource_start(pdev, bar), pci_resource_len(pdev, bar)); - - /* - * This devres utility makes this function sometimes managed - * (when pcim_enable_device() has been called before). - * This is bad because it conflicts with the pcim_ functions being - * exclusively responsible for managed pci. Its "sometimes yes, sometimes - * no" nature can cause bugs. - * - * TODO: Remove this once all users that use pcim_enable_device() PLUS - * a region request function have been ported to using pcim_ functions. - */ - dr = find_pci_dr(pdev); - if (dr) - dr->region_mask &= ~(1 << bar); } EXPORT_SYMBOL(pci_release_region); @@ -3924,14 +3918,18 @@ EXPORT_SYMBOL(pci_release_region); * NOTE: * This is a "hybrid" function: Its normally unmanaged, but becomes managed * when pcim_enable_device() has been called in advance. - * This hybrid feature is DEPRECATED! If you need to implement a new pci - * function that does automatic cleanup, write a new pcim_* function that uses - * devres directly. + * This hybrid feature is DEPRECATED! If you want managed cleanup, use the + * pcim_* functions instead. */ static int __pci_request_region(struct pci_dev *pdev, int bar, const char *res_name, int exclusive) { - struct pci_devres *dr; + if (pci_is_managed(pdev)) { + if (exclusive == IORESOURCE_EXCLUSIVE) + return pcim_request_region_exclusive(pdev, bar, res_name); + else + return pcim_request_region(pdev, bar, res_name); + } if (pci_resource_len(pdev, bar) == 0) return 0; @@ -3947,20 +3945,6 @@ static int __pci_request_region(struct pci_dev *pdev, int bar, goto err_out; } - /* - * This devres utility makes this function sometimes managed - * (when pcim_enable_device() has been called before). - * This is bad because it conflicts with the pcim_ functions being - * exclusively responsible for managed pci. Its "sometimes yes, sometimes - * no" nature can cause bugs. - * - * TODO: Remove this once all users that use pcim_enable_device() PLUS - * a region request function have been ported to using pcim_ functions. - */ - dr = find_pci_dr(pdev); - if (dr) - dr->region_mask |= 1 << bar; - return 0; err_out: diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 4d4bcc2d850f..7c2181677760 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -814,12 +814,6 @@ struct pci_devres { unsigned int orig_intx:1; unsigned int restore_intx:1; unsigned int mwi:1; - - /* - * TODO: remove the region_mask once everyone calling - * pcim_enable_device() + pci_*region*() is ported to pcim_ functions. - */ - u32 region_mask; }; struct pci_devres *find_pci_dr(struct pci_dev *pdev); diff --git a/include/linux/pci.h b/include/linux/pci.h index 3dcd8a5e10b5..641ee30f7d2d 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -2321,6 +2321,7 @@ int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask, const char *name); void pcim_iounmap_regions(struct pci_dev *pdev, int mask); int pcim_request_region(struct pci_dev *pdev, int bar, const char *res_name); +int pcim_request_region_exclusive(struct pci_dev *pdev, int bar, const char *name); void pcim_release_region(struct pci_dev *pdev, int bar); void pcim_release_all_regions(struct pci_dev *pdev); int pcim_request_all_regions(struct pci_dev *pdev, const char *name); From patchwork Mon Jan 15 14:46:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Stanner X-Patchwork-Id: 13519734 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 38FFDC47258 for ; Mon, 15 Jan 2024 14:47:34 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 5820D10E2FE; Mon, 15 Jan 2024 14:47:33 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by gabe.freedesktop.org (Postfix) with ESMTPS id E282910E2FD for ; Mon, 15 Jan 2024 14:47:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705330047; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RO0mZDJz5TK909+4LedW3qKsNhM3MJg2yInHziL/J8s=; b=gZ0pMTEGEBOWNuGxHQQeQ43x1jinD9bNWVOCORLAzn21xe/jRdLmjgdFBrjBWdWtd+RqvV daZv0y3Ql/KjACLiowmK39qtvuq86LFAJXVOdL17oAclflRIMt0rG6dbENwHNSupumOdxu RV0n85sqmCuydAWPHhXU6VSigTsv82k= Received: from mail-vk1-f198.google.com (mail-vk1-f198.google.com [209.85.221.198]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-115-ggcFlzCWPrq_ae8hB4c4tw-1; Mon, 15 Jan 2024 09:47:24 -0500 X-MC-Unique: ggcFlzCWPrq_ae8hB4c4tw-1 Received: by mail-vk1-f198.google.com with SMTP id 71dfb90a1353d-4b721a956cdso200376e0c.1 for ; Mon, 15 Jan 2024 06:47:23 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705330043; x=1705934843; 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=RO0mZDJz5TK909+4LedW3qKsNhM3MJg2yInHziL/J8s=; b=Av/6P29XnDzmMQkIsa8yGhRgJbX+XwV7gHNjYaGc6+xEeuQT3EURLobSuFa/BwLOZw Hhgp+oRv8NIXefKb3aDofaJT9BD5266rQjViZRWknIiIqNB2eFhNJWoQvdVJoDL6P/V6 Ez3cfZoSQPG8G9Pxm31CXiTU/PEJE9KkJ4RtGfLEMz/B613ww+8NesJjwI8h3vbvOhMl Tb9QDw8n9uZTBfLPz2FPTrBnezEFYgbVhv3s0NMTTbHy00GFhxeib5zvgcXWYgOJ4ACC xJSJvDSX3NdRhSraJQ6qSB+0VdspqYUJ2TiWl5W0gxXqx1gqy03hmhxa3NjxJET45KbP 0VsQ== X-Gm-Message-State: AOJu0YzUe0nJr6JkuQWDVfXjRwTXoUUw4qV1iVle8L5xgmac/q83J3Ss /t9BhrZA7R3WB+7RxxYe6pDgLI7E89u3vK0PWsV7W7Vqli/gpSlpGgV6UwRAINPBqbScUEdngya 0QwL0LYBznH3uS/1st1BAbUuWeby4GUby+yh4 X-Received: by 2002:a05:6122:200a:b0:4b6:e3fa:7599 with SMTP id l10-20020a056122200a00b004b6e3fa7599mr4678987vkd.0.1705330043464; Mon, 15 Jan 2024 06:47:23 -0800 (PST) X-Google-Smtp-Source: AGHT+IH6fwAzY9p/B8Ojoob7vJlPit+LMYVgGiOaxw4BacA7x0sKclRH2EeCFfpGqDBHtgs3IUs2RQ== X-Received: by 2002:a05:6122:200a:b0:4b6:e3fa:7599 with SMTP id l10-20020a056122200a00b004b6e3fa7599mr4678977vkd.0.1705330043173; Mon, 15 Jan 2024 06:47:23 -0800 (PST) Received: from pstanner-thinkpadt14sgen1.muc.redhat.com (nat-pool-muc-t.redhat.com. [149.14.88.26]) by smtp.gmail.com with ESMTPSA id ne13-20020a056214424d00b006815cf9a644sm1020720qvb.55.2024.01.15.06.47.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Jan 2024 06:47:22 -0800 (PST) From: Philipp Stanner To: Jonathan Corbet , Hans de Goede , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Daniel Vetter , Bjorn Helgaas , Philipp Stanner , Sam Ravnborg , dakr@redhat.com Subject: [PATCH 05/10] pci: move enabled status bit to pci_dev struct Date: Mon, 15 Jan 2024 15:46:16 +0100 Message-ID: <20240115144655.32046-7-pstanner@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240115144655.32046-2-pstanner@redhat.com> References: <20240115144655.32046-2-pstanner@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The bit describing whether the PCI device is currently enabled is stored in the devres-struct. Besides this struct being subject of a cleanup process, the device-struct is in general the right place to store this information, since it is not devres-specific. Move the 'enabled' boolean bit to struct pci_dev. Signed-off-by: Philipp Stanner --- drivers/pci/devres.c | 11 ++++------- drivers/pci/pci.c | 17 ++++++++++------- drivers/pci/pci.h | 1 - include/linux/pci.h | 1 + 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/pci/devres.c b/drivers/pci/devres.c index 1e5cf950775d..bf957f0bc5ac 100644 --- a/drivers/pci/devres.c +++ b/drivers/pci/devres.c @@ -411,7 +411,7 @@ static void pcim_release(struct device *gendev, void *res) if (this->restore_intx) pci_intx(dev, this->orig_intx); - if (this->enabled && !this->pinned) + if (!this->pinned) pci_disable_device(dev); } @@ -456,14 +456,11 @@ int pcim_enable_device(struct pci_dev *pdev) dr = get_pci_dr(pdev); if (unlikely(!dr)) return -ENOMEM; - if (dr->enabled) - return 0; rc = pci_enable_device(pdev); - if (!rc) { + if (!rc) pdev->is_managed = 1; - dr->enabled = 1; - } + return rc; } EXPORT_SYMBOL(pcim_enable_device); @@ -481,7 +478,7 @@ void pcim_pin_device(struct pci_dev *pdev) struct pci_devres *dr; dr = find_pci_dr(pdev); - WARN_ON(!dr || !dr->enabled); + WARN_ON(!dr || !pdev->enabled); if (dr) dr->pinned = 1; } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 66639dd754c7..0fb9e7bb0e43 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1953,6 +1953,9 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars) u16 cmd; u8 pin; + if (dev->enabled) + return 0; + err = pci_set_power_state(dev, PCI_D0); if (err < 0 && err != -EIO) return err; @@ -1967,7 +1970,7 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars) pci_fixup_device(pci_fixup_enable, dev); if (dev->msi_enabled || dev->msix_enabled) - return 0; + goto success_out; pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); if (pin) { @@ -1977,6 +1980,8 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars) cmd & ~PCI_COMMAND_INTX_DISABLE); } +success_out: + dev->enabled = true; return 0; } @@ -2146,6 +2151,9 @@ static void do_pci_disable_device(struct pci_dev *dev) { u16 pci_command; + if (!dev->enabled) + return; + pci_read_config_word(dev, PCI_COMMAND, &pci_command); if (pci_command & PCI_COMMAND_MASTER) { pci_command &= ~PCI_COMMAND_MASTER; @@ -2153,6 +2161,7 @@ static void do_pci_disable_device(struct pci_dev *dev) } pcibios_disable_device(dev); + dev->enabled = false; } /** @@ -2180,12 +2189,6 @@ void pci_disable_enabled_device(struct pci_dev *dev) */ void pci_disable_device(struct pci_dev *dev) { - struct pci_devres *dr; - - dr = find_pci_dr(dev); - if (dr) - dr->enabled = 0; - dev_WARN_ONCE(&dev->dev, atomic_read(&dev->enable_cnt) <= 0, "disabling already-disabled device"); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 7c2181677760..dbb76a3fb0e4 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -809,7 +809,6 @@ static inline pci_power_t mid_pci_get_power_state(struct pci_dev *pdev) * 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; diff --git a/include/linux/pci.h b/include/linux/pci.h index 641ee30f7d2d..a356bdcc14cc 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -367,6 +367,7 @@ struct pci_dev { this is D0-D3, D0 being fully functional, and D3 being off. */ u8 pm_cap; /* PM capability offset */ + unsigned int enabled:1; /* Whether this dev is enabled */ unsigned int imm_ready:1; /* Supports Immediate Readiness */ unsigned int pme_support:5; /* Bitmask of states from which PME# can be generated */ From patchwork Mon Jan 15 14:46:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Stanner X-Patchwork-Id: 13519735 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D30C5C3DA79 for ; Mon, 15 Jan 2024 14:47:37 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 5153910E301; Mon, 15 Jan 2024 14:47:37 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by gabe.freedesktop.org (Postfix) with ESMTPS id C1BBF10E301 for ; Mon, 15 Jan 2024 14:47:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705330052; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=k3vu21hkZlZsapFSJtp8nhKKQ/3OZTkpZfYIme9+49k=; b=Sg44nE4NTYepuXPKhVTedtOrtBUCtVtXmdBc5e4AV+7i3/BqsehhVuMcgxTwXEKGHBjAGm KLFm+pw4DzH/1SS/kjxDRxtQwzudgIyuoFg93ApUZ55dNCu1i1CADZW6rD+3Kvj3QodY8E kU1EhBxfBobZjLZxikXrkyh9g6l0WzM= Received: from mail-vk1-f199.google.com (mail-vk1-f199.google.com [209.85.221.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-16-3ymTaK0cN3O2uAXnvT7VwA-1; Mon, 15 Jan 2024 09:47:26 -0500 X-MC-Unique: 3ymTaK0cN3O2uAXnvT7VwA-1 Received: by mail-vk1-f199.google.com with SMTP id 71dfb90a1353d-4b7bdc844fcso135151e0c.0 for ; Mon, 15 Jan 2024 06:47:26 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705330046; x=1705934846; 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=k3vu21hkZlZsapFSJtp8nhKKQ/3OZTkpZfYIme9+49k=; b=obXOc+vgSklAC4qUBFuSiiKgU63i+HU1ew4iNoHe5hXVxdmXaUoBjJDGFs/3SJIpI5 tAtXqbz3WmBvXvC/YxfJUQ+9IAXorqdtDQ0f/78qk4R2AhwzUR4PW8UHVxtcY2vj70p/ w8flJJMOzr9u0y8IBUGX4LsTv/ZKR7+OVr4TO1RA/j6ebX3ubhuZCDHV0ceXbv1HkC+R 31m3Pf8hrBBpj8gd4Uozbx+N2tS6aOkyX+zSQPt4glzDm1fc9GX6pz3eiu+ncM3cYBPZ Eeone2FfzNGaofQR4yME4zzpXse912KvIvcV3TeUCER7hK53/Krj4VDFgE9v/BZHgZS6 KBnw== X-Gm-Message-State: AOJu0Yx1M3ztq8TeZYS080hLTNixySAZ1+PNeeka00Gxlxdrv69oX1PC ZrdlVHkETyW5lXr1+4t5awCEOnEkl1kb1q1xYiVlSAAZGP67rkdmstgngidRkYPvcUGIWlOVisr oFZ7IK1kSo3c6XZHo4FoM6stkv8DULcIjfkkQ X-Received: by 2002:a05:6122:2886:b0:4b7:32ac:f4e5 with SMTP id fl6-20020a056122288600b004b732acf4e5mr4682331vkb.1.1705330046100; Mon, 15 Jan 2024 06:47:26 -0800 (PST) X-Google-Smtp-Source: AGHT+IEl3g0muu7xD/Tj+Zr9TyY8gOWhOJboojbdmamx1smFfYvzduqw18AZ9+hpq2S3HXA+drCMKA== X-Received: by 2002:a05:6122:2886:b0:4b7:32ac:f4e5 with SMTP id fl6-20020a056122288600b004b732acf4e5mr4682321vkb.1.1705330045850; Mon, 15 Jan 2024 06:47:25 -0800 (PST) Received: from pstanner-thinkpadt14sgen1.muc.redhat.com (nat-pool-muc-t.redhat.com. [149.14.88.26]) by smtp.gmail.com with ESMTPSA id ne13-20020a056214424d00b006815cf9a644sm1020720qvb.55.2024.01.15.06.47.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Jan 2024 06:47:25 -0800 (PST) From: Philipp Stanner To: Jonathan Corbet , Hans de Goede , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Daniel Vetter , Bjorn Helgaas , Philipp Stanner , Sam Ravnborg , dakr@redhat.com Subject: [PATCH 06/10] pci: move pinned status bit to pci_dev struct Date: Mon, 15 Jan 2024 15:46:17 +0100 Message-ID: <20240115144655.32046-8-pstanner@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240115144655.32046-2-pstanner@redhat.com> References: <20240115144655.32046-2-pstanner@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The bit describing whether the PCI device is currently pinned is stored in the PCI devres struct. To clean up and simplify the pci-devres API, it's better if this information is stored in the pci_dev struct, because it allows for checking that device's pinned-status directly through the device struct. This will later permit simplifying pcim_enable_device(). Move the 'pinned' boolean bit to struct pci_dev. Signed-off-by: Philipp Stanner --- drivers/pci/devres.c | 14 ++++---------- drivers/pci/pci.h | 1 - include/linux/pci.h | 1 + 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/pci/devres.c b/drivers/pci/devres.c index bf957f0bc5ac..de8cf6f87dd7 100644 --- a/drivers/pci/devres.c +++ b/drivers/pci/devres.c @@ -411,7 +411,7 @@ static void pcim_release(struct device *gendev, void *res) if (this->restore_intx) pci_intx(dev, this->orig_intx); - if (!this->pinned) + if (!dev->pinned) pci_disable_device(dev); } @@ -469,18 +469,12 @@ 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(). + * 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 = find_pci_dr(pdev); - WARN_ON(!dr || !pdev->enabled); - if (dr) - dr->pinned = 1; + pdev->pinned = true; } EXPORT_SYMBOL(pcim_pin_device); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index dbb76a3fb0e4..3d9908a69ebf 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -809,7 +809,6 @@ static inline pci_power_t mid_pci_get_power_state(struct pci_dev *pdev) * when a device is enabled using managed PCI device enable interface. */ struct pci_devres { - unsigned int pinned:1; unsigned int orig_intx:1; unsigned int restore_intx:1; unsigned int mwi:1; diff --git a/include/linux/pci.h b/include/linux/pci.h index a356bdcc14cc..2f6f44991003 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -368,6 +368,7 @@ struct pci_dev { functional, and D3 being off. */ u8 pm_cap; /* PM capability offset */ unsigned int enabled:1; /* Whether this dev is enabled */ + unsigned int pinned:1; /* Whether this dev is pinned */ unsigned int imm_ready:1; /* Supports Immediate Readiness */ unsigned int pme_support:5; /* Bitmask of states from which PME# can be generated */ From patchwork Mon Jan 15 14:46:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Stanner X-Patchwork-Id: 13519733 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2918DC3DA79 for ; Mon, 15 Jan 2024 14:47:33 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 720DA10E2FD; Mon, 15 Jan 2024 14:47:32 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by gabe.freedesktop.org (Postfix) with ESMTPS id 34CB810E2FD for ; Mon, 15 Jan 2024 14:47:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705330050; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+s18P47JH053YQ7YJMWBY/f4LBPoNabsZFa7u4jw7Zc=; b=atqgXg+9UWyF1CtFVTr/TTi4tlV8vxp/vghADDo2enwZJxVjtRvlD3iSgU5/6WFcxBbdms HXeooRV1/Vy7YN9mxynhCYXOK0F3xXT27ZWvfmUGC3s16Z9Ddu3L8Dwa5kGZ1bu57Cr9fj +ysuINMw9MhRf46KqdjxBRQ1XArhKvk= Received: from mail-qt1-f197.google.com (mail-qt1-f197.google.com [209.85.160.197]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-262-QNVgCTH3OH-VrnVASsitBA-1; Mon, 15 Jan 2024 09:47:29 -0500 X-MC-Unique: QNVgCTH3OH-VrnVASsitBA-1 Received: by mail-qt1-f197.google.com with SMTP id d75a77b69052e-429d02a62f8so5664321cf.1 for ; Mon, 15 Jan 2024 06:47:29 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705330048; x=1705934848; 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=+s18P47JH053YQ7YJMWBY/f4LBPoNabsZFa7u4jw7Zc=; b=mp/E0KE49P07mpE9dJkz7VgU6DjDhLCB489WBUwXrIcRqmXfcKjsveue9Dv50NTIc6 EN3d76JymCIxIAeMCzji92Fw5ce3tSOZrkb+/JtPClqUbTrlNLv8S6jX+rsW+pJI0ls0 1BwRQ0gXFH+FJL9ClnG7NRUtDfl4Bn/o6eHG+qtTo0diiwlhdPEtY9obNnvbSOtH7QwE jM1h7ZyIREbpUYznESXFSDvV4/h4E9RmRm2iBBuIF5TgH/EE42XodOwVq43fOBRj6Iul 52o2UQdtzCZ40lRFHy7M+pRuSgiF36xZYfYh9m4qKZlTh6erlUDZiRtWrN1yfM9vzYyD jxhg== X-Gm-Message-State: AOJu0YyagCc1AuSgtpylp+PqTT+Dot4TEu8xjWcqcT0dRv64YwXcP8vj u/uVPbEjr472YAIDMqv8dFJh88gS4kx0tzGc3GSb504+9/9Hs6qLiKtSNMwRSxvPUu6wzH5fLae CzK3PyQZ+ATyiOit+WYZoRDAygYi9whFAwgVS X-Received: by 2002:a05:6214:20ca:b0:681:555c:8e64 with SMTP id 10-20020a05621420ca00b00681555c8e64mr6594571qve.6.1705330048587; Mon, 15 Jan 2024 06:47:28 -0800 (PST) X-Google-Smtp-Source: AGHT+IHIFNFH3t9YBVxCpLVDR4bI9FQ3w+V6Y/t4RZxhNK4CjYtj3KjB51ezdoAU+KVMDwPukDm1tQ== X-Received: by 2002:a05:6214:20ca:b0:681:555c:8e64 with SMTP id 10-20020a05621420ca00b00681555c8e64mr6594555qve.6.1705330048349; Mon, 15 Jan 2024 06:47:28 -0800 (PST) Received: from pstanner-thinkpadt14sgen1.muc.redhat.com (nat-pool-muc-t.redhat.com. [149.14.88.26]) by smtp.gmail.com with ESMTPSA id ne13-20020a056214424d00b006815cf9a644sm1020720qvb.55.2024.01.15.06.47.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Jan 2024 06:47:28 -0800 (PST) From: Philipp Stanner To: Jonathan Corbet , Hans de Goede , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Daniel Vetter , Bjorn Helgaas , Philipp Stanner , Sam Ravnborg , dakr@redhat.com Subject: [PATCH 07/10] pci: devres: give mwi its own callback Date: Mon, 15 Jan 2024 15:46:18 +0100 Message-ID: <20240115144655.32046-9-pstanner@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240115144655.32046-2-pstanner@redhat.com> References: <20240115144655.32046-2-pstanner@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" managing mwi with devres can easily be done with its own callback, without the necessity to store any state about it in a device-related struct. Remove the mwi state from the devres-struct. Make the devres-mwi functions set a separate devres-callback. Signed-off-by: Philipp Stanner --- drivers/pci/devres.c | 23 +++++++++++------------ drivers/pci/pci.h | 1 - 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/pci/devres.c b/drivers/pci/devres.c index de8cf6f87dd7..911c2037d9fd 100644 --- a/drivers/pci/devres.c +++ b/drivers/pci/devres.c @@ -378,24 +378,26 @@ void __iomem *devm_pci_remap_cfg_resource(struct device *dev, } EXPORT_SYMBOL(devm_pci_remap_cfg_resource); +static void __pcim_clear_mwi(void *pdev_raw) +{ + struct pci_dev *pdev = pdev_raw; + + pci_clear_mwi(pdev); +} + /** * pcim_set_mwi - a device-managed pci_set_mwi() - * @dev: the PCI device for which MWI is enabled + * @pdev: the PCI device for which MWI is enabled * * Managed pci_set_mwi(). * * RETURNS: An appropriate -ERRNO error value on error, or zero for success. */ -int pcim_set_mwi(struct pci_dev *dev) +int pcim_set_mwi(struct pci_dev *pdev) { - struct pci_devres *dr; - - dr = find_pci_dr(dev); - if (!dr) - return -ENOMEM; + devm_add_action(&pdev->dev, __pcim_clear_mwi, pdev); - dr->mwi = 1; - return pci_set_mwi(dev); + return pci_set_mwi(pdev); } EXPORT_SYMBOL(pcim_set_mwi); @@ -405,9 +407,6 @@ static void pcim_release(struct device *gendev, void *res) struct pci_dev *dev = to_pci_dev(gendev); struct pci_devres *this = res; - if (this->mwi) - pci_clear_mwi(dev); - if (this->restore_intx) pci_intx(dev, this->orig_intx); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 3d9908a69ebf..667bfdd61d5e 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -811,7 +811,6 @@ static inline pci_power_t mid_pci_get_power_state(struct pci_dev *pdev) struct pci_devres { unsigned int orig_intx:1; unsigned int restore_intx:1; - unsigned int mwi:1; }; struct pci_devres *find_pci_dr(struct pci_dev *pdev); From patchwork Mon Jan 15 14:46:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Stanner X-Patchwork-Id: 13519736 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0D86AC47258 for ; Mon, 15 Jan 2024 14:47:39 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id F1D9D10E303; Mon, 15 Jan 2024 14:47:37 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by gabe.freedesktop.org (Postfix) with ESMTPS id 4859910E301 for ; Mon, 15 Jan 2024 14:47:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705330053; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=NKQuejYaTfOy+ygLhxh3ezuOqu6KilFVvxO7msTQ6Q0=; b=RccvRBHxBlEOA0h+ef7a8QX/XzAgzQfLjFnO5JQ3iY7Hm6cSg2CzgdN5l0JXQhRxj9XpTX ilU9lRAI63AAtyErQb3wakvAgg3pWqxzikylE1Ftmfily8Rz6HDo8hXoWe7eqq9BroanaQ vwEQnWeviApu4ZvjsEg8INPPG8sWL+I= 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-442--qNZChrBMbq5T2ijzLm0lA-1; Mon, 15 Jan 2024 09:47:32 -0500 X-MC-Unique: -qNZChrBMbq5T2ijzLm0lA-1 Received: by mail-qv1-f72.google.com with SMTP id 6a1803df08f44-680fce72f68so25068006d6.0 for ; Mon, 15 Jan 2024 06:47:32 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705330052; x=1705934852; 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=NKQuejYaTfOy+ygLhxh3ezuOqu6KilFVvxO7msTQ6Q0=; b=RDomylCkQGM8Mu+/xquzBnAQvQa7KlziXryX2Zi+ZhJylQL7qIXewFzgj0V31dSsh+ uC4Q90eJ5osPbYx4WGJEUcgnfjgpPvSIx8TqU/diJrzOCcf0UvtNLIBK8fcwpbZ51rVv VX667kOt7pg/OB3OUus1Gwj/bUdR3xkFNZFZDxd5iNlcA5h8ph3tHLsqbyPs6ThqP1FX MdxFLHQN7wKs4YLkDqexSAZX18ZUFERrHcVIbnZzcVDkM2P2bFJnvdc2atQRxbfL4vZl UCKqT5JPN29Wiudayca1CfsJam14AIKHg6s/uEmH17XUpqgVd3gsM097iHyL9gzcmiU5 gweQ== X-Gm-Message-State: AOJu0YztuNscFsprCNIggtFsRQVtjujCuYvz6wOCrGTDIieKhQZbn1VP cHfFQFqWJhrTeK4/YCB9F2bUOR+BppukE1T5V5ZuMhTigCXNn/sxVloY4Ks6LcgbO12g/msqbUX WOv4u/536w6WQk+rjvlc30QckS03L1FAja3uP X-Received: by 2002:a05:6214:2409:b0:680:fee0:b9e9 with SMTP id fv9-20020a056214240900b00680fee0b9e9mr10832210qvb.0.1705330051554; Mon, 15 Jan 2024 06:47:31 -0800 (PST) X-Google-Smtp-Source: AGHT+IHKb3jA3FUB/hnqVjWXw40a5VCI+1scQGITF6TP15jP4nIN+0I4b0P9xvnyisVbpi9btL+QGg== X-Received: by 2002:a05:6214:2409:b0:680:fee0:b9e9 with SMTP id fv9-20020a056214240900b00680fee0b9e9mr10832176qvb.0.1705330051170; Mon, 15 Jan 2024 06:47:31 -0800 (PST) Received: from pstanner-thinkpadt14sgen1.muc.redhat.com (nat-pool-muc-t.redhat.com. [149.14.88.26]) by smtp.gmail.com with ESMTPSA id ne13-20020a056214424d00b006815cf9a644sm1020720qvb.55.2024.01.15.06.47.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Jan 2024 06:47:30 -0800 (PST) From: Philipp Stanner To: Jonathan Corbet , Hans de Goede , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Daniel Vetter , Bjorn Helgaas , Philipp Stanner , Sam Ravnborg , dakr@redhat.com Subject: [PATCH 08/10] pci: devres: give pci(m)_intx its own callback Date: Mon, 15 Jan 2024 15:46:19 +0100 Message-ID: <20240115144655.32046-10-pstanner@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240115144655.32046-2-pstanner@redhat.com> References: <20240115144655.32046-2-pstanner@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" pci_intx() is one of the functions that have "hybrid mode" (i.e., sometimes managed, sometimes not). Providing a separate pcim_intx() function with its own device resource and cleanup callback allows for removing further large parts of the legacy pci-devres implementation. As in the region-request-functions, pci_intx() has to call into its managed counterpart for backwards compatibility. Implement pcim_intx() with its own device resource. Make pci_intx() call pcim_intx() in the managed case. Remove the legacy devres struct from pci.h. Signed-off-by: Philipp Stanner --- drivers/pci/devres.c | 77 +++++++++++++++++++++++++++++++++++--------- drivers/pci/pci.c | 23 +++++++------ drivers/pci/pci.h | 20 ------------ include/linux/pci.h | 1 + 4 files changed, 75 insertions(+), 46 deletions(-) diff --git a/drivers/pci/devres.c b/drivers/pci/devres.c index 911c2037d9fd..7c4edcaeb8fe 100644 --- a/drivers/pci/devres.c +++ b/drivers/pci/devres.c @@ -40,6 +40,11 @@ struct pcim_iomap_devres { void __iomem *table[PCI_STD_NUM_BARS]; }; +/* Used to restore the old intx state on driver detach. */ +struct pcim_intx_devres { + int orig_intx; +}; + enum pcim_addr_devres_type { /* Default initializer. */ PCIM_ADDR_DEVRES_TYPE_INVALID, @@ -401,31 +406,71 @@ int pcim_set_mwi(struct pci_dev *pdev) } EXPORT_SYMBOL(pcim_set_mwi); +static void pcim_intx_restore(struct device *dev, void *data) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct pcim_intx_devres *res = data; -static void pcim_release(struct device *gendev, void *res) + pci_intx(pdev, res->orig_intx); +} + +static struct pcim_intx_devres *get_or_create_intx_devres(struct device *dev) { - struct pci_dev *dev = to_pci_dev(gendev); - struct pci_devres *this = res; + struct pcim_intx_devres *res; - if (this->restore_intx) - pci_intx(dev, this->orig_intx); + res = devres_find(dev, pcim_intx_restore, NULL, NULL); + if (res) + return res; - if (!dev->pinned) - pci_disable_device(dev); + res = devres_alloc(pcim_intx_restore, sizeof(*res), GFP_KERNEL); + if (res) + devres_add(dev, res); + + return res; } -/* - * TODO: - * Once the last four callers in pci.c are ported, this function here needs to - * be made static again. +/** + * pcim_intx - managed pci_intx() + * @pdev: the PCI device to operate on + * @enable: boolean: whether to enable or disable PCI INTx + * + * Returns: 0 on success, -ENOMEM on error. + * + * Enables/disables PCI INTx for device @pdev. + * Restores the original state on driver detach. */ -struct pci_devres *find_pci_dr(struct pci_dev *pdev) +int pcim_intx(struct pci_dev *pdev, int enable) { - if (pci_is_managed(pdev)) - return devres_find(&pdev->dev, pcim_release, NULL, NULL); - return NULL; + u16 pci_command, new; + struct pcim_intx_devres *res; + + res = get_or_create_intx_devres(&pdev->dev); + if (!res) + return -ENOMEM; + + res->orig_intx = !enable; + + pci_read_config_word(pdev, PCI_COMMAND, &pci_command); + + if (enable) + new = pci_command & ~PCI_COMMAND_INTX_DISABLE; + else + new = pci_command | PCI_COMMAND_INTX_DISABLE; + + if (new != pci_command) + pci_write_config_word(pdev, PCI_COMMAND, new); + + return 0; +} +EXPORT_SYMBOL_GPL(pcim_intx); + +static void pcim_release(struct device *gendev, void *res) +{ + struct pci_dev *dev = to_pci_dev(gendev); + + if (!dev->pinned) + pci_disable_device(dev); } -EXPORT_SYMBOL(find_pci_dr); static struct pci_devres *get_pci_dr(struct pci_dev *pdev) { diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 0fb9e7bb0e43..a03ad3f17540 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4465,11 +4465,23 @@ void pci_disable_parity(struct pci_dev *dev) * This is a "hybrid" function: Its normally unmanaged, but becomes managed * when pcim_enable_device() has been called in advance. * This hybrid feature is DEPRECATED! + * Use pcim_intx() if you need a managed version. */ void pci_intx(struct pci_dev *pdev, int enable) { u16 pci_command, new; + /* + * This is done for backwards compatibility, because the old pci-devres + * API had a mode in which this function became managed if the dev had + * been enabled with pcim_enable_device() instead of pci_enable_device(). + */ + if (pci_is_managed(pdev)) { + if (pcim_intx(pdev, enable) != 0) + WARN_ON_ONCE(1); + return; + } + pci_read_config_word(pdev, PCI_COMMAND, &pci_command); if (enable) @@ -4477,17 +4489,8 @@ void pci_intx(struct pci_dev *pdev, int enable) else new = pci_command | PCI_COMMAND_INTX_DISABLE; - if (new != pci_command) { - struct pci_devres *dr; - + if (new != pci_command) pci_write_config_word(pdev, PCI_COMMAND, new); - - dr = find_pci_dr(pdev); - if (dr && !dr->restore_intx) { - dr->restore_intx = 1; - dr->orig_intx = !enable; - } - } } EXPORT_SYMBOL_GPL(pci_intx); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 667bfdd61d5e..f43873049d52 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -795,26 +795,6 @@ static inline pci_power_t mid_pci_get_power_state(struct pci_dev *pdev) } #endif -/* - * TODO: - * The following two components wouldn't need to be here if they weren't used 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 orig_intx:1; - unsigned int restore_intx:1; -}; - -struct pci_devres *find_pci_dr(struct pci_dev *pdev); - /* * Config Address for PCI Configuration Mechanism #1 * diff --git a/include/linux/pci.h b/include/linux/pci.h index 2f6f44991003..721657cb59d8 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1354,6 +1354,7 @@ int pci_try_set_mwi(struct pci_dev *dev); void pci_clear_mwi(struct pci_dev *dev); void pci_disable_parity(struct pci_dev *dev); void pci_intx(struct pci_dev *dev, int enable); +int pcim_intx(struct pci_dev *dev, int enable); bool pci_check_and_mask_intx(struct pci_dev *dev); bool pci_check_and_unmask_intx(struct pci_dev *dev); int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask); From patchwork Mon Jan 15 14:46:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Stanner X-Patchwork-Id: 13519737 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6B9BFC3DA79 for ; Mon, 15 Jan 2024 14:47:43 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E5E3B10E305; Mon, 15 Jan 2024 14:47:42 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by gabe.freedesktop.org (Postfix) with ESMTPS id 984BE10E301 for ; Mon, 15 Jan 2024 14:47:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705330055; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6EAnPeJipP0+07a3Rzv2/tb0sjf4e9bqcclnBtzQ1Hw=; b=Cx6fSw5TJk9PenIZrEnwo/hD4cq2tvNRYIczgs+yOXMTzvlEXaj9CKBe0L3DR4tFL66kRy pJsYrgYiqxg3v6Ou7GohcWWlgJkg/qufKuKMlGsNJHiDHy/3FM+KT+H8Hx3jNVVCg/SMAC BDMlAC8VTpvcbGvv9aLOrv6XTguzTz0= Received: from mail-yw1-f197.google.com (mail-yw1-f197.google.com [209.85.128.197]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-541-m_PfQ5uRNCynHMsoo1rYzw-1; Mon, 15 Jan 2024 09:47:34 -0500 X-MC-Unique: m_PfQ5uRNCynHMsoo1rYzw-1 Received: by mail-yw1-f197.google.com with SMTP id 00721157ae682-5fbfa11838cso5004597b3.1 for ; Mon, 15 Jan 2024 06:47:34 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705330054; x=1705934854; 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=6EAnPeJipP0+07a3Rzv2/tb0sjf4e9bqcclnBtzQ1Hw=; b=kQgZ8jKEB9Z0JXsH4zwiv/fqdJ7r/Pf1LlS65LN69J/UNRub+3s8YpXC5V3q8FEarn R0ao3qUWNoE4MzN0vwtDt3rT8ovpgmjGgKh/BjkMi3Op6Ui5A3wUIMVxfyQL/U+FdhF+ SRa+Auz9zJHK1ulRtiKAh7ksibn0mBq2fMXZLuKEnKEqr+TogsnSNCn0mwwIOOs4sCIq WLJ3LY9kpvZSGkd0kbpCZTFXqypEYlTe4TprrqzEwTK0gT45u7AHMrG3Q3WXpy+G6cQP +yNUpESIo/+ccKQ3+ypaiv1TzJAZDW0c5BI2lvQglCFyGNTC/rFspneikBnSQaMy+Zwn 0LDA== X-Gm-Message-State: AOJu0YwVuHq+3Yv/M51G87Qb8yrjlhVr6RAk8/iJsRbL3vo9YnQdJJzP LkIttxvU9x6PYSXmcNGRHqEjOD4fLZn4YN52u/DKpNdGQ9+/B106QA9/n2moI8J7r5OuXB0AVOE RcWCIU82A8sSUKFtbukn3WPxwEBxEVzXnGzVy X-Received: by 2002:a81:9201:0:b0:5af:778e:d53b with SMTP id j1-20020a819201000000b005af778ed53bmr4653022ywg.0.1705330053953; Mon, 15 Jan 2024 06:47:33 -0800 (PST) X-Google-Smtp-Source: AGHT+IFcCQGz1Mr7VFhpZST+41Zk2azRO3t8k7Tu1u+nJkXT6NHZsv59rkNJWBrwhybUyX7sFdqIfA== X-Received: by 2002:a81:9201:0:b0:5af:778e:d53b with SMTP id j1-20020a819201000000b005af778ed53bmr4653002ywg.0.1705330053647; Mon, 15 Jan 2024 06:47:33 -0800 (PST) Received: from pstanner-thinkpadt14sgen1.muc.redhat.com (nat-pool-muc-t.redhat.com. [149.14.88.26]) by smtp.gmail.com with ESMTPSA id ne13-20020a056214424d00b006815cf9a644sm1020720qvb.55.2024.01.15.06.47.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Jan 2024 06:47:33 -0800 (PST) From: Philipp Stanner To: Jonathan Corbet , Hans de Goede , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Daniel Vetter , Bjorn Helgaas , Philipp Stanner , Sam Ravnborg , dakr@redhat.com Subject: [PATCH 09/10] pci: devres: remove legacy pcim_release() Date: Mon, 15 Jan 2024 15:46:20 +0100 Message-ID: <20240115144655.32046-11-pstanner@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240115144655.32046-2-pstanner@redhat.com> References: <20240115144655.32046-2-pstanner@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Thanks to preceding cleanup steps, pcim_release() is now not needed anymore and can be replaced by pcim_disable_device(), which is the exact counterpart to pcim_enable_device(). This permits removing further parts of the old devres API. Replace pcim_release() with pcim_disable_device(). Remove the now surplus get_dr() function. Signed-off-by: Philipp Stanner --- drivers/pci/devres.c | 38 ++++++++------------------------------ 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/drivers/pci/devres.c b/drivers/pci/devres.c index 7c4edcaeb8fe..87bc62be21eb 100644 --- a/drivers/pci/devres.c +++ b/drivers/pci/devres.c @@ -464,48 +464,26 @@ int pcim_intx(struct pci_dev *pdev, int enable) } EXPORT_SYMBOL_GPL(pcim_intx); -static void pcim_release(struct device *gendev, void *res) +static void pcim_disable_device(void *pdev_raw) { - struct pci_dev *dev = to_pci_dev(gendev); - - if (!dev->pinned) - pci_disable_device(dev); -} - -static struct pci_devres *get_pci_dr(struct pci_dev *pdev) -{ - struct pci_devres *dr, *new_dr; - - dr = devres_find(&pdev->dev, pcim_release, NULL, NULL); - if (dr) - return dr; + struct pci_dev *pdev = pdev_raw; - new_dr = devres_alloc(pcim_release, sizeof(*new_dr), GFP_KERNEL); - if (!new_dr) - return NULL; - return devres_get(&pdev->dev, new_dr, NULL, NULL); + if (!pdev->pinned) + pci_disable_device(pdev); } /** * pcim_enable_device - Managed pci_enable_device() * @pdev: PCI device to be initialized * - * Managed pci_enable_device(). + * Managed pci_enable_device(). Device will automatically be disabled on + * driver detach. */ int pcim_enable_device(struct pci_dev *pdev) { - struct pci_devres *dr; - int rc; - - dr = get_pci_dr(pdev); - if (unlikely(!dr)) - return -ENOMEM; - - rc = pci_enable_device(pdev); - if (!rc) - pdev->is_managed = 1; + devm_add_action(&pdev->dev, pcim_disable_device, pdev); - return rc; + return pci_enable_device(pdev); } EXPORT_SYMBOL(pcim_enable_device); From patchwork Mon Jan 15 14:46:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Stanner X-Patchwork-Id: 13519738 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 34F97C3DA79 for ; Mon, 15 Jan 2024 14:47:46 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 90E6D10E2F8; Mon, 15 Jan 2024 14:47:45 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by gabe.freedesktop.org (Postfix) with ESMTPS id 22B1710E307 for ; Mon, 15 Jan 2024 14:47:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705330063; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=jIzHvpzkkigfxw83x1LWeciN350K4+qfOeyYElcXkdQ=; b=NBBlxOGKiAetLYdZkf0QQ2gR5ATofUQ02dpmCDMdRyQEJej9snWEfYiauf7qDBeKpSF5Rm fBrxNICmFy3vZSkKwYSE0LW00g1KHnKdDkRRirn6lu5v8whDrY3qTwfBu4VN7VVCB2cFKt kUE0q+DDKzbeFBsrXL2AgDN6569X20I= Received: from mail-oo1-f70.google.com (mail-oo1-f70.google.com [209.85.161.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-470-EvOWgl6eMIO28-7GrZZwgw-1; Mon, 15 Jan 2024 09:47:37 -0500 X-MC-Unique: EvOWgl6eMIO28-7GrZZwgw-1 Received: by mail-oo1-f70.google.com with SMTP id 006d021491bc7-594cafcc66aso1838910eaf.0 for ; Mon, 15 Jan 2024 06:47:37 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705330056; x=1705934856; 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=jIzHvpzkkigfxw83x1LWeciN350K4+qfOeyYElcXkdQ=; b=vQUV2t7e+XMy7Bc2uSgHGXU3iflycqsXcboCITEAGnZkZpgJhAE8FM1Ozd0C1lTkgh OmLDrOT+5IZ0yGG+pLkWUTV4ZA9pcTq4Qz7/wtMimPyC0dEInvT4+zfYkS2JcaHd7qyk 5dpdZZOZXtBdH+nmGgbBLEzNqC2HJdJoQ1+Ark/BsZUdCr+1RB7Uw/JTjjNKP7FxOFYI mqC86sFefuvDRp4fj9oY5HJViCq6F9VAINcyGEVMIrHIqo9Qe+ugvcMn/XBPzz3IBHg/ UH/Z3mwZXep65DIykA5b5JqUGxyl9SRNBGp7K+HcDZpS0A5nXR94URmHZ/R63KzG3JJu +IIQ== X-Gm-Message-State: AOJu0YzuFQuWKiPKF464OzaPyzATj9PZvgr8ToksnQkeYQiPhCSvd/ia OWXhWYkX7fPQkNzjNO6yFs7QvOA2INcheA2Pq97i9skOgd4Y6MIFqDvIuPz597KDBi8PFx/aY9E oprIKmTsn2t/Yhwosi1avWPpWZ16Nk5rh18ZU X-Received: by 2002:a4a:dd8f:0:b0:598:b2d7:2499 with SMTP id h15-20020a4add8f000000b00598b2d72499mr7707356oov.0.1705330056486; Mon, 15 Jan 2024 06:47:36 -0800 (PST) X-Google-Smtp-Source: AGHT+IHi7+XsSK011xhs3AvyU5Z7vMLQIc2V6iqOiH+OrjwaSbXs/XiSSr4Ft9JY9kxXHF9woE1zRQ== X-Received: by 2002:a4a:dd8f:0:b0:598:b2d7:2499 with SMTP id h15-20020a4add8f000000b00598b2d72499mr7707328oov.0.1705330056145; Mon, 15 Jan 2024 06:47:36 -0800 (PST) Received: from pstanner-thinkpadt14sgen1.muc.redhat.com (nat-pool-muc-t.redhat.com. [149.14.88.26]) by smtp.gmail.com with ESMTPSA id ne13-20020a056214424d00b006815cf9a644sm1020720qvb.55.2024.01.15.06.47.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Jan 2024 06:47:35 -0800 (PST) From: Philipp Stanner To: Jonathan Corbet , Hans de Goede , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Daniel Vetter , Bjorn Helgaas , Philipp Stanner , Sam Ravnborg , dakr@redhat.com Subject: [PATCH 10/10] drm/vboxvideo: fix mapping leaks Date: Mon, 15 Jan 2024 15:46:21 +0100 Message-ID: <20240115144655.32046-12-pstanner@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240115144655.32046-2-pstanner@redhat.com> References: <20240115144655.32046-2-pstanner@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-pci@vger.kernel.org, stable@kernel.vger.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" When the managed PCI-API was introduced to this driver, it was falsly assumed that initializing the device with pcim_enable_device() instead of pci_enable_device() will make all PCI functions managed. This is wrong and was caused by the quite confusing devres API for PCI: The function pci_iomap_range() is never managed. Replace pci_iomap_range() with the actually managed function pcim_iomap_range(). Additionally, add a call to pcim_request_region() to ensure exclusive access to BAR 0. CC: # v5.10+ Fixes: 8558de401b5f ("drm/vboxvideo: use managed pci functions") Signed-off-by: Philipp Stanner --- drivers/gpu/drm/vboxvideo/vbox_main.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/vboxvideo/vbox_main.c b/drivers/gpu/drm/vboxvideo/vbox_main.c index 42c2d8a99509..7f686a0190e6 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_main.c +++ b/drivers/gpu/drm/vboxvideo/vbox_main.c @@ -42,12 +42,11 @@ static int vbox_accel_init(struct vbox_private *vbox) /* Take a command buffer for each screen from the end of usable VRAM. */ vbox->available_vram_size -= vbox->num_crtcs * VBVA_MIN_BUFFER_SIZE; - vbox->vbva_buffers = pci_iomap_range(pdev, 0, - vbox->available_vram_size, - vbox->num_crtcs * - VBVA_MIN_BUFFER_SIZE); - if (!vbox->vbva_buffers) - return -ENOMEM; + vbox->vbva_buffers = pcim_iomap_range( + pdev, 0, vbox->available_vram_size, + vbox->num_crtcs * VBVA_MIN_BUFFER_SIZE); + if (IS_ERR(vbox->vbva_buffers)) + return PTR_ERR(vbox->vbva_buffers); for (i = 0; i < vbox->num_crtcs; ++i) { vbva_setup_buffer_context(&vbox->vbva_info[i], @@ -115,12 +114,15 @@ int vbox_hw_init(struct vbox_private *vbox) DRM_INFO("VRAM %08x\n", vbox->full_vram_size); + ret = pcim_request_region(pdev, 0, "vboxvideo"); + if (ret) + return ret; + /* Map guest-heap at end of vram */ - vbox->guest_heap = - pci_iomap_range(pdev, 0, GUEST_HEAP_OFFSET(vbox), - GUEST_HEAP_SIZE); - if (!vbox->guest_heap) - return -ENOMEM; + vbox->guest_heap = pcim_iomap_range(pdev, 0, + GUEST_HEAP_OFFSET(vbox), GUEST_HEAP_SIZE); + if (IS_ERR(vbox->guest_heap)) + return PTR_ERR(vbox->guest_heap); /* Create guest-heap mem-pool use 2^4 = 16 byte chunks */ vbox->guest_pool = devm_gen_pool_create(vbox->ddev.dev, 4, -1,