Commit 1d9b9f6a authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (21 commits)
  x86/PCI: use dev_printk when possible
  PCI: add D3 power state avoidance quirk
  PCI: fix bogus "'device' may be used uninitialized" warning in pci_slot
  PCI: add an option to allow ASPM enabled forcibly
  PCI: disable ASPM on pre-1.1 PCIe devices
  PCI: disable ASPM per ACPI FADT setting
  PCI MSI: Don't disable MSIs if the mask bit isn't supported
  PCI: handle 64-bit resources better on 32-bit machines
  PCI: rewrite PCI BAR reading code
  PCI: document pci_target_state
  PCI hotplug: fix typo in pcie hotplug output
  x86 gart: replace to_pages macro with iommu_num_pages
  x86, AMD IOMMU: replace to_pages macro with iommu_num_pages
  iommu: add iommu_num_pages helper function
  dma-coherent: add documentation to new interfaces
  Cris: convert to using generic dma-coherent mem allocator
  Sh: use generic per-device coherent dma allocator
  ARM: support generic per-device coherent dma mem
  Generic dma-coherent: fix DMA_MEMORY_EXCLUSIVE
  x86: use generic per-device dma coherent allocator
  ...
parents a3ad7f12 12c0b20f
...@@ -17,6 +17,7 @@ config ARM ...@@ -17,6 +17,7 @@ config ARM
select HAVE_KRETPROBES if (HAVE_KPROBES) select HAVE_KRETPROBES if (HAVE_KPROBES)
select HAVE_FTRACE if (!XIP_KERNEL) select HAVE_FTRACE if (!XIP_KERNEL)
select HAVE_DYNAMIC_FTRACE if (HAVE_FTRACE) select HAVE_DYNAMIC_FTRACE if (HAVE_FTRACE)
select HAVE_GENERIC_DMA_COHERENT
help help
The ARM series is a line of low-power-consumption RISC chip designs The ARM series is a line of low-power-consumption RISC chip designs
licensed by ARM Ltd and targeted at embedded applications and licensed by ARM Ltd and targeted at embedded applications and
......
...@@ -274,6 +274,11 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, ...@@ -274,6 +274,11 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
void * void *
dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp) dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
{ {
void *memory;
if (dma_alloc_from_coherent(dev, size, handle, &memory))
return memory;
if (arch_is_coherent()) { if (arch_is_coherent()) {
void *virt; void *virt;
...@@ -362,6 +367,9 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr ...@@ -362,6 +367,9 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr
WARN_ON(irqs_disabled()); WARN_ON(irqs_disabled());
if (dma_release_from_coherent(dev, get_order(size), cpu_addr))
return;
if (arch_is_coherent()) { if (arch_is_coherent()) {
kfree(cpu_addr); kfree(cpu_addr);
return; return;
......
...@@ -641,6 +641,7 @@ config PCI ...@@ -641,6 +641,7 @@ config PCI
bool bool
depends on ETRAX_CARDBUS depends on ETRAX_CARDBUS
default y default y
select HAVE_GENERIC_DMA_COHERENT
config ETRAX_IOP_FW_LOAD config ETRAX_IOP_FW_LOAD
tristate "IO-processor hotplug firmware loading support" tristate "IO-processor hotplug firmware loading support"
......
...@@ -15,35 +15,16 @@ ...@@ -15,35 +15,16 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <asm/io.h> #include <asm/io.h>
struct dma_coherent_mem {
void *virt_base;
u32 device_base;
int size;
int flags;
unsigned long *bitmap;
};
void *dma_alloc_coherent(struct device *dev, size_t size, void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp) dma_addr_t *dma_handle, gfp_t gfp)
{ {
void *ret; void *ret;
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
int order = get_order(size); int order = get_order(size);
/* ignore region specifiers */ /* ignore region specifiers */
gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
if (mem) { if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
int page = bitmap_find_free_region(mem->bitmap, mem->size,
order);
if (page >= 0) {
*dma_handle = mem->device_base + (page << PAGE_SHIFT);
ret = mem->virt_base + (page << PAGE_SHIFT);
memset(ret, 0, size);
return ret; return ret;
}
if (mem->flags & DMA_MEMORY_EXCLUSIVE)
return NULL;
}
if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
gfp |= GFP_DMA; gfp |= GFP_DMA;
...@@ -60,90 +41,9 @@ void *dma_alloc_coherent(struct device *dev, size_t size, ...@@ -60,90 +41,9 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
void dma_free_coherent(struct device *dev, size_t size, void dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle) void *vaddr, dma_addr_t dma_handle)
{ {
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
int order = get_order(size); int order = get_order(size);
if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) { if (!dma_release_from_coherent(dev, order, vaddr))
int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
bitmap_release_region(mem->bitmap, page, order);
} else
free_pages((unsigned long)vaddr, order); free_pages((unsigned long)vaddr, order);
} }
int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
dma_addr_t device_addr, size_t size, int flags)
{
void __iomem *mem_base;
int pages = size >> PAGE_SHIFT;
int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
goto out;
if (!size)
goto out;
if (dev->dma_mem)
goto out;
/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
mem_base = ioremap(bus_addr, size);
if (!mem_base)
goto out;
dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
if (!dev->dma_mem)
goto iounmap_out;
dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
if (!dev->dma_mem->bitmap)
goto free1_out;
dev->dma_mem->virt_base = mem_base;
dev->dma_mem->device_base = device_addr;
dev->dma_mem->size = pages;
dev->dma_mem->flags = flags;
if (flags & DMA_MEMORY_MAP)
return DMA_MEMORY_MAP;
return DMA_MEMORY_IO;
free1_out:
kfree(dev->dma_mem);
iounmap_out:
iounmap(mem_base);
out:
return 0;
}
EXPORT_SYMBOL(dma_declare_coherent_memory);
void dma_release_declared_memory(struct device *dev)
{
struct dma_coherent_mem *mem = dev->dma_mem;
if(!mem)
return;
dev->dma_mem = NULL;
iounmap(mem->virt_base);
kfree(mem->bitmap);
kfree(mem);
}
EXPORT_SYMBOL(dma_release_declared_memory);
void *dma_mark_declared_memory_occupied(struct device *dev,
dma_addr_t device_addr, size_t size)
{
struct dma_coherent_mem *mem = dev->dma_mem;
int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
int pos, err;
if (!mem)
return ERR_PTR(-EINVAL);
pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
if (err != 0)
return ERR_PTR(err);
return mem->virt_base + (pos << PAGE_SHIFT);
}
EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
...@@ -11,6 +11,7 @@ config SUPERH ...@@ -11,6 +11,7 @@ config SUPERH
select HAVE_CLK select HAVE_CLK
select HAVE_IDE select HAVE_IDE
select HAVE_OPROFILE select HAVE_OPROFILE
select HAVE_GENERIC_DMA_COHERENT
help help
The SuperH is a RISC processor targeted for use in embedded systems The SuperH is a RISC processor targeted for use in embedded systems
and consumer electronics; it was also used in the Sega Dreamcast and consumer electronics; it was also used in the Sega Dreamcast
......
...@@ -28,21 +28,10 @@ void *dma_alloc_coherent(struct device *dev, size_t size, ...@@ -28,21 +28,10 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp) dma_addr_t *dma_handle, gfp_t gfp)
{ {
void *ret, *ret_nocache; void *ret, *ret_nocache;
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
int order = get_order(size); int order = get_order(size);
if (mem) { if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
int page = bitmap_find_free_region(mem->bitmap, mem->size,
order);
if (page >= 0) {
*dma_handle = mem->device_base + (page << PAGE_SHIFT);
ret = mem->virt_base + (page << PAGE_SHIFT);
memset(ret, 0, size);
return ret; return ret;
}
if (mem->flags & DMA_MEMORY_EXCLUSIVE)
return NULL;
}
ret = (void *)__get_free_pages(gfp, order); ret = (void *)__get_free_pages(gfp, order);
if (!ret) if (!ret)
...@@ -72,11 +61,7 @@ void dma_free_coherent(struct device *dev, size_t size, ...@@ -72,11 +61,7 @@ void dma_free_coherent(struct device *dev, size_t size,
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
int order = get_order(size); int order = get_order(size);
if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) { if (!dma_release_from_coherent(dev, order, vaddr)) {
int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
bitmap_release_region(mem->bitmap, page, order);
} else {
WARN_ON(irqs_disabled()); /* for portability */ WARN_ON(irqs_disabled()); /* for portability */
BUG_ON(mem && mem->flags & DMA_MEMORY_EXCLUSIVE); BUG_ON(mem && mem->flags & DMA_MEMORY_EXCLUSIVE);
free_pages((unsigned long)phys_to_virt(dma_handle), order); free_pages((unsigned long)phys_to_virt(dma_handle), order);
...@@ -85,83 +70,6 @@ void dma_free_coherent(struct device *dev, size_t size, ...@@ -85,83 +70,6 @@ void dma_free_coherent(struct device *dev, size_t size,
} }
EXPORT_SYMBOL(dma_free_coherent); EXPORT_SYMBOL(dma_free_coherent);
int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
dma_addr_t device_addr, size_t size, int flags)
{
void __iomem *mem_base = NULL;
int pages = size >> PAGE_SHIFT;
int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
goto out;
if (!size)
goto out;
if (dev->dma_mem)
goto out;
/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
mem_base = ioremap_nocache(bus_addr, size);
if (!mem_base)
goto out;
dev->dma_mem = kmalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
if (!dev->dma_mem)
goto out;
dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
if (!dev->dma_mem->bitmap)
goto free1_out;
dev->dma_mem->virt_base = mem_base;
dev->dma_mem->device_base = device_addr;
dev->dma_mem->size = pages;
dev->dma_mem->flags = flags;
if (flags & DMA_MEMORY_MAP)
return DMA_MEMORY_MAP;
return DMA_MEMORY_IO;
free1_out:
kfree(dev->dma_mem);
out:
if (mem_base)
iounmap(mem_base);
return 0;
}
EXPORT_SYMBOL(dma_declare_coherent_memory);
void dma_release_declared_memory(struct device *dev)
{
struct dma_coherent_mem *mem = dev->dma_mem;
if (!mem)
return;
dev->dma_mem = NULL;
iounmap(mem->virt_base);
kfree(mem->bitmap);
kfree(mem);
}
EXPORT_SYMBOL(dma_release_declared_memory);
void *dma_mark_declared_memory_occupied(struct device *dev,
dma_addr_t device_addr, size_t size)
{
struct dma_coherent_mem *mem = dev->dma_mem;
int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
int pos, err;
if (!mem)
return ERR_PTR(-EINVAL);
pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
if (err != 0)
return ERR_PTR(err);
return mem->virt_base + (pos << PAGE_SHIFT);
}
EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
void dma_cache_sync(struct device *dev, void *vaddr, size_t size, void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction direction) enum dma_data_direction direction)
{ {
......
...@@ -30,6 +30,7 @@ config X86 ...@@ -30,6 +30,7 @@ config X86
select HAVE_FTRACE select HAVE_FTRACE
select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64)
select HAVE_ARCH_KGDB if !X86_VOYAGER select HAVE_ARCH_KGDB if !X86_VOYAGER
select HAVE_GENERIC_DMA_COHERENT if X86_32
select HAVE_EFFICIENT_UNALIGNED_ACCESS select HAVE_EFFICIENT_UNALIGNED_ACCESS
config ARCH_DEFCONFIG config ARCH_DEFCONFIG
......
...@@ -29,9 +29,6 @@ ...@@ -29,9 +29,6 @@
#define CMD_SET_TYPE(cmd, t) ((cmd)->data[1] |= ((t) << 28)) #define CMD_SET_TYPE(cmd, t) ((cmd)->data[1] |= ((t) << 28))
#define to_pages(addr, size) \
(round_up(((addr) & ~PAGE_MASK) + (size), PAGE_SIZE) >> PAGE_SHIFT)
#define EXIT_LOOP_COUNT 10000000 #define EXIT_LOOP_COUNT 10000000
static DEFINE_RWLOCK(amd_iommu_devtable_lock); static DEFINE_RWLOCK(amd_iommu_devtable_lock);
...@@ -185,7 +182,7 @@ static int iommu_flush_pages(struct amd_iommu *iommu, u16 domid, ...@@ -185,7 +182,7 @@ static int iommu_flush_pages(struct amd_iommu *iommu, u16 domid,
u64 address, size_t size) u64 address, size_t size)
{ {
int s = 0; int s = 0;
unsigned pages = to_pages(address, size); unsigned pages = iommu_num_pages(address, size);
address &= PAGE_MASK; address &= PAGE_MASK;
...@@ -557,7 +554,7 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu, ...@@ -557,7 +554,7 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu,
if (iommu->exclusion_start && if (iommu->exclusion_start &&
iommu->exclusion_start < dma_dom->aperture_size) { iommu->exclusion_start < dma_dom->aperture_size) {
unsigned long startpage = iommu->exclusion_start >> PAGE_SHIFT; unsigned long startpage = iommu->exclusion_start >> PAGE_SHIFT;
int pages = to_pages(iommu->exclusion_start, int pages = iommu_num_pages(iommu->exclusion_start,
iommu->exclusion_length); iommu->exclusion_length);
dma_ops_reserve_addresses(dma_dom, startpage, pages); dma_ops_reserve_addresses(dma_dom, startpage, pages);
} }
...@@ -767,7 +764,7 @@ static dma_addr_t __map_single(struct device *dev, ...@@ -767,7 +764,7 @@ static dma_addr_t __map_single(struct device *dev,
unsigned int pages; unsigned int pages;
int i; int i;
pages = to_pages(paddr, size); pages = iommu_num_pages(paddr, size);
paddr &= PAGE_MASK; paddr &= PAGE_MASK;
address = dma_ops_alloc_addresses(dev, dma_dom, pages); address = dma_ops_alloc_addresses(dev, dma_dom, pages);
...@@ -802,7 +799,7 @@ static void __unmap_single(struct amd_iommu *iommu, ...@@ -802,7 +799,7 @@ static void __unmap_single(struct amd_iommu *iommu,
if ((dma_addr == 0) || (dma_addr + size > dma_dom->aperture_size)) if ((dma_addr == 0) || (dma_addr + size > dma_dom->aperture_size))
return; return;
pages = to_pages(dma_addr, size); pages = iommu_num_pages(dma_addr, size);
dma_addr &= PAGE_MASK; dma_addr &= PAGE_MASK;
start = dma_addr; start = dma_addr;
......
...@@ -192,124 +192,6 @@ static __init int iommu_setup(char *p) ...@@ -192,124 +192,6 @@ static __init int iommu_setup(char *p)
} }
early_param("iommu", iommu_setup); early_param("iommu", iommu_setup);
#ifdef CONFIG_X86_32
int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
dma_addr_t device_addr, size_t size, int flags)
{
void __iomem *mem_base = NULL;
int pages = size >> PAGE_SHIFT;
int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
goto out;
if (!size)
goto out;
if (dev->dma_mem)
goto out;
/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
mem_base = ioremap(bus_addr, size);
if (!mem_base)
goto out;
dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
if (!dev->dma_mem)
goto out;
dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
if (!dev->dma_mem->bitmap)
goto free1_out;
dev->dma_mem->virt_base = mem_base;
dev->dma_mem->device_base = device_addr;
dev->dma_mem->size = pages;
dev->dma_mem->flags = flags;
if (flags & DMA_MEMORY_MAP)
return DMA_MEMORY_MAP;
return DMA_MEMORY_IO;
free1_out:
kfree(dev->dma_mem);
out:
if (mem_base)
iounmap(mem_base);
return 0;
}
EXPORT_SYMBOL(dma_declare_coherent_memory);
void dma_release_declared_memory(struct device *dev)
{
struct dma_coherent_mem *mem = dev->dma_mem;
if (!mem)
return;
dev->dma_mem = NULL;
iounmap(mem->virt_base);
kfree(mem->bitmap);
kfree(mem);
}
EXPORT_SYMBOL(dma_release_declared_memory);
void *dma_mark_declared_memory_occupied(struct device *dev,
dma_addr_t device_addr, size_t size)
{
struct dma_coherent_mem *mem = dev->dma_mem;
int pos, err;
int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1);
pages >>= PAGE_SHIFT;
if (!mem)
return ERR_PTR(-EINVAL);
pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
if (err != 0)
return ERR_PTR(err);
return mem->virt_base + (pos << PAGE_SHIFT);
}
EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
static int dma_alloc_from_coherent_mem(struct device *dev, ssize_t size,
dma_addr_t *dma_handle, void **ret)
{
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
int order = get_order(size);
if (mem) {
int page = bitmap_find_free_region(mem->bitmap, mem->size,
order);
if (page >= 0) {
*dma_handle = mem->device_base + (page << PAGE_SHIFT);
*ret = mem->virt_base + (page << PAGE_SHIFT);
memset(*ret, 0, size);
}
if (mem->flags & DMA_MEMORY_EXCLUSIVE)
*ret = NULL;
}
return (mem != NULL);
}
static int dma_release_coherent(struct device *dev, int order, void *vaddr)
{
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
if (mem && vaddr >= mem->virt_base && vaddr <
(mem->virt_base + (mem->size << PAGE_SHIFT))) {
int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
bitmap_release_region(mem->bitmap, page, order);
return 1;
}
return 0;
}
#else
#define dma_alloc_from_coherent_mem(dev, size, handle, ret) (0)
#define dma_release_coherent(dev, order, vaddr) (0)
#endif /* CONFIG_X86_32 */
int dma_supported(struct device *dev, u64 mask) int dma_supported(struct device *dev, u64 mask)
{ {
struct dma_mapping_ops *ops = get_dma_ops(dev); struct dma_mapping_ops *ops = get_dma_ops(dev);
...@@ -379,7 +261,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, ...@@ -379,7 +261,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
/* ignore region specifiers */ /* ignore region specifiers */
gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
if (dma_alloc_from_coherent_mem(dev, size, dma_handle, &memory)) if (dma_alloc_from_coherent(dev, size, dma_handle, &memory))
return memory; return memory;
if (!dev) { if (!dev) {
...@@ -484,7 +366,7 @@ void dma_free_coherent(struct device *dev, size_t size, ...@@ -484,7 +366,7 @@ void dma_free_coherent(struct device *dev, size_t size,
int order = get_order(size); int order = get_order(size);
WARN_ON(irqs_disabled()); /* for portability */ WARN_ON(irqs_disabled()); /* for portability */
if (dma_release_coherent(dev, order, vaddr)) if (dma_release_from_coherent(dev, order, vaddr))
return; return;
if (ops->unmap_single) if (ops->unmap_single)
ops->unmap_single(dev, bus, size, 0); ops->unmap_single(dev, bus, size, 0);
......
...@@ -67,9 +67,6 @@ static u32 gart_unmapped_entry; ...@@ -67,9 +67,6 @@ static u32 gart_unmapped_entry;
(((x) & 0xfffff000) | (((x) >> 32) << 4) | GPTE_VALID | GPTE_COHERENT) (((x) & 0xfffff000) | (((x) >> 32) << 4) | GPTE_VALID | GPTE_COHERENT)
#define GPTE_DECODE(x) (((x) & 0xfffff000) | (((u64)(x) & 0xff0) << 28)) #define GPTE_DECODE(x) (((x) & 0xfffff000) | (((u64)(x) & 0xff0) << 28))
#define to_pages(addr, size) \
(round_up(((addr) & ~PAGE_MASK) + (size), PAGE_SIZE) >> PAGE_SHIFT)
#define EMERGENCY_PAGES 32 /* = 128KB */ #define EMERGENCY_PAGES 32 /* = 128KB */
#ifdef CONFIG_AGP #ifdef CONFIG_AGP
...@@ -241,7 +238,7 @@ nonforced_iommu(struct device *dev, unsigned long addr, size_t size) ...@@ -241,7 +238,7 @@ nonforced_iommu(struct device *dev, unsigned long addr, size_t size)
static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
size_t size, int dir) size_t size, int dir)
{ {
unsigned long npages = to_pages(phys_mem, size); unsigned long npages = iommu_num_pages(phys_mem, size);
unsigned long iommu_page = alloc_iommu(dev, npages); unsigned long iommu_page = alloc_iommu(dev, npages);
int i; int i;
...@@ -304,7 +301,7 @@ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr, ...@@ -304,7 +301,7 @@ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
return; return;
iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT; iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT;
npages = to_pages(dma_addr, size); npages = iommu_num_pages(dma_addr, size);
for (i = 0; i < npages; i++) { for (i = 0; i < npages; i++) {
iommu_gatt_base[iommu_page + i] = gart_unmapped_entry; iommu_gatt_base[iommu_page + i] = gart_unmapped_entry;
CLEAR_LEAK(iommu_page + i); CLEAR_LEAK(iommu_page + i);
...@@ -387,7 +384,7 @@ static int __dma_map_cont(struct device *dev, struct scatterlist *start, ...@@ -387,7 +384,7 @@ static int __dma_map_cont(struct device *dev, struct scatterlist *start,
} }
addr = phys_addr; addr = phys_addr;
pages = to_pages(s->offset, s->length); pages = iommu_num_pages(s->offset, s->length);
while (pages--) { while (pages--) {
iommu_gatt_base[iommu_page] = GPTE_ENCODE(addr); iommu_gatt_base[iommu_page] = GPTE_ENCODE(addr);
SET_LEAK(iommu_page); SET_LEAK(iommu_page);
...@@ -470,7 +467,7 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) ...@@ -470,7 +467,7 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
seg_size += s->length; seg_size += s->length;
need = nextneed; need = nextneed;
pages += to_pages(s->offset, s->length); pages += iommu_num_pages(s->offset, s->length);
ps = s; ps = s;
} }
if (dma_map_cont(dev, start_sg, i - start, sgmap, pages, need) < 0) if (dma_map_cont(dev, start_sg, i - start, sgmap, pages, need) < 0)
......
...@@ -23,7 +23,8 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d) ...@@ -23,7 +23,8 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)
pci_read_config_byte(d, reg++, &busno); pci_read_config_byte(d, reg++, &busno);
pci_read_config_byte(d, reg++, &suba); pci_read_config_byte(d, reg++, &suba);
pci_read_config_byte(d, reg++, &subb); pci_read_config_byte(d, reg++, &subb);
DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb); dev_dbg(&d->dev, "i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno,
suba, subb);
if (busno) if (busno)
pci_scan_bus_with_sysdata(busno); /* Bus A */ pci_scan_bus_with_sysdata(busno); /* Bus A */
if (suba < subb) if (suba < subb)
......
...@@ -128,10 +128,8 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) ...@@ -128,10 +128,8 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
pr = pci_find_parent_resource(dev, r); pr = pci_find_parent_resource(dev, r);
if (!r->start || !pr || if (!r->start || !pr ||
request_resource(pr, r) < 0) { request_resource(pr, r) < 0) {
printk(KERN_ERR "PCI: Cannot allocate " dev_err(&dev->dev, "BAR %d: can't "
"resource region %d " "allocate resource\n", idx);
"of bridge %s\n",
idx, pci_name(dev));
/* /*
* Something is wrong with the region. * Something is wrong with the region.
* Invalidate the resource to prevent * Invalidate the resource to prevent
...@@ -166,15 +164,15 @@ static void __init pcibios_allocate_resources(int pass) ...@@ -166,15 +164,15 @@ static void __init pcibios_allocate_resources(int pass)
else else
disabled = !(command & PCI_COMMAND_MEMORY); disabled = !(command & PCI_COMMAND_MEMORY);
if (pass == disabled) { if (pass == disabled) {
DBG("PCI: Resource %08lx-%08lx " dev_dbg(&dev->dev, "resource %#08llx-%#08llx "
"(f=%lx, d=%d, p=%d)\n", "(f=%lx, d=%d, p=%d)\n",
r->start, r->end, r->flags, disabled, pass); (unsigned long long) r->start,
(unsigned long long) r->end,
r->flags, disabled, pass);
pr = pci_find_parent_resource(dev, r); pr = pci_find_parent_resource(dev, r);
if (!pr || request_resource(pr, r) < 0) { if (!pr || request_resource(pr, r) < 0) {
printk(KERN_ERR "PCI: Cannot allocate " dev_err(&dev->dev, "BAR %d: can't "
"resource region %d " "allocate resource\n", idx);
"of device %s\n",
idx, pci_name(dev));
/* We'll assign a new address later */ /* We'll assign a new address later */
r->end -= r->start; r->end -= r->start;
r->start = 0; r->start = 0;
...@@ -187,8 +185,7 @@ static void __init pcibios_allocate_resources(int pass) ...@@ -187,8 +185,7 @@ static void __init pcibios_allocate_resources(int pass)
/* Turn the ROM off, leave the resource region, /* Turn the ROM off, leave the resource region,
* but keep it unregistered. */ * but keep it unregistered. */
u32 reg; u32 reg;
DBG("PCI: Switching off ROM of %s\n", dev_dbg(&dev->dev, "disabling ROM\n");
pci_name(dev));
r->flags &= ~IORESOURCE_ROM_ENABLE; r->flags &= ~IORESOURCE_ROM_ENABLE;
pci_read_config_dword(dev, pci_read_config_dword(dev,
dev->rom_base_reg, &reg); dev->rom_base_reg, &reg);
...@@ -257,8 +254,7 @@ void pcibios_set_master(struct pci_dev *dev) ...@@ -257,8 +254,7 @@ void pcibios_set_master(struct pci_dev *dev)
lat = pcibios_max_latency; lat = pcibios_max_latency;
else else
return; return;
printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", dev_printk(KERN_DEBUG, &dev->dev, "setting latency timer to %d\n", lat);
pci_name(dev), lat);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
} }
......
...@@ -436,7 +436,7 @@ static int pirq_vlsi_get(struct pci_dev *router, struct pci_dev *dev, int pirq) ...@@ -436,7 +436,7 @@ static int pirq_vlsi_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
{ {
WARN_ON_ONCE(pirq >= 9); WARN_ON_ONCE(pirq >= 9);
if (pirq > 8) { if (pirq > 8) {
printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq); dev_info(&dev->dev, "VLSI router PIRQ escape (%d)\n", pirq);
return 0; return 0;
} }
return read_config_nybble(router, 0x74, pirq-1); return read_config_nybble(router, 0x74, pirq-1);
...@@ -446,7 +446,7 @@ static int pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq, ...@@ -446,7 +446,7 @@ static int pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq,
{ {
WARN_ON_ONCE(pirq >= 9); WARN_ON_ONCE(pirq >= 9);
if (pirq > 8) { if (pirq > 8) {
printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq); dev_info(&dev->dev, "VLSI router PIRQ escape (%d)\n", pirq);
return 0; return 0;
} }
write_config_nybble(router, 0x74, pirq-1, irq); write_config_nybble(router, 0x74, pirq-1, irq);
...@@ -492,14 +492,16 @@ static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq ...@@ -492,14 +492,16 @@ static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq
irq = 0; irq = 0;
if (pirq <= 4) if (pirq <= 4)
irq = read_config_nybble(router, 0x56, pirq - 1); irq = read_config_nybble(router, 0x56, pirq - 1);
printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d get irq : %2d\n", dev_info(&dev->dev,
"AMD756: dev [%04x/%04x], router PIRQ %d get IRQ %d\n",
dev->vendor, dev->device, pirq, irq); dev->vendor, dev->device, pirq, irq);
return irq; return irq;
} }
static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
{ {
printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d SET irq : %2d\n", dev_info(&dev->dev,
"AMD756: dev [%04x/%04x], router PIRQ %d set IRQ %d\n",
dev->vendor, dev->device, pirq, irq); dev->vendor, dev->device, pirq, irq);
if (pirq <= 4) if (pirq <= 4)
write_config_nybble(router, 0x56, pirq - 1, irq); write_config_nybble(router, 0x56, pirq - 1, irq);
...@@ -730,7 +732,6 @@ static __init int ali_router_probe(struct irq_router *r, struct pci_dev *router, ...@@ -730,7 +732,6 @@ static __init int ali_router_probe(struct irq_router *r, struct pci_dev *router,
switch (device) { switch (device) {
case PCI_DEVICE_ID_AL_M1533: case PCI_DEVICE_ID_AL_M1533:
case PCI_DEVICE_ID_AL_M1563: case PCI_DEVICE_ID_AL_M1563:
printk(KERN_DEBUG "PCI: Using ALI IRQ Router\n");
r->name = "ALI"; r->name = "ALI";
r->get = pirq_ali_get; r->get = pirq_ali_get;
r->set = pirq_ali_set; r->set = pirq_ali_set;
...@@ -840,11 +841,9 @@ static void __init pirq_find_router(struct irq_router *r) ...@@ -840,11 +841,9 @@ static void __init pirq_find_router(struct irq_router *r)
h->probe(r, pirq_router_dev, pirq_router_dev->device)) h->probe(r, pirq_router_dev, pirq_router_dev->device))
break; break;
} }
printk(KERN_INFO "PCI: Using IRQ router %s [%04x/%04x] at %s\n", dev_info(&pirq_router_dev->dev, "%s IRQ router [%04x/%04x]\n",
pirq_router.name, pirq_router.name,
pirq_router_dev->vendor, pirq_router_dev->vendor, pirq_router_dev->device);
pirq_router_dev->device,
pci_name(pirq_router_dev));
/* The device remains referenced for the kernel lifetime */ /* The device remains referenced for the kernel lifetime */
} }
...@@ -877,7 +876,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) ...@@ -877,7 +876,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
/* Find IRQ pin */ /* Find IRQ pin */
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (!pin) { if (!pin) {
DBG(KERN_DEBUG " -> no interrupt pin\n"); dev_dbg(&dev->dev, "no interrupt pin\n");
return 0; return 0;
} }
pin = pin - 1; pin = pin - 1;
...@@ -887,20 +886,20 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) ...@@ -887,20 +886,20 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
if (!pirq_table) if (!pirq_table)
return 0; return 0;
DBG(KERN_DEBUG "IRQ for %s[%c]", pci_name(dev), 'A' + pin);
info = pirq_get_info(dev); info = pirq_get_info(dev);
if (!info) { if (!info) {
DBG(" -> not found in routing table\n" KERN_DEBUG); dev_dbg(&dev->dev, "PCI INT %c not found in routing table\n",
'A' + pin);
return 0; return 0;
} }
pirq = info->irq[pin].link; pirq = info->irq[pin].link;
mask = info->irq[pin].bitmap; mask = info->irq[pin].bitmap;
if (!pirq) { if (!pirq) {
DBG(" -> not routed\n" KERN_DEBUG); dev_dbg(&dev->dev, "PCI INT %c not routed\n", 'A' + pin);
return 0; return 0;
} }
DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, dev_dbg(&dev->dev, "PCI INT %c -> PIRQ %02x, mask %04x, excl %04x",
pirq_table->exclusive_irqs); 'A' + pin, pirq, mask, pirq_table->exclusive_irqs);
mask &= pcibios_irq_mask; mask &= pcibios_irq_mask;
/* Work around broken HP Pavilion Notebooks which assign USB to /* Work around broken HP Pavilion Notebooks which assign USB to
...@@ -930,10 +929,8 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) ...@@ -930,10 +929,8 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
if (pci_probe & PCI_USE_PIRQ_MASK) if (pci_probe & PCI_USE_PIRQ_MASK)
newirq = 0; newirq = 0;
else else
printk("\n" KERN_WARNING dev_warn(&dev->dev, "IRQ %d doesn't match PIRQ mask "
"PCI: IRQ %i for device %s doesn't match PIRQ mask - try pci=usepirqmask\n" "%#x; try pci=usepirqmask\n", newirq, mask);
KERN_DEBUG, newirq,
pci_name(dev));
} }
if (!newirq && assign) { if (!newirq && assign) {
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
...@@ -944,39 +941,35 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) ...@@ -944,39 +941,35 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
newirq = i; newirq = i;
} }
} }
DBG(" -> newirq=%d", newirq); dev_dbg(&dev->dev, "PCI INT %c -> newirq %d", 'A' + pin, newirq);
/* Check if it is hardcoded */ /* Check if it is hardcoded */
if ((pirq & 0xf0) == 0xf0) { if ((pirq & 0xf0) == 0xf0) {
irq = pirq & 0xf; irq = pirq & 0xf;
DBG(" -> hardcoded IRQ %d\n", irq); msg = "hardcoded";
msg = "Hardcoded";
} else if (r->get && (irq = r->get(pirq_router_dev, dev, pirq)) && \ } else if (r->get && (irq = r->get(pirq_router_dev, dev, pirq)) && \
((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask))) { ((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask))) {
DBG(" -> got IRQ %d\n", irq); msg = "found";
msg = "Found";
eisa_set_level_irq(irq); eisa_set_level_irq(irq);
} else if (newirq && r->set && } else if (newirq && r->set &&
(dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) { (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
DBG(" -> assigning IRQ %d", newirq);
if (r->set(pirq_router_dev, dev, pirq, newirq)) { if (r->set(pirq_router_dev, dev, pirq, newirq)) {
eisa_set_level_irq(newirq); eisa_set_level_irq(newirq);
DBG(" ... OK\n"); msg = "assigned";
msg = "Assigned";
irq = newirq; irq = newirq;
} }
} }
if (!irq) { if (!irq) {
DBG(" ... failed\n");
if (newirq && mask == (1 << newirq)) { if (newirq && mask == (1 << newirq)) {
msg = "Guessed"; msg = "guessed";
irq = newirq; irq = newirq;
} else } else {
dev_dbg(&dev->dev, "can't route interrupt\n");
return 0; return 0;
} }
printk(KERN_INFO "PCI: %s IRQ %d for device %s\n", msg, irq, }
pci_name(dev)); dev_info(&dev->dev, "%s PCI INT %c -> IRQ %d\n", msg, 'A' + pin, irq);
/* Update IRQ for all devices with the same pirq value */ /* Update IRQ for all devices with the same pirq value */
while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) { while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) {
...@@ -996,16 +989,16 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) ...@@ -996,16 +989,16 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
(!(pci_probe & PCI_USE_PIRQ_MASK) || \ (!(pci_probe & PCI_USE_PIRQ_MASK) || \
((1 << dev2->irq) & mask))) { ((1 << dev2->irq) & mask))) {
#ifndef CONFIG_PCI_MSI #ifndef CONFIG_PCI_MSI
printk(KERN_INFO "IRQ routing conflict for %s, have irq %d, want irq %d\n", dev_info(&dev2->dev, "IRQ routing conflict: "
pci_name(dev2), dev2->irq, irq); "have IRQ %d, want IRQ %d\n",
dev2->irq, irq);
#endif #endif
continue; continue;
} }
dev2->irq = irq; dev2->irq = irq;
pirq_penalty[irq]++; pirq_penalty[irq]++;
if (dev != dev2) if (dev != dev2)
printk(KERN_INFO dev_info(&dev->dev, "sharing IRQ %d with %s\n",
"PCI: Sharing IRQ %d with %s\n",
irq, pci_name(dev2)); irq, pci_name(dev2));
} }
} }
...@@ -1025,8 +1018,7 @@ static void __init pcibios_fixup_irqs(void) ...@@ -1025,8 +1018,7 @@ static void __init pcibios_fixup_irqs(void)
* already in use. * already in use.
*/ */
if (dev->irq >= 16) { if (dev->irq >= 16) {
DBG(KERN_DEBUG "%s: ignoring bogus IRQ %d\n", dev_dbg(&dev->dev, "ignoring bogus IRQ %d\n", dev->irq);
pci_name(dev), dev->irq);
dev->irq = 0; dev->irq = 0;
} }
/* /*
...@@ -1070,12 +1062,12 @@ static void __init pcibios_fixup_irqs(void) ...@@ -1070,12 +1062,12 @@ static void __init pcibios_fixup_irqs(void)
irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
PCI_SLOT(bridge->devfn), pin); PCI_SLOT(bridge->devfn), pin);
if (irq >= 0) if (irq >= 0)
printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n", dev_warn(&dev->dev, "using bridge %s INT %c to get IRQ %d\n",
pci_name(bridge), 'A' + pin, irq); pci_name(bridge),
'A' + pin, irq);
} }
if (irq >= 0) { if (irq >= 0) {
printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n", dev_info(&dev->dev, "PCI->APIC IRQ transform: INT %c -> IRQ %d\n", 'A' + pin, irq);
pci_name(dev), 'A' + pin, irq);
dev->irq = irq; dev->irq = irq;
} }
} }
...@@ -1231,25 +1223,24 @@ static int pirq_enable_irq(struct pci_dev *dev) ...@@ -1231,25 +1223,24 @@ static int pirq_enable_irq(struct pci_dev *dev)
irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
PCI_SLOT(bridge->devfn), pin); PCI_SLOT(bridge->devfn), pin);
if (irq >= 0) if (irq >= 0)
printk(KERN_WARNING dev_warn(&dev->dev, "using bridge %s "
"PCI: using PPB %s[%c] to get irq %d\n", "INT %c to get IRQ %d\n",
pci_name(bridge), pci_name(bridge), 'A' + pin,
'A' + pin, irq); irq);
dev = bridge; dev = bridge;
} }
dev = temp_dev; dev = temp_dev;
if (irq >= 0) { if (irq >= 0) {
printk(KERN_INFO dev_info(&dev->dev, "PCI->APIC IRQ transform: "
"PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n", "INT %c -> IRQ %d\n", 'A' + pin, irq);
pci_name(dev), 'A' + pin, irq);
dev->irq = irq; dev->irq = irq;
return 0; return 0;
} else } else
msg = " Probably buggy MP table."; msg = "; probably buggy MP table";
} else if (pci_probe & PCI_BIOS_IRQ_SCAN) } else if (pci_probe & PCI_BIOS_IRQ_SCAN)
msg = ""; msg = "";
else else
msg = " Please try using pci=biosirq."; msg = "; please try using pci=biosirq";
/* /*
* With IDE legacy devices the IRQ lookup failure is not * With IDE legacy devices the IRQ lookup failure is not
...@@ -1259,9 +1250,8 @@ static int pirq_enable_irq(struct pci_dev *dev) ...@@ -1259,9 +1250,8 @@ static int pirq_enable_irq(struct pci_dev *dev)
!(dev->class & 0x5)) !(dev->class & 0x5))
return 0; return 0;
printk(KERN_WARNING dev_warn(&dev->dev, "can't find IRQ for PCI INT %c%s\n",
"PCI: No IRQ known for interrupt pin %c of device %s.%s\n", 'A' + pin, msg);
'A' + pin, pci_name(dev), msg);
} }
return 0; return 0;
} }
...@@ -131,13 +131,14 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d) ...@@ -131,13 +131,14 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)
u8 busno, suba, subb; u8 busno, suba, subb;
int quad = BUS2QUAD(d->bus->number); int quad = BUS2QUAD(d->bus->number);
printk("PCI: Searching for i450NX host bridges on %s\n", pci_name(d)); dev_info(&d->dev, "searching for i450NX host bridges\n");
reg = 0xd0; reg = 0xd0;
for(pxb=0; pxb<2; pxb++) { for(pxb=0; pxb<2; pxb++) {
pci_read_config_byte(d, reg++, &busno); pci_read_config_byte(d, reg++, &busno);
pci_read_config_byte(d, reg++, &suba); pci_read_config_byte(d, reg++, &suba);
pci_read_config_byte(d, reg++, &subb); pci_read_config_byte(d, reg++, &subb);
DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb); dev_dbg(&d->dev, "i450NX PXB %d: %02x/%02x/%02x\n",
pxb, busno, suba, subb);
if (busno) { if (busno) {
/* Bus A */ /* Bus A */
pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, busno)); pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, busno));
......
...@@ -76,9 +76,9 @@ static struct acpi_pci_driver acpi_pci_slot_driver = { ...@@ -76,9 +76,9 @@ static struct acpi_pci_driver acpi_pci_slot_driver = {
}; };
static int static int
check_slot(acpi_handle handle, int *device, unsigned long *sun) check_slot(acpi_handle handle, unsigned long *sun)
{ {
int retval = 0; int device = -1;
unsigned long adr, sta; unsigned long adr, sta;
acpi_status status; acpi_status status;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
...@@ -89,32 +89,27 @@ check_slot(acpi_handle handle, int *device, unsigned long *sun) ...@@ -89,32 +89,27 @@ check_slot(acpi_handle handle, int *device, unsigned long *sun)
if (check_sta_before_sun) { if (check_sta_before_sun) {
/* If SxFy doesn't have _STA, we just assume it's there */ /* If SxFy doesn't have _STA, we just assume it's there */
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
if (ACPI_SUCCESS(status) && !(sta & ACPI_STA_DEVICE_PRESENT)) { if (ACPI_SUCCESS(status) && !(sta & ACPI_STA_DEVICE_PRESENT))
retval = -1;
goto out; goto out;
} }
}
status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
dbg("_ADR returned %d on %s\n", status, (char *)buffer.pointer); dbg("_ADR returned %d on %s\n", status, (char *)buffer.pointer);
retval = -1;
goto out; goto out;
} }
*device = (adr >> 16) & 0xffff;
/* No _SUN == not a slot == bail */ /* No _SUN == not a slot == bail */
status = acpi_evaluate_integer(handle, "_SUN", NULL, sun); status = acpi_evaluate_integer(handle, "_SUN", NULL, sun);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
dbg("_SUN returned %d on %s\n", status, (char *)buffer.pointer); dbg("_SUN returned %d on %s\n", status, (char *)buffer.pointer);
retval = -1;
goto out; goto out;
} }
device = (adr >> 16) & 0xffff;
out: out:
kfree(buffer.pointer); kfree(buffer.pointer);
return retval; return device;
} }
struct callback_args { struct callback_args {
...@@ -144,7 +139,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) ...@@ -144,7 +139,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
struct callback_args *parent_context = context; struct callback_args *parent_context = context;
struct pci_bus *pci_bus = parent_context->pci_bus; struct pci_bus *pci_bus = parent_context->pci_bus;
if (check_slot(handle, &device, &sun)) device = check_slot(handle, &sun);
if (device < 0)
return AE_OK; return AE_OK;
slot = kmalloc(sizeof(*slot), GFP_KERNEL); slot = kmalloc(sizeof(*slot), GFP_KERNEL);
......
...@@ -1103,7 +1103,7 @@ static inline void dbg_ctrl(struct controller *ctrl) ...@@ -1103,7 +1103,7 @@ static inline void dbg_ctrl(struct controller *ctrl)
dbg(" Power Indicator : %3s\n", PWR_LED(ctrl) ? "yes" : "no"); dbg(" Power Indicator : %3s\n", PWR_LED(ctrl) ? "yes" : "no");
dbg(" Hot-Plug Surprise : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no"); dbg(" Hot-Plug Surprise : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no");
dbg(" EMI Present : %3s\n", EMI(ctrl) ? "yes" : "no"); dbg(" EMI Present : %3s\n", EMI(ctrl) ? "yes" : "no");
dbg(" Comamnd Completed : %3s\n", NO_CMD_CMPL(ctrl)? "no" : "yes"); dbg(" Command Completed : %3s\n", NO_CMD_CMPL(ctrl)? "no" : "yes");
pciehp_readw(ctrl, SLOTSTATUS, &reg16); pciehp_readw(ctrl, SLOTSTATUS, &reg16);
dbg("Slot Status : 0x%04x\n", reg16); dbg("Slot Status : 0x%04x\n", reg16);
pciehp_readw(ctrl, SLOTCTRL, &reg16); pciehp_readw(ctrl, SLOTCTRL, &reg16);
......
...@@ -126,7 +126,16 @@ static void msix_flush_writes(unsigned int irq) ...@@ -126,7 +126,16 @@ static void msix_flush_writes(unsigned int irq)
} }
} }
static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag) /*
* PCI 2.3 does not specify mask bits for each MSI interrupt. Attempting to
* mask all MSI interrupts by clearing the MSI enable bit does not work
* reliably as devices without an INTx disable bit will then generate a
* level IRQ which will never be cleared.
*
* Returns 1 if it succeeded in masking the interrupt and 0 if the device
* doesn't support MSI masking.
*/
static int msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag)
{ {
struct msi_desc *entry; struct msi_desc *entry;
...@@ -144,8 +153,7 @@ static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag) ...@@ -144,8 +153,7 @@ static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag)
mask_bits |= flag & mask; mask_bits |= flag & mask;
pci_write_config_dword(entry->dev, pos, mask_bits); pci_write_config_dword(entry->dev, pos, mask_bits);
} else { } else {
__msi_set_enable(entry->dev, entry->msi_attrib.pos, return 0;
!flag);
} }
break; break;
case PCI_CAP_ID_MSIX: case PCI_CAP_ID_MSIX:
...@@ -161,6 +169,7 @@ static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag) ...@@ -161,6 +169,7 @@ static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag)
break; break;
} }
entry->msi_attrib.masked = !!flag; entry->msi_attrib.masked = !!flag;
return 1;
} }
void read_msi_msg(unsigned int irq, struct msi_msg *msg) void read_msi_msg(unsigned int irq, struct msi_msg *msg)
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci-aspm.h>
#include <acpi/acpi.h> #include <acpi/acpi.h>
#include <acpi/acnamesp.h> #include <acpi/acnamesp.h>
#include <acpi/acresrc.h> #include <acpi/acresrc.h>
...@@ -372,6 +373,12 @@ static int __init acpi_pci_init(void) ...@@ -372,6 +373,12 @@ static int __init acpi_pci_init(void)
printk(KERN_INFO"ACPI FADT declares the system doesn't support MSI, so disable it\n"); printk(KERN_INFO"ACPI FADT declares the system doesn't support MSI, so disable it\n");
pci_no_msi(); pci_no_msi();
} }
if (acpi_gbl_FADT.boot_flags & BAF_PCIE_ASPM_CONTROL) {
printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n");
pcie_no_aspm();
}
ret = register_acpi_bus_type(&acpi_pci_bus); ret = register_acpi_bus_type(&acpi_pci_bus);
if (ret) if (ret)
return 0; return 0;
......
...@@ -572,6 +572,10 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) ...@@ -572,6 +572,10 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
if (!ret) if (!ret)
pci_update_current_state(dev); pci_update_current_state(dev);
} }
/* This device is quirked not to be put into D3, so
don't put it in D3 */
if (state == PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3))
return 0;
error = pci_raw_set_power_state(dev, state); error = pci_raw_set_power_state(dev, state);
...@@ -1123,6 +1127,12 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) ...@@ -1123,6 +1127,12 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable)
} }
/** /**
* pci_target_state - find an appropriate low power state for a given PCI dev
* @dev: PCI device
*
* Use underlying platform code to find a supported low power state for @dev.
* If the platform can't manage @dev, return the deepest state from which it
* can generate wake events, based on any available PME info.
*/ */
pci_power_t pci_target_state(struct pci_dev *dev) pci_power_t pci_target_state(struct pci_dev *dev)
{ {
......
...@@ -55,7 +55,7 @@ struct pcie_link_state { ...@@ -55,7 +55,7 @@ struct pcie_link_state {
struct endpoint_state endpoints[8]; struct endpoint_state endpoints[8];
}; };
static int aspm_disabled; static int aspm_disabled, aspm_force;
static DEFINE_MUTEX(aspm_lock); static DEFINE_MUTEX(aspm_lock);
static LIST_HEAD(link_list); static LIST_HEAD(link_list);
...@@ -510,6 +510,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) ...@@ -510,6 +510,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
{ {
struct pci_dev *child_dev; struct pci_dev *child_dev;
int child_pos; int child_pos;
u32 reg32;
/* /*
* Some functions in a slot might not all be PCIE functions, very * Some functions in a slot might not all be PCIE functions, very
...@@ -519,6 +520,19 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) ...@@ -519,6 +520,19 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP); child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
if (!child_pos) if (!child_pos)
return -EINVAL; return -EINVAL;
/*
* Disable ASPM for pre-1.1 PCIe device, we follow MS to use
* RBER bit to determine if a function is 1.1 version device
*/
pci_read_config_dword(child_dev, child_pos + PCI_EXP_DEVCAP,
&reg32);
if (!(reg32 & PCI_EXP_DEVCAP_RBER && !aspm_force)) {
printk("Pre-1.1 PCIe device detected, "
"disable ASPM for %s. It can be enabled forcedly"
" with 'pcie_aspm=force'\n", pci_name(pdev));
return -EINVAL;
}
} }
return 0; return 0;
} }
...@@ -802,11 +816,23 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev) ...@@ -802,11 +816,23 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
static int __init pcie_aspm_disable(char *str) static int __init pcie_aspm_disable(char *str)
{ {
if (!strcmp(str, "off")) {
aspm_disabled = 1; aspm_disabled = 1;
printk(KERN_INFO "PCIe ASPM is disabled\n");
} else if (!strcmp(str, "force")) {
aspm_force = 1;
printk(KERN_INFO "PCIe ASPM is forcedly enabled\n");
}
return 1; return 1;
} }
__setup("pcie_noaspm", pcie_aspm_disable); __setup("pcie_aspm=", pcie_aspm_disable);
void pcie_no_aspm(void)
{
if (!aspm_force)
aspm_disabled = 1;
}
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
#include <acpi/acpi_bus.h> #include <acpi/acpi_bus.h>
......
...@@ -163,12 +163,9 @@ static inline unsigned int pci_calc_resource_flags(unsigned int flags) ...@@ -163,12 +163,9 @@ static inline unsigned int pci_calc_resource_flags(unsigned int flags)
return IORESOURCE_MEM; return IORESOURCE_MEM;
} }
/* static u64 pci_size(u64 base, u64 maxbase, u64 mask)
* Find the extent of a PCI decode..
*/
static u32 pci_size(u32 base, u32 maxbase, u32 mask)
{ {
u32 size = mask & maxbase; /* Find the significant bits */ u64 size = mask & maxbase; /* Find the significant bits */
if (!size) if (!size)
return 0; return 0;
...@@ -184,135 +181,142 @@ static u32 pci_size(u32 base, u32 maxbase, u32 mask) ...@@ -184,135 +181,142 @@ static u32 pci_size(u32 base, u32 maxbase, u32 mask)
return size; return size;
} }
static u64 pci_size64(u64 base, u64 maxbase, u64 mask) enum pci_bar_type {
{ pci_bar_unknown, /* Standard PCI BAR probe */
u64 size = mask & maxbase; /* Find the significant bits */ pci_bar_io, /* An io port BAR */
if (!size) pci_bar_mem32, /* A 32-bit memory BAR */
return 0; pci_bar_mem64, /* A 64-bit memory BAR */
};
/* Get the lowest of them to find the decode size, and
from that the extent. */
size = (size & ~(size-1)) - 1;
/* base == maxbase can be valid only if the BAR has static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar)
already been programmed with all 1s. */ {
if (base == maxbase && ((base | size) & mask) != mask) if ((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
return 0; res->flags = bar & ~PCI_BASE_ADDRESS_IO_MASK;
return pci_bar_io;
}
return size; res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK;
}
static inline int is_64bit_memory(u32 mask) if (res->flags == PCI_BASE_ADDRESS_MEM_TYPE_64)
{ return pci_bar_mem64;
if ((mask & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == return pci_bar_mem32;
(PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64))
return 1;
return 0;
} }
static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) /*
* If the type is not unknown, we assume that the lowest bit is 'enable'.
* Returns 1 if the BAR was 64-bit and 0 if it was 32-bit.
*/
static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
struct resource *res, unsigned int pos)
{ {
unsigned int pos, reg, next; u32 l, sz, mask;
u32 l, sz;
struct resource *res;
for(pos=0; pos<howmany; pos = next) { mask = type ? ~PCI_ROM_ADDRESS_ENABLE : ~0;
u64 l64;
u64 sz64;
u32 raw_sz;
next = pos+1;
res = &dev->resource[pos];
res->name = pci_name(dev); res->name = pci_name(dev);
reg = PCI_BASE_ADDRESS_0 + (pos << 2);
pci_read_config_dword(dev, reg, &l); pci_read_config_dword(dev, pos, &l);
pci_write_config_dword(dev, reg, ~0); pci_write_config_dword(dev, pos, mask);
pci_read_config_dword(dev, reg, &sz); pci_read_config_dword(dev, pos, &sz);
pci_write_config_dword(dev, reg, l); pci_write_config_dword(dev, pos, l);
/*
* All bits set in sz means the device isn't working properly.
* If the BAR isn't implemented, all bits must be 0. If it's a
* memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit
* 1 must be clear.
*/
if (!sz || sz == 0xffffffff) if (!sz || sz == 0xffffffff)
continue; goto fail;
if (l == 0xffffffff)
l = 0;
raw_sz = sz;
if ((l & PCI_BASE_ADDRESS_SPACE) ==
PCI_BASE_ADDRESS_SPACE_MEMORY) {
sz = pci_size(l, sz, (u32)PCI_BASE_ADDRESS_MEM_MASK);
/* /*
* For 64bit prefetchable memory sz could be 0, if the * I don't know how l can have all bits set. Copied from old code.
* real size is bigger than 4G, so we need to check * Maybe it fixes a bug on some ancient platform.
* szhi for that.
*/ */
if (!is_64bit_memory(l) && !sz) if (l == 0xffffffff)
continue; l = 0;
res->start = l & PCI_BASE_ADDRESS_MEM_MASK;
res->flags |= l & ~PCI_BASE_ADDRESS_MEM_MASK; if (type == pci_bar_unknown) {
type = decode_bar(res, l);
res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN;
if (type == pci_bar_io) {
l &= PCI_BASE_ADDRESS_IO_MASK;
mask = PCI_BASE_ADDRESS_IO_MASK & 0xffff;
} else { } else {
sz = pci_size(l, sz, PCI_BASE_ADDRESS_IO_MASK & 0xffff); l &= PCI_BASE_ADDRESS_MEM_MASK;
if (!sz) mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
continue;
res->start = l & PCI_BASE_ADDRESS_IO_MASK;
res->flags |= l & ~PCI_BASE_ADDRESS_IO_MASK;
} }
res->end = res->start + (unsigned long) sz; } else {
res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN; res->flags |= (l & IORESOURCE_ROM_ENABLE);
if (is_64bit_memory(l)) { l &= PCI_ROM_ADDRESS_MASK;
u32 szhi, lhi; mask = (u32)PCI_ROM_ADDRESS_MASK;
pci_read_config_dword(dev, reg+4, &lhi);
pci_write_config_dword(dev, reg+4, ~0);
pci_read_config_dword(dev, reg+4, &szhi);
pci_write_config_dword(dev, reg+4, lhi);
sz64 = ((u64)szhi << 32) | raw_sz;
l64 = ((u64)lhi << 32) | l;
sz64 = pci_size64(l64, sz64, PCI_BASE_ADDRESS_MEM_MASK);
next++;
#if BITS_PER_LONG == 64
if (!sz64) {
res->start = 0;
res->end = 0;
res->flags = 0;
continue;
} }
res->start = l64 & PCI_BASE_ADDRESS_MEM_MASK;
res->end = res->start + sz64; if (type == pci_bar_mem64) {
#else u64 l64 = l;
if (sz64 > 0x100000000ULL) { u64 sz64 = sz;
dev_err(&dev->dev, "BAR %d: can't handle 64-bit" u64 mask64 = mask | (u64)~0 << 32;
" BAR\n", pos);
res->start = 0; pci_read_config_dword(dev, pos + 4, &l);
res->flags = 0; pci_write_config_dword(dev, pos + 4, ~0);
} else if (lhi) { pci_read_config_dword(dev, pos + 4, &sz);
/* 64-bit wide address, treat as disabled */ pci_write_config_dword(dev, pos + 4, l);
pci_write_config_dword(dev, reg,
l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK); l64 |= ((u64)l << 32);
pci_write_config_dword(dev, reg+4, 0); sz64 |= ((u64)sz << 32);
sz64 = pci_size(l64, sz64, mask64);
if (!sz64)
goto fail;
if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) {
dev_err(&dev->dev, "can't handle 64-bit BAR\n");
goto fail;
} else if ((sizeof(resource_size_t) < 8) && l) {
/* Address above 32-bit boundary; disable the BAR */
pci_write_config_dword(dev, pos, 0);
pci_write_config_dword(dev, pos + 4, 0);
res->start = 0; res->start = 0;
res->end = sz; res->end = sz64;
} else {
res->start = l64;
res->end = l64 + sz64;
} }
#endif } else {
sz = pci_size(l, sz, mask);
if (!sz)
goto fail;
res->start = l;
res->end = l + sz;
} }
out:
return (type == pci_bar_mem64) ? 1 : 0;
fail:
res->flags = 0;
goto out;
}
static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
{
unsigned int pos, reg;
for (pos = 0; pos < howmany; pos++) {
struct resource *res = &dev->resource[pos];
reg = PCI_BASE_ADDRESS_0 + (pos << 2);
pos += __pci_read_base(dev, pci_bar_unknown, res, reg);
} }
if (rom) { if (rom) {
struct resource *res = &dev->resource[PCI_ROM_RESOURCE];
dev->rom_base_reg = rom; dev->rom_base_reg = rom;
res = &dev->resource[PCI_ROM_RESOURCE]; res->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH |
res->name = pci_name(dev);
pci_read_config_dword(dev, rom, &l);
pci_write_config_dword(dev, rom, ~PCI_ROM_ADDRESS_ENABLE);
pci_read_config_dword(dev, rom, &sz);
pci_write_config_dword(dev, rom, l);
if (l == 0xffffffff)
l = 0;
if (sz && sz != 0xffffffff) {
sz = pci_size(l, sz, (u32)PCI_ROM_ADDRESS_MASK);
if (sz) {
res->flags = (l & IORESOURCE_ROM_ENABLE) |
IORESOURCE_MEM | IORESOURCE_PREFETCH |
IORESOURCE_READONLY | IORESOURCE_CACHEABLE | IORESOURCE_READONLY | IORESOURCE_CACHEABLE |
IORESOURCE_SIZEALIGN; IORESOURCE_SIZEALIGN;
res->start = l & PCI_ROM_ADDRESS_MASK; __pci_read_base(dev, pci_bar_mem32, res, rom);
res->end = res->start + (unsigned long) sz;
}
}
} }
} }
...@@ -1053,7 +1057,8 @@ int pci_scan_slot(struct pci_bus *bus, int devfn) ...@@ -1053,7 +1057,8 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
} }
} }
if (bus->self) /* only one slot has pcie device */
if (bus->self && nr)
pcie_aspm_init_link_state(bus->self); pcie_aspm_init_link_state(bus->self);
return nr; return nr;
......
...@@ -923,6 +923,19 @@ static void __init quirk_ide_samemode(struct pci_dev *pdev) ...@@ -923,6 +923,19 @@ static void __init quirk_ide_samemode(struct pci_dev *pdev)
} }
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, quirk_ide_samemode); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, quirk_ide_samemode);
/*
* Some ATA devices break if put into D3
*/
static void __devinit quirk_no_ata_d3(struct pci_dev *pdev)
{
/* Quirk the legacy ATA devices only. The AHCI ones are ok */
if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
pdev->dev_flags |= PCI_DEV_FLAGS_NO_D3;
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_ANY_ID, quirk_no_ata_d3);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, PCI_ANY_ID, quirk_no_ata_d3);
/* This was originally an Alpha specific thing, but it really fits here. /* This was originally an Alpha specific thing, but it really fits here.
* The i82375 PCI/EISA bridge appears as non-classified. Fix that. * The i82375 PCI/EISA bridge appears as non-classified. Fix that.
*/ */
......
...@@ -277,6 +277,7 @@ enum acpi_prefered_pm_profiles { ...@@ -277,6 +277,7 @@ enum acpi_prefered_pm_profiles {
#define BAF_LEGACY_DEVICES 0x0001 #define BAF_LEGACY_DEVICES 0x0001
#define BAF_8042_KEYBOARD_CONTROLLER 0x0002 #define BAF_8042_KEYBOARD_CONTROLLER 0x0002
#define BAF_MSI_NOT_SUPPORTED 0x0008 #define BAF_MSI_NOT_SUPPORTED 0x0008
#define BAF_PCIE_ASPM_CONTROL 0x0010
#define FADT2_REVISION_ID 3 #define FADT2_REVISION_ID 3
#define FADT2_MINUS_REVISION_ID 2 #define FADT2_MINUS_REVISION_ID 2
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <asm-generic/dma-coherent.h>
/* /*
* DMA-consistent mapping functions. These allocate/free a region of * DMA-consistent mapping functions. These allocate/free a region of
* uncached, unwrite-buffered mapped memory space for use with DMA * uncached, unwrite-buffered mapped memory space for use with DMA
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
#include <asm-generic/dma-coherent.h>
void *dma_alloc_coherent(struct device *dev, size_t size, void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag); dma_addr_t *dma_handle, gfp_t flag);
......
#ifndef DMA_COHERENT_H
#define DMA_COHERENT_H
#ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT
/*
* These two functions are only for dma allocator.
* Don't use them in device drivers.
*/
int dma_alloc_from_coherent(struct device *dev, ssize_t size,
dma_addr_t *dma_handle, void **ret);
int dma_release_from_coherent(struct device *dev, int order, void *vaddr);
/*
* Standard interface
*/
#define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
extern int
dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
dma_addr_t device_addr, size_t size, int flags);
extern void
dma_release_declared_memory(struct device *dev);
extern void *
dma_mark_declared_memory_occupied(struct device *dev,
dma_addr_t device_addr, size_t size);
#else
#define dma_alloc_from_coherent(dev, size, handle, ret) (0)
#define dma_release_from_coherent(dev, order, vaddr) (0)
#endif
#endif
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm-generic/dma-coherent.h>
extern struct bus_type pci_bus_type; extern struct bus_type pci_bus_type;
......
...@@ -249,25 +249,5 @@ static inline int dma_get_cache_alignment(void) ...@@ -249,25 +249,5 @@ static inline int dma_get_cache_alignment(void)
#define dma_is_consistent(d, h) (1) #define dma_is_consistent(d, h) (1)
#ifdef CONFIG_X86_32 #include <asm-generic/dma-coherent.h>
# define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
struct dma_coherent_mem {
void *virt_base;
u32 device_base;
int size;
int flags;
unsigned long *bitmap;
};
extern int
dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
dma_addr_t device_addr, size_t size, int flags);
extern void
dma_release_declared_memory(struct device *dev);
extern void *
dma_mark_declared_memory_occupied(struct device *dev,
dma_addr_t device_addr, size_t size);
#endif /* CONFIG_X86_32 */
#endif #endif
...@@ -8,3 +8,4 @@ extern unsigned long iommu_area_alloc(unsigned long *map, unsigned long size, ...@@ -8,3 +8,4 @@ extern unsigned long iommu_area_alloc(unsigned long *map, unsigned long size,
unsigned long align_mask); unsigned long align_mask);
extern void iommu_area_free(unsigned long *map, unsigned long start, extern void iommu_area_free(unsigned long *map, unsigned long start,
unsigned int nr); unsigned int nr);
extern unsigned long iommu_num_pages(unsigned long addr, unsigned long len);
...@@ -27,6 +27,7 @@ extern void pcie_aspm_init_link_state(struct pci_dev *pdev); ...@@ -27,6 +27,7 @@ extern void pcie_aspm_init_link_state(struct pci_dev *pdev);
extern void pcie_aspm_exit_link_state(struct pci_dev *pdev); extern void pcie_aspm_exit_link_state(struct pci_dev *pdev);
extern void pcie_aspm_pm_state_change(struct pci_dev *pdev); extern void pcie_aspm_pm_state_change(struct pci_dev *pdev);
extern void pci_disable_link_state(struct pci_dev *pdev, int state); extern void pci_disable_link_state(struct pci_dev *pdev, int state);
extern void pcie_no_aspm(void);
#else #else
static inline void pcie_aspm_init_link_state(struct pci_dev *pdev) static inline void pcie_aspm_init_link_state(struct pci_dev *pdev)
{ {
...@@ -40,6 +41,10 @@ static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev) ...@@ -40,6 +41,10 @@ static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev)
static inline void pci_disable_link_state(struct pci_dev *pdev, int state) static inline void pci_disable_link_state(struct pci_dev *pdev, int state)
{ {
} }
static inline void pcie_no_aspm(void)
{
}
#endif #endif
#ifdef CONFIG_PCIEASPM_DEBUG /* this depends on CONFIG_PCIEASPM */ #ifdef CONFIG_PCIEASPM_DEBUG /* this depends on CONFIG_PCIEASPM */
......
...@@ -124,6 +124,8 @@ enum pci_dev_flags { ...@@ -124,6 +124,8 @@ enum pci_dev_flags {
* generation too. * generation too.
*/ */
PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG = (__force pci_dev_flags_t) 1, PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG = (__force pci_dev_flags_t) 1,
/* Device configuration is irrevocably lost if disabled into D3 */
PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2,
}; };
typedef unsigned short __bitwise pci_bus_flags_t; typedef unsigned short __bitwise pci_bus_flags_t;
......
...@@ -374,6 +374,7 @@ ...@@ -374,6 +374,7 @@
#define PCI_EXP_DEVCAP_ATN_BUT 0x1000 /* Attention Button Present */ #define PCI_EXP_DEVCAP_ATN_BUT 0x1000 /* Attention Button Present */
#define PCI_EXP_DEVCAP_ATN_IND 0x2000 /* Attention Indicator Present */ #define PCI_EXP_DEVCAP_ATN_IND 0x2000 /* Attention Indicator Present */
#define PCI_EXP_DEVCAP_PWR_IND 0x4000 /* Power Indicator Present */ #define PCI_EXP_DEVCAP_PWR_IND 0x4000 /* Power Indicator Present */
#define PCI_EXP_DEVCAP_RBER 0x8000 /* Role-Based Error Reporting */
#define PCI_EXP_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value */ #define PCI_EXP_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value */
#define PCI_EXP_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale */ #define PCI_EXP_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale */
#define PCI_EXP_DEVCTL 8 /* Device Control */ #define PCI_EXP_DEVCTL 8 /* Device Control */
......
...@@ -802,6 +802,10 @@ config PROC_PAGE_MONITOR ...@@ -802,6 +802,10 @@ config PROC_PAGE_MONITOR
endmenu # General setup endmenu # General setup
config HAVE_GENERIC_DMA_COHERENT
bool
default n
config SLABINFO config SLABINFO
bool bool
depends on PROC_FS depends on PROC_FS
......
...@@ -84,6 +84,7 @@ obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o ...@@ -84,6 +84,7 @@ obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
obj-$(CONFIG_MARKERS) += marker.o obj-$(CONFIG_MARKERS) += marker.o
obj-$(CONFIG_LATENCYTOP) += latencytop.o obj-$(CONFIG_LATENCYTOP) += latencytop.o
obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
obj-$(CONFIG_FTRACE) += trace/ obj-$(CONFIG_FTRACE) += trace/
obj-$(CONFIG_TRACING) += trace/ obj-$(CONFIG_TRACING) += trace/
obj-$(CONFIG_SMP) += sched_cpupri.o obj-$(CONFIG_SMP) += sched_cpupri.o
......
/*
* Coherent per-device memory handling.
* Borrowed from i386
*/
#include <linux/kernel.h>
#include <linux/dma-mapping.h>
struct dma_coherent_mem {
void *virt_base;
u32 device_base;
int size;
int flags;
unsigned long *bitmap;
};
int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
dma_addr_t device_addr, size_t size, int flags)
{
void __iomem *mem_base = NULL;
int pages = size >> PAGE_SHIFT;
int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
goto out;
if (!size)
goto out;
if (dev->dma_mem)
goto out;
/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
mem_base = ioremap(bus_addr, size);
if (!mem_base)
goto out;
dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
if (!dev->dma_mem)
goto out;
dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
if (!dev->dma_mem->bitmap)
goto free1_out;
dev->dma_mem->virt_base = mem_base;
dev->dma_mem->device_base = device_addr;
dev->dma_mem->size = pages;
dev->dma_mem->flags = flags;
if (flags & DMA_MEMORY_MAP)
return DMA_MEMORY_MAP;
return DMA_MEMORY_IO;
free1_out:
kfree(dev->dma_mem);
out:
if (mem_base)
iounmap(mem_base);
return 0;
}
EXPORT_SYMBOL(dma_declare_coherent_memory);
void dma_release_declared_memory(struct device *dev)
{
struct dma_coherent_mem *mem = dev->dma_mem;
if (!mem)
return;
dev->dma_mem = NULL;
iounmap(mem->virt_base);
kfree(mem->bitmap);
kfree(mem);
}
EXPORT_SYMBOL(dma_release_declared_memory);
void *dma_mark_declared_memory_occupied(struct device *dev,
dma_addr_t device_addr, size_t size)
{
struct dma_coherent_mem *mem = dev->dma_mem;
int pos, err;
int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1);
pages >>= PAGE_SHIFT;
if (!mem)
return ERR_PTR(-EINVAL);
pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
if (err != 0)
return ERR_PTR(err);
return mem->virt_base + (pos << PAGE_SHIFT);
}
EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
/**
* Try to allocate memory from the per-device coherent area.
*
* @dev: device from which we allocate memory
* @size: size of requested memory area
* @dma_handle: This will be filled with the correct dma handle
* @ret: This pointer will be filled with the virtual address
* to allocated area.
*
* This function should be only called from per-arch %dma_alloc_coherent()
* to support allocation from per-device coherent memory pools.
*
* Returns 0 if dma_alloc_coherent should continue with allocating from
* generic memory areas, or !0 if dma_alloc_coherent should return %ret.
*/
int dma_alloc_from_coherent(struct device *dev, ssize_t size,
dma_addr_t *dma_handle, void **ret)
{
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
int order = get_order(size);
if (mem) {
int page = bitmap_find_free_region(mem->bitmap, mem->size,
order);
if (page >= 0) {
*dma_handle = mem->device_base + (page << PAGE_SHIFT);
*ret = mem->virt_base + (page << PAGE_SHIFT);
memset(*ret, 0, size);
} else if (mem->flags & DMA_MEMORY_EXCLUSIVE)
*ret = NULL;
}
return (mem != NULL);
}
/**
* Try to free the memory allocated from per-device coherent memory pool.
* @dev: device from which the memory was allocated
* @order: the order of pages allocated
* @vaddr: virtual address of allocated pages
*
* This checks whether the memory was allocated from the per-device
* coherent memory pool and if so, releases that memory.
*
* Returns 1 if we correctly released the memory, or 0 if
* %dma_release_coherent() should proceed with releasing memory from
* generic pools.
*/
int dma_release_from_coherent(struct device *dev, int order, void *vaddr)
{
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
if (mem && vaddr >= mem->virt_base && vaddr <
(mem->virt_base + (mem->size << PAGE_SHIFT))) {
int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
bitmap_release_region(mem->bitmap, page, order);
return 1;
}
return 0;
}
...@@ -80,3 +80,11 @@ void iommu_area_free(unsigned long *map, unsigned long start, unsigned int nr) ...@@ -80,3 +80,11 @@ void iommu_area_free(unsigned long *map, unsigned long start, unsigned int nr)
} }
} }
EXPORT_SYMBOL(iommu_area_free); EXPORT_SYMBOL(iommu_area_free);
unsigned long iommu_num_pages(unsigned long addr, unsigned long len)
{
unsigned long size = roundup((addr & ~PAGE_MASK) + len, PAGE_SIZE);
return size >> PAGE_SHIFT;
}
EXPORT_SYMBOL(iommu_num_pages);
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