2014-01-07 00:55:18

by Bjorn Helgaas

[permalink] [raw]
Subject: [PATCH v7 00/15] PCI: Allocate 64-bit BARs above 4G when possible

This is basically v7 of Yinghai's patch series:
http://lkml.kernel.org/r/[email protected]

The goal is to try to put 64-bit BARs above 4G so we can preserve the
32-bit bus address space for 32-bit BARs.

There are a whole bunch of AGP updates at the beginning because some AGP
devices have 64-bit BARs, but most of the AGP drivers read the aperture
bus address directly from the BAR, and they only handle 32-bit BARs.
Putting BARs above 4G would break those drivers, so we tried to fix them
up first. Yinghai fixed intel-gtt.c, and I made similar fixes to all
the other AGP drivers I could find.

Some of the AGP updates are related to the fact that most of the drivers
assume the PCI bus address is the same as the CPU physical address. For
example, they read the bus address from the BAR, then call ioremap() on
it. This is wrong, because ioremap() expects a CPU physical address,
not a bus address. In most cases, I think AGP devices are in simple
systems where (bus_address == CPU_physical_address), so these updates
probably don't fix any broken systems. I'm pretty sure there are more
things like this that should be fixed.

The important PCI changes are the last two:

PCI: Enforce bus address limits in resource allocation
PCI: Allocate 64-bit BARs above 4G when possible

The first fixes a long-standing bug: we would never assign space to a
32-bit BAR if the *CPU* address didn't fit in 32 bits. But the important
thing is the *bus* address, and that may fit in 32 bits even if the CPU
address doesn't.

The second is the one that tries to allocate space above 4G for 64-bit
BARs. If that fails, we fall back to allocating space anywhere. It's
possible this will expose other broken drivers that can't deal with
64-bit BARs being above 4G.

I kept Yinghai as the author of the patches that originated with him,
but I reworked them substantially to try to simplify the series, so any
bugs here are most likely my fault. If my rework made things worse, or
if it makes your life difficult, I will consider doing something
different; just let me know.

---

Bjorn Helgaas (11):
PCI: Change pci_bus_region addresses to dma_addr_t
PCI: Add pci_bus_address() to get bus address of a BAR
agp: Support 64-bit APBASE
agp: Use pci_resource_start() to get CPU physical address for BAR
drm/i915: Rename gtt_bus_addr to gtt_phys_addr
agp/intel: Rename gtt_bus_addr to gtt_phys_addr
agp/intel: Use pci_bus_address() to get MMADR bus address
agp/intel: Use pci_bus_address() to get GTTADR bus address
agp/intel: Use CPU physical address, not bus address, for ioremap()
agp/ati: Use PCI_COMMAND instead of hard-coded 4
PCI: Split out bridge window override of minimum allocation address

Yinghai Lu (4):
PCI: Convert pcibios_resource_to_bus() to take a pci_bus, not a pci_dev
agp/intel: Support 64-bit GMADR
PCI: Enforce bus address limits in resource allocation
PCI: Allocate 64-bit BARs above 4G when possible


arch/alpha/kernel/pci-sysfs.c | 4 +
arch/powerpc/kernel/pci-common.c | 4 +
arch/powerpc/kernel/pci_of_scan.c | 4 +
arch/sparc/kernel/pci.c | 6 +-
arch/x86/include/asm/pci.h | 1
drivers/char/agp/agp.h | 1
drivers/char/agp/ali-agp.c | 4 +
drivers/char/agp/amd-k7-agp.c | 14 ++--
drivers/char/agp/amd64-agp.c | 5 -
drivers/char/agp/ati-agp.c | 21 +++---
drivers/char/agp/efficeon-agp.c | 5 +
drivers/char/agp/generic.c | 4 +
drivers/char/agp/intel-agp.c | 48 +++++--------
drivers/char/agp/intel-agp.h | 10 +--
drivers/char/agp/intel-gtt.c | 47 +++++--------
drivers/char/agp/nvidia-agp.c | 9 +-
drivers/char/agp/sis-agp.c | 5 +
drivers/char/agp/via-agp.c | 13 ++--
drivers/gpu/drm/i915/i915_gem_gtt.c | 6 +-
drivers/pci/bus.c | 128 +++++++++++++++++++++++++++--------
drivers/pci/host-bridge.c | 19 ++---
drivers/pci/probe.c | 18 ++---
drivers/pci/quirks.c | 2 -
drivers/pci/rom.c | 2 -
drivers/pci/setup-bus.c | 16 ++--
drivers/pci/setup-res.c | 2 -
drivers/pcmcia/i82092.c | 2 -
drivers/pcmcia/yenta_socket.c | 6 +-
drivers/scsi/sym53c8xx_2/sym_glue.c | 5 +
drivers/video/arkfb.c | 2 -
drivers/video/s3fb.c | 2 -
drivers/video/vt8623fb.c | 2 -
include/linux/pci.h | 20 +++--
33 files changed, 241 insertions(+), 196 deletions(-)


2014-01-07 00:55:27

by Bjorn Helgaas

[permalink] [raw]
Subject: [PATCH v7 01/15] PCI: Change pci_bus_region addresses to dma_addr_t

Struct pci_bus_region contains bus addresses, which are type dma_addr_t,
not resource_size_t.

Signed-off-by: Bjorn Helgaas <[email protected]>
---
include/linux/pci.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/pci.h b/include/linux/pci.h
index 1084a15175e0..7d5555270491 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -551,8 +551,8 @@ int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
int reg, int len, u32 val);

struct pci_bus_region {
- resource_size_t start;
- resource_size_t end;
+ dma_addr_t start;
+ dma_addr_t end;
};

struct pci_dynids {

2014-01-07 00:55:33

by Bjorn Helgaas

[permalink] [raw]
Subject: [PATCH v7 02/15] PCI: Convert pcibios_resource_to_bus() to take a pci_bus, not a pci_dev

From: Yinghai Lu <[email protected]>

These interfaces:

pcibios_resource_to_bus(struct pci_dev *dev, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_dev *dev, *resource, *bus_region)

took a pci_dev, but they really depend only on the pci_bus. And we want to
use them in resource allocation paths where we have the bus but not a
device, so this patch converts them to take the pci_bus instead of the
pci_dev:

pcibios_resource_to_bus(struct pci_bus *bus, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_bus *bus, *resource, *bus_region)

In fact, with standard PCI-PCI bridges, they only depend on the host
bridge, because that's the only place address translation occurs, but
we aren't going that far yet.

[bhelgaas: changelog]
Signed-off-by: Yinghai Lu <[email protected]>
Signed-off-by: Bjorn Helgaas <[email protected]>
---
arch/alpha/kernel/pci-sysfs.c | 4 ++--
arch/powerpc/kernel/pci-common.c | 4 ++--
arch/powerpc/kernel/pci_of_scan.c | 4 ++--
arch/sparc/kernel/pci.c | 6 +++---
drivers/pci/host-bridge.c | 19 ++++++++-----------
drivers/pci/probe.c | 18 +++++++++---------
drivers/pci/quirks.c | 2 +-
drivers/pci/rom.c | 2 +-
drivers/pci/setup-bus.c | 16 ++++++++--------
drivers/pci/setup-res.c | 2 +-
drivers/pcmcia/i82092.c | 2 +-
drivers/pcmcia/yenta_socket.c | 6 +++---
drivers/scsi/sym53c8xx_2/sym_glue.c | 5 +++--
drivers/video/arkfb.c | 2 +-
drivers/video/s3fb.c | 2 +-
drivers/video/vt8623fb.c | 2 +-
include/linux/pci.h | 4 ++--
17 files changed, 49 insertions(+), 51 deletions(-)

diff --git a/arch/alpha/kernel/pci-sysfs.c b/arch/alpha/kernel/pci-sysfs.c
index 2b183b0d3207..99e8d4796c96 100644
--- a/arch/alpha/kernel/pci-sysfs.c
+++ b/arch/alpha/kernel/pci-sysfs.c
@@ -83,7 +83,7 @@ static int pci_mmap_resource(struct kobject *kobj,
if (iomem_is_exclusive(res->start))
return -EINVAL;

- pcibios_resource_to_bus(pdev, &bar, res);
+ pcibios_resource_to_bus(pdev->bus, &bar, res);
vma->vm_pgoff += bar.start >> (PAGE_SHIFT - (sparse ? 5 : 0));
mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;

@@ -139,7 +139,7 @@ static int sparse_mem_mmap_fits(struct pci_dev *pdev, int num)
long dense_offset;
unsigned long sparse_size;

- pcibios_resource_to_bus(pdev, &bar, &pdev->resource[num]);
+ pcibios_resource_to_bus(pdev->bus, &bar, &pdev->resource[num]);

/* All core logic chips have 4G sparse address space, except
CIA which has 16G (see xxx_SPARSE_MEM and xxx_DENSE_MEM
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index a1e3e40ca3fd..d9476c1fc959 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -835,7 +835,7 @@ static void pcibios_fixup_resources(struct pci_dev *dev)
* at 0 as unset as well, except if PCI_PROBE_ONLY is also set
* since in that case, we don't want to re-assign anything
*/
- pcibios_resource_to_bus(dev, &reg, res);
+ pcibios_resource_to_bus(dev->bus, &reg, res);
if (pci_has_flag(PCI_REASSIGN_ALL_RSRC) ||
(reg.start == 0 && !pci_has_flag(PCI_PROBE_ONLY))) {
/* Only print message if not re-assigning */
@@ -886,7 +886,7 @@ static int pcibios_uninitialized_bridge_resource(struct pci_bus *bus,

/* Job is a bit different between memory and IO */
if (res->flags & IORESOURCE_MEM) {
- pcibios_resource_to_bus(dev, &region, res);
+ pcibios_resource_to_bus(dev->bus, &region, res);

/* If the BAR is non-0 then it's probably been initialized */
if (region.start != 0)
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c
index ac0b034f9ae0..83c26d829991 100644
--- a/arch/powerpc/kernel/pci_of_scan.c
+++ b/arch/powerpc/kernel/pci_of_scan.c
@@ -111,7 +111,7 @@ static void of_pci_parse_addrs(struct device_node *node, struct pci_dev *dev)
res->name = pci_name(dev);
region.start = base;
region.end = base + size - 1;
- pcibios_bus_to_resource(dev, res, &region);
+ pcibios_bus_to_resource(dev->bus, res, &region);
}
}

@@ -280,7 +280,7 @@ void of_scan_pci_bridge(struct pci_dev *dev)
res->flags = flags;
region.start = of_read_number(&ranges[1], 2);
region.end = region.start + size - 1;
- pcibios_bus_to_resource(dev, res, &region);
+ pcibios_bus_to_resource(dev->bus, res, &region);
}
sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
bus->number);
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index cb021453de2a..7de8d1f590b7 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -392,7 +392,7 @@ static void apb_fake_ranges(struct pci_dev *dev,
res->flags = IORESOURCE_IO;
region.start = (first << 21);
region.end = (last << 21) + ((1 << 21) - 1);
- pcibios_bus_to_resource(dev, res, &region);
+ pcibios_bus_to_resource(dev->bus, res, &region);

pci_read_config_byte(dev, APB_MEM_ADDRESS_MAP, &map);
apb_calc_first_last(map, &first, &last);
@@ -400,7 +400,7 @@ static void apb_fake_ranges(struct pci_dev *dev,
res->flags = IORESOURCE_MEM;
region.start = (first << 29);
region.end = (last << 29) + ((1 << 29) - 1);
- pcibios_bus_to_resource(dev, res, &region);
+ pcibios_bus_to_resource(dev->bus, res, &region);
}

static void pci_of_scan_bus(struct pci_pbm_info *pbm,
@@ -491,7 +491,7 @@ static void of_scan_pci_bridge(struct pci_pbm_info *pbm,
res->flags = flags;
region.start = GET_64BIT(ranges, 1);
region.end = region.start + size - 1;
- pcibios_bus_to_resource(dev, res, &region);
+ pcibios_bus_to_resource(dev->bus, res, &region);
}
after_ranges:
sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index a68dc613a5be..06ace6248c61 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -9,22 +9,19 @@

#include "pci.h"

-static struct pci_bus *find_pci_root_bus(struct pci_dev *dev)
+static struct pci_bus *find_pci_root_bus(struct pci_bus *bus)
{
- struct pci_bus *bus;
-
- bus = dev->bus;
while (bus->parent)
bus = bus->parent;

return bus;
}

-static struct pci_host_bridge *find_pci_host_bridge(struct pci_dev *dev)
+static struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus)
{
- struct pci_bus *bus = find_pci_root_bus(dev);
+ struct pci_bus *root_bus = find_pci_root_bus(bus);

- return to_pci_host_bridge(bus->bridge);
+ return to_pci_host_bridge(root_bus->bridge);
}

void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
@@ -40,10 +37,10 @@ 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_dev *dev, struct pci_bus_region *region,
+void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
struct resource *res)
{
- struct pci_host_bridge *bridge = find_pci_host_bridge(dev);
+ struct pci_host_bridge *bridge = find_pci_host_bridge(bus);
struct pci_host_bridge_window *window;
resource_size_t offset = 0;

@@ -68,10 +65,10 @@ static bool region_contains(struct pci_bus_region *region1,
return region1->start <= region2->start && region1->end >= region2->end;
}

-void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,
struct pci_bus_region *region)
{
- struct pci_host_bridge *bridge = find_pci_host_bridge(dev);
+ struct pci_host_bridge *bridge = find_pci_host_bridge(bus);
struct pci_host_bridge_window *window;
resource_size_t offset = 0;

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 38e403dddf6e..f049e3f53fcc 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -269,8 +269,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
region.end = l + sz;
}

- pcibios_bus_to_resource(dev, res, &region);
- pcibios_resource_to_bus(dev, &inverted_region, res);
+ pcibios_bus_to_resource(dev->bus, res, &region);
+ pcibios_resource_to_bus(dev->bus, &inverted_region, res);

/*
* If "A" is a BAR value (a bus address), "bus_to_resource(A)" is
@@ -364,7 +364,7 @@ static void pci_read_bridge_io(struct pci_bus *child)
res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
region.start = base;
region.end = limit + io_granularity - 1;
- pcibios_bus_to_resource(dev, res, &region);
+ pcibios_bus_to_resource(dev->bus, res, &region);
dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
}
}
@@ -386,7 +386,7 @@ static void pci_read_bridge_mmio(struct pci_bus *child)
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
region.start = base;
region.end = limit + 0xfffff;
- pcibios_bus_to_resource(dev, res, &region);
+ pcibios_bus_to_resource(dev->bus, res, &region);
dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
}
}
@@ -436,7 +436,7 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child)
res->flags |= IORESOURCE_MEM_64;
region.start = base;
region.end = limit + 0xfffff;
- pcibios_bus_to_resource(dev, res, &region);
+ pcibios_bus_to_resource(dev->bus, res, &region);
dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
}
}
@@ -1084,24 +1084,24 @@ int pci_setup_device(struct pci_dev *dev)
region.end = 0x1F7;
res = &dev->resource[0];
res->flags = LEGACY_IO_RESOURCE;
- pcibios_bus_to_resource(dev, res, &region);
+ pcibios_bus_to_resource(dev->bus, res, &region);
region.start = 0x3F6;
region.end = 0x3F6;
res = &dev->resource[1];
res->flags = LEGACY_IO_RESOURCE;
- pcibios_bus_to_resource(dev, res, &region);
+ pcibios_bus_to_resource(dev->bus, res, &region);
}
if ((progif & 4) == 0) {
region.start = 0x170;
region.end = 0x177;
res = &dev->resource[2];
res->flags = LEGACY_IO_RESOURCE;
- pcibios_bus_to_resource(dev, res, &region);
+ pcibios_bus_to_resource(dev->bus, res, &region);
region.start = 0x376;
region.end = 0x376;
res = &dev->resource[3];
res->flags = LEGACY_IO_RESOURCE;
- pcibios_bus_to_resource(dev, res, &region);
+ pcibios_bus_to_resource(dev->bus, res, &region);
}
}
break;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index b3b1b9aa8863..4ad6bf6c107b 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -343,7 +343,7 @@ static void quirk_io_region(struct pci_dev *dev, int port,
/* Convert from PCI bus to resource space */
bus_region.start = region;
bus_region.end = region + size - 1;
- pcibios_bus_to_resource(dev, res, &bus_region);
+ pcibios_bus_to_resource(dev->bus, res, &bus_region);

if (!pci_claim_resource(dev, nr))
dev_info(&dev->dev, "quirk: %pR claimed by %s\n", res, name);
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index c5d0a08a8747..5d595724e5f4 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -31,7 +31,7 @@ int pci_enable_rom(struct pci_dev *pdev)
if (!res->flags)
return -1;

- pcibios_resource_to_bus(pdev, &region, res);
+ pcibios_resource_to_bus(pdev->bus, &region, res);
pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
rom_addr &= ~PCI_ROM_ADDRESS_MASK;
rom_addr |= region.start | PCI_ROM_ADDRESS_ENABLE;
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 219a4106480a..79339822d80e 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -475,7 +475,7 @@ void pci_setup_cardbus(struct pci_bus *bus)
&bus->busn_res);

res = bus->resource[0];
- pcibios_resource_to_bus(bridge, &region, res);
+ pcibios_resource_to_bus(bridge->bus, &region, res);
if (res->flags & IORESOURCE_IO) {
/*
* The IO resource is allocated a range twice as large as it
@@ -489,7 +489,7 @@ void pci_setup_cardbus(struct pci_bus *bus)
}

res = bus->resource[1];
- pcibios_resource_to_bus(bridge, &region, res);
+ pcibios_resource_to_bus(bridge->bus, &region, res);
if (res->flags & IORESOURCE_IO) {
dev_info(&bridge->dev, " bridge window %pR\n", res);
pci_write_config_dword(bridge, PCI_CB_IO_BASE_1,
@@ -499,7 +499,7 @@ void pci_setup_cardbus(struct pci_bus *bus)
}

res = bus->resource[2];
- pcibios_resource_to_bus(bridge, &region, res);
+ pcibios_resource_to_bus(bridge->bus, &region, res);
if (res->flags & IORESOURCE_MEM) {
dev_info(&bridge->dev, " bridge window %pR\n", res);
pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0,
@@ -509,7 +509,7 @@ void pci_setup_cardbus(struct pci_bus *bus)
}

res = bus->resource[3];
- pcibios_resource_to_bus(bridge, &region, res);
+ pcibios_resource_to_bus(bridge->bus, &region, res);
if (res->flags & IORESOURCE_MEM) {
dev_info(&bridge->dev, " bridge window %pR\n", res);
pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1,
@@ -546,7 +546,7 @@ static void pci_setup_bridge_io(struct pci_bus *bus)

/* Set up the top and bottom of the PCI I/O segment for this bus. */
res = bus->resource[0];
- pcibios_resource_to_bus(bridge, &region, res);
+ pcibios_resource_to_bus(bridge->bus, &region, res);
if (res->flags & IORESOURCE_IO) {
pci_read_config_dword(bridge, PCI_IO_BASE, &l);
l &= 0xffff0000;
@@ -578,7 +578,7 @@ static void pci_setup_bridge_mmio(struct pci_bus *bus)

/* Set up the top and bottom of the PCI Memory segment for this bus. */
res = bus->resource[1];
- pcibios_resource_to_bus(bridge, &region, res);
+ pcibios_resource_to_bus(bridge->bus, &region, res);
if (res->flags & IORESOURCE_MEM) {
l = (region.start >> 16) & 0xfff0;
l |= region.end & 0xfff00000;
@@ -604,7 +604,7 @@ static void pci_setup_bridge_mmio_pref(struct pci_bus *bus)
/* Set up PREF base/limit. */
bu = lu = 0;
res = bus->resource[2];
- pcibios_resource_to_bus(bridge, &region, res);
+ pcibios_resource_to_bus(bridge->bus, &region, res);
if (res->flags & IORESOURCE_PREFETCH) {
l = (region.start >> 16) & 0xfff0;
l |= region.end & 0xfff00000;
@@ -1422,7 +1422,7 @@ static int iov_resources_unassigned(struct pci_dev *dev, void *data)
if (!r->flags)
continue;

- pcibios_resource_to_bus(dev, &region, r);
+ pcibios_resource_to_bus(dev->bus, &region, r);
if (!region.start) {
*unassigned = true;
return 1; /* return early from pci_walk_bus() */
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 83c4d3bc47ab..5c060b152ce6 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -52,7 +52,7 @@ void pci_update_resource(struct pci_dev *dev, int resno)
if (res->flags & IORESOURCE_PCI_FIXED)
return;

- pcibios_resource_to_bus(dev, &region, res);
+ pcibios_resource_to_bus(dev->bus, &region, res);

new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
if (res->flags & IORESOURCE_IO)
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index 519c4d6003a6..7d47456429a1 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -608,7 +608,7 @@ static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_

enter("i82092aa_set_mem_map");

- pcibios_resource_to_bus(sock_info->dev, &region, mem->res);
+ pcibios_resource_to_bus(sock_info->dev->bus, &region, mem->res);

map = mem->map;
if (map > 4) {
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index dc18a3a5e010..8485761e76af 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -445,7 +445,7 @@ static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *
unsigned int start, stop, card_start;
unsigned short word;

- pcibios_resource_to_bus(socket->dev, &region, mem->res);
+ pcibios_resource_to_bus(socket->dev->bus, &region, mem->res);

map = mem->map;
start = region.start;
@@ -709,7 +709,7 @@ static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type
region.start = config_readl(socket, addr_start) & mask;
region.end = config_readl(socket, addr_end) | ~mask;
if (region.start && region.end > region.start && !override_bios) {
- pcibios_bus_to_resource(dev, res, &region);
+ pcibios_bus_to_resource(dev->bus, res, &region);
if (pci_claim_resource(dev, PCI_BRIDGE_RESOURCES + nr) == 0)
return 0;
dev_printk(KERN_INFO, &dev->dev,
@@ -1033,7 +1033,7 @@ static void yenta_config_init(struct yenta_socket *socket)
struct pci_dev *dev = socket->dev;
struct pci_bus_region region;

- pcibios_resource_to_bus(socket->dev, &region, &dev->resource[0]);
+ pcibios_resource_to_bus(socket->dev->bus, &region, &dev->resource[0]);

config_writel(socket, CB_LEGACY_MODE_BASE, 0);
config_writel(socket, PCI_BASE_ADDRESS_0, region.start);
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index bac55f7f69f9..6d3ee1ab6362 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -1531,7 +1531,7 @@ static int sym_iomap_device(struct sym_device *device)
struct pci_bus_region bus_addr;
int i = 2;

- pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[1]);
+ pcibios_resource_to_bus(pdev->bus, &bus_addr, &pdev->resource[1]);
device->mmio_base = bus_addr.start;

if (device->chip.features & FE_RAM) {
@@ -1541,7 +1541,8 @@ static int sym_iomap_device(struct sym_device *device)
*/
if (!pdev->resource[i].flags)
i++;
- pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[i]);
+ pcibios_resource_to_bus(pdev->bus, &bus_addr,
+ &pdev->resource[i]);
device->ram_base = bus_addr.start;
}

diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c
index a6b29bd4a12a..adc4ea2cc5a0 100644
--- a/drivers/video/arkfb.c
+++ b/drivers/video/arkfb.c
@@ -1014,7 +1014,7 @@ static int ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)

vga_res.flags = IORESOURCE_IO;

- pcibios_bus_to_resource(dev, &vga_res, &bus_reg);
+ pcibios_bus_to_resource(dev->bus, &vga_res, &bus_reg);

par->state.vgabase = (void __iomem *) vga_res.start;

diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
index 968b2997175a..9a3f8f1c6aab 100644
--- a/drivers/video/s3fb.c
+++ b/drivers/video/s3fb.c
@@ -1180,7 +1180,7 @@ static int s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)

vga_res.flags = IORESOURCE_IO;

- pcibios_bus_to_resource(dev, &vga_res, &bus_reg);
+ pcibios_bus_to_resource(dev->bus, &vga_res, &bus_reg);

par->state.vgabase = (void __iomem *) vga_res.start;

diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c
index 8bc6e0958a09..5c7cbc6c6236 100644
--- a/drivers/video/vt8623fb.c
+++ b/drivers/video/vt8623fb.c
@@ -729,7 +729,7 @@ static int vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)

vga_res.flags = IORESOURCE_IO;

- pcibios_bus_to_resource(dev, &vga_res, &bus_reg);
+ pcibios_bus_to_resource(dev->bus, &vga_res, &bus_reg);

par->state.vgabase = (void __iomem *) vga_res.start;

diff --git a/include/linux/pci.h b/include/linux/pci.h
index 7d5555270491..bf32412704a7 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -737,9 +737,9 @@ void pci_fixup_cardbus(struct pci_bus *);

/* Generic PCI functions used internally */

-void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
struct resource *res);
-void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,
struct pci_bus_region *region);
void pcibios_scan_specific_bus(int busn);
struct pci_bus *pci_find_bus(int domain, int busnr);

2014-01-07 00:55:39

by Bjorn Helgaas

[permalink] [raw]
Subject: [PATCH v7 03/15] PCI: Add pci_bus_address() to get bus address of a BAR

We store BAR information as a struct resource, which contains the CPU
address, not the bus address. Drivers often need the bus address, and
there's currently no convenient way to get it, so they often read the
BAR directly, or use the resource address (which doesn't work if there's
any translation between CPU and bus addresses).

Add pci_bus_address() to make this convenient.

Signed-off-by: Bjorn Helgaas <[email protected]>
---
include/linux/pci.h | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/include/linux/pci.h b/include/linux/pci.h
index bf32412704a7..966b286b5d53 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1077,6 +1077,14 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
resource_size_t),
void *alignf_data);

+static inline dma_addr_t pci_bus_address(struct pci_dev *pdev, int bar)
+{
+ struct pci_bus_region region;
+
+ pcibios_resource_to_bus(pdev->bus, &region, &pdev->resource[bar]);
+ return region.start;
+}
+
/* Proper probing supporting hot-pluggable devices */
int __must_check __pci_register_driver(struct pci_driver *, struct module *,
const char *mod_name);

2014-01-07 00:55:49

by Bjorn Helgaas

[permalink] [raw]
Subject: [PATCH v7 04/15] agp: Support 64-bit APBASE

Per the AGP 3.0 spec, APBASE is a standard PCI BAR and may be either 32
bits or 64 bits wide. Many drivers read APBASE directly, but they only
handled 32-bit BARs.

The PCI core reads APBASE at enumeration-time. Use pci_bus_address()
instead of reading it again in the driver. This works correctly for both
32-bit and 64-bit BARs.

Signed-off-by: Bjorn Helgaas <[email protected]>
---
drivers/char/agp/agp.h | 1 +
drivers/char/agp/ali-agp.c | 4 ++-
drivers/char/agp/amd-k7-agp.c | 6 ++---
drivers/char/agp/amd64-agp.c | 5 +---
drivers/char/agp/ati-agp.c | 9 +++----
drivers/char/agp/efficeon-agp.c | 5 ++--
drivers/char/agp/generic.c | 4 ++-
drivers/char/agp/intel-agp.c | 48 ++++++++++++++++-----------------------
drivers/char/agp/nvidia-agp.c | 5 ++--
drivers/char/agp/sis-agp.c | 5 ++--
drivers/char/agp/via-agp.c | 13 +++++------
11 files changed, 44 insertions(+), 61 deletions(-)

diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index 923f99df4f1c..b709749c8639 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -239,6 +239,7 @@ long compat_agp_ioctl(struct file *file, unsigned int cmd, unsigned long arg);

/* Chipset independent registers (from AGP Spec) */
#define AGP_APBASE 0x10
+#define AGP_APERTURE_BAR 0

#define AGPSTAT 0x4
#define AGPCMD 0x8
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index 443cd6751ca2..19db03667650 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -85,8 +85,8 @@ static int ali_configure(void)
pci_write_config_dword(agp_bridge->dev, ALI_TLBCTRL, ((temp & 0xffffff00) | 0x00000010));

/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);

#if 0
if (agp_bridge->type == ALI_M1541) {
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index 779f0ab845a9..9898ed6d5b9a 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -126,7 +126,6 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge)
unsigned long __iomem *cur_gatt;
unsigned long addr;
int retval;
- u32 temp;
int i;

value = A_SIZE_LVL2(agp_bridge->current_size);
@@ -149,9 +148,8 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge)
* used to program the agp master not the cpu
*/

- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
- agp_bridge->gart_bus_addr = addr;
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);

/* Calculate the agp offset */
for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index d79d692d05b8..95326ac610f6 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -269,7 +269,6 @@ static int agp_aperture_valid(u64 aper, u32 size)
*/
static int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, u16 cap)
{
- u32 aper_low, aper_hi;
u64 aper, nb_aper;
int order = 0;
u32 nb_order, nb_base;
@@ -295,9 +294,7 @@ static int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, u16 cap)
apsize |= 0xf00;
order = 7 - hweight16(apsize);

- pci_read_config_dword(agp, 0x10, &aper_low);
- pci_read_config_dword(agp, 0x14, &aper_hi);
- aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32);
+ aper = pci_bus_address(agp, AGP_APERTURE_BAR);

/*
* On some sick chips APSIZE is 0. This means it wants 4G
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index 03c1dc1ab552..53cb310d433e 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -211,10 +211,10 @@ static int ati_configure(void)
else
pci_write_config_dword(agp_bridge->dev, ATI_RS300_IG_AGPMODE, 0x20000);

- /* address to map too */
+ /* address to map to */
/*
- pci_read_config_dword(agp_bridge.dev, AGP_APBASE, &temp);
- agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge.gart_bus_addr = pci_bus_address(agp_bridge.dev,
+ AGP_APERTURE_BAR);
printk(KERN_INFO PFX "IGP320 gart_bus_addr: %x\n", agp_bridge.gart_bus_addr);
*/
writel(0x60000, ati_generic_private.registers+ATI_GART_FEATURE_ID);
@@ -385,8 +385,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge)
* This is a bus address even on the alpha, b/c its
* used to program the agp master not the cpu
*/
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ addr = pci_bus_address(agp_bridge->dev, AGP_APERTURE_BAR);
agp_bridge->gart_bus_addr = addr;

/* Calculate the agp offset */
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index 6974d5032053..533cb6d229b8 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -128,7 +128,6 @@ static void efficeon_cleanup(void)

static int efficeon_configure(void)
{
- u32 temp;
u16 temp2;
struct aper_size_info_lvl2 *current_size;

@@ -141,8 +140,8 @@ static int efficeon_configure(void)
current_size->size_value);

/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);

/* agpctrl */
pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index a0df182f6f7d..f39437addb58 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -1396,8 +1396,8 @@ int agp3_generic_configure(void)

current_size = A_SIZE_16(agp_bridge->current_size);

- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);

/* set aperture size */
pci_write_config_word(agp_bridge->dev, agp_bridge->capndx+AGPAPSIZE, current_size->size_value);
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index a426ee1f57a6..a7c276585a9f 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -118,7 +118,6 @@ static void intel_8xx_cleanup(void)

static int intel_configure(void)
{
- u32 temp;
u16 temp2;
struct aper_size_info_16 *current_size;

@@ -128,8 +127,8 @@ static int intel_configure(void)
pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);

/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);

/* attbase - aperture base */
pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
@@ -148,7 +147,7 @@ static int intel_configure(void)

static int intel_815_configure(void)
{
- u32 temp, addr;
+ u32 addr;
u8 temp2;
struct aper_size_info_8 *current_size;

@@ -167,8 +166,8 @@ static int intel_815_configure(void)
current_size->size_value);

/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);

pci_read_config_dword(agp_bridge->dev, INTEL_ATTBASE, &addr);
addr &= INTEL_815_ATTBASE_MASK;
@@ -208,7 +207,6 @@ static void intel_820_cleanup(void)

static int intel_820_configure(void)
{
- u32 temp;
u8 temp2;
struct aper_size_info_8 *current_size;

@@ -218,8 +216,8 @@ static int intel_820_configure(void)
pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);

/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);

/* attbase - aperture base */
pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
@@ -239,7 +237,6 @@ static int intel_820_configure(void)

static int intel_840_configure(void)
{
- u32 temp;
u16 temp2;
struct aper_size_info_8 *current_size;

@@ -249,8 +246,8 @@ static int intel_840_configure(void)
pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);

/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);

/* attbase - aperture base */
pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
@@ -268,7 +265,6 @@ static int intel_840_configure(void)

static int intel_845_configure(void)
{
- u32 temp;
u8 temp2;
struct aper_size_info_8 *current_size;

@@ -282,9 +278,9 @@ static int intel_845_configure(void)
agp_bridge->apbase_config);
} else {
/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
- agp_bridge->apbase_config = temp;
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);
+ agp_bridge->apbase_config = agp_bridge->gart_bus_addr;
}

/* attbase - aperture base */
@@ -303,7 +299,6 @@ static int intel_845_configure(void)

static int intel_850_configure(void)
{
- u32 temp;
u16 temp2;
struct aper_size_info_8 *current_size;

@@ -313,8 +308,8 @@ static int intel_850_configure(void)
pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);

/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);

/* attbase - aperture base */
pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
@@ -332,7 +327,6 @@ static int intel_850_configure(void)

static int intel_860_configure(void)
{
- u32 temp;
u16 temp2;
struct aper_size_info_8 *current_size;

@@ -342,8 +336,8 @@ static int intel_860_configure(void)
pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);

/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);

/* attbase - aperture base */
pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
@@ -361,7 +355,6 @@ static int intel_860_configure(void)

static int intel_830mp_configure(void)
{
- u32 temp;
u16 temp2;
struct aper_size_info_8 *current_size;

@@ -371,8 +364,8 @@ static int intel_830mp_configure(void)
pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);

/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);

/* attbase - aperture base */
pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
@@ -390,7 +383,6 @@ static int intel_830mp_configure(void)

static int intel_7505_configure(void)
{
- u32 temp;
u16 temp2;
struct aper_size_info_8 *current_size;

@@ -400,8 +392,8 @@ static int intel_7505_configure(void)
pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);

/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);

/* attbase - aperture base */
pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
index be42a2312dc9..ab65d55272c4 100644
--- a/drivers/char/agp/nvidia-agp.c
+++ b/drivers/char/agp/nvidia-agp.c
@@ -115,9 +115,8 @@ static int nvidia_configure(void)
pci_write_config_byte(agp_bridge->dev, NVIDIA_0_APSIZE,
current_size->size_value);

- /* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &apbase);
- apbase &= PCI_BASE_ADDRESS_MEM_MASK;
+ /* address to map to */
+ apbase = pci_bus_address(agp_bridge->dev, AGP_APERTURE_BAR);
agp_bridge->gart_bus_addr = apbase;
aplimit = apbase + (current_size->size * 1024 * 1024) - 1;
pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_APBASE, apbase);
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
index 79c838c434bc..2c74038da459 100644
--- a/drivers/char/agp/sis-agp.c
+++ b/drivers/char/agp/sis-agp.c
@@ -50,13 +50,12 @@ static void sis_tlbflush(struct agp_memory *mem)

static int sis_configure(void)
{
- u32 temp;
struct aper_size_info_8 *current_size;

current_size = A_SIZE_8(agp_bridge->current_size);
pci_write_config_byte(agp_bridge->dev, SIS_TLBCNTRL, 0x05);
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);
pci_write_config_dword(agp_bridge->dev, SIS_ATTBASE,
agp_bridge->gatt_bus_addr);
pci_write_config_byte(agp_bridge->dev, SIS_APSIZE,
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index 74d3aa3773bf..228f20cddc05 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -43,16 +43,15 @@ static int via_fetch_size(void)

static int via_configure(void)
{
- u32 temp;
struct aper_size_info_8 *current_size;

current_size = A_SIZE_8(agp_bridge->current_size);
/* aperture size */
pci_write_config_byte(agp_bridge->dev, VIA_APSIZE,
current_size->size_value);
- /* address to map too */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ /* address to map to */
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);

/* GART control register */
pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, 0x0000000f);
@@ -132,9 +131,9 @@ static int via_configure_agp3(void)

current_size = A_SIZE_16(agp_bridge->current_size);

- /* address to map too */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ /* address to map to */
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);

/* attbase - aperture GATT base */
pci_write_config_dword(agp_bridge->dev, VIA_AGP3_ATTBASE,

2014-01-07 00:55:55

by Bjorn Helgaas

[permalink] [raw]
Subject: [PATCH v7 05/15] agp: Use pci_resource_start() to get CPU physical address for BAR

amd_irongate_configure(), ati_configure(), and nvidia_configure() call
ioremap() on an address read directly from a BAR. But a BAR contains a
bus address, and ioremap() expects a CPU physical address. Use
pci_resource_start() to obtain the physical address.

Signed-off-by: Bjorn Helgaas <[email protected]>
---
drivers/char/agp/amd-k7-agp.c | 8 ++++----
drivers/char/agp/ati-agp.c | 8 ++++----
drivers/char/agp/nvidia-agp.c | 4 +++-
3 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index 9898ed6d5b9a..e8c2e9167e89 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -11,7 +11,7 @@
#include <linux/slab.h>
#include "agp.h"

-#define AMD_MMBASE 0x14
+#define AMD_MMBASE_BAR 1
#define AMD_APSIZE 0xac
#define AMD_MODECNTL 0xb0
#define AMD_MODECNTL2 0xb2
@@ -205,6 +205,7 @@ static int amd_irongate_fetch_size(void)
static int amd_irongate_configure(void)
{
struct aper_size_info_lvl2 *current_size;
+ phys_addr_t reg;
u32 temp;
u16 enable_reg;

@@ -212,9 +213,8 @@ static int amd_irongate_configure(void)

if (!amd_irongate_private.registers) {
/* Get the memory mapped registers */
- pci_read_config_dword(agp_bridge->dev, AMD_MMBASE, &temp);
- temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);
- amd_irongate_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
+ reg = pci_resource_start(agp_bridge->dev, AMD_MMBASE_BAR);
+ amd_irongate_private.registers = (volatile u8 __iomem *) ioremap(reg, 4096);
if (!amd_irongate_private.registers)
return -ENOMEM;
}
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index 53cb310d433e..ba83c11186ce 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -12,7 +12,7 @@
#include <asm/agp.h>
#include "agp.h"

-#define ATI_GART_MMBASE_ADDR 0x14
+#define ATI_GART_MMBASE_BAR 1
#define ATI_RS100_APSIZE 0xac
#define ATI_RS100_IG_AGPMODE 0xb0
#define ATI_RS300_APSIZE 0xf8
@@ -196,12 +196,12 @@ static void ati_cleanup(void)

static int ati_configure(void)
{
+ phys_addr_t reg;
u32 temp;

/* Get the memory mapped registers */
- pci_read_config_dword(agp_bridge->dev, ATI_GART_MMBASE_ADDR, &temp);
- temp = (temp & 0xfffff000);
- ati_generic_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
+ reg = pci_resource_start(agp_bridge->dev, ATI_GART_MMBASE_BAR);
+ ati_generic_private.registers = (volatile u8 __iomem *) ioremap(reg, 4096);

if (!ati_generic_private.registers)
return -ENOMEM;
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
index ab65d55272c4..a1861b75eb31 100644
--- a/drivers/char/agp/nvidia-agp.c
+++ b/drivers/char/agp/nvidia-agp.c
@@ -106,6 +106,7 @@ static int nvidia_configure(void)
{
int i, rc, num_dirs;
u32 apbase, aplimit;
+ phys_addr_t apbase_phys;
struct aper_size_info_8 *current_size;
u32 temp;

@@ -152,8 +153,9 @@ static int nvidia_configure(void)
pci_write_config_dword(agp_bridge->dev, NVIDIA_0_APSIZE, temp | 0x100);

/* map aperture */
+ apbase_phys = pci_resource_start(agp_bridge->dev, AGP_APERTURE_BAR);
nvidia_private.aperture =
- (volatile u32 __iomem *) ioremap(apbase, 33 * PAGE_SIZE);
+ (volatile u32 __iomem *) ioremap(apbase_phys, 33 * PAGE_SIZE);

if (!nvidia_private.aperture)
return -ENOMEM;

2014-01-07 00:56:02

by Bjorn Helgaas

[permalink] [raw]
Subject: [PATCH v7 06/15] drm/i915: Rename gtt_bus_addr to gtt_phys_addr

We're dealing with CPU physical addresses here, which may be different from
bus addresses, so rename gtt_bus_addr to gtt_phys_addr to avoid confusion.

No functional change.

Signed-off-by: Bjorn Helgaas <[email protected]>
---
drivers/gpu/drm/i915/i915_gem_gtt.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 3620a1b0a73c..15604b3dda3e 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -1260,14 +1260,14 @@ static int ggtt_probe_common(struct drm_device *dev,
size_t gtt_size)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- phys_addr_t gtt_bus_addr;
+ phys_addr_t gtt_phys_addr;
int ret;

/* For Modern GENs the PTEs and register space are split in the BAR */
- gtt_bus_addr = pci_resource_start(dev->pdev, 0) +
+ gtt_phys_addr = pci_resource_start(dev->pdev, 0) +
(pci_resource_len(dev->pdev, 0) / 2);

- dev_priv->gtt.gsm = ioremap_wc(gtt_bus_addr, gtt_size);
+ dev_priv->gtt.gsm = ioremap_wc(gtt_phys_addr, gtt_size);
if (!dev_priv->gtt.gsm) {
DRM_ERROR("Failed to map the gtt page table\n");
return -ENOMEM;

2014-01-07 00:56:10

by Bjorn Helgaas

[permalink] [raw]
Subject: [PATCH v7 07/15] agp/intel: Rename gtt_bus_addr to gtt_phys_addr

The only use of gtt_bus_addr is as an argument to ioremap(), so it is a CPU
physical address, not a bus address. Rename it to gtt_phys_addr to reflect
this.

No functional change.

Signed-off-by: Bjorn Helgaas <[email protected]>
---
drivers/char/agp/intel-gtt.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index b8e2014cb9cb..54202ffcf467 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -64,7 +64,7 @@ static struct _intel_private {
struct pci_dev *pcidev; /* device one */
struct pci_dev *bridge_dev;
u8 __iomem *registers;
- phys_addr_t gtt_bus_addr;
+ phys_addr_t gtt_phys_addr;
u32 PGETBL_save;
u32 __iomem *gtt; /* I915G */
bool clear_fake_agp; /* on first access via agp, fill with scratch */
@@ -191,7 +191,7 @@ static int i810_setup(void)
writel(virt_to_phys(gtt_table) | I810_PGETBL_ENABLED,
intel_private.registers+I810_PGETBL_CTL);

- intel_private.gtt_bus_addr = reg_addr + I810_PTE_BASE;
+ intel_private.gtt_phys_addr = reg_addr + I810_PTE_BASE;

if ((readl(intel_private.registers+I810_DRAM_CTL)
& I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) {
@@ -636,10 +636,10 @@ static int intel_gtt_init(void)

intel_private.gtt = NULL;
if (intel_gtt_can_wc())
- intel_private.gtt = ioremap_wc(intel_private.gtt_bus_addr,
+ intel_private.gtt = ioremap_wc(intel_private.gtt_phys_addr,
gtt_map_size);
if (intel_private.gtt == NULL)
- intel_private.gtt = ioremap(intel_private.gtt_bus_addr,
+ intel_private.gtt = ioremap(intel_private.gtt_phys_addr,
gtt_map_size);
if (intel_private.gtt == NULL) {
intel_private.driver->cleanup();
@@ -796,7 +796,7 @@ static int i830_setup(void)
if (!intel_private.registers)
return -ENOMEM;

- intel_private.gtt_bus_addr = reg_addr + I810_PTE_BASE;
+ intel_private.gtt_phys_addr = reg_addr + I810_PTE_BASE;

return 0;
}
@@ -1123,13 +1123,13 @@ static int i9xx_setup(void)
case 3:
pci_read_config_dword(intel_private.pcidev,
I915_PTEADDR, &gtt_addr);
- intel_private.gtt_bus_addr = gtt_addr;
+ intel_private.gtt_phys_addr = gtt_addr;
break;
case 5:
- intel_private.gtt_bus_addr = reg_addr + MB(2);
+ intel_private.gtt_phys_addr = reg_addr + MB(2);
break;
default:
- intel_private.gtt_bus_addr = reg_addr + KB(512);
+ intel_private.gtt_phys_addr = reg_addr + KB(512);
break;
}

2014-01-07 00:56:18

by Bjorn Helgaas

[permalink] [raw]
Subject: [PATCH v7 08/15] agp/intel: Support 64-bit GMADR

From: Yinghai Lu <[email protected]>

Per the Intel 915G/915GV/... Chipset spec (document number 301467-005),
GMADR is a standard PCI BAR.

The PCI core reads GMADR at enumeration-time. Use pci_bus_address()
instead of reading it again in the driver. This works correctly for both
32-bit and 64-bit BARs. The spec above only mentions 32-bit GMADR, but
Yinghai's patch (link below) indicates some devices have a 64-bit GMADR.

[bhelgaas: reworked starting from http://lkml.kernel.org/r/[email protected]]
Signed-off-by: Yinghai Lu <[email protected]>
Signed-off-by: Bjorn Helgaas <[email protected]>
---
drivers/char/agp/intel-agp.h | 4 ++--
drivers/char/agp/intel-gtt.c | 12 ++++--------
2 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h
index 1042c1b90376..0bf5590fd0f9 100644
--- a/drivers/char/agp/intel-agp.h
+++ b/drivers/char/agp/intel-agp.h
@@ -55,7 +55,7 @@
#define INTEL_I860_ERRSTS 0xc8

/* Intel i810 registers */
-#define I810_GMADDR 0x10
+#define I810_GMADR_BAR 0
#define I810_MMADDR 0x14
#define I810_PTE_BASE 0x10000
#define I810_PTE_MAIN_UNCACHED 0x00000000
@@ -113,7 +113,7 @@
#define INTEL_I850_ERRSTS 0xc8

/* intel 915G registers */
-#define I915_GMADDR 0x18
+#define I915_GMADR_BAR 2
#define I915_MMADDR 0x10
#define I915_PTEADDR 0x1C
#define I915_GMCH_GMS_STOLEN_48M (0x6 << 4)
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index 54202ffcf467..560f66bffebb 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -608,9 +608,8 @@ static bool intel_gtt_can_wc(void)

static int intel_gtt_init(void)
{
- u32 gma_addr;
u32 gtt_map_size;
- int ret;
+ int ret, bar;

ret = intel_private.driver->setup();
if (ret != 0)
@@ -660,14 +659,11 @@ static int intel_gtt_init(void)
}

if (INTEL_GTT_GEN <= 2)
- pci_read_config_dword(intel_private.pcidev, I810_GMADDR,
- &gma_addr);
+ bar = I810_GMADR_BAR;
else
- pci_read_config_dword(intel_private.pcidev, I915_GMADDR,
- &gma_addr);
-
- intel_private.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK);
+ bar = I915_GMADR_BAR;

+ intel_private.gma_bus_addr = pci_bus_address(intel_private.pcidev, bar);
return 0;
}

2014-01-07 00:56:25

by Bjorn Helgaas

[permalink] [raw]
Subject: [PATCH v7 09/15] agp/intel: Use pci_bus_address() to get MMADR bus address

Per the Intel 915G/915GV/... Chipset spec (document number 301467-005),
MMADR is a standard PCI BAR.

The PCI core reads MMADR at enumeration-time. Use pci_bus_address()
instead of reading it again in the driver. This works correctly for both
32-bit and 64-bit BARs. The spec above only mentions 32-bit MMADR, but we
should still use the standard interface.

Also, stop clearing the low 19 bits of the bus address because it's invalid
to use addresses outside the region defined by the BAR. The spec claims
MMADR is 512KB; if that's the case, those bits will be zero anyway.

Signed-off-by: Bjorn Helgaas <[email protected]>
---
drivers/char/agp/intel-agp.h | 4 ++--
drivers/char/agp/intel-gtt.c | 10 +++-------
2 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h
index 0bf5590fd0f9..18bbaafb8509 100644
--- a/drivers/char/agp/intel-agp.h
+++ b/drivers/char/agp/intel-agp.h
@@ -56,7 +56,7 @@

/* Intel i810 registers */
#define I810_GMADR_BAR 0
-#define I810_MMADDR 0x14
+#define I810_MMADR_BAR 1
#define I810_PTE_BASE 0x10000
#define I810_PTE_MAIN_UNCACHED 0x00000000
#define I810_PTE_LOCAL 0x00000002
@@ -114,7 +114,7 @@

/* intel 915G registers */
#define I915_GMADR_BAR 2
-#define I915_MMADDR 0x10
+#define I915_MMADR_BAR 0
#define I915_PTEADDR 0x1C
#define I915_GMCH_GMS_STOLEN_48M (0x6 << 4)
#define I915_GMCH_GMS_STOLEN_64M (0x7 << 4)
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index 560f66bffebb..58916f32c0f3 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -181,8 +181,7 @@ static int i810_setup(void)
return -ENOMEM;
intel_private.i81x_gtt_table = gtt_table;

- pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &reg_addr);
- reg_addr &= 0xfff80000;
+ reg_addr = pci_bus_address(intel_private.pcidev, I810_MMADR_BAR);

intel_private.registers = ioremap(reg_addr, KB(64));
if (!intel_private.registers)
@@ -785,8 +784,7 @@ static int i830_setup(void)
{
u32 reg_addr;

- pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &reg_addr);
- reg_addr &= 0xfff80000;
+ reg_addr = pci_bus_address(intel_private.pcidev, I810_MMADR_BAR);

intel_private.registers = ioremap(reg_addr, KB(64));
if (!intel_private.registers)
@@ -1107,9 +1105,7 @@ static int i9xx_setup(void)
u32 reg_addr, gtt_addr;
int size = KB(512);

- pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &reg_addr);
-
- reg_addr &= 0xfff80000;
+ reg_addr = pci_bus_address(intel_private.pcidev, I915_MMADR_BAR);

intel_private.registers = ioremap(reg_addr, size);
if (!intel_private.registers)

2014-01-07 00:56:31

by Bjorn Helgaas

[permalink] [raw]
Subject: [PATCH v7 10/15] agp/intel: Use pci_bus_address() to get GTTADR bus address

Per the Intel 915G/915GV/... Chipset spec (document number 301467-005),
GTTADR is a standard PCI BAR.

The PCI core reads GTTADR at enumeration-time. Use pci_bus_address()
instead of reading it again in the driver. This works correctly for both
32-bit and 64-bit BARs. The spec above only mentions 32-bit GTTADR, but we
should still use the standard interface.

Signed-off-by: Bjorn Helgaas <[email protected]>
---
drivers/char/agp/intel-agp.h | 2 +-
drivers/char/agp/intel-gtt.c | 7 +++----
2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h
index 18bbaafb8509..fda073dcd967 100644
--- a/drivers/char/agp/intel-agp.h
+++ b/drivers/char/agp/intel-agp.h
@@ -115,7 +115,7 @@
/* intel 915G registers */
#define I915_GMADR_BAR 2
#define I915_MMADR_BAR 0
-#define I915_PTEADDR 0x1C
+#define I915_PTE_BAR 3
#define I915_GMCH_GMS_STOLEN_48M (0x6 << 4)
#define I915_GMCH_GMS_STOLEN_64M (0x7 << 4)
#define G33_GMCH_GMS_STOLEN_128M (0x8 << 4)
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index 58916f32c0f3..dd8b66a617dc 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -1102,7 +1102,7 @@ static void i965_write_entry(dma_addr_t addr,

static int i9xx_setup(void)
{
- u32 reg_addr, gtt_addr;
+ u32 reg_addr;
int size = KB(512);

reg_addr = pci_bus_address(intel_private.pcidev, I915_MMADR_BAR);
@@ -1113,9 +1113,8 @@ static int i9xx_setup(void)

switch (INTEL_GTT_GEN) {
case 3:
- pci_read_config_dword(intel_private.pcidev,
- I915_PTEADDR, &gtt_addr);
- intel_private.gtt_phys_addr = gtt_addr;
+ intel_private.gtt_phys_addr =
+ pci_bus_address(intel_private.pcidev, I915_PTE_BAR);
break;
case 5:
intel_private.gtt_phys_addr = reg_addr + MB(2);

2014-01-07 00:56:37

by Bjorn Helgaas

[permalink] [raw]
Subject: [PATCH v7 11/15] agp/intel: Use CPU physical address, not bus address, for ioremap()

In i810_setup(), i830_setup(), and i9xx_setup(), we use the result of
pci_bus_address() as an argument to ioremap() and to compute gtt_phys_addr.
These should use pci_resource_start() instead because we want the CPU
physical address, not the bus address.

If there were an AGP device behind a host bridge that translated addresses,
e.g., a PNP0A08 device with _TRA != 0, this would fix a bug. I'm not aware
of any of those, but they are possible.

Signed-off-by: Bjorn Helgaas <[email protected]>
---
drivers/char/agp/intel-gtt.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index dd8b66a617dc..ad5da1ffcbe9 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -172,7 +172,7 @@ static void i8xx_destroy_pages(struct page *page)
#define I810_GTT_ORDER 4
static int i810_setup(void)
{
- u32 reg_addr;
+ phys_addr_t reg_addr;
char *gtt_table;

/* i81x does not preallocate the gtt. It's always 64kb in size. */
@@ -181,7 +181,7 @@ static int i810_setup(void)
return -ENOMEM;
intel_private.i81x_gtt_table = gtt_table;

- reg_addr = pci_bus_address(intel_private.pcidev, I810_MMADR_BAR);
+ reg_addr = pci_resource_start(intel_private.pcidev, I810_MMADR_BAR);

intel_private.registers = ioremap(reg_addr, KB(64));
if (!intel_private.registers)
@@ -782,9 +782,9 @@ EXPORT_SYMBOL(intel_enable_gtt);

static int i830_setup(void)
{
- u32 reg_addr;
+ phys_addr_t reg_addr;

- reg_addr = pci_bus_address(intel_private.pcidev, I810_MMADR_BAR);
+ reg_addr = pci_resource_start(intel_private.pcidev, I810_MMADR_BAR);

intel_private.registers = ioremap(reg_addr, KB(64));
if (!intel_private.registers)
@@ -1102,10 +1102,10 @@ static void i965_write_entry(dma_addr_t addr,

static int i9xx_setup(void)
{
- u32 reg_addr;
+ phys_addr_t reg_addr;
int size = KB(512);

- reg_addr = pci_bus_address(intel_private.pcidev, I915_MMADR_BAR);
+ reg_addr = pci_resource_start(intel_private.pcidev, I915_MMADR_BAR);

intel_private.registers = ioremap(reg_addr, size);
if (!intel_private.registers)
@@ -1114,7 +1114,7 @@ static int i9xx_setup(void)
switch (INTEL_GTT_GEN) {
case 3:
intel_private.gtt_phys_addr =
- pci_bus_address(intel_private.pcidev, I915_PTE_BAR);
+ pci_resource_start(intel_private.pcidev, I915_PTE_BAR);
break;
case 5:
intel_private.gtt_phys_addr = reg_addr + MB(2);

2014-01-07 00:56:44

by Bjorn Helgaas

[permalink] [raw]
Subject: [PATCH v7 12/15] agp/ati: Use PCI_COMMAND instead of hard-coded 4

We're accessing the PCI_COMMAND register here, so use the appropriate
#define. The bit we're writing (1 << 14) isn't defined by the PCI or PCIe
spec, so we don't have a name for it.

No functional change.

Signed-off-by: Bjorn Helgaas <[email protected]>
---
drivers/char/agp/ati-agp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index ba83c11186ce..18a7a6baa304 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -221,8 +221,8 @@ static int ati_configure(void)
readl(ati_generic_private.registers+ATI_GART_FEATURE_ID); /* PCI Posting.*/

/* SIGNALED_SYSTEM_ERROR @ NB_STATUS */
- pci_read_config_dword(agp_bridge->dev, 4, &temp);
- pci_write_config_dword(agp_bridge->dev, 4, temp | (1<<14));
+ pci_read_config_dword(agp_bridge->dev, PCI_COMMAND, &temp);
+ pci_write_config_dword(agp_bridge->dev, PCI_COMMAND, temp | (1<<14));

/* Write out the address of the gatt table */
writel(agp_bridge->gatt_bus_addr, ati_generic_private.registers+ATI_GART_BASE);

2014-01-07 00:56:53

by Bjorn Helgaas

[permalink] [raw]
Subject: [PATCH v7 13/15] PCI: Split out bridge window override of minimum allocation address

pci_bus_alloc_resource() avoids allocating space below the "min" supplied
by the caller (usually PCIBIOS_MIN_IO or PCIBIOS_MIN_MEM). This is to
protect badly documented motherboard resources. But if we're allocating
space inside an already-configured PCI-PCI bridge window, we ignore "min".

See 688d191821de ("pci: make bus resource start address override minimum IO
address").

This patch moves the check to make it more visible and simplify future
patches. No functional change.

Signed-off-by: Bjorn Helgaas <[email protected]>
---
drivers/pci/bus.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index fc1b74013743..6f2f47a7b6c6 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -147,11 +147,18 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
!(res->flags & IORESOURCE_PREFETCH))
continue;

+ /*
+ * "min" is typically PCIBIOS_MIN_IO or PCIBIOS_MIN_MEM to
+ * protect badly documented motherboard resources, but if
+ * this is an already-configured bridge window, its start
+ * overrides "min".
+ */
+ if (r->start)
+ min = r->start;
+
/* Ok, try it out.. */
- ret = allocate_resource(r, res, size,
- r->start ? : min,
- max, align,
- alignf, alignf_data);
+ ret = allocate_resource(r, res, size, min, max,
+ align, alignf, alignf_data);
if (ret == 0)
break;
}

2014-01-07 00:56:58

by Bjorn Helgaas

[permalink] [raw]
Subject: [PATCH v7 14/15] PCI: Enforce bus address limits in resource allocation

From: Yinghai Lu <[email protected]>

When allocating space for 32-bit BARs, we previously limited RESOURCE
addresses so they would fit in 32 bits. However, the BUS address need not
be the same as the resource address, and it's the bus address that must fit
in the 32-bit BAR.

This patch adds:

- pci_clip_resource_to_region(), which clips a resource so it contains
only the range that maps to the specified bus address region, e.g., to
clip a resource to 32-bit bus addresses, and

- pci_bus_alloc_from_region(), which allocates space for a resource from
the specified bus address region,

and changes pci_bus_alloc_resource() to allocate space for 64-bit BARs from
the entire bus address region, and space for 32-bit BARs from only the bus
address region below 4GB.

If we had this window:

pci_root HWP0002:0a: host bridge window [mem 0xf0180000000-0xf01fedfffff] (bus address [0x80000000-0xfedfffff])

we previously could not put a 32-bit BAR there, because the CPU addresses
don't fit in 32 bits. This patch fixes this, so we can use this space for
32-bit BARs.

It's also possible (though unlikely) to have resources with 32-bit CPU
addresses but bus addresses above 4GB. In this case the previous code
would allocate space that a 32-bit BAR could not map.

Remove PCIBIOS_MAX_MEM_32, which is no longer used.

[bhelgaas: reworked starting from http://lkml.kernel.org/r/[email protected]]
Signed-off-by: Yinghai Lu <[email protected]>
Signed-off-by: Bjorn Helgaas <[email protected]>
---
arch/x86/include/asm/pci.h | 1
drivers/pci/bus.c | 107 ++++++++++++++++++++++++++++++++------------
include/linux/pci.h | 4 --
3 files changed, 79 insertions(+), 33 deletions(-)

diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 947b5c417e83..122c299e90c8 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -125,7 +125,6 @@ int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,

/* generic pci stuff */
#include <asm-generic/pci.h>
-#define PCIBIOS_MAX_MEM_32 0xffffffff

#ifdef CONFIG_NUMA
/* Returns the node based on pci bus */
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 6f2f47a7b6c6..58beaaba50ee 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -98,41 +98,50 @@ void pci_bus_remove_resources(struct pci_bus *bus)
}
}

-/**
- * pci_bus_alloc_resource - allocate a resource from a parent bus
- * @bus: PCI bus
- * @res: resource to allocate
- * @size: size of resource to allocate
- * @align: alignment of resource to allocate
- * @min: minimum /proc/iomem address to allocate
- * @type_mask: IORESOURCE_* type flags
- * @alignf: resource alignment function
- * @alignf_data: data argument for resource alignment function
- *
- * Given the PCI bus a device resides on, the size, minimum address,
- * alignment and type, try to find an acceptable resource allocation
- * for a specific device resource.
+static struct pci_bus_region pci_32_bit = {0, 0xffffffffULL};
+static struct pci_bus_region pci_64_bit = {0,
+ (resource_size_t) 0xffffffffffffffffULL};
+
+/*
+ * @res contains CPU addresses. Clip it so the corresponding bus addresses
+ * on @bus are entirely within @region. This is used to control the bus
+ * addresses of resources we allocate, e.g., we may need a resource that
+ * can be mapped by a 32-bit BAR.
*/
-int
-pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
+static void pci_clip_resource_to_region(struct pci_bus *bus,
+ struct resource *res,
+ struct pci_bus_region *region)
+{
+ struct pci_bus_region r;
+
+ pcibios_resource_to_bus(bus, &r, res);
+ if (r.start < region->start)
+ r.start = region->start;
+ if (r.end > region->end)
+ r.end = region->end;
+
+ if (r.end < r.start)
+ res->end = res->start - 1;
+ else
+ pcibios_bus_to_resource(bus, res, &r);
+}
+
+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 min, unsigned int type_mask,
resource_size_t (*alignf)(void *,
const struct resource *,
resource_size_t,
resource_size_t),
- void *alignf_data)
+ void *alignf_data,
+ struct pci_bus_region *region)
{
- int i, ret = -ENOMEM;
- struct resource *r;
- resource_size_t max = -1;
+ int i, ret;
+ struct resource *r, avail;
+ resource_size_t max;

type_mask |= IORESOURCE_IO | IORESOURCE_MEM;

- /* don't allocate too high if the pref mem doesn't support 64bit*/
- if (!(res->flags & IORESOURCE_MEM_64))
- max = PCIBIOS_MAX_MEM_32;
-
pci_bus_for_each_resource(bus, r, i) {
if (!r)
continue;
@@ -147,22 +156,64 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
!(res->flags & IORESOURCE_PREFETCH))
continue;

+ avail = *r;
+ pci_clip_resource_to_region(bus, &avail, region);
+ if (!resource_size(&avail))
+ continue;
+
/*
* "min" is typically PCIBIOS_MIN_IO or PCIBIOS_MIN_MEM to
* protect badly documented motherboard resources, but if
* this is an already-configured bridge window, its start
* overrides "min".
*/
- if (r->start)
- min = r->start;
+ if (avail.start)
+ min = avail.start;
+
+ max = avail.end;

/* Ok, try it out.. */
ret = allocate_resource(r, res, size, min, max,
align, alignf, alignf_data);
if (ret == 0)
- break;
+ return 0;
}
- return ret;
+ return -ENOMEM;
+}
+
+/**
+ * pci_bus_alloc_resource - allocate a resource from a parent bus
+ * @bus: PCI bus
+ * @res: resource to allocate
+ * @size: size of resource to allocate
+ * @align: alignment of resource to allocate
+ * @min: minimum /proc/iomem address to allocate
+ * @type_mask: IORESOURCE_* type flags
+ * @alignf: resource alignment function
+ * @alignf_data: data argument for resource alignment function
+ *
+ * Given the PCI bus a device resides on, the size, minimum address,
+ * alignment and type, try to find an acceptable resource allocation
+ * for a specific device resource.
+ */
+int
+pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
+ resource_size_t size, resource_size_t align,
+ resource_size_t min, unsigned int type_mask,
+ resource_size_t (*alignf)(void *,
+ const struct resource *,
+ resource_size_t,
+ resource_size_t),
+ void *alignf_data)
+{
+ if (res->flags & IORESOURCE_MEM_64)
+ return pci_bus_alloc_from_region(bus, res, size, align, min,
+ type_mask, alignf, alignf_data,
+ &pci_64_bit);
+
+ return pci_bus_alloc_from_region(bus, res, size, align, min,
+ type_mask, alignf, alignf_data,
+ &pci_32_bit);
}

void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { }
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 966b286b5d53..095eb44fcbb6 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1493,10 +1493,6 @@ static inline struct pci_dev *pci_dev_get(struct pci_dev *dev)

#include <asm/pci.h>

-#ifndef PCIBIOS_MAX_MEM_32
-#define PCIBIOS_MAX_MEM_32 (-1)
-#endif
-
/* these helpers provide future and backwards compatibility
* for accessing popular PCI BAR info */
#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start)

2014-01-07 00:57:06

by Bjorn Helgaas

[permalink] [raw]
Subject: [PATCH v7 15/15] PCI: Allocate 64-bit BARs above 4G when possible

From: Yinghai Lu <[email protected]>

Try to allocate space for 64-bit BARs above 4G first, to preserve the space
below 4G for 32-bit BARs. If there's no space above 4G available, fall
back to allocating anywhere.

[bhelgaas: reworked starting from http://lkml.kernel.org/r/[email protected]]
Signed-off-by: Yinghai Lu <[email protected]>
Signed-off-by: Bjorn Helgaas <[email protected]>
---
drivers/pci/bus.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 58beaaba50ee..107ad9a5b8aa 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -101,6 +101,8 @@ void pci_bus_remove_resources(struct pci_bus *bus)
static struct pci_bus_region pci_32_bit = {0, 0xffffffffULL};
static struct pci_bus_region pci_64_bit = {0,
(resource_size_t) 0xffffffffffffffffULL};
+static struct pci_bus_region pci_high = {(resource_size_t) 0x100000000ULL,
+ (resource_size_t) 0xffffffffffffffffULL};

/*
* @res contains CPU addresses. Clip it so the corresponding bus addresses
@@ -196,8 +198,7 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
* alignment and type, try to find an acceptable resource allocation
* for a specific device resource.
*/
-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 min, unsigned int type_mask,
resource_size_t (*alignf)(void *,
@@ -206,10 +207,19 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
resource_size_t),
void *alignf_data)
{
- if (res->flags & IORESOURCE_MEM_64)
+ int rc;
+
+ if (res->flags & IORESOURCE_MEM_64) {
+ rc = pci_bus_alloc_from_region(bus, res, size, align, min,
+ type_mask, alignf, alignf_data,
+ &pci_high);
+ if (rc == 0)
+ return 0;
+
return pci_bus_alloc_from_region(bus, res, size, align, min,
type_mask, alignf, alignf_data,
&pci_64_bit);
+ }

return pci_bus_alloc_from_region(bus, res, size, align, min,
type_mask, alignf, alignf_data,

2014-01-07 10:45:00

by Daniel Vetter

[permalink] [raw]
Subject: Re: [PATCH v7 00/15] PCI: Allocate 64-bit BARs above 4G when possible

On Mon, Jan 06, 2014 at 05:55:12PM -0700, Bjorn Helgaas wrote:
> This is basically v7 of Yinghai's patch series:
> http://lkml.kernel.org/r/[email protected]
>
> The goal is to try to put 64-bit BARs above 4G so we can preserve the
> 32-bit bus address space for 32-bit BARs.
>
> There are a whole bunch of AGP updates at the beginning because some AGP
> devices have 64-bit BARs, but most of the AGP drivers read the aperture
> bus address directly from the BAR, and they only handle 32-bit BARs.
> Putting BARs above 4G would break those drivers, so we tried to fix them
> up first. Yinghai fixed intel-gtt.c, and I made similar fixes to all
> the other AGP drivers I could find.
>
> Some of the AGP updates are related to the fact that most of the drivers
> assume the PCI bus address is the same as the CPU physical address. For
> example, they read the bus address from the BAR, then call ioremap() on
> it. This is wrong, because ioremap() expects a CPU physical address,
> not a bus address. In most cases, I think AGP devices are in simple
> systems where (bus_address == CPU_physical_address), so these updates
> probably don't fix any broken systems. I'm pretty sure there are more
> things like this that should be fixed.
>
> The important PCI changes are the last two:
>
> PCI: Enforce bus address limits in resource allocation
> PCI: Allocate 64-bit BARs above 4G when possible
>
> The first fixes a long-standing bug: we would never assign space to a
> 32-bit BAR if the *CPU* address didn't fit in 32 bits. But the important
> thing is the *bus* address, and that may fit in 32 bits even if the CPU
> address doesn't.
>
> The second is the one that tries to allocate space above 4G for 64-bit
> BARs. If that fails, we fall back to allocating space anywhere. It's
> possible this will expose other broken drivers that can't deal with
> 64-bit BARs being above 4G.
>
> I kept Yinghai as the author of the patches that originated with him,
> but I reworked them substantially to try to simplify the series, so any
> bugs here are most likely my fault. If my rework made things worse, or
> if it makes your life difficult, I will consider doing something
> different; just let me know.

Patches 4-11 are Reviewed-by: Daniel Vetter <[email protected]>

A few notes aside:

- intel-gtt.c isn't actually an agp bridge but just exposes the iommu
in the integrated intel gfx blocks to userspace through the only
interface available back in the dark ages over userspace gfx drivers ...

- All agp bridges on ppc don't support cpu access to remapped memory
ranges (iirc due to coherncy issues), so that explains why the cpu vs
bus address mess isn't an issue there.

- If you wonder how this worked on alpha grep for __alpha__ in
drivers/gpu/drm and cry. For added hilarity compare with the fun that's
going on in the alpha specificy mmap handling (everyone else is using
ioremap) in alpha_core_agp_vm_fault set up by agp_mmap.

Probably easier to burn down alpha than fix this mess ... But for
extremely bored souls I guess the simplest fix would be to switch
agp_kern_info.aper_base to a cpu physical address, rip out all the alpha
special casing and hope for the best. Very likely there's no one left to
test this anyway ;-)

Cheers, Daniel

>
> ---
>
> Bjorn Helgaas (11):
> PCI: Change pci_bus_region addresses to dma_addr_t
> PCI: Add pci_bus_address() to get bus address of a BAR
> agp: Support 64-bit APBASE
> agp: Use pci_resource_start() to get CPU physical address for BAR
> drm/i915: Rename gtt_bus_addr to gtt_phys_addr
> agp/intel: Rename gtt_bus_addr to gtt_phys_addr
> agp/intel: Use pci_bus_address() to get MMADR bus address
> agp/intel: Use pci_bus_address() to get GTTADR bus address
> agp/intel: Use CPU physical address, not bus address, for ioremap()
> agp/ati: Use PCI_COMMAND instead of hard-coded 4
> PCI: Split out bridge window override of minimum allocation address
>
> Yinghai Lu (4):
> PCI: Convert pcibios_resource_to_bus() to take a pci_bus, not a pci_dev
> agp/intel: Support 64-bit GMADR
> PCI: Enforce bus address limits in resource allocation
> PCI: Allocate 64-bit BARs above 4G when possible
>
>
> arch/alpha/kernel/pci-sysfs.c | 4 +
> arch/powerpc/kernel/pci-common.c | 4 +
> arch/powerpc/kernel/pci_of_scan.c | 4 +
> arch/sparc/kernel/pci.c | 6 +-
> arch/x86/include/asm/pci.h | 1
> drivers/char/agp/agp.h | 1
> drivers/char/agp/ali-agp.c | 4 +
> drivers/char/agp/amd-k7-agp.c | 14 ++--
> drivers/char/agp/amd64-agp.c | 5 -
> drivers/char/agp/ati-agp.c | 21 +++---
> drivers/char/agp/efficeon-agp.c | 5 +
> drivers/char/agp/generic.c | 4 +
> drivers/char/agp/intel-agp.c | 48 +++++--------
> drivers/char/agp/intel-agp.h | 10 +--
> drivers/char/agp/intel-gtt.c | 47 +++++--------
> drivers/char/agp/nvidia-agp.c | 9 +-
> drivers/char/agp/sis-agp.c | 5 +
> drivers/char/agp/via-agp.c | 13 ++--
> drivers/gpu/drm/i915/i915_gem_gtt.c | 6 +-
> drivers/pci/bus.c | 128 +++++++++++++++++++++++++++--------
> drivers/pci/host-bridge.c | 19 ++---
> drivers/pci/probe.c | 18 ++---
> drivers/pci/quirks.c | 2 -
> drivers/pci/rom.c | 2 -
> drivers/pci/setup-bus.c | 16 ++--
> drivers/pci/setup-res.c | 2 -
> drivers/pcmcia/i82092.c | 2 -
> drivers/pcmcia/yenta_socket.c | 6 +-
> drivers/scsi/sym53c8xx_2/sym_glue.c | 5 +
> drivers/video/arkfb.c | 2 -
> drivers/video/s3fb.c | 2 -
> drivers/video/vt8623fb.c | 2 -
> include/linux/pci.h | 20 +++--
> 33 files changed, 241 insertions(+), 196 deletions(-)

--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

2014-01-07 18:46:50

by Bjorn Helgaas

[permalink] [raw]
Subject: Re: [PATCH v7 00/15] PCI: Allocate 64-bit BARs above 4G when possible

On Tue, Jan 7, 2014 at 3:46 AM, Daniel Vetter <[email protected]> wrote:
> On Mon, Jan 06, 2014 at 05:55:12PM -0700, Bjorn Helgaas wrote:
>> This is basically v7 of Yinghai's patch series:
>> http://lkml.kernel.org/r/[email protected]
>>
>> The goal is to try to put 64-bit BARs above 4G so we can preserve the
>> 32-bit bus address space for 32-bit BARs.
>>
>> There are a whole bunch of AGP updates at the beginning because some AGP
>> devices have 64-bit BARs, but most of the AGP drivers read the aperture
>> bus address directly from the BAR, and they only handle 32-bit BARs.
>> Putting BARs above 4G would break those drivers, so we tried to fix them
>> up first. Yinghai fixed intel-gtt.c, and I made similar fixes to all
>> the other AGP drivers I could find.
>>
>> Some of the AGP updates are related to the fact that most of the drivers
>> assume the PCI bus address is the same as the CPU physical address. For
>> example, they read the bus address from the BAR, then call ioremap() on
>> it. This is wrong, because ioremap() expects a CPU physical address,
>> not a bus address. In most cases, I think AGP devices are in simple
>> systems where (bus_address == CPU_physical_address), so these updates
>> probably don't fix any broken systems. I'm pretty sure there are more
>> things like this that should be fixed.
>> ...

> Patches 4-11 are Reviewed-by: Daniel Vetter <[email protected]>

Thanks a lot! I added your Reviewed-by to those patches.

Bjorn

2014-01-10 21:34:10

by Bjorn Helgaas

[permalink] [raw]
Subject: Re: [PATCH v7 00/15] PCI: Allocate 64-bit BARs above 4G when possible

On Mon, Jan 06, 2014 at 05:55:12PM -0700, Bjorn Helgaas wrote:
> This is basically v7 of Yinghai's patch series:
> http://lkml.kernel.org/r/[email protected]
>
> The goal is to try to put 64-bit BARs above 4G so we can preserve the
> 32-bit bus address space for 32-bit BARs.

I added Daniel's Reviewed-by to the AGP patches (except the trivial
PCI_COMMAND change in ati_configure()).

I added the incremental patch below to fix these warnings found by
Fengguang's autobuilder in the original b1e0e392f5dd commit:

drivers/char/agp/amd-k7-agp.c:115:38: warning: 'addr' may be used uninitialized in this function [-Wmaybe-uninitialized]
drivers/pci/bus.c:105:5: warning: large integer implicitly truncated to unsigned type [-Woverflow]

Finally, I merged the pci/resource branch with these changes into my "next"
branch, so it should appear in v3.14-rc1.

Dave, let me know if you have any issue with these AGP changes going
through my tree.

Bjorn


diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index e8c2e9167e89..3661a51e93e2 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -148,8 +148,8 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge)
* used to program the agp master not the cpu
*/

- agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
- AGP_APERTURE_BAR);
+ addr = pci_bus_address(agp_bridge->dev, AGP_APERTURE_BAR);
+ agp_bridge->gart_bus_addr = addr;

/* Calculate the agp offset */
for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 107ad9a5b8aa..86fb8ec5e448 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -99,10 +99,12 @@ void pci_bus_remove_resources(struct pci_bus *bus)
}

static struct pci_bus_region pci_32_bit = {0, 0xffffffffULL};
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
static struct pci_bus_region pci_64_bit = {0,
- (resource_size_t) 0xffffffffffffffffULL};
-static struct pci_bus_region pci_high = {(resource_size_t) 0x100000000ULL,
- (resource_size_t) 0xffffffffffffffffULL};
+ (dma_addr_t) 0xffffffffffffffffULL};
+static struct pci_bus_region pci_high = {(dma_addr_t) 0x100000000ULL,
+ (dma_addr_t) 0xffffffffffffffffULL};
+#endif

/*
* @res contains CPU addresses. Clip it so the corresponding bus addresses
@@ -207,6 +209,7 @@ int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
resource_size_t),
void *alignf_data)
{
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
int rc;

if (res->flags & IORESOURCE_MEM_64) {
@@ -220,6 +223,7 @@ int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
type_mask, alignf, alignf_data,
&pci_64_bit);
}
+#endif

return pci_bus_alloc_from_region(bus, res, size, align, min,
type_mask, alignf, alignf_data,

2014-01-15 05:14:11

by Dave Airlie

[permalink] [raw]
Subject: Re: [PATCH v7 00/15] PCI: Allocate 64-bit BARs above 4G when possible

>
> I added Daniel's Reviewed-by to the AGP patches (except the trivial
> PCI_COMMAND change in ati_configure()).
>
> I added the incremental patch below to fix these warnings found by
> Fengguang's autobuilder in the original b1e0e392f5dd commit:
>
> drivers/char/agp/amd-k7-agp.c:115:38: warning: 'addr' may be used uninitialized in this function [-Wmaybe-uninitialized]
> drivers/pci/bus.c:105:5: warning: large integer implicitly truncated to unsigned type [-Woverflow]
>
> Finally, I merged the pci/resource branch with these changes into my "next"
> branch, so it should appear in v3.14-rc1.
>
> Dave, let me know if you have any issue with these AGP changes going
> through my tree.

None, all fine by me.

Acked-by: Dave Airlie <[email protected]>

Dave.
>
> Bjorn
>
>
> diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
> index e8c2e9167e89..3661a51e93e2 100644
> --- a/drivers/char/agp/amd-k7-agp.c
> +++ b/drivers/char/agp/amd-k7-agp.c
> @@ -148,8 +148,8 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge)
> * used to program the agp master not the cpu
> */
>
> - agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
> - AGP_APERTURE_BAR);
> + addr = pci_bus_address(agp_bridge->dev, AGP_APERTURE_BAR);
> + agp_bridge->gart_bus_addr = addr;
>
> /* Calculate the agp offset */
> for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
> diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
> index 107ad9a5b8aa..86fb8ec5e448 100644
> --- a/drivers/pci/bus.c
> +++ b/drivers/pci/bus.c
> @@ -99,10 +99,12 @@ void pci_bus_remove_resources(struct pci_bus *bus)
> }
>
> static struct pci_bus_region pci_32_bit = {0, 0xffffffffULL};
> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
> static struct pci_bus_region pci_64_bit = {0,
> - (resource_size_t) 0xffffffffffffffffULL};
> -static struct pci_bus_region pci_high = {(resource_size_t) 0x100000000ULL,
> - (resource_size_t) 0xffffffffffffffffULL};
> + (dma_addr_t) 0xffffffffffffffffULL};
> +static struct pci_bus_region pci_high = {(dma_addr_t) 0x100000000ULL,
> + (dma_addr_t) 0xffffffffffffffffULL};
> +#endif
>
> /*
> * @res contains CPU addresses. Clip it so the corresponding bus addresses
> @@ -207,6 +209,7 @@ int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
> resource_size_t),
> void *alignf_data)
> {
> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
> int rc;
>
> if (res->flags & IORESOURCE_MEM_64) {
> @@ -220,6 +223,7 @@ int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
> type_mask, alignf, alignf_data,
> &pci_64_bit);
> }
> +#endif
>
> return pci_bus_alloc_from_region(bus, res, size, align, min,
> type_mask, alignf, alignf_data,
>
>