mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 00:22:00 +02:00
Merge branch 'pci/devres'
- Enlarge the devres table[] to accommodate bridge windows, ROM, IOV BARs, etc (Philipp Stanner) - Validate BAR index in devres interfaces (Philipp Stanner) * pci/devres: PCI: Check BAR index for validity PCI: Fix wrong length of devres array
This commit is contained in:
commit
67b9f18202
|
|
@ -40,7 +40,7 @@
|
|||
* Legacy struct storing addresses to whole mapped BARs.
|
||||
*/
|
||||
struct pcim_iomap_devres {
|
||||
void __iomem *table[PCI_STD_NUM_BARS];
|
||||
void __iomem *table[PCI_NUM_RESOURCES];
|
||||
};
|
||||
|
||||
/* Used to restore the old INTx state on driver detach. */
|
||||
|
|
@ -577,7 +577,7 @@ static int pcim_add_mapping_to_legacy_table(struct pci_dev *pdev,
|
|||
{
|
||||
void __iomem **legacy_iomap_table;
|
||||
|
||||
if (bar >= PCI_STD_NUM_BARS)
|
||||
if (!pci_bar_index_is_valid(bar))
|
||||
return -EINVAL;
|
||||
|
||||
legacy_iomap_table = (void __iomem **)pcim_iomap_table(pdev);
|
||||
|
|
@ -622,7 +622,7 @@ 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)
|
||||
if (!pci_bar_index_is_valid(bar))
|
||||
return;
|
||||
|
||||
legacy_iomap_table = (void __iomem **)pcim_iomap_table(pdev);
|
||||
|
|
@ -655,6 +655,9 @@ void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
|
|||
void __iomem *mapping;
|
||||
struct pcim_addr_devres *res;
|
||||
|
||||
if (!pci_bar_index_is_valid(bar))
|
||||
return NULL;
|
||||
|
||||
res = pcim_addr_devres_alloc(pdev);
|
||||
if (!res)
|
||||
return NULL;
|
||||
|
|
@ -722,6 +725,9 @@ void __iomem *pcim_iomap_region(struct pci_dev *pdev, int bar,
|
|||
int ret;
|
||||
struct pcim_addr_devres *res;
|
||||
|
||||
if (!pci_bar_index_is_valid(bar))
|
||||
return IOMEM_ERR_PTR(-EINVAL);
|
||||
|
||||
res = pcim_addr_devres_alloc(pdev);
|
||||
if (!res)
|
||||
return IOMEM_ERR_PTR(-ENOMEM);
|
||||
|
|
@ -823,6 +829,9 @@ static int _pcim_request_region(struct pci_dev *pdev, int bar, const char *name,
|
|||
int ret;
|
||||
struct pcim_addr_devres *res;
|
||||
|
||||
if (!pci_bar_index_is_valid(bar))
|
||||
return -EINVAL;
|
||||
|
||||
res = pcim_addr_devres_alloc(pdev);
|
||||
if (!res)
|
||||
return -ENOMEM;
|
||||
|
|
@ -991,6 +1000,9 @@ void __iomem *pcim_iomap_range(struct pci_dev *pdev, int bar,
|
|||
void __iomem *mapping;
|
||||
struct pcim_addr_devres *res;
|
||||
|
||||
if (!pci_bar_index_is_valid(bar))
|
||||
return IOMEM_ERR_PTR(-EINVAL);
|
||||
|
||||
res = pcim_addr_devres_alloc(pdev);
|
||||
if (!res)
|
||||
return IOMEM_ERR_PTR(-ENOMEM);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#include <linux/export.h>
|
||||
|
||||
#include "pci.h" /* for pci_bar_index_is_valid() */
|
||||
|
||||
/**
|
||||
* pci_iomap_range - create a virtual mapping cookie for a PCI BAR
|
||||
* @dev: PCI device that owns the BAR
|
||||
|
|
@ -33,12 +35,19 @@ void __iomem *pci_iomap_range(struct pci_dev *dev,
|
|||
unsigned long offset,
|
||||
unsigned long maxlen)
|
||||
{
|
||||
resource_size_t start = pci_resource_start(dev, bar);
|
||||
resource_size_t len = pci_resource_len(dev, bar);
|
||||
unsigned long flags = pci_resource_flags(dev, bar);
|
||||
resource_size_t start, len;
|
||||
unsigned long flags;
|
||||
|
||||
if (!pci_bar_index_is_valid(bar))
|
||||
return NULL;
|
||||
|
||||
start = pci_resource_start(dev, bar);
|
||||
len = pci_resource_len(dev, bar);
|
||||
flags = pci_resource_flags(dev, bar);
|
||||
|
||||
if (len <= offset || !start)
|
||||
return NULL;
|
||||
|
||||
len -= offset;
|
||||
start += offset;
|
||||
if (maxlen && len > maxlen)
|
||||
|
|
@ -77,16 +86,20 @@ void __iomem *pci_iomap_wc_range(struct pci_dev *dev,
|
|||
unsigned long offset,
|
||||
unsigned long maxlen)
|
||||
{
|
||||
resource_size_t start = pci_resource_start(dev, bar);
|
||||
resource_size_t len = pci_resource_len(dev, bar);
|
||||
unsigned long flags = pci_resource_flags(dev, bar);
|
||||
resource_size_t start, len;
|
||||
unsigned long flags;
|
||||
|
||||
|
||||
if (flags & IORESOURCE_IO)
|
||||
if (!pci_bar_index_is_valid(bar))
|
||||
return NULL;
|
||||
|
||||
start = pci_resource_start(dev, bar);
|
||||
len = pci_resource_len(dev, bar);
|
||||
flags = pci_resource_flags(dev, bar);
|
||||
|
||||
if (len <= offset || !start)
|
||||
return NULL;
|
||||
if (flags & IORESOURCE_IO)
|
||||
return NULL;
|
||||
|
||||
len -= offset;
|
||||
start += offset;
|
||||
|
|
|
|||
|
|
@ -3929,6 +3929,9 @@ EXPORT_SYMBOL(pci_enable_atomic_ops_to_root);
|
|||
*/
|
||||
void pci_release_region(struct pci_dev *pdev, int bar)
|
||||
{
|
||||
if (!pci_bar_index_is_valid(bar))
|
||||
return;
|
||||
|
||||
/*
|
||||
* This is done for backwards compatibility, because the old PCI devres
|
||||
* API had a mode in which the function became managed if it had been
|
||||
|
|
@ -3973,6 +3976,9 @@ EXPORT_SYMBOL(pci_release_region);
|
|||
static int __pci_request_region(struct pci_dev *pdev, int bar,
|
||||
const char *name, int exclusive)
|
||||
{
|
||||
if (!pci_bar_index_is_valid(bar))
|
||||
return -EINVAL;
|
||||
|
||||
if (pci_is_managed(pdev)) {
|
||||
if (exclusive == IORESOURCE_EXCLUSIVE)
|
||||
return pcim_request_region_exclusive(pdev, bar, name);
|
||||
|
|
|
|||
|
|
@ -167,6 +167,22 @@ static inline void pci_wakeup_event(struct pci_dev *dev)
|
|||
pm_wakeup_event(&dev->dev, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_bar_index_is_valid - Check whether a BAR index is within valid range
|
||||
* @bar: BAR index
|
||||
*
|
||||
* Protects against overflowing &struct pci_dev.resource array.
|
||||
*
|
||||
* Return: true for valid index, false otherwise.
|
||||
*/
|
||||
static inline bool pci_bar_index_is_valid(int bar)
|
||||
{
|
||||
if (bar >= 0 && bar < PCI_NUM_RESOURCES)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool pci_has_subordinate(struct pci_dev *pci_dev)
|
||||
{
|
||||
return !!(pci_dev->subordinate);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user