Centos-kernel-stream-9/drivers/pci/devres.c

1081 lines
27 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
#include <linux/device.h>
#include <linux/pci.h>
#include "pci.h"
/*
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
* 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, whereas 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().
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
*
* Users of 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:
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
* Remove the legacy table entirely once all calls to pcim_iomap_table() in
* the kernel have been removed.
*/
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
/*
* Legacy struct storing addresses to whole mapped BARs.
*/
struct pcim_iomap_devres {
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
void __iomem *table[PCI_STD_NUM_BARS];
};
/* Used to restore the old INTx state on driver detach. */
struct pcim_intx_devres {
int orig_intx;
};
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
enum pcim_addr_devres_type {
/* Default initializer. */
PCIM_ADDR_DEVRES_TYPE_INVALID,
/* A requested region spanning an entire BAR. */
PCIM_ADDR_DEVRES_TYPE_REGION,
/*
* A requested region spanning an entire BAR, and a mapping for
* the entire BAR.
*/
PCIM_ADDR_DEVRES_TYPE_REGION_MAPPING,
/*
* A mapping within a BAR, either spanning the whole BAR or just a
* range. Without a requested region.
*/
PCIM_ADDR_DEVRES_TYPE_MAPPING,
};
/*
* This struct envelops IO or MEM addresses, i.e., 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;
int bar;
};
static inline void pcim_addr_devres_clear(struct pcim_addr_devres *res)
{
memset(res, 0, sizeof(*res));
res->bar = -1;
}
/*
* 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: BAR the range is within
* @offset: offset from the BAR's start address
* @maxlen: length in bytes, beginning at @offset
* @name: name associated with the request
* @req_flags: flags for the request, e.g., for kernel-exclusive requests
*
* Returns: 0 on success, a negative error code on failure.
*
* Request a range within a device's PCI BAR. Sanity check the input.
*/
static int __pcim_request_region_range(struct pci_dev *pdev, int bar,
unsigned long offset,
unsigned long maxlen,
const char *name, int req_flags)
{
resource_size_t start = pci_resource_start(pdev, bar);
resource_size_t len = pci_resource_len(pdev, bar);
unsigned long dev_flags = pci_resource_flags(pdev, bar);
if (start == 0 || len == 0) /* Unused BAR. */
return 0;
if (len <= offset)
return -EINVAL;
start += offset;
len -= offset;
if (len > maxlen && maxlen != 0)
len = maxlen;
if (dev_flags & IORESOURCE_IO) {
if (!request_region(start, len, name))
return -EBUSY;
} else if (dev_flags & IORESOURCE_MEM) {
if (!__request_mem_region(start, len, name, req_flags))
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 flags)
{
unsigned long offset = 0;
unsigned long len = pci_resource_len(pdev, bar);
return __pcim_request_region_range(pdev, bar, offset, len, name, flags);
}
static void __pcim_release_region(struct pci_dev *pdev, int bar)
{
unsigned long offset = 0;
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;
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 by devres to identify a pcim_addr_devres.
*/
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;
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;
default:
return 0;
}
}
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
static void devm_pci_unmap_iospace(struct device *dev, void *ptr)
{
struct resource **res = ptr;
pci_unmap_iospace(*res);
}
/**
* devm_pci_remap_iospace - Managed pci_remap_iospace()
* @dev: Generic device to remap IO address for
* @res: Resource describing the I/O space
* @phys_addr: physical address of range to be mapped
*
* Managed pci_remap_iospace(). Map is automatically unmapped on driver
* detach.
*/
int devm_pci_remap_iospace(struct device *dev, const struct resource *res,
phys_addr_t phys_addr)
{
const struct resource **ptr;
int error;
ptr = devres_alloc(devm_pci_unmap_iospace, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return -ENOMEM;
error = pci_remap_iospace(res, phys_addr);
if (error) {
devres_free(ptr);
} else {
*ptr = res;
devres_add(dev, ptr);
}
return error;
}
EXPORT_SYMBOL(devm_pci_remap_iospace);
/**
* devm_pci_remap_cfgspace - Managed pci_remap_cfgspace()
* @dev: Generic device to remap IO address for
* @offset: Resource address to map
* @size: Size of map
*
* Managed pci_remap_cfgspace(). Map is automatically unmapped on driver
* detach.
*/
void __iomem *devm_pci_remap_cfgspace(struct device *dev,
resource_size_t offset,
resource_size_t size)
{
void __iomem **ptr, *addr;
ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return NULL;
addr = pci_remap_cfgspace(offset, size);
if (addr) {
*ptr = addr;
devres_add(dev, ptr);
} else
devres_free(ptr);
return addr;
}
EXPORT_SYMBOL(devm_pci_remap_cfgspace);
/**
* devm_pci_remap_cfg_resource - check, request region and ioremap cfg resource
* @dev: generic device to handle the resource for
* @res: configuration space resource to be handled
*
* Checks that a resource is a valid memory region, requests the memory
* region and ioremaps with pci_remap_cfgspace() API that ensures the
* proper PCI configuration space memory attributes are guaranteed.
*
* All operations are managed and will be undone on driver detach.
*
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
* Returns a pointer to the remapped memory or an IOMEM_ERR_PTR() encoded error
* code on failure. Usage example::
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
*
* res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
* base = devm_pci_remap_cfg_resource(&pdev->dev, res);
* if (IS_ERR(base))
* return PTR_ERR(base);
*/
void __iomem *devm_pci_remap_cfg_resource(struct device *dev,
struct resource *res)
{
resource_size_t size;
const char *name;
void __iomem *dest_ptr;
BUG_ON(!dev);
if (!res || resource_type(res) != IORESOURCE_MEM) {
dev_err(dev, "invalid resource\n");
return IOMEM_ERR_PTR(-EINVAL);
}
size = resource_size(res);
if (res->name)
name = devm_kasprintf(dev, GFP_KERNEL, "%s %s", dev_name(dev),
res->name);
else
name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
if (!name)
return IOMEM_ERR_PTR(-ENOMEM);
if (!devm_request_mem_region(dev, res->start, size, name)) {
dev_err(dev, "can't request region for resource %pR\n", res);
return IOMEM_ERR_PTR(-EBUSY);
}
dest_ptr = devm_pci_remap_cfgspace(dev, res->start, size);
if (!dest_ptr) {
dev_err(dev, "ioremap failed for resource %pR\n", res);
devm_release_mem_region(dev, res->start, size);
dest_ptr = IOMEM_ERR_PTR(-ENOMEM);
}
return dest_ptr;
}
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);
}
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
/**
* pcim_set_mwi - a device-managed pci_set_mwi()
* @pdev: the PCI device for which MWI is enabled
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
*
* Managed pci_set_mwi().
*
* RETURNS: An appropriate -ERRNO error value on error, or zero for success.
*/
int pcim_set_mwi(struct pci_dev *pdev)
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
{
int ret;
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
ret = devm_add_action(&pdev->dev, __pcim_clear_mwi, pdev);
if (ret != 0)
return ret;
ret = pci_set_mwi(pdev);
if (ret != 0)
devm_remove_action(&pdev->dev, __pcim_clear_mwi, pdev);
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
return ret;
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
}
EXPORT_SYMBOL(pcim_set_mwi);
static inline bool mask_contains_bar(int mask, int bar)
{
return mask & BIT(bar);
}
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
/*
* This is a copy of pci_intx() used to bypass the problem of recursive
* function calls due to the hybrid nature of pci_intx().
*/
static void __pcim_intx(struct pci_dev *pdev, int enable)
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
{
u16 pci_command, new;
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
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);
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
}
static void pcim_intx_restore(struct device *dev, void *data)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct pcim_intx_devres *res = data;
__pcim_intx(pdev, res->orig_intx);
}
static struct pcim_intx_devres *get_or_create_intx_devres(struct device *dev)
{
struct pcim_intx_devres *res;
res = devres_find(dev, pcim_intx_restore, NULL, NULL);
if (res)
return res;
res = devres_alloc(pcim_intx_restore, sizeof(*res), GFP_KERNEL);
if (res)
devres_add(dev, res);
return res;
}
/**
* 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.
*
* Enable/disable PCI INTx for device @pdev.
* Restore the original state on driver detach.
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
*/
int pcim_intx(struct pci_dev *pdev, int enable)
{
struct pcim_intx_devres *res;
res = get_or_create_intx_devres(&pdev->dev);
if (!res)
return -ENOMEM;
res->orig_intx = !enable;
__pcim_intx(pdev, enable);
return 0;
}
static void pcim_disable_device(void *pdev_raw)
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
{
struct pci_dev *pdev = pdev_raw;
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
if (!pdev->pinned)
pci_disable_device(pdev);
PCI: Fix potential deadlock in pcim_intx() JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: fc8c818e756991f5f50b8dfab07f970a18da2556 commit fc8c818e756991f5f50b8dfab07f970a18da2556 Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Sep 5 09:25:57 2024 +0200 PCI: Fix potential deadlock in pcim_intx() 25216afc9db5 ("PCI: Add managed pcim_intx()") moved the allocation step for pci_intx()'s device resource from pcim_enable_device() to pcim_intx(). As before, pcim_enable_device() sets pci_dev.is_managed to true; and it is never set to false again. Due to the lifecycle of a struct pci_dev, it can happen that a second driver obtains the same pci_dev after a first driver ran. If one driver uses pcim_enable_device() and the other doesn't, this causes the other driver to run into managed pcim_intx(), which will try to allocate when called for the first time. Allocations might sleep, so calling pci_intx() while holding spinlocks becomes then invalid, which causes lockdep warnings and could cause deadlocks: ======================================================== WARNING: possible irq lock inversion dependency detected 6.11.0-rc6+ #59 Tainted: G W -------------------------------------------------------- CPU 0/KVM/1537 just changed the state of lock: ffffa0f0cff965f0 (&vdev->irqlock){-...}-{2:2}, at: vfio_intx_handler+0x21/0xd0 [vfio_pci_core] but this lock took another, HARDIRQ-unsafe lock in the past: (fs_reclaim){+.+.}-{0:0} and interrupts could create inverse lock ordering between them. other info that might help us debug this: Possible interrupt unsafe locking scenario: CPU0 CPU1 ---- ---- lock(fs_reclaim); local_irq_disable(); lock(&vdev->irqlock); lock(fs_reclaim); <Interrupt> lock(&vdev->irqlock); *** DEADLOCK *** Have pcim_enable_device()'s release function, pcim_disable_device(), set pci_dev.is_managed to false so that subsequent drivers using the same struct pci_dev do not implicitly run into managed code. Link: https://lore.kernel.org/r/20240905072556.11375-2-pstanner@redhat.com Fixes: 25216afc9db5 ("PCI: Add managed pcim_intx()") Reported-by: Alex Williamson <alex.williamson@redhat.com> Closes: https://lore.kernel.org/all/20240903094431.63551744.alex.williamson@redhat.com/ Suggested-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Tested-by: Alex Williamson <alex.williamson@redhat.com> Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-29 15:42:53 +00:00
pdev->is_managed = false;
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
}
/**
* pcim_enable_device - Managed pci_enable_device()
* @pdev: PCI device to be initialized
*
* Returns: 0 on success, negative error code on failure.
*
* Managed pci_enable_device(). Device will automatically be disabled on
* driver detach.
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
*/
int pcim_enable_device(struct pci_dev *pdev)
{
int ret;
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
ret = devm_add_action(&pdev->dev, pcim_disable_device, pdev);
if (ret != 0)
return ret;
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
/*
* We prefer removing the action in case of an error over
* devm_add_action_or_reset() because the latter could theoretically be
* disturbed by users having pinned the device too soon.
*/
ret = pci_enable_device(pdev);
if (ret != 0) {
devm_remove_action(&pdev->dev, pcim_disable_device, pdev);
return ret;
}
pdev->is_managed = true;
return ret;
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
}
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().
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
*/
void pcim_pin_device(struct pci_dev *pdev)
{
pdev->pinned = true;
PCI: Move devres code from pci.c to devres.c JIRA: https://issues.redhat.com/browse/RHEL-33544 Upstream Status: 815a3909ead7440e2827042e5ec618f4396f022c commit 815a3909ead7440e2827042e5ec618f4396f022c Author: Philipp Stanner <pstanner@redhat.com> Date: Wed Jan 31 10:00:23 2024 +0100 PCI: Move devres code from pci.c to devres.c The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/20240131090023.12331-5-pstanner@redhat.com Suggested-by: Danilo Krummrich <dakr@redhat.com> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-05-04 00:42:39 +00:00
}
EXPORT_SYMBOL(pcim_pin_device);
static void pcim_iomap_release(struct device *gendev, void *res)
{
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
/*
* 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 (DEPRECATED)
* @pdev: PCI device to access iomap table for
*
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
* Returns:
* Const pointer to array of __iomem pointers on success, NULL on failure.
*
* Access iomap allocation table for @dev. If iomap table doesn't
* exist and @pdev is managed, it will be allocated. All iomaps
* recorded in the iomap table are automatically unmapped on driver
* detach.
*
* This function might sleep when the table is first allocated but can
* be safely called without context and guaranteed to succeed once
* allocated.
*
* 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, bar, length);
*/
void __iomem * const *pcim_iomap_table(struct pci_dev *pdev)
{
struct pcim_iomap_devres *dr, *new_dr;
dr = devres_find(&pdev->dev, pcim_iomap_release, NULL, NULL);
if (dr)
return dr->table;
new_dr = devres_alloc_node(pcim_iomap_release, sizeof(*new_dr), GFP_KERNEL,
dev_to_node(&pdev->dev));
if (!new_dr)
return NULL;
dr = devres_get(&pdev->dev, new_dr, NULL, NULL);
return dr->table;
}
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, int 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;
}
/*
* Remove 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)
{
int 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;
}
}
}
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
/*
* 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, int 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
*
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
* 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.
*
* NOTE:
* Contrary to the other pcim_* functions, this function does not return an
* IOMEM_ERR_PTR() on failure, but a simple NULL. This is done for backwards
* compatibility.
*/
void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
{
void __iomem *mapping;
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
struct pcim_addr_devres *res;
res = pcim_addr_devres_alloc(pdev);
if (!res)
return NULL;
res->type = PCIM_ADDR_DEVRES_TYPE_MAPPING;
mapping = pci_iomap(pdev, bar, maxlen);
if (!mapping)
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
goto err_iomap;
res->baseaddr = mapping;
if (pcim_add_mapping_to_legacy_table(pdev, mapping, bar) != 0)
goto err_table;
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
devres_add(&pdev->dev, res);
return mapping;
err_table:
pci_iounmap(pdev, mapping);
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
err_iomap:
pcim_addr_devres_free(res);
return NULL;
}
EXPORT_SYMBOL(pcim_iomap);
/**
* pcim_iounmap - Managed pci_iounmap()
* @pdev: PCI device to iounmap for
* @addr: Address to unmap
*
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
* Managed pci_iounmap(). @addr must have been mapped using a pcim_* mapping
* function.
*/
void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr)
{
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
struct pcim_addr_devres res_searched;
pcim_addr_devres_clear(&res_searched);
res_searched.type = PCIM_ADDR_DEVRES_TYPE_MAPPING;
res_searched.baseaddr = addr;
if (devres_release(&pdev->dev, pcim_addr_resource_release,
pcim_addr_resources_match, &res_searched) != 0) {
/* Doesn't exist. User passed nonsense. */
return;
}
pcim_remove_mapping_from_legacy_table(pdev, addr);
}
EXPORT_SYMBOL(pcim_iounmap);
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
/**
* 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,
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
const char *name)
{
int ret;
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);
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
/**
* 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().
*/
static 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);
}
/**
* 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
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
* @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. Do not use it in new code.
* Use pcim_iomap_region() instead.
*/
int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name)
{
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
int ret;
int bar;
void __iomem *mapping;
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
for (bar = 0; bar < DEVICE_COUNT_RESOURCE; bar++) {
if (!mask_contains_bar(mask, bar))
continue;
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
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;
}
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
return 0;
err:
while (--bar >= 0) {
pcim_iounmap_region(pdev, bar);
pcim_remove_bar_from_legacy_table(pdev, bar);
}
return ret;
}
EXPORT_SYMBOL(pcim_iomap_regions);
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
static int _pcim_request_region(struct pci_dev *pdev, int bar, const char *name,
int request_flags)
{
int ret;
struct pcim_addr_devres *res;
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
res = pcim_addr_devres_alloc(pdev);
if (!res)
return -ENOMEM;
res->type = PCIM_ADDR_DEVRES_TYPE_REGION;
res->bar = bar;
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
ret = __pcim_request_region(pdev, bar, name, request_flags);
if (ret != 0) {
pcim_addr_devres_free(res);
return ret;
}
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
devres_add(&pdev->dev, res);
return 0;
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
}
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
/**
* 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)
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
{
return _pcim_request_region(pdev, bar, name, 0);
}
EXPORT_SYMBOL(pcim_request_region);
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
/**
* 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);
}
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
/**
* 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)
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
{
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);
}
/**
* pcim_release_all_regions - Release all regions of a PCI-device
* @pdev: the PCI device
*
* 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().
*/
static void pcim_release_all_regions(struct pci_dev *pdev)
{
int bar;
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
pcim_release_region(pdev, bar);
}
/**
* pcim_request_all_regions - Request all regions
* @pdev: PCI device to map IO resources for
* @name: name associated with the request
*
* Returns: 0 on success, negative error code on failure.
*
* 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().
*/
static int pcim_request_all_regions(struct pci_dev *pdev, const char *name)
{
int ret;
int bar;
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
ret = pcim_request_region(pdev, bar, name);
if (ret != 0)
goto err;
}
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
return 0;
err:
pcim_release_all_regions(pdev);
return ret;
}
/**
* 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
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
* @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.
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
*
* 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. Instead, use one
* of the pcim_* region request functions in combination with a pcim_*
* mapping function.
*/
int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask,
const char *name)
{
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
int bar;
int ret;
void __iomem **legacy_iomap_table;
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
ret = pcim_request_all_regions(pdev, name);
if (ret != 0)
return ret;
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
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:
/*
* If bar is larger than 0, then pcim_iomap() above has most likely
* failed because of -EINVAL. If it is equal 0, most likely the table
* couldn't be created, indicating -ENOMEM.
*/
ret = bar > 0 ? -EINVAL : -ENOMEM;
legacy_iomap_table = (void __iomem **)pcim_iomap_table(pdev);
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
* @pdev: PCI device to map IO resources for
* @mask: Mask of BARs to unmap and release
*
* Unmap and release regions specified by @mask.
*/
void pcim_iounmap_regions(struct pci_dev *pdev, int mask)
{
int i;
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
for (i = 0; i < PCI_STD_NUM_BARS; i++) {
if (!mask_contains_bar(mask, i))
continue;
PCI: Add managed partial-BAR request and map infrastructure JIRA: https://issues.redhat.com/browse/RHEL-59033 Upstream Status: bbaff68bf4a404bee5f5e20e7b1e30301b26304a commit bbaff68bf4a404bee5f5e20e7b1e30301b26304a Author: Philipp Stanner <pstanner@redhat.com> Date: Thu Jun 13 13:50:16 2024 +0200 PCI: Add managed partial-BAR request and map infrastructure The pcim_iomap_devres table tracks entire-BAR mappings, so we can't use it to build a managed version of pci_iomap_range(), which maps partial BARs. Add struct pcim_addr_devres, which can track request and mapping of both entire BARs and partial BARs. Add the following internal devres functions based on struct pcim_addr_devres: pcim_iomap_region() # request & map entire BAR pcim_iounmap_region() # unmap & release entire BAR pcim_request_region() # request entire BAR pcim_release_region() # release entire BAR pcim_request_all_regions() # request all entire BARs pcim_release_all_regions() # release all entire BARs Rework the following public interfaces using the new infrastructure listed above: pcim_iomap() # map partial BAR pcim_iounmap() # unmap partial BAR pcim_iomap_regions() # request & map specified BARs pcim_iomap_regions_request_all() # request all BARs, map specified BARs pcim_iounmap_regions() # unmap & release specified BARs Link: https://lore.kernel.org/r/20240613115032.29098-4-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Myron Stowe <mstowe@redhat.com>
2024-09-16 20:51:02 +00:00
pcim_iounmap_region(pdev, i);
pcim_remove_bar_from_legacy_table(pdev, i);
}
}
EXPORT_SYMBOL(pcim_iounmap_regions);
/**
* 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);