Commit 71c54597 authored by David S. Miller's avatar David S. Miller

Model Sparc64 pci_assign_resource more closely to the

implementation in drivers/pci/setup-res.c to make it
easier to track bugs.

Fix calculation of mem_space end on Sparc64 Schizo PCI controllers.
The decode register is set up for the whole 4GB even though the
top 2GB is reserved for DMA to/from main memory (ie. IOMMU translated)
parent c92b7ab8
...@@ -234,33 +234,63 @@ int pci_claim_resource(struct pci_dev *pdev, int resource) ...@@ -234,33 +234,63 @@ int pci_claim_resource(struct pci_dev *pdev, int resource)
return request_resource(root, res); return request_resource(root, res);
} }
/*
* Given the PCI bus a device resides on, try to
* find an acceptable resource allocation for a
* specific device resource..
*/
static int pci_assign_bus_resource(const struct pci_bus *bus,
struct pci_dev *dev,
struct resource *res,
unsigned long size,
unsigned long min,
int resno)
{
unsigned int type_mask;
int i;
type_mask = IORESOURCE_IO | IORESOURCE_MEM;
for (i = 0 ; i < 4; i++) {
struct resource *r = bus->resource[i];
if (!r)
continue;
/* type_mask must match */
if ((res->flags ^ r->flags) & type_mask)
continue;
/* Ok, try it out.. */
if (allocate_resource(r, res, size, min, -1, size, NULL, NULL) < 0)
continue;
/* PCI config space updated by caller. */
return 0;
}
return -EBUSY;
}
int pci_assign_resource(struct pci_dev *pdev, int resource) int pci_assign_resource(struct pci_dev *pdev, int resource)
{ {
struct pcidev_cookie *pcp = pdev->sysdata; struct pcidev_cookie *pcp = pdev->sysdata;
struct pci_pbm_info *pbm = pcp->pbm; struct pci_pbm_info *pbm = pcp->pbm;
struct resource *res = &pdev->resource[resource]; struct resource *res = &pdev->resource[resource];
struct resource *root; unsigned long min, size;
unsigned long min, max, size, align;
int err; int err;
if (res->flags & IORESOURCE_IO) { if (res->flags & IORESOURCE_IO)
root = &pbm->io_space; min = pbm->io_space.start + 0x400UL;
min = root->start + 0x400UL; else
max = root->end; min = pbm->mem_space.start;
} else {
root = &pbm->mem_space; size = res->end - res->start + 1;
min = root->start;
max = min + 0x80000000UL;
}
size = res->end - res->start; err = pci_assign_bus_resource(pdev->bus, pdev, res, size, min, resource);
align = size + 1;
err = allocate_resource(root, res, size + 1, min, max, align, NULL, NULL);
if (err < 0) { if (err < 0) {
printk("PCI: Failed to allocate resource %d for %s\n", printk("PCI: Failed to allocate resource %d for %s\n",
resource, pdev->name); resource, pdev->name);
} else { } else {
/* Update PCI config space. */
pbm->parent->base_address_update(pdev, resource); pbm->parent->base_address_update(pdev, resource);
} }
......
...@@ -1483,24 +1483,12 @@ static void __init schizo_resource_adjust(struct pci_dev *pdev, ...@@ -1483,24 +1483,12 @@ static void __init schizo_resource_adjust(struct pci_dev *pdev,
#define SCHIZO_PCI_B_IO_MATCH 0x00070UL #define SCHIZO_PCI_B_IO_MATCH 0x00070UL
#define SCHIZO_PCI_B_IO_MASK 0x00078UL #define SCHIZO_PCI_B_IO_MASK 0x00078UL
/* VAL must be non-zero. */
static unsigned long strip_to_lowest_bit_set(unsigned long val)
{
unsigned long tmp;
tmp = 1UL;
while (!(tmp & val))
tmp <<= 1UL;
return tmp;
}
static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm, static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm,
int is_pbm_a, unsigned long reg_base) int is_pbm_a, unsigned long reg_base)
{ {
u64 mem_match, mem_mask; u64 mem_match, mem_mask;
u64 io_match; u64 io_match;
u64 long a, b; u64 a;
if (is_pbm_a) { if (is_pbm_a) {
mem_match = reg_base + SCHIZO_PCI_A_MEM_MATCH; mem_match = reg_base + SCHIZO_PCI_A_MEM_MATCH;
...@@ -1512,11 +1500,12 @@ static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm, ...@@ -1512,11 +1500,12 @@ static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm,
mem_mask = mem_match + 0x8UL; mem_mask = mem_match + 0x8UL;
a = schizo_read(mem_match) & ~0x8000000000000000UL; a = schizo_read(mem_match) & ~0x8000000000000000UL;
b = strip_to_lowest_bit_set(schizo_read(mem_mask));
/* It should be 2GB in size. */ /* It should be 2GB in size but the decode is set for the full
* 4GB so we have to add the 2G by hand.
*/
pbm->mem_space.start = a; pbm->mem_space.start = a;
pbm->mem_space.end = a + (b - 1UL); pbm->mem_space.end = a + 0x80000000;
pbm->mem_space.flags = IORESOURCE_MEM; pbm->mem_space.flags = IORESOURCE_MEM;
/* This 32MB area is divided into two pieces. The first /* This 32MB area is divided into two pieces. The first
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment