Merge branch 'pci/resource' into next
* pci/resource: (26 commits) Revert "[PATCH] Insert GART region into resource map" PCI: Log IDE resource quirk in dmesg PCI: Change pci_bus_alloc_resource() type_mask to unsigned long PCI: Check all IORESOURCE_TYPE_BITS in pci_bus_alloc_from_region() resources: Set type in __request_region() PCI: Don't check resource_size() in pci_bus_alloc_resource() s390/PCI: Use generic pci_enable_resources() tile PCI RC: Use default pcibios_enable_device() sparc/PCI: Use default pcibios_enable_device() (Leon only) sh/PCI: Use default pcibios_enable_device() microblaze/PCI: Use default pcibios_enable_device() alpha/PCI: Use default pcibios_enable_device() PCI: Add "weak" generic pcibios_enable_device() implementation PCI: Don't enable decoding if BAR hasn't been assigned an address PCI: Mark 64-bit resource as IORESOURCE_UNSET if we only support 32-bit PCI: Don't try to claim IORESOURCE_UNSET resources PCI: Check IORESOURCE_UNSET before updating BAR PCI: Don't clear IORESOURCE_UNSET when updating BAR PCI: Mark resources as IORESOURCE_UNSET if we can't assign them PCI: Remove pci_find_parent_resource() use for allocation ...
This commit is contained in:
commit
30723cbf6f
|
@ -254,12 +254,6 @@ void pcibios_fixup_bus(struct pci_bus *bus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
pcibios_enable_device(struct pci_dev *dev, int mask)
|
|
||||||
{
|
|
||||||
return pci_enable_resources(dev, mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we set up a device for bus mastering, we need to check the latency
|
* If we set up a device for bus mastering, we need to check the latency
|
||||||
* timer as certain firmware forgets to set it properly, as seen
|
* timer as certain firmware forgets to set it properly, as seen
|
||||||
|
|
|
@ -1294,11 +1294,6 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
|
EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
|
||||||
|
|
||||||
int pcibios_enable_device(struct pci_dev *dev, int mask)
|
|
||||||
{
|
|
||||||
return pci_enable_resources(dev, mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pcibios_setup_phb_resources(struct pci_controller *hose,
|
static void pcibios_setup_phb_resources(struct pci_controller *hose,
|
||||||
struct list_head *resources)
|
struct list_head *resources)
|
||||||
{
|
{
|
||||||
|
|
|
@ -686,27 +686,13 @@ int pcibios_add_device(struct pci_dev *pdev)
|
||||||
int pcibios_enable_device(struct pci_dev *pdev, int mask)
|
int pcibios_enable_device(struct pci_dev *pdev, int mask)
|
||||||
{
|
{
|
||||||
struct zpci_dev *zdev = get_zdev(pdev);
|
struct zpci_dev *zdev = get_zdev(pdev);
|
||||||
struct resource *res;
|
|
||||||
u16 cmd;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
zdev->pdev = pdev;
|
zdev->pdev = pdev;
|
||||||
zpci_debug_init_device(zdev);
|
zpci_debug_init_device(zdev);
|
||||||
zpci_fmb_enable_device(zdev);
|
zpci_fmb_enable_device(zdev);
|
||||||
zpci_map_resources(zdev);
|
zpci_map_resources(zdev);
|
||||||
|
|
||||||
pci_read_config_word(pdev, PCI_COMMAND, &cmd);
|
return pci_enable_resources(pdev, mask);
|
||||||
for (i = 0; i < PCI_BAR_COUNT; i++) {
|
|
||||||
res = &pdev->resource[i];
|
|
||||||
|
|
||||||
if (res->flags & IORESOURCE_IO)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (res->flags & IORESOURCE_MEM)
|
|
||||||
cmd |= PCI_COMMAND_MEMORY;
|
|
||||||
}
|
|
||||||
pci_write_config_word(pdev, PCI_COMMAND, cmd);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pcibios_disable_device(struct pci_dev *pdev)
|
void pcibios_disable_device(struct pci_dev *pdev)
|
||||||
|
|
|
@ -186,11 +186,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pcibios_enable_device(struct pci_dev *dev, int mask)
|
|
||||||
{
|
|
||||||
return pci_enable_resources(dev, mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __init
|
static void __init
|
||||||
pcibios_bus_report_status_early(struct pci_channel *hose,
|
pcibios_bus_report_status_early(struct pci_channel *hose,
|
||||||
int top_bus, int current_bus,
|
int top_bus, int current_bus,
|
||||||
|
|
|
@ -99,11 +99,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
|
||||||
return res->start;
|
return res->start;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pcibios_enable_device(struct pci_dev *dev, int mask)
|
|
||||||
{
|
|
||||||
return pci_enable_resources(dev, mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* in/out routines taken from pcic.c
|
/* in/out routines taken from pcic.c
|
||||||
*
|
*
|
||||||
* This probably belongs here rather than ioport.c because
|
* This probably belongs here rather than ioport.c because
|
||||||
|
|
|
@ -1064,18 +1064,6 @@ char *__init pcibios_setup(char *str)
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Enable memory address decoding, as appropriate, for the
|
|
||||||
* device described by the 'dev' struct.
|
|
||||||
*
|
|
||||||
* This is called from the generic PCI layer, and can be called
|
|
||||||
* for bridges or endpoints.
|
|
||||||
*/
|
|
||||||
int pcibios_enable_device(struct pci_dev *dev, int mask)
|
|
||||||
{
|
|
||||||
return pci_enable_resources(dev, mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called for each device after PCI setup is done.
|
* Called for each device after PCI setup is done.
|
||||||
* We initialize the PCI device capabilities conservatively, assuming that
|
* We initialize the PCI device capabilities conservatively, assuming that
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include <linux/pci_ids.h>
|
#include <linux/pci_ids.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/ioport.h>
|
|
||||||
#include <linux/suspend.h>
|
#include <linux/suspend.h>
|
||||||
#include <asm/e820.h>
|
#include <asm/e820.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
@ -54,18 +53,6 @@ int fallback_aper_force __initdata;
|
||||||
|
|
||||||
int fix_aperture __initdata = 1;
|
int fix_aperture __initdata = 1;
|
||||||
|
|
||||||
static struct resource gart_resource = {
|
|
||||||
.name = "GART",
|
|
||||||
.flags = IORESOURCE_MEM,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void __init insert_aperture_resource(u32 aper_base, u32 aper_size)
|
|
||||||
{
|
|
||||||
gart_resource.start = aper_base;
|
|
||||||
gart_resource.end = aper_base + aper_size - 1;
|
|
||||||
insert_resource(&iomem_resource, &gart_resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This code runs before the PCI subsystem is initialized, so just
|
/* This code runs before the PCI subsystem is initialized, so just
|
||||||
access the northbridge directly. */
|
access the northbridge directly. */
|
||||||
|
|
||||||
|
@ -96,7 +83,6 @@ static u32 __init allocate_aperture(void)
|
||||||
memblock_reserve(addr, aper_size);
|
memblock_reserve(addr, aper_size);
|
||||||
printk(KERN_INFO "Mapping aperture over %d KB of RAM @ %lx\n",
|
printk(KERN_INFO "Mapping aperture over %d KB of RAM @ %lx\n",
|
||||||
aper_size >> 10, addr);
|
aper_size >> 10, addr);
|
||||||
insert_aperture_resource((u32)addr, aper_size);
|
|
||||||
register_nosave_region(addr >> PAGE_SHIFT,
|
register_nosave_region(addr >> PAGE_SHIFT,
|
||||||
(addr+aper_size) >> PAGE_SHIFT);
|
(addr+aper_size) >> PAGE_SHIFT);
|
||||||
|
|
||||||
|
@ -444,12 +430,8 @@ int __init gart_iommu_hole_init(void)
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (!fix && !fallback_aper_force) {
|
if (!fix && !fallback_aper_force) {
|
||||||
if (last_aper_base) {
|
if (last_aper_base)
|
||||||
unsigned long n = (32 * 1024 * 1024) << last_aper_order;
|
|
||||||
|
|
||||||
insert_aperture_resource((u32)last_aper_base, n);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -652,6 +652,44 @@ static int i2o_iop_activate(struct i2o_controller *c)
|
||||||
return i2o_hrt_get(c);
|
return i2o_hrt_get(c);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void i2o_res_alloc(struct i2o_controller *c, unsigned long flags)
|
||||||
|
{
|
||||||
|
i2o_status_block *sb = c->status_block.virt;
|
||||||
|
struct resource *res = &c->mem_resource;
|
||||||
|
resource_size_t size, align;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
res->name = c->pdev->bus->name;
|
||||||
|
res->flags = flags;
|
||||||
|
res->start = 0;
|
||||||
|
res->end = 0;
|
||||||
|
osm_info("%s: requires private memory resources.\n", c->name);
|
||||||
|
|
||||||
|
if (flags & IORESOURCE_MEM) {
|
||||||
|
size = sb->desired_mem_size;
|
||||||
|
align = 1 << 20; /* unspecified, use 1Mb and play safe */
|
||||||
|
} else {
|
||||||
|
size = sb->desired_io_size;
|
||||||
|
align = 1 << 12; /* unspecified, use 4Kb and play safe */
|
||||||
|
}
|
||||||
|
|
||||||
|
err = pci_bus_alloc_resource(c->pdev->bus, res, size, align, 0, 0,
|
||||||
|
NULL, NULL);
|
||||||
|
if (err < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (flags & IORESOURCE_MEM) {
|
||||||
|
c->mem_alloc = 1;
|
||||||
|
sb->current_mem_size = resource_size(res);
|
||||||
|
sb->current_mem_base = res->start;
|
||||||
|
} else if (flags & IORESOURCE_IO) {
|
||||||
|
c->io_alloc = 1;
|
||||||
|
sb->current_io_size = resource_size(res);
|
||||||
|
sb->current_io_base = res->start;
|
||||||
|
}
|
||||||
|
osm_info("%s: allocated PCI space %pR\n", c->name, res);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* i2o_iop_systab_set - Set the I2O System Table of the specified IOP
|
* i2o_iop_systab_set - Set the I2O System Table of the specified IOP
|
||||||
* @c: I2O controller to which the system table should be send
|
* @c: I2O controller to which the system table should be send
|
||||||
|
@ -665,52 +703,13 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
|
||||||
struct i2o_message *msg;
|
struct i2o_message *msg;
|
||||||
i2o_status_block *sb = c->status_block.virt;
|
i2o_status_block *sb = c->status_block.virt;
|
||||||
struct device *dev = &c->pdev->dev;
|
struct device *dev = &c->pdev->dev;
|
||||||
struct resource *root;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (sb->current_mem_size < sb->desired_mem_size) {
|
if (sb->current_mem_size < sb->desired_mem_size)
|
||||||
struct resource *res = &c->mem_resource;
|
i2o_res_alloc(c, IORESOURCE_MEM);
|
||||||
res->name = c->pdev->bus->name;
|
|
||||||
res->flags = IORESOURCE_MEM;
|
|
||||||
res->start = 0;
|
|
||||||
res->end = 0;
|
|
||||||
osm_info("%s: requires private memory resources.\n", c->name);
|
|
||||||
root = pci_find_parent_resource(c->pdev, res);
|
|
||||||
if (root == NULL)
|
|
||||||
osm_warn("%s: Can't find parent resource!\n", c->name);
|
|
||||||
if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */
|
|
||||||
NULL, NULL) >= 0) {
|
|
||||||
c->mem_alloc = 1;
|
|
||||||
sb->current_mem_size = resource_size(res);
|
|
||||||
sb->current_mem_base = res->start;
|
|
||||||
osm_info("%s: allocated %llu bytes of PCI memory at "
|
|
||||||
"0x%016llX.\n", c->name,
|
|
||||||
(unsigned long long)resource_size(res),
|
|
||||||
(unsigned long long)res->start);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sb->current_io_size < sb->desired_io_size) {
|
if (sb->current_io_size < sb->desired_io_size)
|
||||||
struct resource *res = &c->io_resource;
|
i2o_res_alloc(c, IORESOURCE_IO);
|
||||||
res->name = c->pdev->bus->name;
|
|
||||||
res->flags = IORESOURCE_IO;
|
|
||||||
res->start = 0;
|
|
||||||
res->end = 0;
|
|
||||||
osm_info("%s: requires private memory resources.\n", c->name);
|
|
||||||
root = pci_find_parent_resource(c->pdev, res);
|
|
||||||
if (root == NULL)
|
|
||||||
osm_warn("%s: Can't find parent resource!\n", c->name);
|
|
||||||
if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */
|
|
||||||
NULL, NULL) >= 0) {
|
|
||||||
c->io_alloc = 1;
|
|
||||||
sb->current_io_size = resource_size(res);
|
|
||||||
sb->current_mem_base = res->start;
|
|
||||||
osm_info("%s: allocated %llu bytes of PCI I/O at "
|
|
||||||
"0x%016llX.\n", c->name,
|
|
||||||
(unsigned long long)resource_size(res),
|
|
||||||
(unsigned long long)res->start);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
|
msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
|
||||||
if (IS_ERR(msg))
|
if (IS_ERR(msg))
|
||||||
|
|
|
@ -132,7 +132,7 @@ static void pci_clip_resource_to_region(struct pci_bus *bus,
|
||||||
|
|
||||||
static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
|
static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
|
||||||
resource_size_t size, resource_size_t align,
|
resource_size_t size, resource_size_t align,
|
||||||
resource_size_t min, unsigned int type_mask,
|
resource_size_t min, unsigned long type_mask,
|
||||||
resource_size_t (*alignf)(void *,
|
resource_size_t (*alignf)(void *,
|
||||||
const struct resource *,
|
const struct resource *,
|
||||||
resource_size_t,
|
resource_size_t,
|
||||||
|
@ -144,7 +144,7 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
|
||||||
struct resource *r, avail;
|
struct resource *r, avail;
|
||||||
resource_size_t max;
|
resource_size_t max;
|
||||||
|
|
||||||
type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
|
type_mask |= IORESOURCE_TYPE_BITS;
|
||||||
|
|
||||||
pci_bus_for_each_resource(bus, r, i) {
|
pci_bus_for_each_resource(bus, r, i) {
|
||||||
if (!r)
|
if (!r)
|
||||||
|
@ -162,8 +162,6 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
|
||||||
|
|
||||||
avail = *r;
|
avail = *r;
|
||||||
pci_clip_resource_to_region(bus, &avail, region);
|
pci_clip_resource_to_region(bus, &avail, region);
|
||||||
if (!resource_size(&avail))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "min" is typically PCIBIOS_MIN_IO or PCIBIOS_MIN_MEM to
|
* "min" is typically PCIBIOS_MIN_IO or PCIBIOS_MIN_MEM to
|
||||||
|
@ -202,7 +200,7 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
|
||||||
*/
|
*/
|
||||||
int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
|
int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
|
||||||
resource_size_t size, resource_size_t align,
|
resource_size_t size, resource_size_t align,
|
||||||
resource_size_t min, unsigned int type_mask,
|
resource_size_t min, unsigned long type_mask,
|
||||||
resource_size_t (*alignf)(void *,
|
resource_size_t (*alignf)(void *,
|
||||||
const struct resource *,
|
const struct resource *,
|
||||||
resource_size_t,
|
resource_size_t,
|
||||||
|
|
|
@ -32,11 +32,6 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
|
||||||
bridge->release_data = release_data;
|
bridge->release_data = release_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool resource_contains(struct resource *res1, struct resource *res2)
|
|
||||||
{
|
|
||||||
return res1->start <= res2->start && res1->end >= res2->end;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
|
void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
|
||||||
struct resource *res)
|
struct resource *res)
|
||||||
{
|
{
|
||||||
|
@ -45,9 +40,6 @@ void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
|
||||||
resource_size_t offset = 0;
|
resource_size_t offset = 0;
|
||||||
|
|
||||||
list_for_each_entry(window, &bridge->windows, list) {
|
list_for_each_entry(window, &bridge->windows, list) {
|
||||||
if (resource_type(res) != resource_type(window->res))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (resource_contains(window->res, res)) {
|
if (resource_contains(window->res, res)) {
|
||||||
offset = window->offset;
|
offset = window->offset;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -401,33 +401,40 @@ EXPORT_SYMBOL_GPL(pci_find_ht_capability);
|
||||||
* @res: child resource record for which parent is sought
|
* @res: child resource record for which parent is sought
|
||||||
*
|
*
|
||||||
* For given resource region of given device, return the resource
|
* For given resource region of given device, return the resource
|
||||||
* region of parent bus the given region is contained in or where
|
* region of parent bus the given region is contained in.
|
||||||
* it should be allocated from.
|
|
||||||
*/
|
*/
|
||||||
struct resource *
|
struct resource *
|
||||||
pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
|
pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
|
||||||
{
|
{
|
||||||
const struct pci_bus *bus = dev->bus;
|
const struct pci_bus *bus = dev->bus;
|
||||||
|
struct resource *r;
|
||||||
int i;
|
int i;
|
||||||
struct resource *best = NULL, *r;
|
|
||||||
|
|
||||||
pci_bus_for_each_resource(bus, r, i) {
|
pci_bus_for_each_resource(bus, r, i) {
|
||||||
if (!r)
|
if (!r)
|
||||||
continue;
|
continue;
|
||||||
if (res->start && !(res->start >= r->start && res->end <= r->end))
|
if (res->start && resource_contains(r, res)) {
|
||||||
continue; /* Not contained */
|
|
||||||
if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM))
|
/*
|
||||||
continue; /* Wrong type */
|
* If the window is prefetchable but the BAR is
|
||||||
if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH))
|
* not, the allocator made a mistake.
|
||||||
return r; /* Exact match */
|
*/
|
||||||
/* We can't insert a non-prefetch resource inside a prefetchable parent .. */
|
if (r->flags & IORESOURCE_PREFETCH &&
|
||||||
if (r->flags & IORESOURCE_PREFETCH)
|
!(res->flags & IORESOURCE_PREFETCH))
|
||||||
continue;
|
return NULL;
|
||||||
/* .. but we can put a prefetchable resource inside a non-prefetchable one */
|
|
||||||
if (!best)
|
/*
|
||||||
best = r;
|
* If we're below a transparent bridge, there may
|
||||||
|
* be both a positively-decoded aperture and a
|
||||||
|
* subtractively-decoded region that contain the BAR.
|
||||||
|
* We want the positively-decoded one, so this depends
|
||||||
|
* on pci_bus_for_each_resource() giving us those
|
||||||
|
* first.
|
||||||
|
*/
|
||||||
|
return r;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return best;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1178,6 +1185,11 @@ int pci_load_and_free_saved_state(struct pci_dev *dev,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(pci_load_and_free_saved_state);
|
EXPORT_SYMBOL_GPL(pci_load_and_free_saved_state);
|
||||||
|
|
||||||
|
int __weak pcibios_enable_device(struct pci_dev *dev, int bars)
|
||||||
|
{
|
||||||
|
return pci_enable_resources(dev, bars);
|
||||||
|
}
|
||||||
|
|
||||||
static int do_pci_enable_device(struct pci_dev *dev, int bars)
|
static int do_pci_enable_device(struct pci_dev *dev, int bars)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
@ -4262,6 +4274,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
|
||||||
"Rounding up size of resource #%d to %#llx.\n",
|
"Rounding up size of resource #%d to %#llx.\n",
|
||||||
i, (unsigned long long)size);
|
i, (unsigned long long)size);
|
||||||
}
|
}
|
||||||
|
r->flags |= IORESOURCE_UNSET;
|
||||||
r->end = size - 1;
|
r->end = size - 1;
|
||||||
r->start = 0;
|
r->start = 0;
|
||||||
}
|
}
|
||||||
|
@ -4275,6 +4288,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
|
||||||
r = &dev->resource[i];
|
r = &dev->resource[i];
|
||||||
if (!(r->flags & IORESOURCE_MEM))
|
if (!(r->flags & IORESOURCE_MEM))
|
||||||
continue;
|
continue;
|
||||||
|
r->flags |= IORESOURCE_UNSET;
|
||||||
r->end = resource_size(r) - 1;
|
r->end = resource_size(r) - 1;
|
||||||
r->start = 0;
|
r->start = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -252,6 +252,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
||||||
/* Address above 32-bit boundary; disable the BAR */
|
/* Address above 32-bit boundary; disable the BAR */
|
||||||
pci_write_config_dword(dev, pos, 0);
|
pci_write_config_dword(dev, pos, 0);
|
||||||
pci_write_config_dword(dev, pos + 4, 0);
|
pci_write_config_dword(dev, pos + 4, 0);
|
||||||
|
res->flags |= IORESOURCE_UNSET;
|
||||||
region.start = 0;
|
region.start = 0;
|
||||||
region.end = sz64;
|
region.end = sz64;
|
||||||
bar_disabled = true;
|
bar_disabled = true;
|
||||||
|
@ -1107,10 +1108,10 @@ int pci_setup_device(struct pci_dev *dev)
|
||||||
pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &dev->subsystem_device);
|
pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &dev->subsystem_device);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do the ugly legacy mode stuff here rather than broken chip
|
* Do the ugly legacy mode stuff here rather than broken chip
|
||||||
* quirk code. Legacy mode ATA controllers have fixed
|
* quirk code. Legacy mode ATA controllers have fixed
|
||||||
* addresses. These are not always echoed in BAR0-3, and
|
* addresses. These are not always echoed in BAR0-3, and
|
||||||
* BAR0-3 in a few cases contain junk!
|
* BAR0-3 in a few cases contain junk!
|
||||||
*/
|
*/
|
||||||
if (class == PCI_CLASS_STORAGE_IDE) {
|
if (class == PCI_CLASS_STORAGE_IDE) {
|
||||||
u8 progif;
|
u8 progif;
|
||||||
|
@ -1121,11 +1122,15 @@ int pci_setup_device(struct pci_dev *dev)
|
||||||
res = &dev->resource[0];
|
res = &dev->resource[0];
|
||||||
res->flags = LEGACY_IO_RESOURCE;
|
res->flags = LEGACY_IO_RESOURCE;
|
||||||
pcibios_bus_to_resource(dev->bus, res, ®ion);
|
pcibios_bus_to_resource(dev->bus, res, ®ion);
|
||||||
|
dev_info(&dev->dev, "legacy IDE quirk: reg 0x10: %pR\n",
|
||||||
|
res);
|
||||||
region.start = 0x3F6;
|
region.start = 0x3F6;
|
||||||
region.end = 0x3F6;
|
region.end = 0x3F6;
|
||||||
res = &dev->resource[1];
|
res = &dev->resource[1];
|
||||||
res->flags = LEGACY_IO_RESOURCE;
|
res->flags = LEGACY_IO_RESOURCE;
|
||||||
pcibios_bus_to_resource(dev->bus, res, ®ion);
|
pcibios_bus_to_resource(dev->bus, res, ®ion);
|
||||||
|
dev_info(&dev->dev, "legacy IDE quirk: reg 0x14: %pR\n",
|
||||||
|
res);
|
||||||
}
|
}
|
||||||
if ((progif & 4) == 0) {
|
if ((progif & 4) == 0) {
|
||||||
region.start = 0x170;
|
region.start = 0x170;
|
||||||
|
@ -1133,11 +1138,15 @@ int pci_setup_device(struct pci_dev *dev)
|
||||||
res = &dev->resource[2];
|
res = &dev->resource[2];
|
||||||
res->flags = LEGACY_IO_RESOURCE;
|
res->flags = LEGACY_IO_RESOURCE;
|
||||||
pcibios_bus_to_resource(dev->bus, res, ®ion);
|
pcibios_bus_to_resource(dev->bus, res, ®ion);
|
||||||
|
dev_info(&dev->dev, "legacy IDE quirk: reg 0x18: %pR\n",
|
||||||
|
res);
|
||||||
region.start = 0x376;
|
region.start = 0x376;
|
||||||
region.end = 0x376;
|
region.end = 0x376;
|
||||||
res = &dev->resource[3];
|
res = &dev->resource[3];
|
||||||
res->flags = LEGACY_IO_RESOURCE;
|
res->flags = LEGACY_IO_RESOURCE;
|
||||||
pcibios_bus_to_resource(dev->bus, res, ®ion);
|
pcibios_bus_to_resource(dev->bus, res, ®ion);
|
||||||
|
dev_info(&dev->dev, "legacy IDE quirk: reg 0x1c: %pR\n",
|
||||||
|
res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -296,6 +296,7 @@ static void quirk_s3_64M(struct pci_dev *dev)
|
||||||
struct resource *r = &dev->resource[0];
|
struct resource *r = &dev->resource[0];
|
||||||
|
|
||||||
if ((r->start & 0x3ffffff) || r->end != r->start + 0x3ffffff) {
|
if ((r->start & 0x3ffffff) || r->end != r->start + 0x3ffffff) {
|
||||||
|
r->flags |= IORESOURCE_UNSET;
|
||||||
r->start = 0;
|
r->start = 0;
|
||||||
r->end = 0x3ffffff;
|
r->end = 0x3ffffff;
|
||||||
}
|
}
|
||||||
|
@ -937,6 +938,8 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C
|
||||||
static void quirk_dunord(struct pci_dev *dev)
|
static void quirk_dunord(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
struct resource *r = &dev->resource [1];
|
struct resource *r = &dev->resource [1];
|
||||||
|
|
||||||
|
r->flags |= IORESOURCE_UNSET;
|
||||||
r->start = 0;
|
r->start = 0;
|
||||||
r->end = 0xffffff;
|
r->end = 0xffffff;
|
||||||
}
|
}
|
||||||
|
@ -1740,6 +1743,7 @@ static void quirk_tc86c001_ide(struct pci_dev *dev)
|
||||||
struct resource *r = &dev->resource[0];
|
struct resource *r = &dev->resource[0];
|
||||||
|
|
||||||
if (r->start & 0x8) {
|
if (r->start & 0x8) {
|
||||||
|
r->flags |= IORESOURCE_UNSET;
|
||||||
r->start = 0;
|
r->start = 0;
|
||||||
r->end = 0xf;
|
r->end = 0xf;
|
||||||
}
|
}
|
||||||
|
@ -1769,6 +1773,7 @@ static void quirk_plx_pci9050(struct pci_dev *dev)
|
||||||
dev_info(&dev->dev,
|
dev_info(&dev->dev,
|
||||||
"Re-allocating PLX PCI 9050 BAR %u to length 256 to avoid bit 7 bug\n",
|
"Re-allocating PLX PCI 9050 BAR %u to length 256 to avoid bit 7 bug\n",
|
||||||
bar);
|
bar);
|
||||||
|
r->flags |= IORESOURCE_UNSET;
|
||||||
r->start = 0;
|
r->start = 0;
|
||||||
r->end = 0xff;
|
r->end = 0xff;
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,8 +197,10 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
|
||||||
void pci_cleanup_rom(struct pci_dev *pdev)
|
void pci_cleanup_rom(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
|
struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
|
||||||
|
|
||||||
if (res->flags & IORESOURCE_ROM_COPY) {
|
if (res->flags & IORESOURCE_ROM_COPY) {
|
||||||
kfree((void*)(unsigned long)res->start);
|
kfree((void*)(unsigned long)res->start);
|
||||||
|
res->flags |= IORESOURCE_UNSET;
|
||||||
res->flags &= ~IORESOURCE_ROM_COPY;
|
res->flags &= ~IORESOURCE_ROM_COPY;
|
||||||
res->start = 0;
|
res->start = 0;
|
||||||
res->end = 0;
|
res->end = 0;
|
||||||
|
|
|
@ -44,6 +44,9 @@ void pci_update_resource(struct pci_dev *dev, int resno)
|
||||||
if (!res->flags)
|
if (!res->flags)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (res->flags & IORESOURCE_UNSET)
|
||||||
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ignore non-moveable resources. This might be legacy resources for
|
* Ignore non-moveable resources. This might be legacy resources for
|
||||||
* which no functional BAR register exists or another important
|
* which no functional BAR register exists or another important
|
||||||
|
@ -101,11 +104,6 @@ void pci_update_resource(struct pci_dev *dev, int resno)
|
||||||
|
|
||||||
if (disable)
|
if (disable)
|
||||||
pci_write_config_word(dev, PCI_COMMAND, cmd);
|
pci_write_config_word(dev, PCI_COMMAND, cmd);
|
||||||
|
|
||||||
res->flags &= ~IORESOURCE_UNSET;
|
|
||||||
dev_dbg(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n",
|
|
||||||
resno, res, (unsigned long long)region.start,
|
|
||||||
(unsigned long long)region.end);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int pci_claim_resource(struct pci_dev *dev, int resource)
|
int pci_claim_resource(struct pci_dev *dev, int resource)
|
||||||
|
@ -113,18 +111,23 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
|
||||||
struct resource *res = &dev->resource[resource];
|
struct resource *res = &dev->resource[resource];
|
||||||
struct resource *root, *conflict;
|
struct resource *root, *conflict;
|
||||||
|
|
||||||
|
if (res->flags & IORESOURCE_UNSET) {
|
||||||
|
dev_info(&dev->dev, "can't claim BAR %d %pR: no address assigned\n",
|
||||||
|
resource, res);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
root = pci_find_parent_resource(dev, res);
|
root = pci_find_parent_resource(dev, res);
|
||||||
if (!root) {
|
if (!root) {
|
||||||
dev_info(&dev->dev, "no compatible bridge window for %pR\n",
|
dev_info(&dev->dev, "can't claim BAR %d %pR: no compatible bridge window\n",
|
||||||
res);
|
resource, res);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
conflict = request_resource_conflict(root, res);
|
conflict = request_resource_conflict(root, res);
|
||||||
if (conflict) {
|
if (conflict) {
|
||||||
dev_info(&dev->dev,
|
dev_info(&dev->dev, "can't claim BAR %d %pR: address conflict with %s %pR\n",
|
||||||
"address space collision: %pR conflicts with %s %pR\n",
|
resource, res, conflict->name, conflict);
|
||||||
res, conflict->name, conflict);
|
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,6 +266,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
|
||||||
resource_size_t align, size;
|
resource_size_t align, size;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
res->flags |= IORESOURCE_UNSET;
|
||||||
align = pci_resource_alignment(dev, res);
|
align = pci_resource_alignment(dev, res);
|
||||||
if (!align) {
|
if (!align) {
|
||||||
dev_info(&dev->dev, "BAR %d: can't assign %pR "
|
dev_info(&dev->dev, "BAR %d: can't assign %pR "
|
||||||
|
@ -282,6 +286,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
|
||||||
ret = pci_revert_fw_address(res, dev, resno, size);
|
ret = pci_revert_fw_address(res, dev, resno, size);
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
|
res->flags &= ~IORESOURCE_UNSET;
|
||||||
res->flags &= ~IORESOURCE_STARTALIGN;
|
res->flags &= ~IORESOURCE_STARTALIGN;
|
||||||
dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
|
dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
|
||||||
if (resno < PCI_BRIDGE_RESOURCES)
|
if (resno < PCI_BRIDGE_RESOURCES)
|
||||||
|
@ -297,6 +302,7 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz
|
||||||
resource_size_t new_size;
|
resource_size_t new_size;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
res->flags |= IORESOURCE_UNSET;
|
||||||
if (!res->parent) {
|
if (!res->parent) {
|
||||||
dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resource %pR "
|
dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resource %pR "
|
||||||
"\n", resno, res);
|
"\n", resno, res);
|
||||||
|
@ -307,6 +313,7 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz
|
||||||
new_size = resource_size(res) + addsize;
|
new_size = resource_size(res) + addsize;
|
||||||
ret = _pci_assign_resource(dev, resno, new_size, min_align);
|
ret = _pci_assign_resource(dev, resno, new_size, min_align);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
|
res->flags &= ~IORESOURCE_UNSET;
|
||||||
res->flags &= ~IORESOURCE_STARTALIGN;
|
res->flags &= ~IORESOURCE_STARTALIGN;
|
||||||
dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res);
|
dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res);
|
||||||
if (resno < PCI_BRIDGE_RESOURCES)
|
if (resno < PCI_BRIDGE_RESOURCES)
|
||||||
|
@ -336,9 +343,15 @@ int pci_enable_resources(struct pci_dev *dev, int mask)
|
||||||
(!(r->flags & IORESOURCE_ROM_ENABLE)))
|
(!(r->flags & IORESOURCE_ROM_ENABLE)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (r->flags & IORESOURCE_UNSET) {
|
||||||
|
dev_err(&dev->dev, "can't enable device: BAR %d %pR not assigned\n",
|
||||||
|
i, r);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!r->parent) {
|
if (!r->parent) {
|
||||||
dev_err(&dev->dev, "device not available "
|
dev_err(&dev->dev, "can't enable device: BAR %d %pR not claimed\n",
|
||||||
"(can't reserve %pR)\n", r);
|
i, r);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ struct resource {
|
||||||
|
|
||||||
#define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */
|
#define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */
|
||||||
#define IORESOURCE_DISABLED 0x10000000
|
#define IORESOURCE_DISABLED 0x10000000
|
||||||
#define IORESOURCE_UNSET 0x20000000
|
#define IORESOURCE_UNSET 0x20000000 /* No address assigned yet */
|
||||||
#define IORESOURCE_AUTO 0x40000000
|
#define IORESOURCE_AUTO 0x40000000
|
||||||
#define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */
|
#define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */
|
||||||
|
|
||||||
|
@ -169,6 +169,16 @@ static inline unsigned long resource_type(const struct resource *res)
|
||||||
{
|
{
|
||||||
return res->flags & IORESOURCE_TYPE_BITS;
|
return res->flags & IORESOURCE_TYPE_BITS;
|
||||||
}
|
}
|
||||||
|
/* True iff r1 completely contains r2 */
|
||||||
|
static inline bool resource_contains(struct resource *r1, struct resource *r2)
|
||||||
|
{
|
||||||
|
if (resource_type(r1) != resource_type(r2))
|
||||||
|
return false;
|
||||||
|
if (r1->flags & IORESOURCE_UNSET || r2->flags & IORESOURCE_UNSET)
|
||||||
|
return false;
|
||||||
|
return r1->start <= r2->start && r1->end >= r2->end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Convenience shorthand with allocation */
|
/* Convenience shorthand with allocation */
|
||||||
#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0)
|
#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0)
|
||||||
|
|
|
@ -1066,7 +1066,7 @@ void pci_bus_remove_resources(struct pci_bus *bus);
|
||||||
int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
|
int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
|
||||||
struct resource *res, resource_size_t size,
|
struct resource *res, resource_size_t size,
|
||||||
resource_size_t align, resource_size_t min,
|
resource_size_t align, resource_size_t min,
|
||||||
unsigned int type_mask,
|
unsigned long type_mask,
|
||||||
resource_size_t (*alignf)(void *,
|
resource_size_t (*alignf)(void *,
|
||||||
const struct resource *,
|
const struct resource *,
|
||||||
resource_size_t,
|
resource_size_t,
|
||||||
|
|
|
@ -432,11 +432,6 @@ static void resource_clip(struct resource *res, resource_size_t min,
|
||||||
res->end = max;
|
res->end = max;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool resource_contains(struct resource *res1, struct resource *res2)
|
|
||||||
{
|
|
||||||
return res1->start <= res2->start && res1->end >= res2->end;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find empty slot in the resource tree with the given range and
|
* Find empty slot in the resource tree with the given range and
|
||||||
* alignment constraints
|
* alignment constraints
|
||||||
|
@ -471,10 +466,11 @@ static int __find_resource(struct resource *root, struct resource *old,
|
||||||
arch_remove_reservations(&tmp);
|
arch_remove_reservations(&tmp);
|
||||||
|
|
||||||
/* Check for overflow after ALIGN() */
|
/* Check for overflow after ALIGN() */
|
||||||
avail = *new;
|
|
||||||
avail.start = ALIGN(tmp.start, constraint->align);
|
avail.start = ALIGN(tmp.start, constraint->align);
|
||||||
avail.end = tmp.end;
|
avail.end = tmp.end;
|
||||||
|
avail.flags = new->flags & ~IORESOURCE_UNSET;
|
||||||
if (avail.start >= tmp.start) {
|
if (avail.start >= tmp.start) {
|
||||||
|
alloc.flags = avail.flags;
|
||||||
alloc.start = constraint->alignf(constraint->alignf_data, &avail,
|
alloc.start = constraint->alignf(constraint->alignf_data, &avail,
|
||||||
size, constraint->align);
|
size, constraint->align);
|
||||||
alloc.end = alloc.start + size - 1;
|
alloc.end = alloc.start + size - 1;
|
||||||
|
@ -949,8 +945,8 @@ struct resource * __request_region(struct resource *parent,
|
||||||
res->name = name;
|
res->name = name;
|
||||||
res->start = start;
|
res->start = start;
|
||||||
res->end = start + n - 1;
|
res->end = start + n - 1;
|
||||||
res->flags = IORESOURCE_BUSY;
|
res->flags = resource_type(parent);
|
||||||
res->flags |= flags;
|
res->flags |= IORESOURCE_BUSY | flags;
|
||||||
|
|
||||||
write_lock(&resource_lock);
|
write_lock(&resource_lock);
|
||||||
|
|
||||||
|
|
|
@ -719,10 +719,15 @@ char *resource_string(char *buf, char *end, struct resource *res,
|
||||||
specp = &mem_spec;
|
specp = &mem_spec;
|
||||||
decode = 0;
|
decode = 0;
|
||||||
}
|
}
|
||||||
p = number(p, pend, res->start, *specp);
|
if (decode && res->flags & IORESOURCE_UNSET) {
|
||||||
if (res->start != res->end) {
|
p = string(p, pend, "size ", str_spec);
|
||||||
*p++ = '-';
|
p = number(p, pend, resource_size(res), *specp);
|
||||||
p = number(p, pend, res->end, *specp);
|
} else {
|
||||||
|
p = number(p, pend, res->start, *specp);
|
||||||
|
if (res->start != res->end) {
|
||||||
|
*p++ = '-';
|
||||||
|
p = number(p, pend, res->end, *specp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (decode) {
|
if (decode) {
|
||||||
if (res->flags & IORESOURCE_MEM_64)
|
if (res->flags & IORESOURCE_MEM_64)
|
||||||
|
|
Loading…
Reference in a new issue