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:
Linus Torvalds 2007-10-12 15:50:23 -07:00
commit 6a84258e5f
38 changed files with 654 additions and 544 deletions

View File

@ -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
------------------------------------------

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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;

View File

@ -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));

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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.
*

View File

@ -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;

View File

@ -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 }
};

View File

@ -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;

View File

@ -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"

View File

@ -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,

View File

@ -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);
}

View File

@ -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");

View File

@ -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");

View File

@ -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__,

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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)) {

View File

@ -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)) {

View File

@ -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;

View File

@ -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"

View File

@ -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);
}

View File

@ -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, &region, &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, &region, &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, &region, &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, &region, &resource);
dev->resource[3].start = region.start;
dev->resource[3].end = region.end;
dev->resource[3].flags = resource.flags;
}
}
break;

View File

@ -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;
}

View File

@ -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, &region);
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

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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));