Commit 6a84258e authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6: (37 commits)
  PCI: merge almost all of pci_32.h and pci_64.h together
  PCI: X86: Introduce and enable PCI domain support
  PCI: Add 'nodomains' boot option, and pci_domains_supported global
  PCI: modify PCI bridge control ISA flag for clarity
  PCI: use _CRS for PCI resource allocation
  PCI: avoid P2P prefetch window for expansion ROMs
  PCI: skip ISA ioresource alignment on some systems
  PCI: remove transparent bridge sizing
  pci: write file size to inode on proc bus file write
  pci: use size stored in proc_dir_entry for proc bus files
  pci: implement "pci=noaer"
  PCI: fix IDE legacy mode resources
  MSI: Use correct data offset for 32-bit MSI in read_msi_msg()
  PCI: Fix incorrect argument order to list_add_tail() in PCI dynamic ID code
  PCI: i386: Compaq EVO N800c needs PCI bus renumbering
  PCI: Remove no longer correct documentation regarding MSI vector assignment
  PCI: re-enable onboard sound on "MSI K8T Neo2-FIR"
  PCI: quirk_vt82c586_acpi: Omit reading PCI revision ID
  PCI: quirk amd_8131_mmrbc: Omit reading pci revision ID
  cpqphp: Use PCI_CLASS_REVISION instead of PCI_REVISION_ID for read
  ...
parents efefc6eb f3e6f164
......@@ -68,6 +68,9 @@ size and dma_handle must all be the same as those passed into the
consistent allocate. cpu_addr must be the virtual address returned by
the consistent allocate.
Note that unlike their sibling allocation calls, these routines
may only be called with IRQs enabled.
Part Ib - Using small dma-coherent buffers
------------------------------------------
......
......@@ -241,68 +241,7 @@ address space of the MSI-X table/MSI-X PBA. Otherwise, the PCI subsystem
will fail enabling MSI-X on its hardware device when it calls the function
pci_enable_msix().
5.3.2 Handling MSI-X allocation
Determining the number of MSI-X vectors allocated to a function is
dependent on the number of MSI capable devices and MSI-X capable
devices populated in the system. The policy of allocating MSI-X
vectors to a function is defined as the following:
#of MSI-X vectors allocated to a function = (x - y)/z where
x = The number of available PCI vector resources by the time
the device driver calls pci_enable_msix(). The PCI vector
resources is the sum of the number of unassigned vectors
(new) and the number of released vectors when any MSI/MSI-X
device driver switches its hardware device back to a legacy
mode or is hot-removed. The number of unassigned vectors
may exclude some vectors reserved, as defined in parameter
NR_HP_RESERVED_VECTORS, for the case where the system is
capable of supporting hot-add/hot-remove operations. Users
may change the value defined in NR_HR_RESERVED_VECTORS to
meet their specific needs.
y = The number of MSI capable devices populated in the system.
This policy ensures that each MSI capable device has its
vector reserved to avoid the case where some MSI-X capable
drivers may attempt to claim all available vector resources.
z = The number of MSI-X capable devices populated in the system.
This policy ensures that maximum (x - y) is distributed
evenly among MSI-X capable devices.
Note that the PCI subsystem scans y and z during a bus enumeration.
When the PCI subsystem completes configuring MSI/MSI-X capability
structure of a device as requested by its device driver, y/z is
decremented accordingly.
5.3.3 Handling MSI-X shortages
For the case where fewer MSI-X vectors are allocated to a function
than requested, the function pci_enable_msix() will return the
maximum number of MSI-X vectors available to the caller. A device
driver may re-send its request with fewer or equal vectors indicated
in the return. For example, if a device driver requests 5 vectors, but
the number of available vectors is 3 vectors, a value of 3 will be
returned as a result of pci_enable_msix() call. A function could be
designed for its driver to use only 3 MSI-X table entries as
different combinations as ABC--, A-B-C, A--CB, etc. Note that this
patch does not support multiple entries with the same vector. Such
attempt by a device driver to use 5 MSI-X table entries with 3 vectors
as ABBCC, AABCC, BCCBA, etc will result as a failure by the function
pci_enable_msix(). Below are the reasons why supporting multiple
entries with the same vector is an undesirable solution.
- The PCI subsystem cannot determine the entry that
generated the message to mask/unmask MSI while handling
software driver ISR. Attempting to walk through all MSI-X
table entries (2048 max) to mask/unmask any match vector
is an undesirable solution.
- Walking through all MSI-X table entries (2048 max) to handle
SMP affinity of any match vector is an undesirable solution.
5.3.4 API pci_enable_msix
5.3.2 API pci_enable_msix
int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)
......@@ -339,7 +278,7 @@ a failure. This failure may be a result of duplicate entries
specified in second argument, or a result of no available vector,
or a result of failing to initialize MSI-X table entries.
5.3.5 API pci_disable_msix
5.3.3 API pci_disable_msix
void pci_disable_msix(struct pci_dev *dev)
......@@ -349,7 +288,7 @@ always call free_irq() on all MSI-X vectors it has done request_irq()
on before calling this API. Failure to do so results in a BUG_ON() and
a device will be left with MSI-X enabled and leaks its vectors.
5.3.6 MSI-X mode vs. legacy mode diagram
5.3.4 MSI-X mode vs. legacy mode diagram
The below diagram shows the events which switch the interrupt
mode on the MSI-X capable device function between MSI-X mode and
......@@ -407,7 +346,7 @@ between MSI mod MSI-X mode during a run-time.
MSI/MSI-X support requires support from both system hardware and
individual hardware device functions.
5.5.1 System hardware support
5.5.1 Required x86 hardware support
Since the target of MSI address is the local APIC CPU, enabling
MSI/MSI-X support in the Linux kernel is dependent on whether existing
......
......@@ -68,6 +68,7 @@ parameter is applicable:
PARIDE The ParIDE (parallel port IDE) subsystem is enabled.
PARISC The PA-RISC architecture is enabled.
PCI PCI bus support is enabled.
PCIE PCI Express support is enabled.
PCMCIA The PCMCIA subsystem is enabled.
PNP Plug & Play support is enabled.
PPC PowerPC architecture is enabled.
......@@ -1277,6 +1278,11 @@ and is between 256 and 4096 characters. It is defined in the file
Mechanism 1.
conf2 [X86-32] Force use of PCI Configuration
Mechanism 2.
noaer [PCIE] If the PCIEAER kernel config parameter is
enabled, this kernel boot option can be used to
disable the use of PCIE advanced error reporting.
nodomains [PCI] Disable support for multiple PCI
root domains (aka PCI segments, in ACPI-speak).
nommconf [X86-32,X86_64] Disable use of MMCONFIG for PCI
Configuration
nomsi [MSI] If the PCI_MSI kernel config parameter is
......@@ -1321,6 +1327,8 @@ and is between 256 and 4096 characters. It is defined in the file
IRQ routing is enabled.
noacpi [X86-32] Do not use ACPI for IRQ routing
or for PCI scanning.
use_crs [X86-32] Use _CRS for PCI resource
allocation.
routeirq Do IRQ routing for all PCI devices.
This is normally done in pci_enable_device(),
so this option is a temporary workaround
......
......@@ -1137,6 +1137,11 @@ config PCI_MMCONFIG
depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
default y
config PCI_DOMAINS
bool
depends on PCI
default y
source "drivers/pci/pcie/Kconfig"
source "drivers/pci/Kconfig"
......
......@@ -63,7 +63,8 @@ void dma_free_coherent(struct device *dev, size_t size,
{
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
int order = get_order(size);
WARN_ON(irqs_disabled()); /* for portability */
if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) {
int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
......
......@@ -167,6 +167,7 @@ EXPORT_SYMBOL(dma_alloc_coherent);
void dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t bus)
{
WARN_ON(irqs_disabled()); /* for portability */
if (dma_ops->unmap_single)
dma_ops->unmap_single(dev, bus, size, 0);
free_pages((unsigned long)vaddr, get_order(size));
......
......@@ -11,6 +11,7 @@
#include <asm/delay.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <asm/reboot_fixups.h>
#include <asm/msr.h>
......@@ -56,6 +57,11 @@ void mach_reboot_fixups(void)
struct pci_dev *dev;
int i;
/* we can be called from sysrq-B code. In such a case it is
* prohibited to dig PCI */
if (in_interrupt())
return;
for (i=0; i < ARRAY_SIZE(fixups_table); i++) {
cur = &(fixups_table[i]);
dev = pci_get_device(cur->vendor, cur->device, NULL);
......
......@@ -2,15 +2,199 @@
#include <linux/acpi.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/dmi.h>
#include <asm/numa.h>
#include "pci.h"
static int __devinit can_skip_ioresource_align(struct dmi_system_id *d)
{
pci_probe |= PCI_CAN_SKIP_ISA_ALIGN;
printk(KERN_INFO "PCI: %s detected, can skip ISA alignment\n", d->ident);
return 0;
}
static struct dmi_system_id acpi_pciprobe_dmi_table[] = {
/*
* Systems where PCI IO resource ISA alignment can be skipped
* when the ISA enable bit in the bridge control is not set
*/
{
.callback = can_skip_ioresource_align,
.ident = "IBM System x3800",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
DMI_MATCH(DMI_PRODUCT_NAME, "x3800"),
},
},
{
.callback = can_skip_ioresource_align,
.ident = "IBM System x3850",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
DMI_MATCH(DMI_PRODUCT_NAME, "x3850"),
},
},
{
.callback = can_skip_ioresource_align,
.ident = "IBM System x3950",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
DMI_MATCH(DMI_PRODUCT_NAME, "x3950"),
},
},
{}
};
struct pci_root_info {
char *name;
unsigned int res_num;
struct resource *res;
struct pci_bus *bus;
int busnum;
};
static acpi_status
resource_to_addr(struct acpi_resource *resource,
struct acpi_resource_address64 *addr)
{
acpi_status status;
status = acpi_resource_to_address64(resource, addr);
if (ACPI_SUCCESS(status) &&
(addr->resource_type == ACPI_MEMORY_RANGE ||
addr->resource_type == ACPI_IO_RANGE) &&
addr->address_length > 0 &&
addr->producer_consumer == ACPI_PRODUCER) {
return AE_OK;
}
return AE_ERROR;
}
static acpi_status
count_resource(struct acpi_resource *acpi_res, void *data)
{
struct pci_root_info *info = data;
struct acpi_resource_address64 addr;
acpi_status status;
status = resource_to_addr(acpi_res, &addr);
if (ACPI_SUCCESS(status))
info->res_num++;
return AE_OK;
}
static acpi_status
setup_resource(struct acpi_resource *acpi_res, void *data)
{
struct pci_root_info *info = data;
struct resource *res;
struct acpi_resource_address64 addr;
acpi_status status;
unsigned long flags;
struct resource *root;
status = resource_to_addr(acpi_res, &addr);
if (!ACPI_SUCCESS(status))
return AE_OK;
if (addr.resource_type == ACPI_MEMORY_RANGE) {
root = &iomem_resource;
flags = IORESOURCE_MEM;
if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
flags |= IORESOURCE_PREFETCH;
} else if (addr.resource_type == ACPI_IO_RANGE) {
root = &ioport_resource;
flags = IORESOURCE_IO;
} else
return AE_OK;
res = &info->res[info->res_num];
res->name = info->name;
res->flags = flags;
res->start = addr.minimum + addr.translation_offset;
res->end = res->start + addr.address_length - 1;
res->child = NULL;
if (insert_resource(root, res)) {
printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx "
"from %s for %s\n", (unsigned long) res->start,
(unsigned long) res->end, root->name, info->name);
} else {
info->bus->resource[info->res_num] = res;
info->res_num++;
}
return AE_OK;
}
static void
adjust_transparent_bridge_resources(struct pci_bus *bus)
{
struct pci_dev *dev;
list_for_each_entry(dev, &bus->devices, bus_list) {
int i;
u16 class = dev->class >> 8;
if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent) {
for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++)
dev->subordinate->resource[i] =
dev->bus->resource[i - 3];
}
}
}
static void
get_current_resources(struct acpi_device *device, int busnum,
struct pci_bus *bus)
{
struct pci_root_info info;
size_t size;
info.bus = bus;
info.res_num = 0;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
&info);
if (!info.res_num)
return;
size = sizeof(*info.res) * info.res_num;
info.res = kmalloc(size, GFP_KERNEL);
if (!info.res)
goto res_alloc_fail;
info.name = kmalloc(12, GFP_KERNEL);
if (!info.name)
goto name_alloc_fail;
sprintf(info.name, "PCI Bus #%02x", busnum);
info.res_num = 0;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
&info);
if (info.res_num)
adjust_transparent_bridge_resources(bus);
return;
name_alloc_fail:
kfree(info.res);
res_alloc_fail:
return;
}
struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum)
{
struct pci_bus *bus;
struct pci_sysdata *sd;
int pxm;
dmi_check_system(acpi_pciprobe_dmi_table);
if (domain && !pci_domains_supported) {
printk(KERN_WARNING "PCI: Multiple domains not supported "
"(dom %d, bus %d)\n", domain, busnum);
return NULL;
}
/* Allocate per-root-bus (not per bus) arch-specific data.
* TODO: leak; this memory is never freed.
* It's arguable whether it's worth the trouble to care.
......@@ -21,12 +205,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
return NULL;
}
if (domain != 0) {
printk(KERN_WARNING "PCI: Multiple domains not supported\n");
kfree(sd);
return NULL;
}
sd->domain = domain;
sd->node = -1;
pxm = acpi_get_pxm(device->handle);
......@@ -47,6 +226,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
}
}
#endif
if (bus && (pci_probe & PCI_USE__CRS))
get_current_resources(device, busnum, bus);
return bus;
}
......
......@@ -29,12 +29,14 @@ struct pci_raw_ops *raw_pci_ops;
static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
{
return raw_pci_ops->read(0, bus->number, devfn, where, size, value);
return raw_pci_ops->read(pci_domain_nr(bus), bus->number,
devfn, where, size, value);
}
static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
{
return raw_pci_ops->write(0, bus->number, devfn, where, size, value);
return raw_pci_ops->write(pci_domain_nr(bus), bus->number,
devfn, where, size, value);
}
struct pci_ops pci_root_ops = {
......@@ -287,6 +289,16 @@ static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"),
},
},
#ifdef __i386__
{
.callback = assign_all_busses,
.ident = "Compaq EVO N800c",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
DMI_MATCH(DMI_PRODUCT_NAME, "EVO N800c"),
},
},
#endif
{}
};
......@@ -426,6 +438,9 @@ char * __devinit pcibios_setup(char *str)
} else if (!strcmp(str, "assign-busses")) {
pci_probe |= PCI_ASSIGN_ALL_BUSSES;
return NULL;
} else if (!strcmp(str, "use_crs")) {
pci_probe |= PCI_USE__CRS;
return NULL;
} else if (!strcmp(str, "routeirq")) {
pci_routeirq = 1;
return NULL;
......
......@@ -353,6 +353,53 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
static struct dmi_system_id __devinitdata msi_k8t_dmi_table[] = {
{
.ident = "MSI-K8T-Neo2Fir",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "MSI"),
DMI_MATCH(DMI_PRODUCT_NAME, "MS-6702E"),
},
},
{}
};
/*
* The AMD-Athlon64 board MSI "K8T Neo2-FIR" disables the onboard sound
* card if a PCI-soundcard is added.
*
* The BIOS only gives options "DISABLED" and "AUTO". This code sets
* the corresponding register-value to enable the soundcard.
*
* The soundcard is only enabled, if the mainborad is identified
* via DMI-tables and the soundcard is detected to be off.
*/
static void __devinit pci_fixup_msi_k8t_onboard_sound(struct pci_dev *dev)
{
unsigned char val;
if (!dmi_check_system(msi_k8t_dmi_table))
return; /* only applies to MSI K8T Neo2-FIR */
pci_read_config_byte(dev, 0x50, &val);
if (val & 0x40) {
pci_write_config_byte(dev, 0x50, val & (~0x40));
/* verify the change for status output */
pci_read_config_byte(dev, 0x50, &val);
if (val & 0x40)
printk(KERN_INFO "PCI: Detected MSI K8T Neo2-FIR, "
"can't enable onboard soundcard!\n");
else
printk(KERN_INFO "PCI: Detected MSI K8T Neo2-FIR, "
"enabled onboard soundcard.\n");
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,
pci_fixup_msi_k8t_onboard_sound);
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,
pci_fixup_msi_k8t_onboard_sound);
/*
* Some Toshiba laptops need extra code to enable their TI TSB43AB22/A.
*
......
......@@ -33,6 +33,15 @@
#include "pci.h"
static int
skip_isa_ioresource_align(struct pci_dev *dev) {
if ((pci_probe & PCI_CAN_SKIP_ISA_ALIGN) &&
!(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA))
return 1;
return 0;
}
/*
* We need to avoid collisions with `mirrored' VGA ports
* and other strange ISA hardware, so we always want the
......@@ -50,9 +59,13 @@ void
pcibios_align_resource(void *data, struct resource *res,
resource_size_t size, resource_size_t align)
{
struct pci_dev *dev = data;
if (res->flags & IORESOURCE_IO) {
resource_size_t start = res->start;
if (skip_isa_ioresource_align(dev))
return;
if (start & 0x300) {
start = (start + 0x3ff) & ~0x3ff;
res->start = start;
......
......@@ -492,6 +492,26 @@ static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq
return 1;
}
/*
* PicoPower PT86C523
*/
static int pirq_pico_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
{
outb(0x10 + ((pirq - 1) >> 1), 0x24);
return ((pirq - 1) & 1) ? (inb(0x26) >> 4) : (inb(0x26) & 0xf);
}
static int pirq_pico_set(struct pci_dev *router, struct pci_dev *dev, int pirq,
int irq)
{
unsigned int x;
outb(0x10 + ((pirq - 1) >> 1), 0x24);
x = inb(0x26);
x = ((pirq - 1) & 1) ? ((x & 0x0f) | (irq << 4)) : ((x & 0xf0) | (irq));
outb(x, 0x26);
return 1;
}
#ifdef CONFIG_PCI_BIOS
static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
......@@ -721,6 +741,24 @@ static __init int amd_router_probe(struct irq_router *r, struct pci_dev *router,
return 1;
}
static __init int pico_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
{
switch (device) {
case PCI_DEVICE_ID_PICOPOWER_PT86C523:
r->name = "PicoPower PT86C523";
r->get = pirq_pico_get;
r->set = pirq_pico_set;
return 1;
case PCI_DEVICE_ID_PICOPOWER_PT86C523BBP:
r->name = "PicoPower PT86C523 rev. BB+";
r->get = pirq_pico_get;
r->set = pirq_pico_set;
return 1;
}
return 0;
}
static __initdata struct irq_router_handler pirq_routers[] = {
{ PCI_VENDOR_ID_INTEL, intel_router_probe },
{ PCI_VENDOR_ID_AL, ali_router_probe },
......@@ -732,6 +770,7 @@ static __initdata struct irq_router_handler pirq_routers[] = {
{ PCI_VENDOR_ID_VLSI, vlsi_router_probe },
{ PCI_VENDOR_ID_SERVERWORKS, serverworks_router_probe },
{ PCI_VENDOR_ID_AMD, amd_router_probe },
{ PCI_VENDOR_ID_PICOPOWER, pico_router_probe },
/* Someone with docs needs to add the ATI Radeon IGP */
{ 0, NULL }
};
......
......@@ -26,6 +26,8 @@
#define PCI_ASSIGN_ROMS 0x1000
#define PCI_BIOS_IRQ_SCAN 0x2000
#define PCI_ASSIGN_ALL_BUSSES 0x4000
#define PCI_CAN_SKIP_ISA_ALIGN 0x8000
#define PCI_USE__CRS 0x10000
extern unsigned int pci_probe;
extern unsigned long pirq_table_addr;
......
......@@ -738,6 +738,11 @@ config PCI_MMCONFIG
bool "Support mmconfig PCI config space access"
depends on PCI && ACPI
config PCI_DOMAINS
bool
depends on PCI
default y
source "drivers/pci/pcie/Kconfig"