mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-29 15:14:18 +08:00
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 ...
This commit is contained in:
commit
6a84258e5f
@ -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"
|
||||
|
||||
source "drivers/pci/Kconfig"
|
||||
|
@ -549,7 +549,7 @@ get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot)
|
||||
* slot. */
|
||||
bus->number = tbus;
|
||||
pci_bus_read_config_dword(bus, PCI_DEVFN(tdevice, 0),
|
||||
PCI_REVISION_ID, &work);
|
||||
PCI_CLASS_REVISION, &work);
|
||||
|
||||
if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
|
||||
pci_bus_read_config_dword(bus,
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pci_hotplug.h>
|
||||
#include <linux/kthread.h>
|
||||
#include "cpqphp.h"
|
||||
|
||||
static u32 configure_new_device(struct controller* ctrl, struct pci_func *func,
|
||||
@ -45,34 +46,20 @@ static int configure_new_function(struct controller* ctrl, struct pci_func *func
|
||||
u8 behind_bridge, struct resource_lists *resources);
|
||||
static void interrupt_event_handler(struct controller *ctrl);
|
||||
|
||||
static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */
|
||||
static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */
|
||||
static int event_finished;
|
||||
static unsigned long pushbutton_pending; /* = 0 */
|
||||
|
||||
/* things needed for the long_delay function */
|
||||
static struct semaphore delay_sem;
|
||||
static wait_queue_head_t delay_wait;
|
||||
static struct task_struct *cpqhp_event_thread;
|
||||
static unsigned long pushbutton_pending; /* = 0 */
|
||||
|
||||
/* delay is in jiffies to wait for */
|
||||
static void long_delay(int delay)
|
||||
{
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
|
||||
/* only allow 1 customer into the delay queue at once
|
||||
* yes this makes some people wait even longer, but who really cares?
|
||||
* this is for _huge_ delays to make the hardware happy as the
|
||||
* signals bounce around
|
||||
/*
|
||||
* XXX(hch): if someone is bored please convert all callers
|
||||
* to call msleep_interruptible directly. They really want
|
||||
* to specify timeouts in natural units and spend a lot of
|
||||
* effort converting them to jiffies..
|
||||
*/
|
||||
down (&delay_sem);
|
||||
|
||||
init_waitqueue_head(&delay_wait);
|
||||
|
||||
add_wait_queue(&delay_wait, &wait);
|
||||
msleep_interruptible(jiffies_to_msecs(delay));
|
||||
remove_wait_queue(&delay_wait, &wait);
|
||||
|
||||
up(&delay_sem);
|
||||
}
|
||||
|
||||
|
||||
@ -955,8 +942,8 @@ irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data)
|
||||
}
|
||||
|
||||
if (schedule_flag) {
|
||||
up(&event_semaphore);
|
||||
dbg("Signal event_semaphore\n");
|
||||
wake_up_process(cpqhp_event_thread);
|
||||
dbg("Waking even thread");
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -973,16 +960,13 @@ struct pci_func *cpqhp_slot_create(u8 busnumber)
|
||||
struct pci_func *new_slot;
|
||||
struct pci_func *next;
|
||||
|
||||
new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL);
|
||||
|
||||
new_slot = kzalloc(sizeof(*new_slot), GFP_KERNEL);
|
||||
if (new_slot == NULL) {
|
||||
/* I'm not dead yet!
|
||||
* You will be. */
|
||||
return new_slot;
|
||||
}
|
||||
|
||||
memset(new_slot, 0, sizeof(struct pci_func));
|
||||
|
||||
new_slot->next = NULL;
|
||||
new_slot->configured = 1;
|
||||
|
||||
@ -1738,7 +1722,7 @@ static u32 remove_board(struct pci_func * func, u32 replace_flag, struct control
|
||||
static void pushbutton_helper_thread(unsigned long data)
|
||||
{
|
||||
pushbutton_pending = data;
|
||||
up(&event_semaphore);
|
||||
wake_up_process(cpqhp_event_thread);
|
||||
}
|
||||
|
||||
|
||||
@ -1747,13 +1731,13 @@ static int event_thread(void* data)
|
||||
{
|
||||
struct controller *ctrl;
|
||||
|
||||
daemonize("phpd_event");
|
||||
|
||||
while (1) {
|
||||
dbg("!!!!event_thread sleeping\n");
|
||||
down_interruptible (&event_semaphore);
|
||||
dbg("event_thread woken finished = %d\n", event_finished);
|
||||
if (event_finished) break;
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule();
|
||||
|
||||
if (kthread_should_stop())
|
||||
break;
|
||||
/* Do stuff here */
|
||||
if (pushbutton_pending)
|
||||
cpqhp_pushbutton_thread(pushbutton_pending);
|
||||
@ -1762,38 +1746,24 @@ static int event_thread(void* data)
|
||||
interrupt_event_handler(ctrl);
|
||||
}
|
||||
dbg("event_thread signals exit\n");
|
||||
up(&event_exit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cpqhp_event_start_thread(void)
|
||||
{
|
||||
int pid;
|
||||
|
||||
/* initialize our semaphores */
|
||||
init_MUTEX(&delay_sem);
|
||||
init_MUTEX_LOCKED(&event_semaphore);
|
||||
init_MUTEX_LOCKED(&event_exit);
|
||||
event_finished=0;
|
||||
|
||||
pid = kernel_thread(event_thread, NULL, 0);
|
||||
if (pid < 0) {
|
||||
cpqhp_event_thread = kthread_run(event_thread, NULL, "phpd_event");
|
||||
if (IS_ERR(cpqhp_event_thread)) {
|
||||
err ("Can't start up our event thread\n");
|
||||
return -1;
|
||||
return PTR_ERR(cpqhp_event_thread);
|
||||
}
|
||||
dbg("Our event thread pid = %d\n", pid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void cpqhp_event_stop_thread(void)
|
||||
{
|
||||
event_finished = 1;
|
||||
dbg("event_thread finish command given\n");
|
||||
up(&event_semaphore);
|
||||
dbg("wait for event_thread to exit\n");
|
||||
down(&event_exit);
|
||||
kthread_stop(cpqhp_event_thread);
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <linux/kthread.h>
|
||||
#include "ibmphp.h"
|
||||
|
||||
static int to_debug = 0;
|
||||
@ -101,12 +101,11 @@ static int to_debug = 0;
|
||||
//----------------------------------------------------------------------------
|
||||
// global variables
|
||||
//----------------------------------------------------------------------------
|
||||
static int ibmphp_shutdown;
|
||||
static int tid_poll;
|
||||
static struct mutex sem_hpcaccess; // lock access to HPC
|
||||
static struct semaphore semOperations; // lock all operations and
|
||||
// access to data structures
|
||||
static struct semaphore sem_exit; // make sure polling thread goes away
|
||||
static struct task_struct *ibmphp_poll_thread;
|
||||
//----------------------------------------------------------------------------
|
||||
// local function prototypes
|
||||
//----------------------------------------------------------------------------
|
||||
@ -116,10 +115,9 @@ static u8 hpc_writecmdtoindex (u8, u8);
|
||||
static u8 hpc_readcmdtoindex (u8, u8);
|
||||
static void get_hpc_access (void);
|
||||
static void free_hpc_access (void);
|
||||
static void poll_hpc (void);
|
||||
static int poll_hpc(void *data);
|
||||
static int process_changeinstatus (struct slot *, struct slot *);
|
||||
static int process_changeinlatch (u8, u8, struct controller *);
|
||||
static int hpc_poll_thread (void *);
|
||||
static int hpc_wait_ctlr_notworking (int, struct controller *, void __iomem *, u8 *);
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@ -137,8 +135,6 @@ void __init ibmphp_hpc_initvars (void)
|
||||
init_MUTEX (&semOperations);
|
||||
init_MUTEX_LOCKED (&sem_exit);
|
||||
to_debug = 0;
|
||||
ibmphp_shutdown = 0;
|
||||
tid_poll = 0;
|
||||
|
||||
debug ("%s - Exit\n", __FUNCTION__);
|
||||
}
|
||||
@ -819,7 +815,7 @@ void ibmphp_unlock_operations (void)
|
||||
#define POLL_LATCH_REGISTER 0
|
||||
#define POLL_SLOTS 1
|
||||
#define POLL_SLEEP 2
|
||||
static void poll_hpc (void)
|
||||
static int poll_hpc(void *data)
|
||||
{
|
||||
struct slot myslot;
|
||||
struct slot *pslot = NULL;
|
||||
@ -833,10 +829,7 @@ static void poll_hpc (void)
|
||||
|
||||
debug ("%s - Entry\n", __FUNCTION__);
|
||||
|
||||
while (!ibmphp_shutdown) {
|
||||
if (ibmphp_shutdown)
|
||||
break;
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
/* try to get the lock to do some kind of hardware access */
|
||||
down (&semOperations);
|
||||
|
||||
@ -896,7 +889,7 @@ static void poll_hpc (void)
|
||||
up (&semOperations);
|
||||
msleep(POLL_INTERVAL_SEC * 1000);
|
||||
|
||||
if (ibmphp_shutdown)
|
||||
if (kthread_should_stop())
|
||||
break;
|
||||
|
||||
down (&semOperations);
|
||||
@ -915,6 +908,7 @@ static void poll_hpc (void)
|
||||
}
|
||||
up (&sem_exit);
|
||||
debug ("%s - Exit\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1049,29 +1043,6 @@ static int process_changeinlatch (u8 old, u8 new, struct controller *ctrl)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* Name: hpc_poll_thread
|
||||
*
|
||||
* Action: polling
|
||||
*
|
||||
* Return 0
|
||||
* Value:
|
||||
*---------------------------------------------------------------------*/
|
||||
static int hpc_poll_thread (void *data)
|
||||
{
|
||||
debug ("%s - Entry\n", __FUNCTION__);
|
||||
|
||||
daemonize("hpc_poll");
|
||||
allow_signal(SIGKILL);
|
||||
|
||||
poll_hpc ();
|
||||
|
||||
tid_poll = 0;
|
||||
debug ("%s - Exit\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* Name: ibmphp_hpc_start_poll_thread
|
||||
*
|
||||
@ -1079,18 +1050,14 @@ static int hpc_poll_thread (void *data)
|
||||
*---------------------------------------------------------------------*/
|
||||
int __init ibmphp_hpc_start_poll_thread (void)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
debug ("%s - Entry\n", __FUNCTION__);
|
||||
|
||||
tid_poll = kernel_thread (hpc_poll_thread, NULL, 0);
|
||||
if (tid_poll < 0) {
|
||||
ibmphp_poll_thread = kthread_run(poll_hpc, NULL, "hpc_poll");
|
||||
if (IS_ERR(ibmphp_poll_thread)) {
|
||||
err ("%s - Error, thread not started\n", __FUNCTION__);
|
||||
rc = -1;
|
||||
return PTR_ERR(ibmphp_poll_thread);
|
||||
}
|
||||
|
||||
debug ("%s - Exit tid_poll[%d] rc[%d]\n", __FUNCTION__, tid_poll, rc);
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
@ -1102,7 +1069,7 @@ void __exit ibmphp_hpc_stop_poll_thread (void)
|
||||
{
|
||||
debug ("%s - Entry\n", __FUNCTION__);
|
||||
|
||||
ibmphp_shutdown = 1;
|
||||
kthread_stop(ibmphp_poll_thread);
|
||||
debug ("before locking operations \n");
|
||||
ibmphp_lock_operations ();
|
||||
debug ("after locking operations \n");
|
||||
|
@ -304,8 +304,8 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
||||
hotplug_slot->info->attention_status = status;
|
||||
|
||||
if (ATTN_LED(slot->ctrl->ctrlcap))
|
||||
|
||||
if (ATTN_LED(slot->ctrl->ctrlcap))
|
||||
slot->hpc_ops->set_attention_status(slot, status);
|
||||
|
||||
return 0;
|
||||
@ -405,7 +405,7 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
|
||||
int retval;
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
||||
|
||||
retval = slot->hpc_ops->get_max_bus_speed(slot, value);
|
||||
if (retval < 0)
|
||||
*value = PCI_SPEED_UNKNOWN;
|
||||
@ -419,7 +419,7 @@ static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
|
||||
int retval;
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
||||
|
||||
retval = slot->hpc_ops->get_cur_bus_speed(slot, value);
|
||||
if (retval < 0)
|
||||
*value = PCI_SPEED_UNKNOWN;
|
||||
@ -434,7 +434,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
||||
struct slot *t_slot;
|
||||
u8 value;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
|
||||
ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
|
||||
if (!ctrl) {
|
||||
err("%s : out of memory\n", __FUNCTION__);
|
||||
@ -502,23 +502,23 @@ static void pciehp_remove (struct pcie_device *dev)
|
||||
#ifdef CONFIG_PM
|
||||
static int pciehp_suspend (struct pcie_device *dev, pm_message_t state)
|
||||
{
|
||||
printk("%s ENTRY\n", __FUNCTION__);
|
||||
printk("%s ENTRY\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pciehp_resume (struct pcie_device *dev)
|
||||
{
|
||||
printk("%s ENTRY\n", __FUNCTION__);
|
||||
printk("%s ENTRY\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct pcie_port_service_id port_pci_ids[] = { {
|
||||
.vendor = PCI_ANY_ID,
|
||||
static struct pcie_port_service_id port_pci_ids[] = { {
|
||||
.vendor = PCI_ANY_ID,
|
||||
.device = PCI_ANY_ID,
|
||||
.port_type = PCIE_ANY_PORT,
|
||||
.service_type = PCIE_PORT_SERVICE_HP,
|
||||
.driver_data = 0,
|
||||
.driver_data = 0,
|
||||
}, { /* end: all zeroes */ }
|
||||
};
|
||||
static const char device_name[] = "hpdriver";
|
||||
@ -540,10 +540,6 @@ static int __init pcied_init(void)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE
|
||||
pciehp_poll_mode = 1;
|
||||
#endif
|
||||
|
||||
retval = pcie_port_service_register(&hpdriver_portdrv);
|
||||
dbg("pcie_port_service_register = %d\n", retval);
|
||||
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
|
||||
|
@ -173,7 +173,7 @@ u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The following routines constitute the bulk of the
|
||||
/* The following routines constitute the bulk of the
|
||||
hotplug controller logic
|
||||
*/
|
||||
|
||||
@ -181,7 +181,7 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
|
||||
{
|
||||
/* turn off slot, turn on Amber LED, turn off Green LED if supported*/
|
||||
if (POWER_CTRL(ctrl->ctrlcap)) {
|
||||
if (pslot->hpc_ops->power_off_slot(pslot)) {
|
||||
if (pslot->hpc_ops->power_off_slot(pslot)) {
|
||||
err("%s: Issue of Slot Power Off command failed\n",
|
||||
__FUNCTION__);
|
||||
return;
|
||||
@ -189,7 +189,7 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
|
||||
}
|
||||
|
||||
if (PWR_LED(ctrl->ctrlcap))
|
||||
pslot->hpc_ops->green_led_off(pslot);
|
||||
pslot->hpc_ops->green_led_off(pslot);
|
||||
|
||||
if (ATTN_LED(ctrl->ctrlcap)) {
|
||||
if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
|
||||
@ -231,7 +231,7 @@ static int board_added(struct slot *p_slot)
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
if (PWR_LED(ctrl->ctrlcap))
|
||||
p_slot->hpc_ops->green_led_blink(p_slot);
|
||||
|
||||
@ -548,7 +548,7 @@ int pciehp_enable_slot(struct slot *p_slot)
|
||||
mutex_unlock(&p_slot->ctrl->crit_sect);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
|
||||
if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
|
||||
rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
|
||||
if (rc || getstatus) {
|
||||
info("%s: latch open on slot(%s)\n", __FUNCTION__,
|
||||
@ -557,8 +557,8 @@ int pciehp_enable_slot(struct slot *p_slot)
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
|
||||
|
||||
if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
|
||||
rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
|
||||
if (rc || getstatus) {
|
||||
info("%s: already enabled on slot(%s)\n", __FUNCTION__,
|
||||
@ -593,7 +593,7 @@ int pciehp_disable_slot(struct slot *p_slot)
|
||||
/* Check to see if (latch closed, card present, power on) */
|
||||
mutex_lock(&p_slot->ctrl->crit_sect);
|
||||
|
||||
if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) {
|
||||
if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) {
|
||||
ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
|
||||
if (ret || !getstatus) {
|
||||
info("%s: no adapter on slot(%s)\n", __FUNCTION__,
|
||||
@ -603,7 +603,7 @@ int pciehp_disable_slot(struct slot *p_slot)
|
||||
}
|
||||
}
|
||||
|
||||
if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
|
||||
if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
|
||||
ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
|
||||
if (ret || getstatus) {
|
||||
info("%s: latch open on slot(%s)\n", __FUNCTION__,
|
||||
@ -613,7 +613,7 @@ int pciehp_disable_slot(struct slot *p_slot)
|
||||
}
|
||||
}
|
||||
|
||||
if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
|
||||
if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
|
||||
ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
|
||||
if (ret || !getstatus) {
|
||||
info("%s: already disabled slot(%s)\n", __FUNCTION__,
|
||||
|
@ -39,37 +39,6 @@
|
||||
|
||||
#include "../pci.h"
|
||||
#include "pciehp.h"
|
||||
#ifdef DEBUG
|
||||
#define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */
|
||||
#define DBG_K_TRACE_EXIT ((unsigned int)0x00000002) /* On function exit */
|
||||
#define DBG_K_INFO ((unsigned int)0x00000004) /* Info messages */
|
||||
#define DBG_K_ERROR ((unsigned int)0x00000008) /* Error messages */
|
||||
#define DBG_K_TRACE (DBG_K_TRACE_ENTRY|DBG_K_TRACE_EXIT)
|
||||
#define DBG_K_STANDARD (DBG_K_INFO|DBG_K_ERROR|DBG_K_TRACE)
|
||||
/* Redefine this flagword to set debug level */
|
||||
#define DEBUG_LEVEL DBG_K_STANDARD
|
||||
|
||||
#define DEFINE_DBG_BUFFER char __dbg_str_buf[256];
|
||||
|
||||
#define DBG_PRINT( dbg_flags, args... ) \
|
||||
do { \
|
||||
if ( DEBUG_LEVEL & ( dbg_flags ) ) \
|
||||
{ \
|
||||
int len; \
|
||||
len = sprintf( __dbg_str_buf, "%s:%d: %s: ", \
|
||||
__FILE__, __LINE__, __FUNCTION__ ); \
|
||||
sprintf( __dbg_str_buf + len, args ); \
|
||||
printk( KERN_NOTICE "%s\n", __dbg_str_buf ); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DBG_ENTER_ROUTINE DBG_PRINT (DBG_K_TRACE_ENTRY, "%s", "[Entry]");
|
||||
#define DBG_LEAVE_ROUTINE DBG_PRINT (DBG_K_TRACE_EXIT, "%s", "[Exit]");
|
||||
#else
|
||||
#define DEFINE_DBG_BUFFER
|
||||
#define DBG_ENTER_ROUTINE
|
||||
#define DBG_LEAVE_ROUTINE
|
||||
#endif /* DEBUG */
|
||||
|
||||
static atomic_t pciehp_num_controllers = ATOMIC_INIT(0);
|
||||
|
||||
@ -160,10 +129,10 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value)
|
||||
/* Link Width Encoding */
|
||||
#define LNK_X1 0x01
|
||||
#define LNK_X2 0x02
|
||||
#define LNK_X4 0x04
|
||||
#define LNK_X4 0x04
|
||||
#define LNK_X8 0x08
|
||||
#define LNK_X12 0x0C
|
||||
#define LNK_X16 0x10
|
||||
#define LNK_X16 0x10
|
||||
#define LNK_X32 0x20
|
||||
|
||||
/*Field definitions of Link Status Register */
|
||||
@ -221,8 +190,6 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value)
|
||||
#define EMI_STATE 0x0080
|
||||
#define EMI_STATUS_BIT 7
|
||||
|
||||
DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */
|
||||
|
||||
static irqreturn_t pcie_isr(int irq, void *dev_id);
|
||||
static void start_int_poll_timer(struct controller *ctrl, int sec);
|
||||
|
||||
@ -231,14 +198,12 @@ static void int_poll_timeout(unsigned long data)
|
||||
{
|
||||
struct controller *ctrl = (struct controller *)data;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
/* Poll for interrupt events. regs == NULL => polling */
|
||||
pcie_isr(0, ctrl);
|
||||
|
||||
init_timer(&ctrl->poll_timer);
|
||||
if (!pciehp_poll_time)
|
||||
pciehp_poll_time = 2; /* reset timer to poll in 2 secs if user doesn't specify at module installation*/
|
||||
pciehp_poll_time = 2; /* default polling interval is 2 sec */
|
||||
|
||||
start_int_poll_timer(ctrl, pciehp_poll_time);
|
||||
}
|
||||
@ -289,8 +254,6 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
|
||||
u16 slot_ctrl;
|
||||
unsigned long flags;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
mutex_lock(&ctrl->ctrl_lock);
|
||||
|
||||
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
|
||||
@ -299,7 +262,7 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) {
|
||||
if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) {
|
||||
/* After 1 sec and CMD_COMPLETED still not set, just
|
||||
proceed forward to issue the next command according
|
||||
to spec. Just print out the error message */
|
||||
@ -332,7 +295,6 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
|
||||
retval = pcie_wait_cmd(ctrl);
|
||||
out:
|
||||
mutex_unlock(&ctrl->ctrl_lock);
|
||||
DBG_LEAVE_ROUTINE
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -341,8 +303,6 @@ static int hpc_check_lnk_status(struct controller *ctrl)
|
||||
u16 lnk_status;
|
||||
int retval = 0;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
|
||||
if (retval) {
|
||||
err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__);
|
||||
@ -350,26 +310,22 @@ static int hpc_check_lnk_status(struct controller *ctrl)
|
||||
}
|
||||
|
||||
dbg("%s: lnk_status = %x\n", __FUNCTION__, lnk_status);
|
||||
if ( (lnk_status & LNK_TRN) || (lnk_status & LNK_TRN_ERR) ||
|
||||
if ( (lnk_status & LNK_TRN) || (lnk_status & LNK_TRN_ERR) ||
|
||||
!(lnk_status & NEG_LINK_WD)) {
|
||||
err("%s : Link Training Error occurs \n", __FUNCTION__);
|
||||
retval = -1;
|
||||
return retval;
|
||||
}
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static int hpc_get_attention_status(struct slot *slot, u8 *status)
|
||||
{
|
||||
struct controller *ctrl = slot->ctrl;
|
||||
u16 slot_ctrl;
|
||||
u8 atten_led_state;
|
||||
int retval = 0;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
|
||||
if (retval) {
|
||||
@ -400,7 +356,6 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
|
||||
break;
|
||||
}
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -410,8 +365,6 @@ static int hpc_get_power_status(struct slot *slot, u8 *status)
|
||||
u16 slot_ctrl;
|
||||
u8 pwr_state;
|
||||
int retval = 0;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
|
||||
if (retval) {
|
||||
@ -428,35 +381,30 @@ static int hpc_get_power_status(struct slot *slot, u8 *status)
|
||||
*status = 1;
|
||||
break;
|
||||
case 1:
|
||||
*status = 0;
|
||||
*status = 0;
|
||||
break;
|
||||
default:
|
||||
*status = 0xFF;
|
||||
break;
|
||||
}
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static int hpc_get_latch_status(struct slot *slot, u8 *status)
|
||||
{
|
||||
struct controller *ctrl = slot->ctrl;
|
||||
u16 slot_status;
|
||||
int retval = 0;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
|
||||
if (retval) {
|
||||
err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
|
||||
return retval;
|
||||
}
|
||||
|
||||
*status = (((slot_status & MRL_STATE) >> 5) == 0) ? 0 : 1;
|
||||
*status = (((slot_status & MRL_STATE) >> 5) == 0) ? 0 : 1;
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -467,8 +415,6 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
|
||||
u8 card_state;
|
||||
int retval = 0;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
|
||||
if (retval) {
|
||||
err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
|
||||
@ -477,7 +423,6 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
|
||||
card_state = (u8)((slot_status & PRSN_STATE) >> 6);
|
||||
*status = (card_state == 1) ? 1 : 0;
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -488,16 +433,13 @@ static int hpc_query_power_fault(struct slot *slot)
|
||||
u8 pwr_fault;
|
||||
int retval = 0;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
|
||||
if (retval) {
|
||||
err("%s: Cannot check for power fault\n", __FUNCTION__);
|
||||
return retval;
|
||||
}
|
||||
pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
|
||||
return pwr_fault;
|
||||
}
|
||||
|
||||
@ -507,8 +449,6 @@ static int hpc_get_emi_status(struct slot *slot, u8 *status)
|
||||
u16 slot_status;
|
||||
int retval = 0;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
|
||||
if (retval) {
|
||||
err("%s : Cannot check EMI status\n", __FUNCTION__);
|
||||
@ -516,7 +456,6 @@ static int hpc_get_emi_status(struct slot *slot, u8 *status)
|
||||
}
|
||||
*status = (slot_status & EMI_STATE) >> EMI_STATUS_BIT;
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -526,8 +465,6 @@ static int hpc_toggle_emi(struct slot *slot)
|
||||
u16 cmd_mask;
|
||||
int rc;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
slot_cmd = EMI_CTRL;
|
||||
cmd_mask = EMI_CTRL;
|
||||
if (!pciehp_poll_mode) {
|
||||
@ -537,7 +474,7 @@ static int hpc_toggle_emi(struct slot *slot)
|
||||
|
||||
rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
|
||||
slot->last_emi_toggle = get_seconds();
|
||||
DBG_LEAVE_ROUTINE
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -548,8 +485,6 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
|
||||
u16 cmd_mask;
|
||||
int rc;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
cmd_mask = ATTN_LED_CTRL;
|
||||
switch (value) {
|
||||
case 0 : /* turn off */
|
||||
@ -572,19 +507,15 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
|
||||
rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
|
||||
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
||||
__FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static void hpc_set_green_led_on(struct slot *slot)
|
||||
{
|
||||
struct controller *ctrl = slot->ctrl;
|
||||
u16 slot_cmd;
|
||||
u16 cmd_mask;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
slot_cmd = 0x0100;
|
||||
cmd_mask = PWR_LED_CTRL;
|
||||
@ -597,8 +528,6 @@ static void hpc_set_green_led_on(struct slot *slot)
|
||||
|
||||
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
||||
__FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||
DBG_LEAVE_ROUTINE
|
||||
return;
|
||||
}
|
||||
|
||||
static void hpc_set_green_led_off(struct slot *slot)
|
||||
@ -607,8 +536,6 @@ static void hpc_set_green_led_off(struct slot *slot)
|
||||
u16 slot_cmd;
|
||||
u16 cmd_mask;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
slot_cmd = 0x0300;
|
||||
cmd_mask = PWR_LED_CTRL;
|
||||
if (!pciehp_poll_mode) {
|
||||
@ -619,9 +546,6 @@ static void hpc_set_green_led_off(struct slot *slot)
|
||||
pcie_write_cmd(slot, slot_cmd, cmd_mask);
|
||||
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
||||
__FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return;
|
||||
}
|
||||
|
||||
static void hpc_set_green_led_blink(struct slot *slot)
|
||||
@ -629,8 +553,6 @@ static void hpc_set_green_led_blink(struct slot *slot)
|
||||
struct controller *ctrl = slot->ctrl;
|
||||
u16 slot_cmd;
|
||||
u16 cmd_mask;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
slot_cmd = 0x0200;
|
||||
cmd_mask = PWR_LED_CTRL;
|
||||
@ -643,14 +565,10 @@ static void hpc_set_green_led_blink(struct slot *slot)
|
||||
|
||||
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
||||
__FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||
DBG_LEAVE_ROUTINE
|
||||
return;
|
||||
}
|
||||
|
||||
static void hpc_release_ctlr(struct controller *ctrl)
|
||||
{
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
if (pciehp_poll_mode)
|
||||
del_timer(&ctrl->poll_timer);
|
||||
else
|
||||
@ -662,8 +580,6 @@ static void hpc_release_ctlr(struct controller *ctrl)
|
||||
*/
|
||||
if (atomic_dec_and_test(&pciehp_num_controllers))
|
||||
destroy_workqueue(pciehp_wq);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
}
|
||||
|
||||
static int hpc_power_on_slot(struct slot * slot)
|
||||
@ -674,8 +590,6 @@ static int hpc_power_on_slot(struct slot * slot)
|
||||
u16 slot_status;
|
||||
int retval = 0;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
|
||||
|
||||
/* Clear sticky power-fault bit from previous power failures */
|
||||
@ -719,8 +633,6 @@ static int hpc_power_on_slot(struct slot * slot)
|
||||
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
||||
__FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -731,8 +643,6 @@ static int hpc_power_off_slot(struct slot * slot)
|
||||
u16 cmd_mask;
|
||||
int retval = 0;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
|
||||
|
||||
slot_cmd = POWER_OFF;
|
||||
@ -764,8 +674,6 @@ static int hpc_power_off_slot(struct slot * slot)
|
||||
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
||||
__FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -784,8 +692,8 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
intr_detect = ( ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED | MRL_SENS_CHANGED |
|
||||
PRSN_DETECT_CHANGED | CMD_COMPLETED );
|
||||
intr_detect = (ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED |
|
||||
MRL_SENS_CHANGED | PRSN_DETECT_CHANGED | CMD_COMPLETED);
|
||||
|
||||
intr_loc = slot_status & intr_detect;
|
||||
|
||||
@ -807,7 +715,8 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
|
||||
|
||||
dbg("%s: pciehp_readw(SLOTCTRL) with value %x\n",
|
||||
__FUNCTION__, temp_word);
|
||||
temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;
|
||||
temp_word = (temp_word & ~HP_INTR_ENABLE &
|
||||
~CMD_CMPL_INTR_ENABLE) | 0x00;
|
||||
rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
|
||||
if (rc) {
|
||||
err("%s: Cannot write to SLOTCTRL register\n",
|
||||
@ -825,7 +734,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
|
||||
}
|
||||
dbg("%s: pciehp_readw(SLOTSTATUS) with value %x\n",
|
||||
__FUNCTION__, slot_status);
|
||||
|
||||
|
||||
/* Clear command complete interrupt caused by this write */
|
||||
temp_word = 0x1f;
|
||||
rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
|
||||
@ -835,10 +744,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
|
||||
return IRQ_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (intr_loc & CMD_COMPLETED) {
|
||||
/*
|
||||
* Command Complete Interrupt Pending
|
||||
/*
|
||||
* Command Complete Interrupt Pending
|
||||
*/
|
||||
ctrl->cmd_busy = 0;
|
||||
wake_up_interruptible(&ctrl->queue);
|
||||
@ -892,7 +801,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
|
||||
__FUNCTION__);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
|
||||
/* Clear command complete interrupt caused by this write */
|
||||
temp_word = 0x1F;
|
||||
rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
|
||||
@ -904,19 +813,17 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
|
||||
dbg("%s: pciehp_writew(SLOTSTATUS) with value %x\n",
|
||||
__FUNCTION__, temp_word);
|
||||
}
|
||||
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
|
||||
static int hpc_get_max_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
|
||||
{
|
||||
struct controller *ctrl = slot->ctrl;
|
||||
enum pcie_link_speed lnk_speed;
|
||||
u32 lnk_cap;
|
||||
int retval = 0;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap);
|
||||
if (retval) {
|
||||
err("%s: Cannot read LNKCAP register\n", __FUNCTION__);
|
||||
@ -934,19 +841,18 @@ static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
|
||||
|
||||
*value = lnk_speed;
|
||||
dbg("Max link speed = %d\n", lnk_speed);
|
||||
DBG_LEAVE_ROUTINE
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value)
|
||||
static int hpc_get_max_lnk_width(struct slot *slot,
|
||||
enum pcie_link_width *value)
|
||||
{
|
||||
struct controller *ctrl = slot->ctrl;
|
||||
enum pcie_link_width lnk_wdth;
|
||||
u32 lnk_cap;
|
||||
int retval = 0;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap);
|
||||
if (retval) {
|
||||
err("%s: Cannot read LNKCAP register\n", __FUNCTION__);
|
||||
@ -985,19 +891,17 @@ static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value
|
||||
|
||||
*value = lnk_wdth;
|
||||
dbg("Max link width = %d\n", lnk_wdth);
|
||||
DBG_LEAVE_ROUTINE
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int hpc_get_cur_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
|
||||
static int hpc_get_cur_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
|
||||
{
|
||||
struct controller *ctrl = slot->ctrl;
|
||||
enum pcie_link_speed lnk_speed = PCI_SPEED_UNKNOWN;
|
||||
int retval = 0;
|
||||
u16 lnk_status;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
|
||||
if (retval) {
|
||||
err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__);
|
||||
@ -1015,25 +919,24 @@ static int hpc_get_cur_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
|
||||
|
||||
*value = lnk_speed;
|
||||
dbg("Current link speed = %d\n", lnk_speed);
|
||||
DBG_LEAVE_ROUTINE
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int hpc_get_cur_lnk_width (struct slot *slot, enum pcie_link_width *value)
|
||||
static int hpc_get_cur_lnk_width(struct slot *slot,
|
||||
enum pcie_link_width *value)
|
||||
{
|
||||
struct controller *ctrl = slot->ctrl;
|
||||
enum pcie_link_width lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;
|
||||
int retval = 0;
|
||||
u16 lnk_status;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
|
||||
if (retval) {
|
||||
err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
switch ((lnk_status & 0x03F0) >> 4){
|
||||
case 0:
|
||||
lnk_wdth = PCIE_LNK_WIDTH_RESRV;
|
||||
@ -1066,7 +969,7 @@ static int hpc_get_cur_lnk_width (struct slot *slot, enum pcie_link_width *value
|
||||
|
||||
*value = lnk_wdth;
|
||||
dbg("Current link width = %d\n", lnk_wdth);
|
||||
DBG_LEAVE_ROUTINE
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -1085,12 +988,12 @@ static struct hpc_ops pciehp_hpc_ops = {
|
||||
.get_cur_bus_speed = hpc_get_cur_lnk_speed,
|
||||
.get_max_lnk_width = hpc_get_max_lnk_width,
|
||||
.get_cur_lnk_width = hpc_get_cur_lnk_width,
|
||||
|
||||
|
||||
.query_power_fault = hpc_query_power_fault,
|
||||
.green_led_on = hpc_set_green_led_on,
|
||||
.green_led_off = hpc_set_green_led_off,
|
||||
.green_led_blink = hpc_set_green_led_blink,
|
||||
|
||||
|
||||
.release_ctlr = hpc_release_ctlr,
|
||||
.check_lnk_status = hpc_check_lnk_status,
|
||||
};
|
||||
@ -1138,6 +1041,7 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
|
||||
dbg("Trying to get hotplug control for %s \n",
|
||||
(char *)string.pointer);
|
||||
status = pci_osc_control_set(handle,
|
||||
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL |
|
||||
OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
|
||||
if (status == AE_NOT_FOUND)
|
||||
status = acpi_run_oshp(handle);
|
||||
@ -1163,8 +1067,6 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
int pcie_init(struct controller * ctrl, struct pcie_device *dev)
|
||||
{
|
||||
int rc;
|
||||
@ -1176,8 +1078,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
|
||||
u16 slot_status, slot_ctrl;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
pdev = dev->port;
|
||||
ctrl->pci_dev = pdev; /* save pci_dev in context */
|
||||
|
||||
@ -1201,9 +1101,11 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
|
||||
dbg("%s: CAPREG offset %x cap_reg %x\n",
|
||||
__FUNCTION__, ctrl->cap_base + CAPREG, cap_reg);
|
||||
|
||||
if (((cap_reg & SLOT_IMPL) == 0) || (((cap_reg & DEV_PORT_TYPE) != 0x0040)
|
||||
if (((cap_reg & SLOT_IMPL) == 0) ||
|
||||
(((cap_reg & DEV_PORT_TYPE) != 0x0040)
|
||||
&& ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {
|
||||
dbg("%s : This is not a root port or the port is not connected to a slot\n", __FUNCTION__);
|
||||
dbg("%s : This is not a root port or the port is not "
|
||||
"connected to a slot\n", __FUNCTION__);
|
||||
goto abort_free_ctlr;
|
||||
}
|
||||
|
||||
@ -1236,14 +1138,15 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
|
||||
dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
|
||||
__FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
|
||||
|
||||
for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
|
||||
for (rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
|
||||
if (pci_resource_len(pdev, rc) > 0)
|
||||
dbg("pci resource[%d] start=0x%llx(len=0x%llx)\n", rc,
|
||||
(unsigned long long)pci_resource_start(pdev, rc),
|
||||
(unsigned long long)pci_resource_len(pdev, rc));
|
||||
|
||||
info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device,
|
||||
pdev->subsystem_vendor, pdev->subsystem_device);
|
||||
info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
|
||||
pdev->vendor, pdev->device,
|
||||
pdev->subsystem_vendor, pdev->subsystem_device);
|
||||
|
||||
mutex_init(&ctrl->crit_sect);
|
||||
mutex_init(&ctrl->ctrl_lock);
|
||||
@ -1267,7 +1170,8 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
|
||||
|
||||
dbg("%s: SLOTCTRL %x value read %x\n",
|
||||
__FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word);
|
||||
temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;
|
||||
temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
|
||||
0x00;
|
||||
|
||||
rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
|
||||
if (rc) {
|
||||
@ -1330,14 +1234,14 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
|
||||
|
||||
if (ATTN_BUTTN(slot_cap))
|
||||
intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
|
||||
|
||||
|
||||
if (POWER_CTRL(slot_cap))
|
||||
intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
|
||||
|
||||
|
||||
if (MRL_SENS(slot_cap))
|
||||
intr_enable = intr_enable | MRL_DETECT_ENABLE;
|
||||
|
||||
temp_word = (temp_word & ~intr_enable) | intr_enable;
|
||||
temp_word = (temp_word & ~intr_enable) | intr_enable;
|
||||
|
||||
if (pciehp_poll_mode) {
|
||||
temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
|
||||
@ -1345,7 +1249,10 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
|
||||
temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
|
||||
}
|
||||
|
||||
/* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */
|
||||
/*
|
||||
* Unmask Hot-plug Interrupt Enable for the interrupt
|
||||
* notification mechanism case.
|
||||
*/
|
||||
rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
|
||||
if (rc) {
|
||||
err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
|
||||
@ -1356,14 +1263,14 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
|
||||
err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
|
||||
goto abort_disable_intr;
|
||||
}
|
||||
|
||||
|
||||
temp_word = 0x1F; /* Clear all events */
|
||||
rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
|
||||
if (rc) {
|
||||
err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
|
||||
goto abort_disable_intr;
|
||||
}
|
||||
|
||||
|
||||
if (pciehp_force) {
|
||||
dbg("Bypassing BIOS check for pciehp use on %s\n",
|
||||
pci_name(ctrl->pci_dev));
|
||||
@ -1375,10 +1282,9 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
|
||||
|
||||
ctrl->hpc_ops = &pciehp_hpc_ops;
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return 0;
|
||||
|
||||
/* We end up here for the many possible ways to fail this API. */
|
||||
/* We end up here for the many possible ways to fail this API. */
|
||||
abort_disable_intr:
|
||||
rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
|
||||
if (!rc) {
|
||||
@ -1395,6 +1301,5 @@ abort_free_irq:
|
||||
free_irq(ctrl->pci_dev->irq, ctrl);
|
||||
|
||||
abort_free_ctlr:
|
||||
DBG_LEAVE_ROUTINE
|
||||
return -1;
|
||||
}
|
||||
|
@ -243,9 +243,10 @@ int pciehp_configure_device(struct slot *p_slot)
|
||||
|
||||
int pciehp_unconfigure_device(struct slot *p_slot)
|
||||
{
|
||||
int rc = 0;
|
||||
int ret, rc = 0;
|
||||
int j;
|
||||
u8 bctl = 0;
|
||||
u8 presence = 0;
|
||||
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
|
||||
|
||||
dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus,
|
||||
@ -263,23 +264,28 @@ int pciehp_unconfigure_device(struct slot *p_slot)
|
||||
continue;
|
||||
}
|
||||
if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
|
||||
if (bctl & PCI_BRIDGE_CTL_VGA) {
|
||||
err("Cannot remove display device %s\n",
|
||||
ret = p_slot->hpc_ops->get_adapter_status(p_slot,
|
||||
&presence);
|
||||
if (!ret && presence) {
|
||||
pci_read_config_byte(temp, PCI_BRIDGE_CONTROL,
|
||||
&bctl);
|
||||
if (bctl & PCI_BRIDGE_CTL_VGA) {
|
||||
err("Cannot remove display device %s\n",
|
||||
pci_name(temp));
|
||||
pci_dev_put(temp);
|
||||
continue;
|
||||
pci_dev_put(temp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
pci_remove_bus_device(temp);
|
||||
pci_dev_put(temp);
|
||||
}
|
||||
/*
|
||||
/*
|
||||
* Some PCI Express root ports require fixup after hot-plug operation.
|
||||
*/
|
||||
if (pcie_mch_quirk)
|
||||
if (pcie_mch_quirk)
|
||||
pci_fixup_device(pci_fixup_final, p_slot->ctrl->pci_dev);
|
||||
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ void read_msi_msg(unsigned int irq, struct msi_msg *msg)
|
||||
pci_read_config_word(dev, msi_data_reg(pos, 1), &data);
|
||||
} else {
|
||||
msg->address_hi = 0;
|
||||
pci_read_config_word(dev, msi_data_reg(pos, 1), &data);
|
||||
pci_read_config_word(dev, msi_data_reg(pos, 0), &data);
|
||||
}
|
||||
msg->data = data;
|
||||
break;
|
||||
|
@ -54,7 +54,6 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
|
||||
if (!dynid)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&dynid->node);
|
||||
dynid->id.vendor = vendor;
|
||||
dynid->id.device = device;
|
||||
dynid->id.subvendor = subvendor;
|
||||
@ -65,7 +64,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
|
||||
driver_data : 0UL;
|
||||
|
||||
spin_lock(&pdrv->dynids.lock);
|
||||
list_add_tail(&pdrv->dynids.list, &dynid->node);
|
||||
list_add_tail(&dynid->node, &pdrv->dynids.list);
|
||||
spin_unlock(&pdrv->dynids.lock);
|
||||
|
||||
if (get_driver(&pdrv->driver)) {
|
||||
|
@ -17,11 +17,16 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/log2.h>
|
||||
#include <asm/dma.h> /* isa_dma_bridge_buggy */
|
||||
#include "pci.h"
|
||||
|
||||
unsigned int pci_pm_d3_delay = 10;
|
||||
|
||||
#ifdef CONFIG_PCI_DOMAINS
|
||||
int pci_domains_supported = 1;
|
||||
#endif
|
||||
|
||||
#define DEFAULT_CARDBUS_IO_SIZE (256)
|
||||
#define DEFAULT_CARDBUS_MEM_SIZE (64*1024*1024)
|
||||
/* pci=cbmemsize=nnM,cbiosize=nn can override this */
|
||||
@ -1454,7 +1459,7 @@ int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc)
|
||||
int cap, err = -EINVAL;
|
||||
u32 stat, cmd, v, o;
|
||||
|
||||
if (mmrbc < 512 || mmrbc > 4096 || (mmrbc & (mmrbc-1)))
|
||||
if (mmrbc < 512 || mmrbc > 4096 || !is_power_of_2(mmrbc))
|
||||
goto out;
|
||||
|
||||
v = ffs(mmrbc) - 10;
|
||||
@ -1526,7 +1531,7 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
|
||||
int cap, err = -EINVAL;
|
||||
u16 ctl, v;
|
||||
|
||||
if (rq < 128 || rq > 4096 || (rq & (rq-1)))
|
||||
if (rq < 128 || rq > 4096 || !is_power_of_2(rq))
|
||||
goto out;
|
||||
|
||||
v = (ffs(rq) - 8) << 12;
|
||||
@ -1566,6 +1571,13 @@ int pci_select_bars(struct pci_dev *dev, unsigned long flags)
|
||||
return bars;
|
||||
}
|
||||
|
||||
static void __devinit pci_no_domains(void)
|
||||
{
|
||||
#ifdef CONFIG_PCI_DOMAINS
|
||||
pci_domains_supported = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int __devinit pci_init(void)
|
||||
{
|
||||
struct pci_dev *dev = NULL;
|
||||
@ -1585,6 +1597,10 @@ static int __devinit pci_setup(char *str)
|
||||
if (*str && (str = pcibios_setup(str)) && *str) {
|
||||
if (!strcmp(str, "nomsi")) {
|
||||
pci_no_msi();
|
||||
} else if (!strcmp(str, "noaer")) {
|
||||
pci_no_aer();
|
||||
} else if (!strcmp(str, "nodomains")) {
|
||||
pci_no_domains();
|
||||
} else if (!strncmp(str, "cbiosize=", 9)) {
|
||||
pci_cardbus_io_size = memparse(str + 9, &str);
|
||||
} else if (!strncmp(str, "cbmemsize=", 10)) {
|
||||
|
@ -51,6 +51,12 @@ void pci_restore_msi_state(struct pci_dev *dev);
|
||||
static inline void pci_restore_msi_state(struct pci_dev *dev) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PCIEAER
|
||||
void pci_no_aer(void);
|
||||
#else
|
||||
static inline void pci_no_aer(void) { }
|
||||
#endif
|
||||
|
||||
static inline int pci_no_d1d2(struct pci_dev *dev)
|
||||
{
|
||||
unsigned int parent_dstates = 0;
|
||||
|
@ -25,13 +25,4 @@ config HOTPLUG_PCI_PCIE
|
||||
|
||||
When in doubt, say N.
|
||||
|
||||
config HOTPLUG_PCI_PCIE_POLL_EVENT_MODE
|
||||
bool "Use polling mechanism for hot-plug events (for testing purpose)"
|
||||
depends on HOTPLUG_PCI_PCIE
|
||||
help
|
||||
Say Y here if you want to use the polling mechanism for hot-plug
|
||||
events for early platform testing.
|
||||
|
||||
When in doubt, say N.
|
||||
|
||||
source "drivers/pci/pcie/aer/Kconfig"
|
||||
|
@ -81,6 +81,13 @@ static struct pcie_port_service_driver aerdriver = {
|
||||
.reset_link = aer_root_reset,
|
||||
};
|
||||
|
||||
static int pcie_aer_disable;
|
||||
|
||||
void pci_no_aer(void)
|
||||
{
|
||||
pcie_aer_disable = 1; /* has priority over 'forceload' */
|
||||
}
|
||||
|
||||
/**
|
||||
* aer_irq - Root Port's ISR
|
||||
* @irq: IRQ assigned to Root Port
|
||||
@ -327,6 +334,8 @@ static void aer_error_resume(struct pci_dev *dev)
|
||||
**/
|
||||
static int __init aer_service_init(void)
|
||||
{
|
||||
if (pcie_aer_disable)
|
||||
return -ENXIO;
|
||||
return pcie_port_service_register(&aerdriver);
|
||||
}
|
||||
|
||||
|
@ -276,8 +276,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
|
||||
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_MEM | IORESOURCE_READONLY;
|
||||
res->start = l & PCI_ROM_ADDRESS_MASK;
|
||||
res->end = res->start + (unsigned long) sz;
|
||||
}
|
||||
@ -597,7 +596,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass
|
||||
pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
|
||||
|
||||
if (!is_cardbus) {
|
||||
child->bridge_ctl = bctl | PCI_BRIDGE_CTL_NO_ISA;
|
||||
child->bridge_ctl = bctl;
|
||||
/*
|
||||
* Adjust subordinate busnr in parent buses.
|
||||
* We do this before scanning for children because
|
||||
@ -744,22 +743,46 @@ static int pci_setup_device(struct pci_dev * dev)
|
||||
*/
|
||||
if (class == PCI_CLASS_STORAGE_IDE) {
|
||||
u8 progif;
|
||||
struct pci_bus_region region;
|
||||
|
||||
pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
|
||||
if ((progif & 1) == 0) {
|
||||
dev->resource[0].start = 0x1F0;
|
||||
dev->resource[0].end = 0x1F7;
|
||||
dev->resource[0].flags = LEGACY_IO_RESOURCE;
|
||||
dev->resource[1].start = 0x3F6;
|
||||
dev->resource[1].end = 0x3F6;
|
||||
dev->resource[1].flags = LEGACY_IO_RESOURCE;
|
||||
struct resource resource = {
|
||||
.start = 0x1F0,
|
||||
.end = 0x1F7,
|
||||
.flags = LEGACY_IO_RESOURCE,
|
||||
};
|
||||
|
||||
pcibios_resource_to_bus(dev, ®ion, &resource);
|
||||
dev->resource[0].start = region.start;
|
||||
dev->resource[0].end = region.end;
|
||||
dev->resource[0].flags = resource.flags;
|
||||
resource.start = 0x3F6;
|
||||
resource.end = 0x3F6;
|
||||
resource.flags = LEGACY_IO_RESOURCE;
|
||||
pcibios_resource_to_bus(dev, ®ion, &resource);
|
||||
dev->resource[1].start = region.start;
|
||||
dev->resource[1].end = region.end;
|
||||
dev->resource[1].flags = resource.flags;
|
||||
}
|
||||
if ((progif & 4) == 0) {
|
||||
dev->resource[2].start = 0x170;
|
||||
dev->resource[2].end = 0x177;
|
||||
dev->resource[2].flags = LEGACY_IO_RESOURCE;
|
||||
dev->resource[3].start = 0x376;
|
||||
dev->resource[3].end = 0x376;
|
||||
dev->resource[3].flags = LEGACY_IO_RESOURCE;
|
||||
struct resource resource = {
|
||||
.start = 0x170,
|
||||
.end = 0x177,
|
||||
.flags = LEGACY_IO_RESOURCE,
|
||||
};
|
||||
|
||||
pcibios_resource_to_bus(dev, ®ion, &resource);
|
||||
dev->resource[2].start = region.start;
|
||||
dev->resource[2].end = region.end;
|
||||
dev->resource[2].flags = resource.flags;
|
||||
resource.start = 0x376;
|
||||
resource.end = 0x376;
|
||||
resource.flags = LEGACY_IO_RESOURCE;
|
||||
pcibios_resource_to_bus(dev, ®ion, &resource);
|
||||
dev->resource[3].start = region.start;
|
||||
dev->resource[3].end = region.end;
|
||||
dev->resource[3].flags = resource.flags;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -60,7 +60,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
|
||||
*/
|
||||
|
||||
if (capable(CAP_SYS_ADMIN))
|
||||
size = dev->cfg_size;
|
||||
size = dp->size;
|
||||
else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
|
||||
size = 128;
|
||||
else
|
||||
@ -129,11 +129,11 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
|
||||
static ssize_t
|
||||
proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, loff_t *ppos)
|
||||
{
|
||||
const struct inode *ino = file->f_path.dentry->d_inode;
|
||||
struct inode *ino = file->f_path.dentry->d_inode;
|
||||
const struct proc_dir_entry *dp = PDE(ino);
|
||||
struct pci_dev *dev = dp->data;
|
||||
int pos = *ppos;
|
||||
int size = dev->cfg_size;
|
||||
int size = dp->size;
|
||||
int cnt;
|
||||
|
||||
if (pos >= size)
|
||||
@ -193,6 +193,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
|
||||
}
|
||||
|
||||
*ppos = pos;
|
||||
i_size_write(ino, dp->size);
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
|
@ -472,11 +472,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, quirk_
|
||||
*/
|
||||
static void __devinit quirk_vt82c586_acpi(struct pci_dev *dev)
|
||||
{
|
||||
u8 rev;
|
||||
u32 region;
|
||||
|
||||
pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
|
||||
if (rev & 0x10) {
|
||||
if (dev->revision & 0x10) {
|
||||
pci_read_config_dword(dev, 0x48, ®ion);
|
||||
region &= PCI_BASE_ADDRESS_IO_MASK;
|
||||
quirk_io_region(dev, region, 256, PCI_BRIDGE_RESOURCES, "vt82c586 ACPI");
|
||||
@ -629,12 +627,9 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk
|
||||
*/
|
||||
static void __init quirk_amd_8131_mmrbc(struct pci_dev *dev)
|
||||
{
|
||||
unsigned char revid;
|
||||
|
||||
pci_read_config_byte(dev, PCI_REVISION_ID, &revid);
|
||||
if (dev->subordinate && revid <= 0x12) {
|
||||
if (dev->subordinate && dev->revision <= 0x12) {
|
||||
printk(KERN_INFO "AMD8131 rev %x detected, disabling PCI-X "
|
||||
"MMRBC\n", revid);
|
||||
"MMRBC\n", dev->revision);
|
||||
dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MMRBC;
|
||||
}
|
||||
}
|
||||
@ -930,38 +925,6 @@ static void __init quirk_eisa_bridge(struct pci_dev *dev)
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_eisa_bridge );
|
||||
|
||||
/*
|
||||
* On the MSI-K8T-Neo2Fir Board, the internal Soundcard is disabled
|
||||
* when a PCI-Soundcard is added. The BIOS only gives Options
|
||||
* "Disabled" and "AUTO". This Quirk Sets the corresponding
|
||||
* Register-Value to enable the Soundcard.
|
||||
*
|
||||
* FIXME: Presently this quirk will run on anything that has an 8237
|
||||
* which isn't correct, we need to check DMI tables or something in
|
||||
* order to make sure it only runs on the MSI-K8T-Neo2Fir. Because it
|
||||
* runs everywhere at present we suppress the printk output in most
|
||||
* irrelevant cases.
|
||||
*/
|
||||
static void k8t_sound_hostbridge(struct pci_dev *dev)
|
||||
{
|
||||
unsigned char val;
|
||||
|
||||
pci_read_config_byte(dev, 0x50, &val);
|
||||
if (val == 0xc8) {
|
||||
/* Assume it's probably a MSI-K8T-Neo2Fir */
|
||||
printk(KERN_INFO "PCI: MSI-K8T-Neo2Fir, attempting to turn soundcard ON\n");
|
||||
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: MSI-K8T-Neo2Fir, soundcard still off\n");
|
||||
else
|
||||
printk(KERN_INFO "PCI: MSI-K8T-Neo2Fir, soundcard on\n");
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge);
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge);
|
||||
|
||||
/*
|
||||
* On ASUS P4B boards, the SMBus PCI Device within the ICH2/4 southbridge
|
||||
|
@ -472,7 +472,12 @@ void pci_bus_size_bridges(struct pci_bus *bus)
|
||||
break;
|
||||
|
||||
case PCI_CLASS_BRIDGE_PCI:
|
||||
/* don't size subtractive decoding (transparent)
|
||||
* PCI-to-PCI bridges */
|
||||
if (bus->self->transparent)
|
||||
break;
|
||||
pci_bridge_check_ranges(bus);
|
||||
/* fall through */
|
||||
default:
|
||||
pbus_size_io(bus);
|
||||
/* If the bridge supports prefetchable range, size it
|
||||
|
@ -1,5 +1,95 @@
|
||||
#ifndef __x86_PCI_H
|
||||
#define __x86_PCI_H
|
||||
|
||||
#include <linux/mm.h> /* for struct page */
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/scatterlist.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
struct pci_sysdata {
|
||||
int domain; /* PCI domain */
|
||||
int node; /* NUMA node */
|
||||
#ifdef CONFIG_X86_64
|
||||
void* iommu; /* IOMMU private data */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* scan a bus after allocating a pci_sysdata for it */
|
||||
extern struct pci_bus *pci_scan_bus_with_sysdata(int busno);
|
||||
|
||||
static inline int pci_domain_nr(struct pci_bus *bus)
|
||||
{
|
||||
struct pci_sysdata *sd = bus->sysdata;
|
||||
return sd->domain;
|
||||
}
|
||||
|
||||
static inline int pci_proc_domain(struct pci_bus *bus)
|
||||
{
|
||||
return pci_domain_nr(bus);
|
||||
}
|
||||
|
||||
|
||||
/* Can be used to override the logic in pci_scan_bus for skipping
|
||||
already-configured bus numbers - to be used for buggy BIOSes
|
||||
or architectures with incomplete PCI setup by the loader */
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
extern unsigned int pcibios_assign_all_busses(void);
|
||||
#else
|
||||
#define pcibios_assign_all_busses() 0
|
||||
#endif
|
||||
#define pcibios_scan_all_fns(a, b) 0
|
||||
|
||||
extern unsigned long pci_mem_start;
|
||||
#define PCIBIOS_MIN_IO 0x1000
|
||||
#define PCIBIOS_MIN_MEM (pci_mem_start)
|
||||
|
||||
#define PCIBIOS_MIN_CARDBUS_IO 0x4000
|
||||
|
||||
void pcibios_config_init(void);
|
||||
struct pci_bus * pcibios_scan_root(int bus);
|
||||
|
||||
void pcibios_set_master(struct pci_dev *dev);
|
||||
void pcibios_penalize_isa_irq(int irq, int active);
|
||||
struct irq_routing_table *pcibios_get_irq_routing_table(void);
|
||||
int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
|
||||
|
||||
|
||||
#define HAVE_PCI_MMAP
|
||||
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine);
|
||||
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
|
||||
enum pci_dma_burst_strategy *strat,
|
||||
unsigned long *strategy_parameter)
|
||||
{
|
||||
*strat = PCI_DMA_BURST_INFINITY;
|
||||
*strategy_parameter = ~0UL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
# include "pci_32.h"
|
||||
#else
|
||||
# include "pci_64.h"
|
||||
#endif
|
||||
|
||||
/* implement the pci_ DMA API in terms of the generic device dma_ one */
|
||||
#include <asm-generic/pci-dma-compat.h>
|
||||
|
||||
/* generic pci stuff */
|
||||
#include <asm-generic/pci.h>
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -4,50 +4,11 @@
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
struct pci_sysdata {
|
||||
int node; /* NUMA node */
|
||||
};
|
||||
|
||||
/* scan a bus after allocating a pci_sysdata for it */
|
||||
extern struct pci_bus *pci_scan_bus_with_sysdata(int busno);
|
||||
|
||||
#include <linux/mm.h> /* for struct page */
|
||||
|
||||
/* Can be used to override the logic in pci_scan_bus for skipping
|
||||
already-configured bus numbers - to be used for buggy BIOSes
|
||||
or architectures with incomplete PCI setup by the loader */
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
extern unsigned int pcibios_assign_all_busses(void);
|
||||
#else
|
||||
#define pcibios_assign_all_busses() 0
|
||||
#endif
|
||||
#define pcibios_scan_all_fns(a, b) 0
|
||||
|
||||
extern unsigned long pci_mem_start;
|
||||
#define PCIBIOS_MIN_IO 0x1000
|
||||
#define PCIBIOS_MIN_MEM (pci_mem_start)
|
||||
|
||||
#define PCIBIOS_MIN_CARDBUS_IO 0x4000
|
||||
|
||||
void pcibios_config_init(void);
|
||||
struct pci_bus * pcibios_scan_root(int bus);
|
||||
|
||||
void pcibios_set_master(struct pci_dev *dev);
|
||||
void pcibios_penalize_isa_irq(int irq, int active);
|
||||
struct irq_routing_table *pcibios_get_irq_routing_table(void);
|
||||
int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
|
||||
|
||||
/* Dynamic DMA mapping stuff.
|
||||
* i386 has everything mapped statically.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/scatterlist.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
struct pci_dev;
|
||||
|
||||
/* The PCI address space does equal the physical memory
|
||||
@ -64,27 +25,8 @@ struct pci_dev;
|
||||
#define pci_unmap_len(PTR, LEN_NAME) (0)
|
||||
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
|
||||
|
||||
#define HAVE_PCI_MMAP
|
||||
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine);
|
||||
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
|
||||
enum pci_dma_burst_strategy *strat,
|
||||
unsigned long *strategy_parameter)
|
||||
{
|
||||
*strat = PCI_DMA_BURST_INFINITY;
|
||||
*strategy_parameter = ~0UL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
/* implement the pci_ DMA API in terms of the generic device dma_ one */
|
||||
#include <asm-generic/pci-dma-compat.h>
|
||||
|
||||
/* generic pci stuff */
|
||||
#include <asm-generic/pci.h>
|
||||
|
||||
#endif /* __i386_PCI_H */
|
||||
|
@ -1,16 +1,9 @@
|
||||
#ifndef __x8664_PCI_H
|
||||
#define __x8664_PCI_H
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
struct pci_sysdata {
|
||||
int node; /* NUMA node */
|
||||
void* iommu; /* IOMMU private data */
|
||||
};
|
||||
|
||||
extern struct pci_bus *pci_scan_bus_with_sysdata(int busno);
|
||||
|
||||
#ifdef CONFIG_CALGARY_IOMMU
|
||||
static inline void* pci_iommu(struct pci_bus *bus)
|
||||
@ -26,40 +19,11 @@ static inline void set_pci_iommu(struct pci_bus *bus, void *val)
|
||||
}
|
||||
#endif /* CONFIG_CALGARY_IOMMU */
|
||||
|
||||
#include <linux/mm.h> /* for struct page */
|
||||
|
||||
/* Can be used to override the logic in pci_scan_bus for skipping
|
||||
already-configured bus numbers - to be used for buggy BIOSes
|
||||
or architectures with incomplete PCI setup by the loader */
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
extern unsigned int pcibios_assign_all_busses(void);
|
||||
#else
|
||||
#define pcibios_assign_all_busses() 0
|
||||
#endif
|
||||
#define pcibios_scan_all_fns(a, b) 0
|
||||
|
||||
extern unsigned long pci_mem_start;
|
||||
#define PCIBIOS_MIN_IO 0x1000
|
||||
#define PCIBIOS_MIN_MEM (pci_mem_start)
|
||||
|
||||
#define PCIBIOS_MIN_CARDBUS_IO 0x4000
|
||||
|
||||
void pcibios_config_init(void);
|
||||
struct pci_bus * pcibios_scan_root(int bus);
|
||||
extern int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value);
|
||||
extern int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value);
|
||||
|
||||
void pcibios_set_master(struct pci_dev *dev);
|
||||
void pcibios_penalize_isa_irq(int irq, int active);
|
||||
struct irq_routing_table *pcibios_get_irq_routing_table(void);
|
||||
int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/scatterlist.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
extern void pci_iommu_alloc(void);
|
||||
extern int iommu_setup(char *opt);
|
||||
@ -100,27 +64,7 @@ extern int iommu_setup(char *opt);
|
||||
|
||||
#endif
|
||||
|
||||
#include <asm-generic/pci-dma-compat.h>
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
|
||||
enum pci_dma_burst_strategy *strat,
|
||||
unsigned long *strategy_parameter)
|
||||
{
|
||||
*strat = PCI_DMA_BURST_INFINITY;
|
||||
*strategy_parameter = ~0UL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define HAVE_PCI_MMAP
|
||||
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
/* generic pci stuff */
|
||||
#ifdef CONFIG_PCI
|
||||
#include <asm-generic/pci.h>
|
||||
#endif
|
||||
|
||||
#endif /* __x8664_PCI_H */
|
||||
|
@ -685,13 +685,16 @@ extern void pci_unblock_user_cfg_access(struct pci_dev *dev);
|
||||
* a PCI domain is defined to be a set of PCI busses which share
|
||||
* configuration space.
|
||||
*/
|
||||
#ifndef CONFIG_PCI_DOMAINS
|
||||
#ifdef CONFIG_PCI_DOMAINS
|
||||
extern int pci_domains_supported;
|
||||
#else
|
||||
enum { pci_domains_supported = 0 };
|
||||
static inline int pci_domain_nr(struct pci_bus *bus) { return 0; }
|
||||
static inline int pci_proc_domain(struct pci_bus *bus)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_PCI_DOMAINS */
|
||||
|
||||
#else /* CONFIG_PCI is not enabled */
|
||||
|
||||
|
@ -829,6 +829,9 @@
|
||||
#define PCI_DEVICE_ID_UMC_UM8886BF 0x673a
|
||||
#define PCI_DEVICE_ID_UMC_UM8886A 0x886a
|
||||
|
||||
#define PCI_VENDOR_ID_PICOPOWER 0x1066
|
||||
#define PCI_DEVICE_ID_PICOPOWER_PT86C523 0x0002
|
||||
#define PCI_DEVICE_ID_PICOPOWER_PT86C523BBP 0x8002
|
||||
|
||||
#define PCI_VENDOR_ID_MYLEX 0x1069
|
||||
#define PCI_DEVICE_ID_MYLEX_DAC960_P 0x0001
|
||||
|
@ -147,7 +147,7 @@
|
||||
#define PCI_BRIDGE_CONTROL 0x3e
|
||||
#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */
|
||||
#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */
|
||||
#define PCI_BRIDGE_CTL_NO_ISA 0x04 /* Disable bridging of ISA ports */
|
||||
#define PCI_BRIDGE_CTL_ISA 0x04 /* Enable ISA mode */
|
||||
#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */
|
||||
#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */
|
||||
#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */
|
||||
@ -202,8 +202,12 @@
|
||||
#define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */
|
||||
#define PCI_CAP_ID_PCIX 0x07 /* PCI-X */
|
||||
#define PCI_CAP_ID_HT 0x08 /* HyperTransport */
|
||||
#define PCI_CAP_ID_VNDR 0x09 /* Vendor specific capability */
|
||||
#define PCI_CAP_ID_VNDR 0x09 /* Vendor specific */
|
||||
#define PCI_CAP_ID_DBG 0x0A /* Debug port */
|
||||
#define PCI_CAP_ID_CCRC 0x0B /* CompactPCI Central Resource Control */
|
||||
#define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */
|
||||
#define PCI_CAP_ID_SSVID 0x0D /* Bridge subsystem vendor/device ID */
|
||||
#define PCI_CAP_ID_AGP3 0x0E /* AGP Target PCI-PCI bridge */
|
||||
#define PCI_CAP_ID_EXP 0x10 /* PCI Express */
|
||||
#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */
|
||||
#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */
|
||||
|
@ -497,6 +497,7 @@ void
|
||||
swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
|
||||
dma_addr_t dma_handle)
|
||||
{
|
||||
WARN_ON(irqs_disabled());
|
||||
if (!(vaddr >= (void *)io_tlb_start
|
||||
&& vaddr < (void *)io_tlb_end))
|
||||
free_pages((unsigned long) vaddr, get_order(size));
|
||||
|
Loading…
Reference in New Issue
Block a user