Commit 11bd04f6 authored by Linus Torvalds's avatar Linus Torvalds

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

* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (109 commits)
  PCI: fix coding style issue in pci_save_state()
  PCI: add pci_request_acs
  PCI: fix BUG_ON triggered by logical PCIe root port removal
  PCI: remove ifdefed pci_cleanup_aer_correct_error_status
  PCI: unconditionally clear AER uncorr status register during cleanup
  x86/PCI: claim SR-IOV BARs in pcibios_allocate_resource
  PCI: portdrv: remove redundant definitions
  PCI: portdrv: remove unnecessary struct pcie_port_data
  PCI: portdrv: minor cleanup for pcie_port_device_register
  PCI: portdrv: add missing irq cleanup
  PCI: portdrv: enable device before irq initialization
  PCI: portdrv: cleanup service irqs initialization
  PCI: portdrv: check capabilities first
  PCI: portdrv: move PME capability check
  PCI: portdrv: remove redundant pcie type calculation
  PCI: portdrv: cleanup pcie_device registration
  PCI: portdrv: remove redundant pcie_port_device_probe
  PCI: Always set prefetchable base/limit upper32 registers
  PCI: read-modify-write the pcie device control register when initiating pcie flr
  PCI: show dma_mask bits in /sys
  ...

Fixed up conflicts in:
	arch/x86/kernel/amd_iommu_init.c
	drivers/pci/dmar.c
	drivers/pci/hotplug/acpiphp_glue.c
parents 4e2ccdb0 9e0b5b2c
...@@ -37,35 +37,9 @@ ...@@ -37,35 +37,9 @@
#include <xen/interface/xen.h> #include <xen/interface/xen.h>
#include <xen/interface/version.h> /* to compile feature.c */ #include <xen/interface/version.h> /* to compile feature.c */
#include <xen/features.h> /* to comiple xen-netfront.c */ #include <xen/features.h> /* to comiple xen-netfront.c */
#include <xen/xen.h>
#include <asm/xen/hypercall.h> #include <asm/xen/hypercall.h>
/* xen_domain_type is set before executing any C code by early_xen_setup */
enum xen_domain_type {
XEN_NATIVE, /* running on bare hardware */
XEN_PV_DOMAIN, /* running in a PV domain */
XEN_HVM_DOMAIN, /* running in a Xen hvm domain*/
};
#ifdef CONFIG_XEN
extern enum xen_domain_type xen_domain_type;
#else
#define xen_domain_type XEN_NATIVE
#endif
#define xen_domain() (xen_domain_type != XEN_NATIVE)
#define xen_pv_domain() (xen_domain() && \
xen_domain_type == XEN_PV_DOMAIN)
#define xen_hvm_domain() (xen_domain() && \
xen_domain_type == XEN_HVM_DOMAIN)
#ifdef CONFIG_XEN_DOM0
#define xen_initial_domain() (xen_pv_domain() && \
(xen_start_info->flags & SIF_INITDOMAIN))
#else
#define xen_initial_domain() (0)
#endif
#ifdef CONFIG_XEN #ifdef CONFIG_XEN
extern struct shared_info *HYPERVISOR_shared_info; extern struct shared_info *HYPERVISOR_shared_info;
extern struct start_info *xen_start_info; extern struct start_info *xen_start_info;
......
...@@ -131,6 +131,7 @@ alloc_pci_controller (int seg) ...@@ -131,6 +131,7 @@ alloc_pci_controller (int seg)
} }
struct pci_root_info { struct pci_root_info {
struct acpi_device *bridge;
struct pci_controller *controller; struct pci_controller *controller;
char *name; char *name;
}; };
...@@ -297,9 +298,20 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) ...@@ -297,9 +298,20 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
window->offset = offset; window->offset = offset;
if (insert_resource(root, &window->resource)) { if (insert_resource(root, &window->resource)) {
printk(KERN_ERR "alloc 0x%llx-0x%llx from %s for %s failed\n", dev_err(&info->bridge->dev,
window->resource.start, window->resource.end, "can't allocate host bridge window %pR\n",
root->name, info->name); &window->resource);
} else {
if (offset)
dev_info(&info->bridge->dev, "host bridge window %pR "
"(PCI address [%#llx-%#llx])\n",
&window->resource,
window->resource.start - offset,
window->resource.end - offset);
else
dev_info(&info->bridge->dev,
"host bridge window %pR\n",
&window->resource);
} }
return AE_OK; return AE_OK;
...@@ -319,8 +331,9 @@ pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl) ...@@ -319,8 +331,9 @@ pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl)
(res->end - res->start < 16)) (res->end - res->start < 16))
continue; continue;
if (j >= PCI_BUS_NUM_RESOURCES) { if (j >= PCI_BUS_NUM_RESOURCES) {
printk("Ignoring range [%#llx-%#llx] (%lx)\n", dev_warn(&bus->dev,
res->start, res->end, res->flags); "ignoring host bridge window %pR (no space)\n",
res);
continue; continue;
} }
bus->resource[j++] = res; bus->resource[j++] = res;
...@@ -364,6 +377,7 @@ pci_acpi_scan_root(struct acpi_device *device, int domain, int bus) ...@@ -364,6 +377,7 @@ pci_acpi_scan_root(struct acpi_device *device, int domain, int bus)
goto out3; goto out3;
sprintf(name, "PCI Bus %04x:%02x", domain, bus); sprintf(name, "PCI Bus %04x:%02x", domain, bus);
info.bridge = device;
info.controller = controller; info.controller = controller;
info.name = name; info.name = name;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, acpi_walk_resources(device->handle, METHOD_NAME__CRS,
...@@ -720,9 +734,6 @@ int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size) ...@@ -720,9 +734,6 @@ int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size)
return ret; return ret;
} }
/* It's defined in drivers/pci/pci.c */
extern u8 pci_cache_line_size;
/** /**
* set_pci_cacheline_size - determine cacheline size for PCI devices * set_pci_cacheline_size - determine cacheline size for PCI devices
* *
...@@ -731,7 +742,7 @@ extern u8 pci_cache_line_size; ...@@ -731,7 +742,7 @@ extern u8 pci_cache_line_size;
* *
* Code mostly taken from arch/ia64/kernel/palinfo.c:cache_info(). * Code mostly taken from arch/ia64/kernel/palinfo.c:cache_info().
*/ */
static void __init set_pci_cacheline_size(void) static void __init set_pci_dfl_cacheline_size(void)
{ {
unsigned long levels, unique_caches; unsigned long levels, unique_caches;
long status; long status;
...@@ -751,7 +762,7 @@ static void __init set_pci_cacheline_size(void) ...@@ -751,7 +762,7 @@ static void __init set_pci_cacheline_size(void)
"(status=%ld)\n", __func__, status); "(status=%ld)\n", __func__, status);
return; return;
} }
pci_cache_line_size = (1 << cci.pcci_line_size) / 4; pci_dfl_cache_line_size = (1 << cci.pcci_line_size) / 4;
} }
u64 ia64_dma_get_required_mask(struct device *dev) u64 ia64_dma_get_required_mask(struct device *dev)
...@@ -782,7 +793,7 @@ EXPORT_SYMBOL_GPL(dma_get_required_mask); ...@@ -782,7 +793,7 @@ EXPORT_SYMBOL_GPL(dma_get_required_mask);
static int __init pcibios_init(void) static int __init pcibios_init(void)
{ {
set_pci_cacheline_size(); set_pci_dfl_cacheline_size();
return 0; return 0;
} }
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
#define PCI_IRQ_NONE 0xffffffff #define PCI_IRQ_NONE 0xffffffff
#define PCI_CACHE_LINE_BYTES 64
static inline void pcibios_set_master(struct pci_dev *dev) static inline void pcibios_set_master(struct pci_dev *dev)
{ {
/* No special bus mastering setup handling */ /* No special bus mastering setup handling */
......
...@@ -1081,3 +1081,10 @@ void pci_resource_to_user(const struct pci_dev *pdev, int bar, ...@@ -1081,3 +1081,10 @@ void pci_resource_to_user(const struct pci_dev *pdev, int bar,
*start = rp->start - offset; *start = rp->start - offset;
*end = rp->end - offset; *end = rp->end - offset;
} }
static int __init pcibios_init(void)
{
pci_dfl_cache_line_size = 64 >> 2;
return 0;
}
subsys_initcall(pcibios_init);
...@@ -118,11 +118,27 @@ extern int __init pcibios_init(void); ...@@ -118,11 +118,27 @@ extern int __init pcibios_init(void);
/* pci-mmconfig.c */ /* pci-mmconfig.c */
/* "PCI MMCONFIG %04x [bus %02x-%02x]" */
#define PCI_MMCFG_RESOURCE_NAME_LEN (22 + 4 + 2 + 2)
struct pci_mmcfg_region {
struct list_head list;
struct resource res;
u64 address;
char __iomem *virt;
u16 segment;
u8 start_bus;
u8 end_bus;
char name[PCI_MMCFG_RESOURCE_NAME_LEN];
};
extern int __init pci_mmcfg_arch_init(void); extern int __init pci_mmcfg_arch_init(void);
extern void __init pci_mmcfg_arch_free(void); extern void __init pci_mmcfg_arch_free(void);
extern struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus);
extern struct list_head pci_mmcfg_list;
extern struct acpi_mcfg_allocation *pci_mmcfg_config; #define PCI_MMCFG_BUS_OFFSET(bus) ((bus) << 20)
extern int pci_mmcfg_config_num;
/* /*
* AMD Fam10h CPUs are buggy, and cannot access MMIO config space * AMD Fam10h CPUs are buggy, and cannot access MMIO config space
......
...@@ -37,31 +37,4 @@ ...@@ -37,31 +37,4 @@
extern struct shared_info *HYPERVISOR_shared_info; extern struct shared_info *HYPERVISOR_shared_info;
extern struct start_info *xen_start_info; extern struct start_info *xen_start_info;
enum xen_domain_type {
XEN_NATIVE, /* running on bare hardware */
XEN_PV_DOMAIN, /* running in a PV domain */
XEN_HVM_DOMAIN, /* running in a Xen hvm domain */
};
#ifdef CONFIG_XEN
extern enum xen_domain_type xen_domain_type;
#else
#define xen_domain_type XEN_NATIVE
#endif
#define xen_domain() (xen_domain_type != XEN_NATIVE)
#define xen_pv_domain() (xen_domain() && \
xen_domain_type == XEN_PV_DOMAIN)
#define xen_hvm_domain() (xen_domain() && \
xen_domain_type == XEN_HVM_DOMAIN)
#ifdef CONFIG_XEN_DOM0
#include <xen/interface/xen.h>
#define xen_initial_domain() (xen_pv_domain() && \
xen_start_info->flags & SIF_INITDOMAIN)
#else /* !CONFIG_XEN_DOM0 */
#define xen_initial_domain() (0)
#endif /* CONFIG_XEN_DOM0 */
#endif /* _ASM_X86_XEN_HYPERVISOR_H */ #endif /* _ASM_X86_XEN_HYPERVISOR_H */
...@@ -1336,6 +1336,9 @@ void __init amd_iommu_detect(void) ...@@ -1336,6 +1336,9 @@ void __init amd_iommu_detect(void)
iommu_detected = 1; iommu_detected = 1;
amd_iommu_detected = 1; amd_iommu_detected = 1;
x86_init.iommu.iommu_init = amd_iommu_init; x86_init.iommu.iommu_init = amd_iommu_init;
/* Make sure ACS will be enabled */
pci_request_acs();
} }
} }
......
...@@ -15,3 +15,8 @@ obj-$(CONFIG_X86_NUMAQ) += numaq_32.o ...@@ -15,3 +15,8 @@ obj-$(CONFIG_X86_NUMAQ) += numaq_32.o
obj-y += common.o early.o obj-y += common.o early.o
obj-y += amd_bus.o obj-y += amd_bus.o
obj-$(CONFIG_X86_64) += bus_numa.o intel_bus.o
ifeq ($(CONFIG_PCI_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <asm/pci_x86.h> #include <asm/pci_x86.h>
struct pci_root_info { struct pci_root_info {
struct acpi_device *bridge;
char *name; char *name;
unsigned int res_num; unsigned int res_num;
struct resource *res; struct resource *res;
...@@ -58,6 +59,30 @@ bus_has_transparent_bridge(struct pci_bus *bus) ...@@ -58,6 +59,30 @@ bus_has_transparent_bridge(struct pci_bus *bus)
return false; return false;
} }
static void
align_resource(struct acpi_device *bridge, struct resource *res)
{
int align = (res->flags & IORESOURCE_MEM) ? 16 : 4;
/*
* Host bridge windows are not BARs, but the decoders on the PCI side
* that claim this address space have starting alignment and length
* constraints, so fix any obvious BIOS goofs.
*/
if (!IS_ALIGNED(res->start, align)) {
dev_printk(KERN_DEBUG, &bridge->dev,
"host bridge window %pR invalid; "
"aligning start to %d-byte boundary\n", res, align);
res->start &= ~(align - 1);
}
if (!IS_ALIGNED(res->end + 1, align)) {
dev_printk(KERN_DEBUG, &bridge->dev,
"host bridge window %pR invalid; "
"aligning end to %d-byte boundary\n", res, align);
res->end = ALIGN(res->end, align) - 1;
}
}
static acpi_status static acpi_status
setup_resource(struct acpi_resource *acpi_res, void *data) setup_resource(struct acpi_resource *acpi_res, void *data)
{ {
...@@ -91,11 +116,12 @@ setup_resource(struct acpi_resource *acpi_res, void *data) ...@@ -91,11 +116,12 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
start = addr.minimum + addr.translation_offset; start = addr.minimum + addr.translation_offset;
end = start + addr.address_length - 1; end = start + addr.address_length - 1;
if (info->res_num >= max_root_bus_resources) { if (info->res_num >= max_root_bus_resources) {
printk(KERN_WARNING "PCI: Failed to allocate 0x%lx-0x%lx " if (pci_probe & PCI_USE__CRS)
"from %s for %s due to _CRS returning more than " printk(KERN_WARNING "PCI: Failed to allocate "
"%d resource descriptors\n", (unsigned long) start, "0x%lx-0x%lx from %s for %s due to _CRS "
(unsigned long) end, root->name, info->name, "returning more than %d resource descriptors\n",
max_root_bus_resources); (unsigned long) start, (unsigned long) end,
root->name, info->name, max_root_bus_resources);
return AE_OK; return AE_OK;
} }
...@@ -105,14 +131,28 @@ setup_resource(struct acpi_resource *acpi_res, void *data) ...@@ -105,14 +131,28 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
res->start = start; res->start = start;
res->end = end; res->end = end;
res->child = NULL; res->child = NULL;
align_resource(info->bridge, res);
if (!(pci_probe & PCI_USE__CRS)) {
dev_printk(KERN_DEBUG, &info->bridge->dev,
"host bridge window %pR (ignored)\n", res);
return AE_OK;
}
if (insert_resource(root, res)) { if (insert_resource(root, res)) {
printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx " dev_err(&info->bridge->dev,
"from %s for %s\n", (unsigned long) res->start, "can't allocate host bridge window %pR\n", res);
(unsigned long) res->end, root->name, info->name);
} else { } else {
info->bus->resource[info->res_num] = res; info->bus->resource[info->res_num] = res;
info->res_num++; info->res_num++;
if (addr.translation_offset)
dev_info(&info->bridge->dev, "host bridge window %pR "
"(PCI address [%#llx-%#llx])\n",
res, res->start - addr.translation_offset,
res->end - addr.translation_offset);
else
dev_info(&info->bridge->dev,
"host bridge window %pR\n", res);
} }
return AE_OK; return AE_OK;
} }
...@@ -124,6 +164,12 @@ get_current_resources(struct acpi_device *device, int busnum, ...@@ -124,6 +164,12 @@ get_current_resources(struct acpi_device *device, int busnum,
struct pci_root_info info; struct pci_root_info info;
size_t size; size_t size;
if (!(pci_probe & PCI_USE__CRS))
dev_info(&device->dev,
"ignoring host bridge windows from ACPI; "
"boot with \"pci=use_crs\" to use them\n");
info.bridge = device;
info.bus = bus; info.bus = bus;
info.res_num = 0; info.res_num = 0;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource, acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
...@@ -163,8 +209,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do ...@@ -163,8 +209,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
#endif #endif
if (domain && !pci_domains_supported) { if (domain && !pci_domains_supported) {
printk(KERN_WARNING "PCI: Multiple domains not supported " printk(KERN_WARNING "pci_bus %04x:%02x: "
"(dom %d, bus %d)\n", domain, busnum); "ignored (multiple domains not supported)\n",
domain, busnum);
return NULL; return NULL;
} }
...@@ -188,7 +235,8 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do ...@@ -188,7 +235,8 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
*/ */
sd = kzalloc(sizeof(*sd), GFP_KERNEL); sd = kzalloc(sizeof(*sd), GFP_KERNEL);
if (!sd) { if (!sd) {
printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum); printk(KERN_WARNING "pci_bus %04x:%02x: "
"ignored (out of memory)\n", domain, busnum);
return NULL; return NULL;
} }
...@@ -209,9 +257,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do ...@@ -209,9 +257,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
} else { } else {
bus = pci_create_bus(NULL, busnum, &pci_root_ops, sd); bus = pci_create_bus(NULL, busnum, &pci_root_ops, sd);
if (bus) { if (bus) {
if (pci_probe & PCI_USE__CRS) get_current_resources(device, busnum, domain, bus);
get_current_resources(device, busnum, domain,
bus);
bus->subordinate = pci_scan_child_bus(bus); bus->subordinate = pci_scan_child_bus(bus);
} }
} }
......
...@@ -6,10 +6,10 @@ ...@@ -6,10 +6,10 @@
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
#include <asm/pci-direct.h> #include <asm/pci-direct.h>
#include <asm/mpspec.h>
#include <linux/cpumask.h>
#endif #endif
#include "bus_numa.h"
/* /*
* This discovers the pcibus <-> node mapping on AMD K8. * This discovers the pcibus <-> node mapping on AMD K8.
* also get peer root bus resource for io,mmio * also get peer root bus resource for io,mmio
...@@ -17,67 +17,6 @@ ...@@ -17,67 +17,6 @@
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
/*
* sub bus (transparent) will use entres from 3 to store extra from root,
* so need to make sure have enought slot there, increase PCI_BUS_NUM_RESOURCES?
*/
#define RES_NUM 16
struct pci_root_info {
char name[12];
unsigned int res_num;
struct resource res[RES_NUM];
int bus_min;
int bus_max;
int node;
int link;
};
/* 4 at this time, it may become to 32 */
#define PCI_ROOT_NR 4
static int pci_root_num;
static struct pci_root_info pci_root_info[PCI_ROOT_NR];
void x86_pci_root_bus_res_quirks(struct pci_bus *b)
{
int i;
int j;
struct pci_root_info *info;
/* don't go for it if _CRS is used already */
if (b->resource[0] != &ioport_resource ||
b->resource[1] != &iomem_resource)
return;
/* if only one root bus, don't need to anything */
if (pci_root_num < 2)
return;
for (i = 0; i < pci_root_num; i++) {
if (pci_root_info[i].bus_min == b->number)
break;
}
if (i == pci_root_num)
return;
printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n",
b->number);
info = &pci_root_info[i];
for (j = 0; j < info->res_num; j++) {
struct resource *res;
struct resource *root;
res = &info->res[j];
b->resource[j] = res;
if (res->flags & IORESOURCE_IO)
root = &ioport_resource;
else
root = &iomem_resource;
insert_resource(root, res);
}
}
#define RANGE_NUM 16 #define RANGE_NUM 16
struct res_range { struct res_range {
...@@ -130,52 +69,6 @@ static void __init update_range(struct res_range *range, size_t start, ...@@ -130,52 +69,6 @@ static void __init update_range(struct res_range *range, size_t start,
} }
} }
static void __init update_res(struct pci_root_info *info, size_t start,
size_t end, unsigned long flags, int merge)
{
int i;
struct resource *res;
if (!merge)
goto addit;
/* try to merge it with old one */
for (i = 0; i < info->res_num; i++) {
size_t final_start, final_end;
size_t common_start, common_end;
res = &info->res[i];
if (res->flags != flags)
continue;
common_start = max((size_t)res->start, start);
common_end = min((size_t)res->end, end);
if (common_start > common_end + 1)
continue;
final_start = min((size_t)res->start, start);
final_end = max((size_t)res->end, end);
res->start = final_start;
res->end = final_end;
return;
}
addit:
/* need to add that */
if (info->res_num >= RES_NUM)
return;
res = &info->res[info->res_num];
res->name = info->name;
res->flags = flags;
res->start = start;
res->end = end;
res->child = NULL;
info->res_num++;
}
struct pci_hostbridge_probe { struct pci_hostbridge_probe {
u32 bus; u32 bus;
u32 slot; u32 slot;
...@@ -230,7 +123,6 @@ static int __init early_fill_mp_bus_info(void) ...@@ -230,7 +123,6 @@ static int __init early_fill_mp_bus_info(void)
int j; int j;
unsigned bus; unsigned bus;
unsigned slot; unsigned slot;
int found;
int node; int node;
int link; int link;
int def_node; int def_node;
...@@ -247,7 +139,7 @@ static int __init early_fill_mp_bus_info(void) ...@@ -247,7 +139,7 @@ static int __init early_fill_mp_bus_info(void)
if (!early_pci_allowed()) if (!early_pci_allowed())
return -1; return -1;
found = 0; found_all_numa_early = 0;
for (i = 0; i < ARRAY_SIZE(pci_probes); i++) { for (i = 0; i < ARRAY_SIZE(pci_probes); i++) {
u32 id; u32 id;
u16 device; u16 device;
...@@ -261,12 +153,12 @@ static int __init early_fill_mp_bus_info(void) ...@@ -261,12 +153,12 @@ static int __init early_fill_mp_bus_info(void)
device = (id>>16) & 0xffff; device = (id>>16) & 0xffff;
if (pci_probes[i].vendor == vendor && if (pci_probes[i].vendor == vendor &&
pci_probes[i].device == device) { pci_probes[i].device == device) {
found = 1; found_all_numa_early = 1;
break; break;
} }
} }
if (!found) if (!found_all_numa_early)
return 0; return 0;
pci_root_num = 0; pci_root_num = 0;
...@@ -488,7 +380,7 @@ static int __init early_fill_mp_bus_info(void) ...@@ -488,7 +380,7 @@ static int __init early_fill_mp_bus_info(void)
info = &pci_root_info[i]; info = &pci_root_info[i];
res_num = info->res_num; res_num = info->res_num;
busnum = info->bus_min; busnum = info->bus_min;
printk(KERN_DEBUG "bus: [%02x,%02x] on node %x link %x\n", printk(KERN_DEBUG "bus: [%02x, %02x] on node %x link %x\n",
info->bus_min, info->bus_max, info->node, info->link); info->bus_min, info->bus_max, info->node, info->link);
for (j = 0; j < res_num; j++) { for (j = 0; j < res_num; j++) {
res = &info->res[j]; res = &info->res[j];
......
#include <linux/init.h>
#include <linux/pci.h>
#include "bus_numa.h"
int pci_root_num;
struct pci_root_info pci_root_info[PCI_ROOT_NR];
int found_all_numa_early;
void x86_pci_root_bus_res_quirks(struct pci_bus *b)
{
int i;
int j;
struct pci_root_info *info;
/* don't go for it if _CRS is used already */
if (b->resource[0] != &ioport_resource ||
b->resource[1] != &iomem_resource)
return;
if (!pci_root_num)
return;
/* for amd, if only one root bus, don't need to do anything */
if (pci_root_num < 2 && found_all_numa_early)
return;
for (i = 0; i < pci_root_num; i++) {
if (pci_root_info[i].bus_min == b->number)
break;
}
if (i == pci_root_num)
return;
printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n",
b->number);
info = &pci_root_info[i];
for (j = 0; j < info->res_num; j++) {
struct resource *res;
struct resource *root;
res = &info->res[j];
b->resource[j] = res;
if (res->flags & IORESOURCE_IO)
root = &ioport_resource;
else
root = &iomem_resource;
insert_resource(root, res);
}
}
void __init update_res(struct pci_root_info *info, size_t start,
size_t end, unsigned long flags, int merge)
{
int i;
struct resource *res;
if (start > end)
return;
if (!merge)
goto addit;
/* try to merge it with old one */
for (i = 0; i < info->res_num; i++) {
size_t final_start, final_end;
size_t common_start, common_end;
res = &info->res[i];
if (res->flags != flags)
continue;
common_start = max((size_t)res->start, start);
common_end = min((size_t)res->end, end);
if (common_start > common_end + 1)
continue;
final_start = min((size_t)res->start, start);
final_end = max((size_t)res->end, end);
res->start = final_start;
res->end = final_end;
return;
}
addit:
/* need to add that */
if (info->res_num >= RES_NUM)
return;
res = &info->res[info->res_num];
res->name = info->name;
res->flags = flags;
res->start = start;
res->end = end;
res->child = NULL;
info->res_num++;
}
#ifdef CONFIG_X86_64
/*
* sub bus (transparent) will use entres from 3 to store extra from
* root, so need to make sure we have enough slot there, Should we
* increase PCI_BUS_NUM_RESOURCES?
*/
#define RES_NUM 16
struct pci_root_info {
char name[12];
unsigned int res_num;
struct resource res[RES_NUM];
int bus_min;
int bus_max;
int node;
int link;
};
/* 4 at this time, it may become to 32 */
#define PCI_ROOT_NR 4
extern int pci_root_num;
extern struct pci_root_info pci_root_info[PCI_ROOT_NR];
extern int found_all_numa_early;
extern void update_res(struct pci_root_info *info, size_t start,
size_t end, unsigned long flags, int merge);
#endif
...@@ -410,8 +410,6 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum) ...@@ -410,8 +410,6 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum)
return bus; return bus;
} }
extern u8 pci_cache_line_size;
int __init pcibios_init(void) int __init pcibios_init(void)
{ {
struct cpuinfo_x86 *c = &boot_cpu_data; struct cpuinfo_x86 *c = &boot_cpu_data;
...@@ -422,15 +420,19 @@ int __init pcibios_init(void) ...@@ -422,15 +420,19 @@ int __init pcibios_init(void)
} }
/* /*
* Assume PCI cacheline size of 32 bytes for all x86s except K7/K8 * Set PCI cacheline size to that of the CPU if the CPU has reported it.
* and P4. It's also good for 386/486s (which actually have 16) * (For older CPUs that don't support cpuid, we se it to 32 bytes
* It's also good for 386/486s (which actually have 16)
* as quite a few PCI devices do not support smaller values. * as quite a few PCI devices do not support smaller values.
*/ */
pci_cache_line_size = 32 >> 2; if (c->x86_clflush_size > 0) {
if (c->x86 >= 6 && c->x86_vendor == X86_VENDOR_AMD) pci_dfl_cache_line_size = c->x86_clflush_size >> 2;
pci_cache_line_size = 64 >> 2; /* K7 & K8 */ printk(KERN_DEBUG "PCI: pci_cache_line_size set to %d bytes\n",
else if (c->x86 > 6 && c->x86_vendor == X86_VENDOR_INTEL) pci_dfl_cache_line_size << 2);
pci_cache_line_size = 128 >> 2; /* P4 */ } else {
pci_dfl_cache_line_size = 32 >> 2;
printk(KERN_DEBUG "PCI: Unknown cacheline size. Setting to 32 bytes\n");
}
pcibios_resource_survey(); pcibios_resource_survey();
......
...@@ -12,8 +12,6 @@ u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset) ...@@ -12,8 +12,6 @@ u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset)
u32 v; u32 v;
outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
v = inl(0xcfc); v = inl(0xcfc);
if (v != 0xffffffff)
pr_debug("%x reading 4 from %x: %x\n", slot, offset, v);
return v; return v;
} }
...@@ -22,7 +20,6 @@ u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset) ...@@ -22,7 +20,6 @@ u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset)
u8 v; u8 v;
outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
v = inb(0xcfc + (offset&3)); v = inb(0xcfc + (offset&3));
pr_debug("%x reading 1 from %x: %x\n", slot, offset, v);
return v; return v;
} }
...@@ -31,28 +28,24 @@ u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset) ...@@ -31,28 +28,24 @@ u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset)
u16 v; u16 v;
outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
v = inw(0xcfc + (offset&2)); v = inw(0xcfc + (offset&2));
pr_debug("%x reading 2 from %x: %x\n", slot, offset, v);
return v; return v;
} }
void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset, void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset,
u32 val) u32 val)
{ {
pr_debug("%x writing to %x: %x\n", slot, offset, val);
outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
outl(val, 0xcfc); outl(val, 0xcfc);
} }
void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val) void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val)
{ {
pr_debug("%x writing to %x: %x\n", slot, offset, val);
outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
outb(val, 0xcfc + (offset&3)); outb(val, 0xcfc + (offset&3));
} }
void write_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset, u16 val) void write_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset, u16 val)
{ {
pr_debug("%x writing to %x: %x\n", slot, offset, val);
outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
outw(val, 0xcfc + (offset&2)); outw(val, 0xcfc + (offset&2));
} }
......
...@@ -129,7 +129,9 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) ...@@ -129,7 +129,9 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
continue; continue;
if (!r->start || if (!r->start ||
pci_claim_resource(dev, idx) < 0) { pci_claim_resource(dev, idx) < 0) {
dev_info(&dev->dev, "BAR %d: can't allocate resource\n", idx); dev_info(&dev->dev,
"can't reserve window %pR\n",
r);
/* /*
* Something is wrong with the region. * Something is wrong with the region.
* Invalidate the resource to prevent * Invalidate the resource to prevent
...@@ -144,16 +146,29 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) ...@@ -144,16 +146,29 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
} }
} }
struct pci_check_idx_range {
int start;
int end;
};
static void __init pcibios_allocate_resources(int pass) static void __init pcibios_allocate_resources(int pass)
{ {
struct pci_dev *dev = NULL; struct pci_dev *dev = NULL;
int idx, disabled; int idx, disabled, i;
u16 command; u16 command;
struct resource *r; struct resource *r;
struct pci_check_idx_range idx_range[] = {
{ PCI_STD_RESOURCES, PCI_STD_RESOURCE_END },
#ifdef CONFIG_PCI_IOV
{ PCI_IOV_RESOURCES, PCI_IOV_RESOURCE_END },
#endif
};
for_each_pci_dev(dev) { for_each_pci_dev(dev) {
pci_read_config_word(dev, PCI_COMMAND, &command); pci_read_config_word(dev, PCI_COMMAND, &command);
for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { for (i = 0; i < ARRAY_SIZE(idx_range); i++)
for (idx = idx_range[i].start; idx <= idx_range[i].end; idx++) {
r = &dev->resource[idx]; r = &dev->resource[idx];
if (r->parent) /* Already allocated */ if (r->parent) /* Already allocated */
continue; continue;
...@@ -164,12 +179,12 @@ static void __init pcibios_allocate_resources(int pass) ...@@ -164,12 +179,12 @@ static void __init pcibios_allocate_resources(int pass)
else else
disabled = !(command & PCI_COMMAND_MEMORY); disabled = !(command & PCI_COMMAND_MEMORY);
if (pass == disabled) { if (pass == disabled) {
dev_dbg(&dev->dev, "resource %#08llx-%#08llx (f=%lx, d=%d, p=%d)\n", dev_dbg(&dev->dev,
(unsigned long long) r->start, "BAR %d: reserving %pr (d=%d, p=%d)\n",
(unsigned long long) r->end, idx, r, disabled, pass);
r->flags, disabled, pass);
if (pci_claim_resource(dev, idx) < 0) { if (pci_claim_resource(dev, idx) < 0) {
dev_info(&dev->dev, "BAR %d: can't allocate resource\n", idx); dev_info(&dev->dev,
"can't reserve %pR\n", r);
/* We'll assign a new address later */ /* We'll assign a new address later */
r->end -= r->start; r->end -= r->start;
r->start = 0; r->start = 0;
...@@ -182,7 +197,7 @@ static void __init pcibios_allocate_resources(int pass) ...@@ -182,7 +197,7 @@ static void __init pcibios_allocate_resources(int pass)
/* Turn the ROM off, leave the resource region, /* Turn the ROM off, leave the resource region,
* but keep it unregistered. */ * but keep it unregistered. */
u32 reg; u32 reg;
dev_dbg(&dev->dev, "disabling ROM\n"); dev_dbg(&dev->dev, "disabling ROM %pR\n", r);
r->flags &= ~IORESOURCE_ROM_ENABLE; r->flags &= ~IORESOURCE_ROM_ENABLE;
pci_read_config_dword(dev, pci_read_config_dword(dev,
dev->rom_base_reg, &reg); dev->rom_base_reg, &reg);
...@@ -282,6 +297,15 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, ...@@ -282,6 +297,15 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
return -EINVAL; return -EINVAL;
prot = pgprot_val(vma->vm_page_prot); prot = pgprot_val(vma->vm_page_prot);
/*
* Return error if pat is not enabled and write_combine is requested.
* Caller can followup with UC MINUS request and add a WC mtrr if there
* is a free mtrr slot.
*/
if (!pat_enabled && write_combine)
return -EINVAL;
if (pat_enabled && write_combine) if (pat_enabled && write_combine)
prot |= _PAGE_CACHE_WC; prot |= _PAGE_CACHE_WC;
else if (pat_enabled || boot_cpu_data.x86 > 3) else if (pat_enabled || boot_cpu_data.x86 > 3)
......
/*
* to read io range from IOH pci conf, need to do it after mmconfig is there
*/
#include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <asm/pci_x86.h>
#include "bus_numa.h"
static inline void print_ioh_resources(struct pci_root_info *info)
{
int res_num;
int busnum;
int i;
printk(KERN_DEBUG "IOH bus: [%02x, %02x]\n",
info->bus_min, info->bus_max);
res_num = info->res_num;
busnum = info->bus_min;
for (i = 0; i < res_num; i++) {
struct resource *res;
res = &info->res[i];
printk(KERN_DEBUG "IOH bus: %02x index %x %s: [%llx, %llx]\n",
busnum, i,
(res->flags & IORESOURCE_IO) ? "io port" :
"mmio",
res->start, res->end);
}
}
#define IOH_LIO 0x108
#define IOH_LMMIOL 0x10c
#define IOH_LMMIOH 0x110
#define IOH_LMMIOH_BASEU 0x114
#define IOH_LMMIOH_LIMITU 0x118
#define IOH_LCFGBUS 0x11c
static void __devinit pci_root_bus_res(struct pci_dev *dev)
{
u16 word;
u32 dword;
struct pci_root_info *info;
u16 io_base, io_end;
u32 mmiol_base, mmiol_end;
u64 mmioh_base, mmioh_end;
int bus_base, bus_end;
if (pci_root_num >= PCI_ROOT_NR) {
printk(KERN_DEBUG "intel_bus.c: PCI_ROOT_NR is too small\n");
return;
}
info = &pci_root_info[pci_root_num];
pci_root_num++;
pci_read_config_word(dev, IOH_LCFGBUS, &word);
bus_base = (word & 0xff);
bus_end = (word & 0xff00) >> 8;
sprintf(info->name, "PCI Bus #%02x", bus_base);
info->bus_min = bus_base;
info->bus_max = bus_end;
pci_read_config_word(dev, IOH_LIO, &word);
io_base = (word & 0xf0) << (12 - 4);
io_end = (word & 0xf000) | 0xfff;
update_res(info, io_base, io_end, IORESOURCE_IO, 0);
pci_read_config_dword(dev, IOH_LMMIOL, &dword);
mmiol_base = (dword & 0xff00) << (24 - 8);
mmiol_end = (dword & 0xff000000) | 0xffffff;
update_res(info, mmiol_base, mmiol_end, IORESOURCE_MEM, 0);
pci_read_config_dword(dev, IOH_LMMIOH, &dword);
mmioh_base = ((u64)(dword & 0xfc00)) << (26 - 10);
mmioh_end = ((u64)(dword & 0xfc000000) | 0x3ffffff);
pci_read_config_dword(dev, IOH_LMMIOH_BASEU, &dword);
mmioh_base |= ((u64)(dword & 0x7ffff)) << 32;
pci_read_config_dword(dev, IOH_LMMIOH_LIMITU, &dword);
mmioh_end |= ((u64)(dword & 0x7ffff)) << 32;
update_res(info, mmioh_base, mmioh_end, IORESOURCE_MEM, 0);
print_ioh_resources(info);
}
/* intel IOH */
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x342e, pci_root_bus_res);
This diff is collapsed.
...@@ -27,18 +27,10 @@ static int mmcfg_last_accessed_cpu; ...@@ -27,18 +27,10 @@ static int mmcfg_last_accessed_cpu;
*/ */
static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn) static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
{ {
struct acpi_mcfg_allocation *cfg; struct pci_mmcfg_region *cfg = pci_mmconfig_lookup(seg, bus);
int cfg_num;
for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) {
cfg = &pci_mmcfg_config[cfg_num];
if (cfg->pci_segment == seg &&
(cfg->start_bus_number <= bus) &&
(cfg->end_bus_number >= bus))
return cfg->address;
}
/* Fall back to type 0 */ if (cfg)
return cfg->address;
return 0; return 0;
} }
...@@ -47,7 +39,7 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn) ...@@ -47,7 +39,7 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
*/ */
static void pci_exp_set_dev_base(unsigned int base, int bus, int devfn) static void pci_exp_set_dev_base(unsigned int base, int bus, int devfn)
{ {
u32 dev_base = base | (bus << 20) | (devfn << 12); u32 dev_base = base | PCI_MMCFG_BUS_OFFSET(bus) | (devfn << 12);
int cpu = smp_processor_id(); int cpu = smp_processor_id();
if (dev_base != mmcfg_last_accessed_device || if (dev_base != mmcfg_last_accessed_device ||
cpu != mmcfg_last_accessed_cpu) { cpu != mmcfg_last_accessed_cpu) {
......
...@@ -12,38 +12,15 @@ ...@@ -12,38 +12,15 @@
#include <asm/e820.h> #include <asm/e820.h>
#include <asm/pci_x86.h> #include <asm/pci_x86.h>
/* Static virtual mapping of the MMCONFIG aperture */ #define PREFIX "PCI: "
struct mmcfg_virt {
struct acpi_mcfg_allocation *cfg;
char __iomem *virt;
};
static struct mmcfg_virt *pci_mmcfg_virt;
static char __iomem *get_virt(unsigned int seg, unsigned bus)
{
struct acpi_mcfg_allocation *cfg;
int cfg_num;
for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) {
cfg = pci_mmcfg_virt[cfg_num].cfg;
if (cfg->pci_segment == seg &&
(cfg->start_bus_number <= bus) &&
(cfg->end_bus_number >= bus))
return pci_mmcfg_virt[cfg_num].virt;
}
/* Fall back to type 0 */
return NULL;
}
static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
{ {
char __iomem *addr; struct pci_mmcfg_region *cfg = pci_mmconfig_lookup(seg, bus);
addr = get_virt(seg, bus); if (cfg && cfg->virt)
if (!addr) return cfg->virt + (PCI_MMCFG_BUS_OFFSET(bus) | (devfn << 12));
return NULL; return NULL;
return addr + ((bus << 20) | (devfn << 12));
} }
static int pci_mmcfg_read(unsigned int seg, unsigned int bus, static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
...@@ -109,42 +86,30 @@ static struct pci_raw_ops pci_mmcfg = { ...@@ -109,42 +86,30 @@ static struct pci_raw_ops pci_mmcfg = {
.write = pci_mmcfg_write, .write = pci_mmcfg_write,
}; };
static void __iomem * __init mcfg_ioremap(struct acpi_mcfg_allocation *cfg) static void __iomem * __init mcfg_ioremap(struct pci_mmcfg_region *cfg)
{ {
void __iomem *addr; void __iomem *addr;
u64 start, size; u64 start, size;
int num_buses;
start = cfg->start_bus_number; start = cfg->address + PCI_MMCFG_BUS_OFFSET(cfg->start_bus);
start <<= 20; num_buses = cfg->end_bus - cfg->start_bus + 1;
start += cfg->address; size = PCI_MMCFG_BUS_OFFSET(num_buses);
size = cfg->end_bus_number + 1 - cfg->start_bus_number;
size <<= 20;
addr = ioremap_nocache(start, size); addr = ioremap_nocache(start, size);
if (addr) { if (addr)
printk(KERN_INFO "PCI: Using MMCONFIG at %Lx - %Lx\n", addr -= PCI_MMCFG_BUS_OFFSET(cfg->start_bus);
start, start + size - 1);
addr -= cfg->start_bus_number << 20;
}
return addr; return addr;
} }
int __init pci_mmcfg_arch_init(void) int __init pci_mmcfg_arch_init(void)
{ {
int i; struct pci_mmcfg_region *cfg;
pci_mmcfg_virt = kzalloc(sizeof(*pci_mmcfg_virt) *
pci_mmcfg_config_num, GFP_KERNEL);
if (pci_mmcfg_virt == NULL) {
printk(KERN_ERR "PCI: Can not allocate memory for mmconfig structures\n");
return 0;
}
for (i = 0; i < pci_mmcfg_config_num; ++i) { list_for_each_entry(cfg, &pci_mmcfg_list, list) {
pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i]; cfg->virt = mcfg_ioremap(cfg);
pci_mmcfg_virt[i].virt = mcfg_ioremap(&pci_mmcfg_config[i]); if (!cfg->virt) {
if (!pci_mmcfg_virt[i].virt) { printk(KERN_ERR PREFIX "can't map MMCONFIG at %pR\n",
printk(KERN_ERR "PCI: Cannot map mmconfig aperture for " &cfg->res);
"segment %d\n",
pci_mmcfg_config[i].pci_segment);
pci_mmcfg_arch_free(); pci_mmcfg_arch_free();
return 0; return 0;
} }
...@@ -155,19 +120,12 @@ int __init pci_mmcfg_arch_init(void) ...@@ -155,19 +120,12 @@ int __init pci_mmcfg_arch_init(void)
void __init pci_mmcfg_arch_free(void) void __init pci_mmcfg_arch_free(void)
{ {
int i; struct pci_mmcfg_region *cfg;
if (pci_mmcfg_virt == NULL)
return;
for (i = 0; i < pci_mmcfg_config_num; ++i) { list_for_each_entry(cfg, &pci_mmcfg_list, list) {
if (pci_mmcfg_virt[i].virt) { if (cfg->virt) {
iounmap(pci_mmcfg_virt[i].virt + (pci_mmcfg_virt[i].cfg->start_bus_number << 20)); iounmap(cfg->virt + PCI_MMCFG_BUS_OFFSET(cfg->start_bus));
pci_mmcfg_virt[i].virt = NULL; cfg->virt = NULL;
pci_mmcfg_virt[i].cfg = NULL;
} }
} }
kfree(pci_mmcfg_virt);
pci_mmcfg_virt = NULL;
} }
...@@ -27,7 +27,9 @@ ...@@ -27,7 +27,9 @@
#include <linux/page-flags.h> #include <linux/page-flags.h>
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/pci.h>
#include <xen/xen.h>
#include <xen/interface/xen.h> #include <xen/interface/xen.h>
#include <xen/interface/version.h> #include <xen/interface/version.h>
#include <xen/interface/physdev.h> #include <xen/interface/physdev.h>
...@@ -1175,7 +1177,11 @@ asmlinkage void __init xen_start_kernel(void) ...@@ -1175,7 +1177,11 @@ asmlinkage void __init xen_start_kernel(void)
add_preferred_console("xenboot", 0, NULL); add_preferred_console("xenboot", 0, NULL);
add_preferred_console("tty", 0, NULL); add_preferred_console("tty", 0, NULL);
add_preferred_console("hvc", 0, NULL); add_preferred_console("hvc", 0, NULL);
} else {
/* Make sure ACS will be enabled */
pci_request_acs();
} }
xen_raw_console_write("about to get started...\n"); xen_raw_console_write("about to get started...\n");
......
...@@ -19,6 +19,7 @@ obj-y += acpi.o \ ...@@ -19,6 +19,7 @@ obj-y += acpi.o \
# All the builtin files are in the "acpi." module_param namespace. # All the builtin files are in the "acpi." module_param namespace.
acpi-y += osl.o utils.o reboot.o acpi-y += osl.o utils.o reboot.o
acpi-y += hest.o
# sleep related files # sleep related files
acpi-y += wakeup.o acpi-y += wakeup.o
......
#include <linux/acpi.h>
#include <linux/pci.h>
#define PREFIX "ACPI: "
static inline unsigned long parse_acpi_hest_ia_machine_check(struct acpi_hest_ia_machine_check *p)
{
return sizeof(*p) +
(sizeof(struct acpi_hest_ia_error_bank) * p->num_hardware_banks);
}
static inline unsigned long parse_acpi_hest_ia_corrected(struct acpi_hest_ia_corrected *p)
{
return sizeof(*p) +
(sizeof(struct acpi_hest_ia_error_bank) * p->num_hardware_banks);
}
static inline unsigned long parse_acpi_hest_ia_nmi(struct acpi_hest_ia_nmi *p)
{
return sizeof(*p);
}
static inline unsigned long parse_acpi_hest_generic(struct acpi_hest_generic *p)
{
return sizeof(*p);
}
static inline unsigned int hest_match_pci(struct acpi_hest_aer_common *p, struct pci_dev *pci)
{
return (0 == pci_domain_nr(pci->bus) &&
p->bus == pci->bus->number &&
p->device == PCI_SLOT(pci->devfn) &&
p->function == PCI_FUNC(pci->devfn));
}
static unsigned long parse_acpi_hest_aer(void *hdr, int type, struct pci_dev *pci, int *firmware_first)
{
struct acpi_hest_aer_common *p = hdr + sizeof(struct acpi_hest_header);
unsigned long rc=0;
u8 pcie_type = 0;
u8 bridge = 0;
switch (type) {
case ACPI_HEST_TYPE_AER_ROOT_PORT:
rc = sizeof(struct acpi_hest_aer_root);
pcie_type = PCI_EXP_TYPE_ROOT_PORT;
break;
case ACPI_HEST_TYPE_AER_ENDPOINT:
rc = sizeof(struct acpi_hest_aer);
pcie_type = PCI_EXP_TYPE_ENDPOINT;
break;
case ACPI_HEST_TYPE_AER_BRIDGE:
rc = sizeof(struct acpi_hest_aer_bridge);
if ((pci->class >> 16) == PCI_BASE_CLASS_BRIDGE)
bridge = 1;
break;
}
if (p->flags & ACPI_HEST_GLOBAL) {
if ((pci->is_pcie && (pci->pcie_type == pcie_type)) || bridge)
*firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
}
else
if (hest_match_pci(p, pci))
*firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
return rc;
}
static int acpi_hest_firmware_first(struct acpi_table_header *stdheader, struct pci_dev *pci)
{
struct acpi_table_hest *hest = (struct acpi_table_hest *)stdheader;
void *p = (void *)hest + sizeof(*hest); /* defined by the ACPI 4.0 spec */
struct acpi_hest_header *hdr = p;
int i;
int firmware_first = 0;
static unsigned char printed_unused = 0;
static unsigned char printed_reserved = 0;
for (i=0, hdr=p; p < (((void *)hest) + hest->header.length) && i < hest->error_source_count; i++) {
switch (hdr->type) {
case ACPI_HEST_TYPE_IA32_CHECK:
p += parse_acpi_hest_ia_machine_check(p);
break;
case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
p += parse_acpi_hest_ia_corrected(p);
break;
case ACPI_HEST_TYPE_IA32_NMI:
p += parse_acpi_hest_ia_nmi(p);
break;
/* These three should never appear */
case ACPI_HEST_TYPE_NOT_USED3:
case ACPI_HEST_TYPE_NOT_USED4:
case ACPI_HEST_TYPE_NOT_USED5:
if (!printed_unused) {
printk(KERN_DEBUG PREFIX
"HEST Error Source list contains an obsolete type (%d).\n", hdr->type);
printed_unused = 1;
}
break;
case ACPI_HEST_TYPE_AER_ROOT_PORT:
case ACPI_HEST_TYPE_AER_ENDPOINT:
case ACPI_HEST_TYPE_AER_BRIDGE:
p += parse_acpi_hest_aer(p, hdr->type, pci, &firmware_first);
break;
case ACPI_HEST_TYPE_GENERIC_ERROR:
p += parse_acpi_hest_generic(p);
break;
/* These should never appear either */
case ACPI_HEST_TYPE_RESERVED:
default:
if (!printed_reserved) {
printk(KERN_DEBUG PREFIX
"HEST Error Source list contains a reserved type (%d).\n", hdr->type);
printed_reserved = 1;
}
break;
}
}
return firmware_first;
}
int acpi_hest_firmware_first_pci(struct pci_dev *pci)
{
acpi_status status = AE_NOT_FOUND;
struct acpi_table_header *hest = NULL;
status = acpi_get_table(ACPI_SIG_HEST, 1, &hest);
if (ACPI_SUCCESS(status)) {
if (acpi_hest_firmware_first(hest, pci)) {
return 1;
}
}
return 0;
}
EXPORT_SYMBOL_GPL(acpi_hest_firmware_first_pci);
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <xen/xen.h>
#include <xen/xenbus.h> #include <xen/xenbus.h>
#include <xen/grant_table.h> #include <xen/grant_table.h>
#include <xen/events.h> #include <xen/events.h>
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include <linux/types.h> #include <linux/types.h>
#include <asm/xen/hypervisor.h> #include <asm/xen/hypervisor.h>
#include <xen/xen.h>
#include <xen/page.h> #include <xen/page.h>
#include <xen/events.h> #include <xen/events.h>
#include <xen/interface/io/console.h> #include <xen/interface/io/console.h>
......
...@@ -21,7 +21,10 @@ ...@@ -21,7 +21,10 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/input.h> #include <linux/input.h>
#include <asm/xen/hypervisor.h> #include <asm/xen/hypervisor.h>
#include <xen/xen.h>
#include <xen/events.h> #include <xen/events.h>
#include <xen/page.h> #include <xen/page.h>
#include <xen/interface/io/fbif.h> #include <xen/interface/io/fbif.h>
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <net/ip.h> #include <net/ip.h>
#include <xen/xen.h>
#include <xen/xenbus.h> #include <xen/xenbus.h>
#include <xen/events.h> #include <xen/events.h>
#include <xen/page.h> #include <xen/page.h>
......
...@@ -27,10 +27,10 @@ config PCI_LEGACY ...@@ -27,10 +27,10 @@ config PCI_LEGACY
default y default y
help help
Say Y here if you want to include support for the deprecated Say Y here if you want to include support for the deprecated
pci_find_slot() and pci_find_device() APIs. Most drivers have pci_find_device() API. Most drivers have been converted over
been converted over to using the proper hotplug APIs, so this to using the proper hotplug APIs, so this option serves to
option serves to include/exclude only a few drivers that are include/exclude only a few drivers that are still using this
still using this API. API.
config PCI_DEBUG config PCI_DEBUG
bool "PCI Debugging" bool "PCI Debugging"
...@@ -69,3 +69,10 @@ config PCI_IOV ...@@ -69,3 +69,10 @@ config PCI_IOV
physical resources. physical resources.
If unsure, say N. If unsure, say N.
config PCI_IOAPIC
bool
depends on PCI
depends on ACPI
depends on HOTPLUG
default y
...@@ -14,6 +14,8 @@ CFLAGS_legacy.o += -Wno-deprecated-declarations ...@@ -14,6 +14,8 @@ CFLAGS_legacy.o += -Wno-deprecated-declarations
# Build PCI Express stuff if needed # Build PCI Express stuff if needed
obj-$(CONFIG_PCIEPORTBUS) += pcie/ obj-$(CONFIG_PCIEPORTBUS) += pcie/
obj-$(CONFIG_PCI_IOAPIC) += ioapic.o
obj-$(CONFIG_HOTPLUG) += hotplug.o obj-$(CONFIG_HOTPLUG) += hotplug.o
# Build the PCI Hotplug drivers if we were asked to # Build the PCI Hotplug drivers if we were asked to
......
...@@ -320,7 +320,7 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev) ...@@ -320,7 +320,7 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev)
for (bus = dev->bus; bus; bus = bus->parent) { for (bus = dev->bus; bus; bus = bus->parent) {
struct pci_dev *bridge = bus->self; struct pci_dev *bridge = bus->self;
if (!bridge || !bridge->is_pcie || if (!bridge || !pci_is_pcie(bridge) ||
bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
return 0; return 0;
...@@ -645,8 +645,11 @@ void __init detect_intel_iommu(void) ...@@ -645,8 +645,11 @@ void __init detect_intel_iommu(void)
"x2apic and Intr-remapping.\n"); "x2apic and Intr-remapping.\n");
#endif #endif
#ifdef CONFIG_DMAR #ifdef CONFIG_DMAR
if (ret && !no_iommu && !iommu_detected && !dmar_disabled) if (ret && !no_iommu && !iommu_detected && !dmar_disabled) {
iommu_detected = 1; iommu_detected = 1;
/* Make sure ACS will be enabled */
pci_request_acs();
}
#endif #endif
#ifdef CONFIG_X86 #ifdef CONFIG_X86
if (ret) if (ret)
......
...@@ -6,18 +6,22 @@ obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o ...@@ -6,18 +6,22 @@ obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o
obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o
obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o
# pciehp should be linked before acpiphp in order to allow the native driver # native drivers should be linked before acpiphp in order to allow the
# to attempt to bind first. We can then fall back to generic support. # native driver to attempt to bind first. We can then fall back to
# generic support.
obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o
obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o
obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o
obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o
obj-$(CONFIG_HOTPLUG_PCI_SGI) += sgi_hotplug.o obj-$(CONFIG_HOTPLUG_PCI_SGI) += sgi_hotplug.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
# acpiphp_ibm extends acpiphp, so should be linked afterwards.
obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o
# Link this last so it doesn't claim devices that have a real hotplug driver # Link this last so it doesn't claim devices that have a real hotplug driver
obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o
......
...@@ -362,6 +362,8 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) ...@@ -362,6 +362,8 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
status = acpi_pci_osc_control_set(handle, flags); status = acpi_pci_osc_control_set(handle, flags);
if (ACPI_SUCCESS(status)) if (ACPI_SUCCESS(status))
goto got_one; goto got_one;
if (status == AE_SUPPORT)
goto no_control;
kfree(string.pointer); kfree(string.pointer);
string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL }; string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL };
} }
...@@ -394,10 +396,9 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) ...@@ -394,10 +396,9 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
break; break;
} }
no_control:
dbg("Cannot get control of hotplug hardware for pci %s\n", dbg("Cannot get control of hotplug hardware for pci %s\n",
pci_name(pdev)); pci_name(pdev));
kfree(string.pointer); kfree(string.pointer);
return -ENODEV; return -ENODEV;
got_one: got_one:
......
...@@ -146,12 +146,6 @@ struct acpiphp_attention_info ...@@ -146,12 +146,6 @@ struct acpiphp_attention_info
struct module *owner; struct module *owner;
}; };
struct acpiphp_ioapic {
struct pci_dev *dev;
u32 gsi_base;
struct list_head list;
};
/* PCI bus bridge HID */ /* PCI bus bridge HID */
#define ACPI_PCI_HOST_HID "PNP0A03" #define ACPI_PCI_HOST_HID "PNP0A03"
......
This diff is collapsed.
...@@ -890,7 +890,7 @@ static int poll_hpc(void *data) ...@@ -890,7 +890,7 @@ static int poll_hpc(void *data)
msleep(POLL_INTERVAL_SEC * 1000); msleep(POLL_INTERVAL_SEC * 1000);
if (kthread_should_stop()) if (kthread_should_stop())
break; goto out_sleep;
down (&semOperations); down (&semOperations);
...@@ -904,6 +904,7 @@ static int poll_hpc(void *data) ...@@ -904,6 +904,7 @@ static int poll_hpc(void *data)
/* give up the hardware semaphore */ /* give up the hardware semaphore */
up (&semOperations); up (&semOperations);
/* sleep for a short time just for good measure */ /* sleep for a short time just for good measure */
out_sleep:
msleep(100); msleep(100);
} }
up (&sem_exit); up (&sem_exit);
......
...@@ -68,26 +68,26 @@ static DEFINE_MUTEX(pci_hp_mutex); ...@@ -68,26 +68,26 @@ static DEFINE_MUTEX(pci_hp_mutex);
static char *pci_bus_speed_strings[] = { static char *pci_bus_speed_strings[] = {
"33 MHz PCI", /* 0x00 */ "33 MHz PCI", /* 0x00 */
"66 MHz PCI", /* 0x01 */ "66 MHz PCI", /* 0x01 */
"66 MHz PCIX", /* 0x02 */ "66 MHz PCI-X", /* 0x02 */
"100 MHz PCIX", /* 0x03 */ "100 MHz PCI-X", /* 0x03 */
"133 MHz PCIX", /* 0x04 */ "133 MHz PCI-X", /* 0x04 */
NULL, /* 0x05 */ NULL, /* 0x05 */
NULL, /* 0x06 */ NULL, /* 0x06 */
NULL, /* 0x07 */ NULL, /* 0x07 */
NULL, /* 0x08 */ NULL, /* 0x08 */
"66 MHz PCIX 266", /* 0x09 */ "66 MHz PCI-X 266", /* 0x09 */
"100 MHz PCIX 266", /* 0x0a */ "100 MHz PCI-X 266", /* 0x0a */
"133 MHz PCIX 266", /* 0x0b */ "133 MHz PCI-X 266", /* 0x0b */
NULL, /* 0x0c */ NULL, /* 0x0c */
NULL, /* 0x0d */ NULL, /* 0x0d */
NULL, /* 0x0e */ NULL, /* 0x0e */
NULL, /* 0x0f */ NULL, /* 0x0f */
NULL, /* 0x10 */ NULL, /* 0x10 */
"66 MHz PCIX 533", /* 0x11 */ "66 MHz PCI-X 533", /* 0x11 */
"100 MHz PCIX 533", /* 0x12 */ "100 MHz PCI-X 533", /* 0x12 */
"133 MHz PCIX 533", /* 0x13 */ "133 MHz PCI-X 533", /* 0x13 */
"2.5 GT/s PCI-E", /* 0x14 */ "2.5 GT/s PCIe", /* 0x14 */
"5.0 GT/s PCI-E", /* 0x15 */ "5.0 GT/s PCIe", /* 0x15 */
}; };
#ifdef CONFIG_HOTPLUG_PCI_CPCI #ifdef CONFIG_HOTPLUG_PCI_CPCI
......
...@@ -91,7 +91,6 @@ struct controller { ...@@ -91,7 +91,6 @@ struct controller {
struct slot *slot; struct slot *slot;
wait_queue_head_t queue; /* sleep & wake process */ wait_queue_head_t queue; /* sleep & wake process */
u32 slot_cap; u32 slot_cap;
u8 cap_base;
struct timer_list poll_timer; struct timer_list poll_timer;
unsigned int cmd_busy:1; unsigned int cmd_busy:1;
unsigned int no_cmd_complete:1; unsigned int no_cmd_complete:1;
......
...@@ -87,7 +87,8 @@ static int __init dummy_probe(struct pcie_device *dev) ...@@ -87,7 +87,8 @@ static int __init dummy_probe(struct pcie_device *dev)
/* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */ /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */
if (pciehp_get_hp_hw_control_from_firmware(pdev)) if (pciehp_get_hp_hw_control_from_firmware(pdev))
return -ENODEV; return -ENODEV;
if (!(pos = pci_find_capability(pdev, PCI_CAP_ID_EXP))) pos = pci_pcie_cap(pdev);
if (!pos)
return -ENODEV; return -ENODEV;
pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, &slot_cap); pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, &slot_cap);
slot = kzalloc(sizeof(*slot), GFP_KERNEL); slot = kzalloc(sizeof(*slot), GFP_KERNEL);
......
...@@ -72,18 +72,6 @@ static int get_adapter_status (struct hotplug_slot *slot, u8 *value); ...@@ -72,18 +72,6 @@ static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
.set_attention_status = set_attention_status,
.enable_slot = enable_slot,
.disable_slot = disable_slot,
.get_power_status = get_power_status,
.get_attention_status = get_attention_status,
.get_latch_status = get_latch_status,
.get_adapter_status = get_adapter_status,
.get_max_bus_speed = get_max_bus_speed,
.get_cur_bus_speed = get_cur_bus_speed,
};
/** /**
* release_slot - free up the memory used by a slot * release_slot - free up the memory used by a slot
* @hotplug_slot: slot to free * @hotplug_slot: slot to free
...@@ -95,6 +83,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot) ...@@ -95,6 +83,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
__func__, hotplug_slot_name(hotplug_slot)); __func__, hotplug_slot_name(hotplug_slot));
kfree(hotplug_slot->ops);
kfree(hotplug_slot->info); kfree(hotplug_slot->info);
kfree(hotplug_slot); kfree(hotplug_slot);
} }
...@@ -104,6 +93,7 @@ static int init_slot(struct controller *ctrl) ...@@ -104,6 +93,7 @@ static int init_slot(struct controller *ctrl)
struct slot *slot = ctrl->slot; struct slot *slot = ctrl->slot;
struct hotplug_slot *hotplug = NULL; struct hotplug_slot *hotplug = NULL;
struct hotplug_slot_info *info = NULL; struct hotplug_slot_info *info = NULL;
struct hotplug_slot_ops *ops = NULL;
char name[SLOT_NAME_SIZE]; char name[SLOT_NAME_SIZE];
int retval = -ENOMEM; int retval = -ENOMEM;
...@@ -115,11 +105,28 @@ static int init_slot(struct controller *ctrl) ...@@ -115,11 +105,28 @@ static int init_slot(struct controller *ctrl)
if (!info) if (!info)
goto out; goto out;
/* Setup hotplug slot ops */
ops = kzalloc(sizeof(*ops), GFP_KERNEL);
if (!ops)
goto out;
ops->enable_slot = enable_slot;
ops->disable_slot = disable_slot;
ops->get_power_status = get_power_status;
ops->get_adapter_status = get_adapter_status;
ops->get_max_bus_speed = get_max_bus_speed;
ops->get_cur_bus_speed = get_cur_bus_speed;
if (MRL_SENS(ctrl))
ops->get_latch_status = get_latch_status;
if (ATTN_LED(ctrl)) {
ops->get_attention_status = get_attention_status;
ops->set_attention_status = set_attention_status;
}
/* register this slot with the hotplug pci core */ /* register this slot with the hotplug pci core */
hotplug->info = info; hotplug->info = info;
hotplug->private = slot; hotplug->private = slot;
hotplug->release = &release_slot; hotplug->release = &release_slot;
hotplug->ops = &pciehp_hotplug_slot_ops; hotplug->ops = ops;
slot->hotplug_slot = hotplug; slot->hotplug_slot = hotplug;
snprintf(name, SLOT_NAME_SIZE, "%u", PSN(ctrl)); snprintf(name, SLOT_NAME_SIZE, "%u", PSN(ctrl));
...@@ -128,17 +135,12 @@ static int init_slot(struct controller *ctrl) ...@@ -128,17 +135,12 @@ static int init_slot(struct controller *ctrl)
ctrl->pcie->port->subordinate->number, PSN(ctrl)); ctrl->pcie->port->subordinate->number, PSN(ctrl));
retval = pci_hp_register(hotplug, retval = pci_hp_register(hotplug,
ctrl->pcie->port->subordinate, 0, name); ctrl->pcie->port->subordinate, 0, name);
if (retval) { if (retval)
ctrl_err(ctrl, ctrl_err(ctrl,
"pci_hp_register failed with error %d\n", retval); "pci_hp_register failed with error %d\n", retval);
goto out;
}
get_power_status(hotplug, &info->power_status);
get_attention_status(hotplug, &info->attention_status);
get_latch_status(hotplug, &info->latch_status);
get_adapter_status(hotplug, &info->adapter_status);
out: out:
if (retval) { if (retval) {
kfree(ops);
kfree(info); kfree(info);
kfree(hotplug); kfree(hotplug);
} }
...@@ -160,12 +162,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) ...@@ -160,12 +162,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
__func__, slot_name(slot)); __func__, slot_name(slot));
hotplug_slot->info->attention_status = status; return pciehp_set_attention_status(slot, status);
if (ATTN_LED(slot->ctrl))
pciehp_set_attention_status(slot, status);
return 0;
} }
...@@ -193,92 +190,62 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) ...@@ -193,92 +190,62 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
{ {
struct slot *slot = hotplug_slot->private; struct slot *slot = hotplug_slot->private;
int retval;
ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
__func__, slot_name(slot)); __func__, slot_name(slot));
retval = pciehp_get_power_status(slot, value); return pciehp_get_power_status(slot, value);
if (retval < 0)
*value = hotplug_slot->info->power_status;
return 0;
} }
static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
{ {
struct slot *slot = hotplug_slot->private; struct slot *slot = hotplug_slot->private;
int retval;
ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
__func__, slot_name(slot)); __func__, slot_name(slot));
retval = pciehp_get_attention_status(slot, value); return pciehp_get_attention_status(slot, value);
if (retval < 0)
*value = hotplug_slot->info->attention_status;
return 0;
} }
static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
{ {
struct slot *slot = hotplug_slot->private; struct slot *slot = hotplug_slot->private;
int retval;
ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
__func__, slot_name(slot)); __func__, slot_name(slot));
retval = pciehp_get_latch_status(slot, value); return pciehp_get_latch_status(slot, value);
if (retval < 0)
*value = hotplug_slot->info->latch_status;
return 0;
} }
static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
{ {
struct slot *slot = hotplug_slot->private; struct slot *slot = hotplug_slot->private;
int retval;
ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
__func__, slot_name(slot)); __func__, slot_name(slot));
retval = pciehp_get_adapter_status(slot, value); return pciehp_get_adapter_status(slot, value);
if (retval < 0)
*value = hotplug_slot->info->adapter_status;
return 0;
} }
static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
enum pci_bus_speed *value) enum pci_bus_speed *value)
{ {
struct slot *slot = hotplug_slot->private; struct slot *slot = hotplug_slot->private;
int retval;
ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
__func__, slot_name(slot)); __func__, slot_name(slot));
retval = pciehp_get_max_link_speed(slot, value); return pciehp_get_max_link_speed(slot, value);
if (retval < 0)
*value = PCI_SPEED_UNKNOWN;
return 0;
} }
static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
{ {
struct slot *slot = hotplug_slot->private; struct slot *slot = hotplug_slot->private;
int retval;
ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
__func__, slot_name(slot)); __func__, slot_name(slot));
retval = pciehp_get_cur_link_speed(slot, value); return pciehp_get_cur_link_speed(slot, value);
if (retval < 0)
*value = PCI_SPEED_UNKNOWN;
return 0;
} }
static int pciehp_probe(struct pcie_device *dev) static int pciehp_probe(struct pcie_device *dev)
...@@ -286,14 +253,13 @@ static int pciehp_probe(struct pcie_device *dev) ...@@ -286,14 +253,13 @@ static int pciehp_probe(struct pcie_device *dev)
int rc; int rc;
struct controller *ctrl; struct controller *ctrl;
struct slot *slot; struct slot *slot;
u8 value; u8 occupied, poweron;
struct pci_dev *pdev = dev->port;
if (pciehp_force) if (pciehp_force)
dev_info(&dev->device, dev_info(&dev->device,
"Bypassing BIOS check for pciehp use on %s\n", "Bypassing BIOS check for pciehp use on %s\n",
pci_name(pdev)); pci_name(dev->port));
else if (pciehp_get_hp_hw_control_from_firmware(pdev)) else if (pciehp_get_hp_hw_control_from_firmware(dev->port))
goto err_out_none; goto err_out_none;
ctrl = pcie_init(dev); ctrl = pcie_init(dev);
...@@ -318,23 +284,18 @@ static int pciehp_probe(struct pcie_device *dev) ...@@ -318,23 +284,18 @@ static int pciehp_probe(struct pcie_device *dev)
rc = pcie_init_notification(ctrl); rc = pcie_init_notification(ctrl);
if (rc) { if (rc) {
ctrl_err(ctrl, "Notification initialization failed\n"); ctrl_err(ctrl, "Notification initialization failed\n");
goto err_out_release_ctlr; goto err_out_free_ctrl_slot;
} }
/* Check if slot is occupied */ /* Check if slot is occupied */
slot = ctrl->slot; slot = ctrl->slot;
pciehp_get_adapter_status(slot, &value); pciehp_get_adapter_status(slot, &occupied);
if (value) { pciehp_get_power_status(slot, &poweron);
if (pciehp_force) if (occupied && pciehp_force)
pciehp_enable_slot(slot); pciehp_enable_slot(slot);
} else { /* If empty slot's power status is on, turn power off */
/* Power off slot if not occupied */ if (!occupied && poweron && POWER_CTRL(ctrl))
if (POWER_CTRL(ctrl)) { pciehp_power_off_slot(slot);
rc = pciehp_power_off_slot(slot);
if (rc)
goto err_out_free_ctrl_slot;
}
}
return 0; return 0;
......
...@@ -142,23 +142,9 @@ u8 pciehp_handle_power_fault(struct slot *p_slot) ...@@ -142,23 +142,9 @@ u8 pciehp_handle_power_fault(struct slot *p_slot)
/* power fault */ /* power fault */
ctrl_dbg(ctrl, "Power fault interrupt received\n"); ctrl_dbg(ctrl, "Power fault interrupt received\n");
ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
if (!pciehp_query_power_fault(p_slot)) { event_type = INT_POWER_FAULT;
/* ctrl_info(ctrl, "Power fault bit %x set\n", 0);
* power fault Cleared
*/
ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n",
slot_name(p_slot));
event_type = INT_POWER_FAULT_CLEAR;
} else {
/*
* power fault
*/
ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot));
event_type = INT_POWER_FAULT;
ctrl_info(ctrl, "Power fault bit %x set\n", 0);
}
queue_interrupt_event(p_slot, event_type); queue_interrupt_event(p_slot, event_type);
return 1; return 1;
...@@ -224,13 +210,12 @@ static int board_added(struct slot *p_slot) ...@@ -224,13 +210,12 @@ static int board_added(struct slot *p_slot)
retval = pciehp_check_link_status(ctrl); retval = pciehp_check_link_status(ctrl);
if (retval) { if (retval) {
ctrl_err(ctrl, "Failed to check link status\n"); ctrl_err(ctrl, "Failed to check link status\n");
set_slot_off(ctrl, p_slot); goto err_exit;
return retval;
} }
/* Check for a power fault */ /* Check for a power fault */
if (pciehp_query_power_fault(p_slot)) { if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) {
ctrl_dbg(ctrl, "Power fault detected\n"); ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
retval = -EIO; retval = -EIO;
goto err_exit; goto err_exit;
} }
...@@ -363,25 +348,6 @@ void pciehp_queue_pushbutton_work(struct work_struct *work) ...@@ -363,25 +348,6 @@ void pciehp_queue_pushbutton_work(struct work_struct *work)
mutex_unlock(&p_slot->lock); mutex_unlock(&p_slot->lock);
} }
static int update_slot_info(struct slot *slot)
{
struct hotplug_slot_info *info;
int result;
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
pciehp_get_power_status(slot, &info->power_status);
pciehp_get_attention_status(slot, &info->attention_status);
pciehp_get_latch_status(slot, &info->latch_status);
pciehp_get_adapter_status(slot, &info->adapter_status);
result = pci_hp_change_slot_info(slot->hotplug_slot, info);
kfree (info);
return result;
}
/* /*
* Note: This function must be called with slot->lock held * Note: This function must be called with slot->lock held
*/ */
...@@ -442,7 +408,6 @@ static void handle_button_press_event(struct slot *p_slot) ...@@ -442,7 +408,6 @@ static void handle_button_press_event(struct slot *p_slot)
* to hot-add or hot-remove is undergoing * to hot-add or hot-remove is undergoing
*/ */
ctrl_info(ctrl, "Button ignore on Slot(%s)\n", slot_name(p_slot)); ctrl_info(ctrl, "Button ignore on Slot(%s)\n", slot_name(p_slot));
update_slot_info(p_slot);
break; break;
default: default:
ctrl_warn(ctrl, "Not a valid state\n"); ctrl_warn(ctrl, "Not a valid state\n");
...@@ -500,11 +465,9 @@ static void interrupt_event_handler(struct work_struct *work) ...@@ -500,11 +465,9 @@ static void interrupt_event_handler(struct work_struct *work)
if (!HP_SUPR_RM(ctrl)) if (!HP_SUPR_RM(ctrl))
break; break;
ctrl_dbg(ctrl, "Surprise Removal\n"); ctrl_dbg(ctrl, "Surprise Removal\n");
update_slot_info(p_slot);
handle_surprise_event(p_slot); handle_surprise_event(p_slot);
break; break;
default: default:
update_slot_info(p_slot);
break; break;
} }
mutex_unlock(&p_slot->lock); mutex_unlock(&p_slot->lock);
...@@ -547,9 +510,6 @@ int pciehp_enable_slot(struct slot *p_slot) ...@@ -547,9 +510,6 @@ int pciehp_enable_slot(struct slot *p_slot)
if (rc) { if (rc) {
pciehp_get_latch_status(p_slot, &getstatus); pciehp_get_latch_status(p_slot, &getstatus);
} }
update_slot_info(p_slot);
return rc; return rc;
} }
...@@ -590,10 +550,7 @@ int pciehp_disable_slot(struct slot *p_slot) ...@@ -590,10 +550,7 @@ int pciehp_disable_slot(struct slot *p_slot)
} }
} }
ret = remove_board(p_slot); return remove_board(p_slot);
update_slot_info(p_slot);
return ret;
} }
int pciehp_sysfs_enable_slot(struct slot *p_slot) int pciehp_sysfs_enable_slot(struct slot *p_slot)
......
...@@ -45,25 +45,25 @@ static atomic_t pciehp_num_controllers = ATOMIC_INIT(0); ...@@ -45,25 +45,25 @@ static atomic_t pciehp_num_controllers = ATOMIC_INIT(0);
static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value) static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value)
{ {
struct pci_dev *dev = ctrl->pcie->port; struct pci_dev *dev = ctrl->pcie->port;
return pci_read_config_word(dev, ctrl->cap_base + reg, value); return pci_read_config_word(dev, pci_pcie_cap(dev) + reg, value);
} }
static inline int pciehp_readl(struct controller *ctrl, int reg, u32 *value) static inline int pciehp_readl(struct controller *ctrl, int reg, u32 *value)
{ {
struct pci_dev *dev = ctrl->pcie->port; struct pci_dev *dev = ctrl->pcie->port;
return pci_read_config_dword(dev, ctrl->cap_base + reg, value); return pci_read_config_dword(dev, pci_pcie_cap(dev) + reg, value);
} }
static inline int pciehp_writew(struct controller *ctrl, int reg, u16 value) static inline int pciehp_writew(struct controller *ctrl, int reg, u16 value)
{ {
struct pci_dev *dev = ctrl->pcie->port; struct pci_dev *dev = ctrl->pcie->port;
return pci_write_config_word(dev, ctrl->cap_base + reg, value); return pci_write_config_word(dev, pci_pcie_cap(dev) + reg, value);
} }
static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value)
{ {
struct pci_dev *dev = ctrl->pcie->port; struct pci_dev *dev = ctrl->pcie->port;
return pci_write_config_dword(dev, ctrl->cap_base + reg, value); return pci_write_config_dword(dev, pci_pcie_cap(dev) + reg, value);
} }
/* Power Control Command */ /* Power Control Command */
...@@ -318,8 +318,8 @@ int pciehp_get_attention_status(struct slot *slot, u8 *status) ...@@ -318,8 +318,8 @@ int pciehp_get_attention_status(struct slot *slot, u8 *status)
return retval; return retval;
} }
ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", __func__,
__func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_ctrl); pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl);
atten_led_state = (slot_ctrl & PCI_EXP_SLTCTL_AIC) >> 6; atten_led_state = (slot_ctrl & PCI_EXP_SLTCTL_AIC) >> 6;
...@@ -356,8 +356,8 @@ int pciehp_get_power_status(struct slot *slot, u8 *status) ...@@ -356,8 +356,8 @@ int pciehp_get_power_status(struct slot *slot, u8 *status)
ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__);
return retval; return retval;
} }
ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", __func__,
__func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_ctrl); pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl);
pwr_state = (slot_ctrl & PCI_EXP_SLTCTL_PCC) >> 10; pwr_state = (slot_ctrl & PCI_EXP_SLTCTL_PCC) >> 10;
...@@ -427,27 +427,24 @@ int pciehp_set_attention_status(struct slot *slot, u8 value) ...@@ -427,27 +427,24 @@ int pciehp_set_attention_status(struct slot *slot, u8 value)
struct controller *ctrl = slot->ctrl; struct controller *ctrl = slot->ctrl;
u16 slot_cmd; u16 slot_cmd;
u16 cmd_mask; u16 cmd_mask;
int rc;
cmd_mask = PCI_EXP_SLTCTL_AIC; cmd_mask = PCI_EXP_SLTCTL_AIC;
switch (value) { switch (value) {
case 0 : /* turn off */ case 0 : /* turn off */
slot_cmd = 0x00C0; slot_cmd = 0x00C0;
break; break;
case 1: /* turn on */ case 1: /* turn on */
slot_cmd = 0x0040; slot_cmd = 0x0040;
break; break;
case 2: /* turn blink */ case 2: /* turn blink */
slot_cmd = 0x0080; slot_cmd = 0x0080;
break; break;
default: default:
return -1; return -EINVAL;
} }
rc = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
__func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); return pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
return rc;
} }
void pciehp_green_led_on(struct slot *slot) void pciehp_green_led_on(struct slot *slot)
...@@ -459,8 +456,8 @@ void pciehp_green_led_on(struct slot *slot) ...@@ -459,8 +456,8 @@ void pciehp_green_led_on(struct slot *slot)
slot_cmd = 0x0100; slot_cmd = 0x0100;
cmd_mask = PCI_EXP_SLTCTL_PIC; cmd_mask = PCI_EXP_SLTCTL_PIC;
pcie_write_cmd(ctrl, slot_cmd, cmd_mask); pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
__func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
} }
void pciehp_green_led_off(struct slot *slot) void pciehp_green_led_off(struct slot *slot)
...@@ -472,8 +469,8 @@ void pciehp_green_led_off(struct slot *slot) ...@@ -472,8 +469,8 @@ void pciehp_green_led_off(struct slot *slot)
slot_cmd = 0x0300; slot_cmd = 0x0300;
cmd_mask = PCI_EXP_SLTCTL_PIC; cmd_mask = PCI_EXP_SLTCTL_PIC;
pcie_write_cmd(ctrl, slot_cmd, cmd_mask); pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
__func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
} }
void pciehp_green_led_blink(struct slot *slot) void pciehp_green_led_blink(struct slot *slot)
...@@ -485,8 +482,8 @@ void pciehp_green_led_blink(struct slot *slot) ...@@ -485,8 +482,8 @@ void pciehp_green_led_blink(struct slot *slot)
slot_cmd = 0x0200; slot_cmd = 0x0200;
cmd_mask = PCI_EXP_SLTCTL_PIC; cmd_mask = PCI_EXP_SLTCTL_PIC;
pcie_write_cmd(ctrl, slot_cmd, cmd_mask); pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
__func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
} }
int pciehp_power_on_slot(struct slot * slot) int pciehp_power_on_slot(struct slot * slot)
...@@ -514,97 +511,38 @@ int pciehp_power_on_slot(struct slot * slot) ...@@ -514,97 +511,38 @@ int pciehp_power_on_slot(struct slot * slot)
return retval; return retval;
} }
} }
ctrl->power_fault_detected = 0;
slot_cmd = POWER_ON; slot_cmd = POWER_ON;
cmd_mask = PCI_EXP_SLTCTL_PCC; cmd_mask = PCI_EXP_SLTCTL_PCC;
if (!pciehp_poll_mode) {
/* Enable power fault detection turned off at power off time */
slot_cmd |= PCI_EXP_SLTCTL_PFDE;
cmd_mask |= PCI_EXP_SLTCTL_PFDE;
}
retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
if (retval) { if (retval) {
ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd); ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd);
return retval; return retval;
} }
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
__func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
ctrl->power_fault_detected = 0;
return retval; return retval;
} }
static inline int pcie_mask_bad_dllp(struct controller *ctrl)
{
struct pci_dev *dev = ctrl->pcie->port;
int pos;
u32 reg;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (!pos)
return 0;
pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
if (reg & PCI_ERR_COR_BAD_DLLP)
return 0;
reg |= PCI_ERR_COR_BAD_DLLP;
pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
return 1;
}
static inline void pcie_unmask_bad_dllp(struct controller *ctrl)
{
struct pci_dev *dev = ctrl->pcie->port;
u32 reg;
int pos;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (!pos)
return;
pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
if (!(reg & PCI_ERR_COR_BAD_DLLP))
return;
reg &= ~PCI_ERR_COR_BAD_DLLP;
pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
}
int pciehp_power_off_slot(struct slot * slot) int pciehp_power_off_slot(struct slot * slot)
{ {
struct controller *ctrl = slot->ctrl; struct controller *ctrl = slot->ctrl;
u16 slot_cmd; u16 slot_cmd;
u16 cmd_mask; u16 cmd_mask;
int retval = 0; int retval;
int changed;
/*
* Set Bad DLLP Mask bit in Correctable Error Mask
* Register. This is the workaround against Bad DLLP error
* that sometimes happens during turning power off the slot
* which conforms to PCI Express 1.0a spec.
*/
changed = pcie_mask_bad_dllp(ctrl);
slot_cmd = POWER_OFF; slot_cmd = POWER_OFF;
cmd_mask = PCI_EXP_SLTCTL_PCC; cmd_mask = PCI_EXP_SLTCTL_PCC;
if (!pciehp_poll_mode) {
/* Disable power fault detection */
slot_cmd &= ~PCI_EXP_SLTCTL_PFDE;
cmd_mask |= PCI_EXP_SLTCTL_PFDE;
}
retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
if (retval) { if (retval) {
ctrl_err(ctrl, "Write command failed!\n"); ctrl_err(ctrl, "Write command failed!\n");
retval = -1; return retval;
goto out;
} }
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
__func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
out: return 0;
if (changed)
pcie_unmask_bad_dllp(ctrl);
return retval;
} }
static irqreturn_t pcie_isr(int irq, void *dev_id) static irqreturn_t pcie_isr(int irq, void *dev_id)
...@@ -840,11 +778,19 @@ int pcie_enable_notification(struct controller *ctrl) ...@@ -840,11 +778,19 @@ int pcie_enable_notification(struct controller *ctrl)
{ {
u16 cmd, mask; u16 cmd, mask;
/*
* TBD: Power fault detected software notification support.
*
* Power fault detected software notification is not enabled
* now, because it caused power fault detected interrupt storm
* on some machines. On those machines, power fault detected
* bit in the slot status register was set again immediately
* when it is cleared in the interrupt service routine, and
* next power fault detected interrupt was notified again.
*/
cmd = PCI_EXP_SLTCTL_PDCE; cmd = PCI_EXP_SLTCTL_PDCE;
if (ATTN_BUTTN(ctrl)) if (ATTN_BUTTN(ctrl))
cmd |= PCI_EXP_SLTCTL_ABPE; cmd |= PCI_EXP_SLTCTL_ABPE;
if (POWER_CTRL(ctrl))
cmd |= PCI_EXP_SLTCTL_PFDE;
if (MRL_SENS(ctrl)) if (MRL_SENS(ctrl))
cmd |= PCI_EXP_SLTCTL_MRLSCE; cmd |= PCI_EXP_SLTCTL_MRLSCE;
if (!pciehp_poll_mode) if (!pciehp_poll_mode)
...@@ -866,7 +812,8 @@ static void pcie_disable_notification(struct controller *ctrl) ...@@ -866,7 +812,8 @@ static void pcie_disable_notification(struct controller *ctrl)
u16 mask; u16 mask;
mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE | mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE |
PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE |
PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE); PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE |
PCI_EXP_SLTCTL_DLLSCE);
if (pcie_write_cmd(ctrl, 0, mask)) if (pcie_write_cmd(ctrl, 0, mask))
ctrl_warn(ctrl, "Cannot disable software notification\n"); ctrl_warn(ctrl, "Cannot disable software notification\n");
} }
...@@ -934,7 +881,8 @@ static inline void dbg_ctrl(struct controller *ctrl) ...@@ -934,7 +881,8 @@ static inline void dbg_ctrl(struct controller *ctrl)
pdev->subsystem_device); pdev->subsystem_device);
ctrl_info(ctrl, " Subsystem Vendor ID : 0x%04x\n", ctrl_info(ctrl, " Subsystem Vendor ID : 0x%04x\n",
pdev->subsystem_vendor); pdev->subsystem_vendor);
ctrl_info(ctrl, " PCIe Cap offset : 0x%02x\n", ctrl->cap_base); ctrl_info(ctrl, " PCIe Cap offset : 0x%02x\n",
pci_pcie_cap(pdev));
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
if (!pci_resource_len(pdev, i)) if (!pci_resource_len(pdev, i))
continue; continue;
...@@ -978,8 +926,7 @@ struct controller *pcie_init(struct pcie_device *dev) ...@@ -978,8 +926,7 @@ struct controller *pcie_init(struct pcie_device *dev)
goto abort; goto abort;
} }
ctrl->pcie = dev; ctrl->pcie = dev;
ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP); if (!pci_pcie_cap(pdev)) {
if (!ctrl->cap_base) {
ctrl_err(ctrl, "Cannot find PCI Express capability\n"); ctrl_err(ctrl, "Cannot find PCI Express capability\n");
goto abort_ctrl; goto abort_ctrl;
} }
......
...@@ -43,7 +43,7 @@ static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp) ...@@ -43,7 +43,7 @@ static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp)
* Perhaps we *should* use default settings for PCIe, but * Perhaps we *should* use default settings for PCIe, but
* pciehp didn't, so we won't either. * pciehp didn't, so we won't either.
*/ */
if (dev->is_pcie) if (pci_is_pcie(dev))
return; return;
dev_info(&dev->dev, "using default PCI settings\n"); dev_info(&dev->dev, "using default PCI settings\n");
hpp = &pci_default_type0; hpp = &pci_default_type0;
...@@ -102,7 +102,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) ...@@ -102,7 +102,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
return; return;
/* Find PCI Express capability */ /* Find PCI Express capability */
pos = pci_find_capability(dev, PCI_CAP_ID_EXP); pos = pci_pcie_cap(dev);
if (!pos) if (!pos)
return; return;
......
...@@ -1611,7 +1611,7 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev, ...@@ -1611,7 +1611,7 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev,
return ret; return ret;
parent = parent->bus->self; parent = parent->bus->self;
} }
if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */ if (pci_is_pcie(tmp)) /* this is a PCIE-to-PCI bridge */
return domain_context_mapping_one(domain, return domain_context_mapping_one(domain,
pci_domain_nr(tmp->subordinate), pci_domain_nr(tmp->subordinate),
tmp->subordinate->number, 0, tmp->subordinate->number, 0,
...@@ -1651,7 +1651,7 @@ static int domain_context_mapped(struct pci_dev *pdev) ...@@ -1651,7 +1651,7 @@ static int domain_context_mapped(struct pci_dev *pdev)
return ret; return ret;
parent = parent->bus->self; parent = parent->bus->self;
} }
if (tmp->is_pcie) if (pci_is_pcie(tmp))
return device_context_mapped(iommu, tmp->subordinate->number, return device_context_mapped(iommu, tmp->subordinate->number,
0); 0);
else else
...@@ -1821,7 +1821,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) ...@@ -1821,7 +1821,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
dev_tmp = pci_find_upstream_pcie_bridge(pdev); dev_tmp = pci_find_upstream_pcie_bridge(pdev);
if (dev_tmp) { if (dev_tmp) {
if (dev_tmp->is_pcie) { if (pci_is_pcie(dev_tmp)) {
bus = dev_tmp->subordinate->number; bus = dev_tmp->subordinate->number;
devfn = 0; devfn = 0;
} else { } else {
...@@ -2182,7 +2182,7 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup) ...@@ -2182,7 +2182,7 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
* the 1:1 domain, just in _case_ one of their siblings turns out * the 1:1 domain, just in _case_ one of their siblings turns out
* not to be able to map all of memory. * not to be able to map all of memory.
*/ */
if (!pdev->is_pcie) { if (!pci_is_pcie(pdev)) {
if (!pci_is_root_bus(pdev->bus)) if (!pci_is_root_bus(pdev->bus))
return 0; return 0;
if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI) if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
...@@ -3319,7 +3319,7 @@ static void iommu_detach_dependent_devices(struct intel_iommu *iommu, ...@@ -3319,7 +3319,7 @@ static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
parent->devfn); parent->devfn);
parent = parent->bus->self; parent = parent->bus->self;
} }
if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */ if (pci_is_pcie(tmp)) /* this is a PCIE-to-PCI bridge */
iommu_detach_dev(iommu, iommu_detach_dev(iommu,
tmp->subordinate->number, 0); tmp->subordinate->number, 0);
else /* this is a legacy PCI bridge */ else /* this is a legacy PCI bridge */
......
...@@ -520,7 +520,7 @@ int set_msi_sid(struct irte *irte, struct pci_dev *dev) ...@@ -520,7 +520,7 @@ int set_msi_sid(struct irte *irte, struct pci_dev *dev)
return -1; return -1;
/* PCIe device or Root Complex integrated PCI device */ /* PCIe device or Root Complex integrated PCI device */
if (dev->is_pcie || !dev->bus->parent) { if (pci_is_pcie(dev) || !dev->bus->parent) {
set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
(dev->bus->number << 8) | dev->devfn); (dev->bus->number << 8) | dev->devfn);
return 0; return 0;
...@@ -528,7 +528,7 @@ int set_msi_sid(struct irte *irte, struct pci_dev *dev) ...@@ -528,7 +528,7 @@ int set_msi_sid(struct irte *irte, struct pci_dev *dev)
bridge = pci_find_upstream_pcie_bridge(dev); bridge = pci_find_upstream_pcie_bridge(dev);
if (bridge) { if (bridge) {
if (bridge->is_pcie) /* this is a PCIE-to-PCI/PCIX bridge */ if (pci_is_pcie(bridge))/* this is a PCIE-to-PCI/PCIX bridge */
set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16, set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16,
(bridge->bus->number << 8) | dev->bus->number); (bridge->bus->number << 8) | dev->bus->number);
else /* this is a legacy PCI bridge */ else /* this is a legacy PCI bridge */
......
/*
* IOAPIC/IOxAPIC/IOSAPIC driver
*
* Copyright (C) 2009 Fujitsu Limited.
* (c) Copyright 2009 Hewlett-Packard Development Company, L.P.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*
* This driver manages PCI I/O APICs added by hotplug after boot. We try to
* claim all I/O APIC PCI devices, but those present at boot were registered
* when we parsed the ACPI MADT, so we'll fail when we try to re-register
* them.
*/
#include <linux/pci.h>
#include <linux/acpi.h>
#include <acpi/acpi_bus.h>
struct ioapic {
acpi_handle handle;
u32 gsi_base;
};
static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
{
acpi_handle handle;
acpi_status status;
unsigned long long gsb;
struct ioapic *ioapic;
u64 addr;
int ret;
char *type;
handle = DEVICE_ACPI_HANDLE(&dev->dev);
if (!handle)
return -EINVAL;
status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);
if (ACPI_FAILURE(status))
return -EINVAL;
/*
* The previous code in acpiphp evaluated _MAT if _GSB failed, but
* ACPI spec 4.0 sec 6.2.2 requires _GSB for hot-pluggable I/O APICs.
*/
ioapic = kzalloc(sizeof(*ioapic), GFP_KERNEL);
if (!ioapic)
return -ENOMEM;
ioapic->handle = handle;
ioapic->gsi_base = (u32) gsb;
if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC)
type = "IOAPIC";
else
type = "IOxAPIC";
ret = pci_enable_device(dev);
if (ret < 0)
goto exit_free;
pci_set_master(dev);
if (pci_request_region(dev, 0, type))
goto exit_disable;
addr = pci_resource_start(dev, 0);
if (acpi_register_ioapic(ioapic->handle, addr, ioapic->gsi_base))
goto exit_release;
pci_set_drvdata(dev, ioapic);
dev_info(&dev->dev, "%s at %#llx, GSI %u\n", type, addr,
ioapic->gsi_base);
return 0;
exit_release:
pci_release_region(dev, 0);
exit_disable:
pci_disable_device(dev);
exit_free:
kfree(ioapic);
return -ENODEV;
}
static void ioapic_remove(struct pci_dev *dev)
{
struct ioapic *ioapic = pci_get_drvdata(dev);
acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base);
pci_release_region(dev, 0);
pci_disable_device(dev);
kfree(ioapic);
}
static struct pci_device_id ioapic_devices[] = {
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_SYSTEM_PIC_IOAPIC << 8, 0xffff00, },
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_SYSTEM_PIC_IOXAPIC << 8, 0xffff00, },
{ }
};
static struct pci_driver ioapic_driver = {
.name = "ioapic",
.id_table = ioapic_devices,
.probe = ioapic_probe,
.remove = __devexit_p(ioapic_remove),
};
static int __init ioapic_init(void)
{
return pci_register_driver(&ioapic_driver);
}
static void __exit ioapic_exit(void)
{
pci_unregister_driver(&ioapic_driver);
}
module_init(ioapic_init);
module_exit(ioapic_exit);
...@@ -555,7 +555,7 @@ int pci_iov_init(struct pci_dev *dev) ...@@ -555,7 +555,7 @@ int pci_iov_init(struct pci_dev *dev)
{ {
int pos; int pos;
if (!dev->is_pcie) if (!pci_is_pcie(dev))
return -ENODEV; return -ENODEV;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV);
......
...@@ -116,7 +116,7 @@ static void acpi_pci_propagate_wakeup_enable(struct pci_bus *bus, bool enable) ...@@ -116,7 +116,7 @@ static void acpi_pci_propagate_wakeup_enable(struct pci_bus *bus, bool enable)
int ret; int ret;
ret = acpi_pm_device_sleep_wake(&bridge->dev, enable); ret = acpi_pm_device_sleep_wake(&bridge->dev, enable);
if (!ret || bridge->is_pcie) if (!ret || pci_is_pcie(bridge))
return; return;
bus = bus->parent; bus = bus->parent;
} }
...@@ -131,7 +131,7 @@ static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable) ...@@ -131,7 +131,7 @@ static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable)
if (acpi_pci_can_wakeup(dev)) if (acpi_pci_can_wakeup(dev))
return acpi_pm_device_sleep_wake(&dev->dev, enable); return acpi_pm_device_sleep_wake(&dev->dev, enable);
if (!dev->is_pcie) if (!pci_is_pcie(dev))
acpi_pci_propagate_wakeup_enable(dev->bus, enable); acpi_pci_propagate_wakeup_enable(dev->bus, enable);
return 0; return 0;
......
...@@ -74,7 +74,11 @@ static ssize_t local_cpus_show(struct device *dev, ...@@ -74,7 +74,11 @@ static ssize_t local_cpus_show(struct device *dev,
const struct cpumask *mask; const struct cpumask *mask;
int len; int len;
#ifdef CONFIG_NUMA
mask = cpumask_of_node(dev_to_node(dev));
#else
mask = cpumask_of_pcibus(to_pci_dev(dev)->bus); mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
#endif
len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask); len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
buf[len++] = '\n'; buf[len++] = '\n';
buf[len] = '\0'; buf[len] = '\0';
...@@ -88,7 +92,11 @@ static ssize_t local_cpulist_show(struct device *dev, ...@@ -88,7 +92,11 @@ static ssize_t local_cpulist_show(struct device *dev,
const struct cpumask *mask; const struct cpumask *mask;
int len; int len;
#ifdef CONFIG_NUMA
mask = cpumask_of_node(dev_to_node(dev));
#else
mask = cpumask_of_pcibus(to_pci_dev(dev)->bus); mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
#endif
len = cpulist_scnprintf(buf, PAGE_SIZE-2, mask); len = cpulist_scnprintf(buf, PAGE_SIZE-2, mask);
buf[len++] = '\n'; buf[len++] = '\n';
buf[len] = '\0'; buf[len] = '\0';
...@@ -175,6 +183,21 @@ numa_node_show(struct device *dev, struct device_attribute *attr, char *buf) ...@@ -175,6 +183,21 @@ numa_node_show(struct device *dev, struct device_attribute *attr, char *buf)
} }
#endif #endif
static ssize_t
dma_mask_bits_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev = to_pci_dev(dev);
return sprintf (buf, "%d\n", fls64(pdev->dma_mask));
}
static ssize_t
consistent_dma_mask_bits_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
return sprintf (buf, "%d\n", fls64(dev->coherent_dma_mask));
}
static ssize_t static ssize_t
msi_bus_show(struct device *dev, struct device_attribute *attr, char *buf) msi_bus_show(struct device *dev, struct device_attribute *attr, char *buf)
{ {
...@@ -306,6 +329,8 @@ struct device_attribute pci_dev_attrs[] = { ...@@ -306,6 +329,8 @@ struct device_attribute pci_dev_attrs[] = {
#ifdef CONFIG_NUMA #ifdef CONFIG_NUMA
__ATTR_RO(numa_node), __ATTR_RO(numa_node),
#endif #endif
__ATTR_RO(dma_mask_bits),
__ATTR_RO(consistent_dma_mask_bits),
__ATTR(enable, 0600, is_enabled_show, is_enabled_store), __ATTR(enable, 0600, is_enabled_show, is_enabled_store),
__ATTR(broken_parity_status,(S_IRUGO|S_IWUSR), __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR),
broken_parity_status_show,broken_parity_status_store), broken_parity_status_show,broken_parity_status_store),
......
...@@ -47,6 +47,15 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE; ...@@ -47,6 +47,15 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
unsigned long pci_hotplug_io_size = DEFAULT_HOTPLUG_IO_SIZE; unsigned long pci_hotplug_io_size = DEFAULT_HOTPLUG_IO_SIZE;
unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE; unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE;
/*
* The default CLS is used if arch didn't set CLS explicitly and not
* all pci devices agree on the same value. Arch can override either
* the dfl or actual value as it sees fit. Don't forget this is
* measured in 32-bit words, not bytes.
*/
u8 pci_dfl_cache_line_size __devinitdata = L1_CACHE_BYTES >> 2;
u8 pci_cache_line_size;
/** /**
* pci_bus_max_busnr - returns maximum PCI bus number of given bus' children * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
* @bus: pointer to PCI bus structure to search * @bus: pointer to PCI bus structure to search
...@@ -373,8 +382,12 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res) ...@@ -373,8 +382,12 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
continue; /* Wrong type */ continue; /* Wrong type */
if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH)) if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH))
return r; /* Exact match */ return r; /* Exact match */
if ((res->flags & IORESOURCE_PREFETCH) && !(r->flags & IORESOURCE_PREFETCH)) /* We can't insert a non-prefetch resource inside a prefetchable parent .. */
best = r; /* Approximating prefetchable by non-prefetchable */ if (r->flags & IORESOURCE_PREFETCH)
continue;
/* .. but we can put a prefetchable resource inside a non-prefetchable one */
if (!best)
best = r;
} }
return best; return best;
} }
...@@ -728,8 +741,8 @@ static int pci_save_pcie_state(struct pci_dev *dev) ...@@ -728,8 +741,8 @@ static int pci_save_pcie_state(struct pci_dev *dev)
u16 *cap; u16 *cap;
u16 flags; u16 flags;
pos = pci_find_capability(dev, PCI_CAP_ID_EXP); pos = pci_pcie_cap(dev);
if (pos <= 0) if (!pos)
return 0; return 0;
save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
...@@ -837,7 +850,7 @@ pci_save_state(struct pci_dev *dev) ...@@ -837,7 +850,7 @@ pci_save_state(struct pci_dev *dev)
int i; int i;
/* XXX: 100% dword access ok here? */ /* XXX: 100% dword access ok here? */
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]); pci_read_config_dword(dev, i * 4, &dev->saved_config_space[i]);
dev->state_saved = true; dev->state_saved = true;
if ((i = pci_save_pcie_state(dev)) != 0) if ((i = pci_save_pcie_state(dev)) != 0)
return i; return i;
...@@ -1202,7 +1215,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable) ...@@ -1202,7 +1215,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
dev_printk(KERN_INFO, &dev->dev, "PME# %s\n", dev_printk(KERN_DEBUG, &dev->dev, "PME# %s\n",
enable ? "enabled" : "disabled"); enable ? "enabled" : "disabled");
} }
...@@ -1413,7 +1426,8 @@ void pci_pm_init(struct pci_dev *dev) ...@@ -1413,7 +1426,8 @@ void pci_pm_init(struct pci_dev *dev)
pmc &= PCI_PM_CAP_PME_MASK; pmc &= PCI_PM_CAP_PME_MASK;
if (pmc) { if (pmc) {
dev_info(&dev->dev, "PME# supported from%s%s%s%s%s\n", dev_printk(KERN_DEBUG, &dev->dev,
"PME# supported from%s%s%s%s%s\n",
(pmc & PCI_PM_CAP_PME_D0) ? " D0" : "", (pmc & PCI_PM_CAP_PME_D0) ? " D0" : "",
(pmc & PCI_PM_CAP_PME_D1) ? " D1" : "", (pmc & PCI_PM_CAP_PME_D1) ? " D1" : "",
(pmc & PCI_PM_CAP_PME_D2) ? " D2" : "", (pmc & PCI_PM_CAP_PME_D2) ? " D2" : "",
...@@ -1510,7 +1524,7 @@ void pci_enable_ari(struct pci_dev *dev) ...@@ -1510,7 +1524,7 @@ void pci_enable_ari(struct pci_dev *dev)
u16 ctrl; u16 ctrl;
struct pci_dev *bridge; struct pci_dev *bridge;
if (!dev->is_pcie || dev->devfn) if (!pci_is_pcie(dev) || dev->devfn)
return; return;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
...@@ -1518,10 +1532,10 @@ void pci_enable_ari(struct pci_dev *dev) ...@@ -1518,10 +1532,10 @@ void pci_enable_ari(struct pci_dev *dev)
return; return;
bridge = dev->bus->self; bridge = dev->bus->self;
if (!bridge || !bridge->is_pcie) if (!bridge || !pci_is_pcie(bridge))
return; return;
pos = pci_find_capability(bridge, PCI_CAP_ID_EXP); pos = pci_pcie_cap(bridge);
if (!pos) if (!pos)
return; return;
...@@ -1536,6 +1550,54 @@ void pci_enable_ari(struct pci_dev *dev) ...@@ -1536,6 +1550,54 @@ void pci_enable_ari(struct pci_dev *dev)
bridge->ari_enabled = 1; bridge->ari_enabled = 1;
} }
static int pci_acs_enable;
/**
* pci_request_acs - ask for ACS to be enabled if supported
*/
void pci_request_acs(void)
{
pci_acs_enable = 1;
}
/**
* pci_enable_acs - enable ACS if hardware support it
* @dev: the PCI device
*/
void pci_enable_acs(struct pci_dev *dev)
{
int pos;
u16 cap;
u16 ctrl;
if (!pci_acs_enable)
return;
if (!pci_is_pcie(dev))
return;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
if (!pos)
return;
pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);
pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
/* Source Validation */
ctrl |= (cap & PCI_ACS_SV);
/* P2P Request Redirect */
ctrl |= (cap & PCI_ACS_RR);
/* P2P Completion Redirect */
ctrl |= (cap & PCI_ACS_CR);
/* Upstream Forwarding */
ctrl |= (cap & PCI_ACS_UF);
pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
}
/** /**
* pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge
* @dev: the PCI device * @dev: the PCI device
...@@ -1669,9 +1731,7 @@ static int __pci_request_region(struct pci_dev *pdev, int bar, const char *res_n ...@@ -1669,9 +1731,7 @@ static int __pci_request_region(struct pci_dev *pdev, int bar, const char *res_n
return 0; return 0;
err_out: err_out:
dev_warn(&pdev->dev, "BAR %d: can't reserve %s region %pR\n", dev_warn(&pdev->dev, "BAR %d: can't reserve %pR\n", bar,
bar,
pci_resource_flags(pdev, bar) & IORESOURCE_IO ? "I/O" : "mem",
&pdev->resource[bar]); &pdev->resource[bar]);
return -EBUSY; return -EBUSY;
} }
...@@ -1866,31 +1926,6 @@ void pci_clear_master(struct pci_dev *dev) ...@@ -1866,31 +1926,6 @@ void pci_clear_master(struct pci_dev *dev)
__pci_set_master(dev, false); __pci_set_master(dev, false);
} }
#ifdef PCI_DISABLE_MWI
int pci_set_mwi(struct pci_dev *dev)
{
return 0;
}
int pci_try_set_mwi(struct pci_dev *dev)
{
return 0;
}
void pci_clear_mwi(struct pci_dev *dev)
{
}
#else
#ifndef PCI_CACHE_LINE_BYTES
#define PCI_CACHE_LINE_BYTES L1_CACHE_BYTES
#endif
/* This can be overridden by arch code. */
/* Don't forget this is measured in 32-bit words, not bytes */
u8 pci_cache_line_size = PCI_CACHE_LINE_BYTES / 4;
/** /**
* pci_set_cacheline_size - ensure the CACHE_LINE_SIZE register is programmed * pci_set_cacheline_size - ensure the CACHE_LINE_SIZE register is programmed
* @dev: the PCI device for which MWI is to be enabled * @dev: the PCI device for which MWI is to be enabled
...@@ -1901,13 +1936,12 @@ u8 pci_cache_line_size = PCI_CACHE_LINE_BYTES / 4; ...@@ -1901,13 +1936,12 @@ u8 pci_cache_line_size = PCI_CACHE_LINE_BYTES / 4;
* *
* RETURNS: An appropriate -ERRNO error value on error, or zero for success. * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
*/ */
static int int pci_set_cacheline_size(struct pci_dev *dev)
pci_set_cacheline_size(struct pci_dev *dev)
{ {
u8 cacheline_size; u8 cacheline_size;
if (!pci_cache_line_size) if (!pci_cache_line_size)
return -EINVAL; /* The system doesn't support MWI. */ return -EINVAL;
/* Validate current setting: the PCI_CACHE_LINE_SIZE must be /* Validate current setting: the PCI_CACHE_LINE_SIZE must be
equal to or multiple of the right value. */ equal to or multiple of the right value. */
...@@ -1928,6 +1962,24 @@ pci_set_cacheline_size(struct pci_dev *dev) ...@@ -1928,6 +1962,24 @@ pci_set_cacheline_size(struct pci_dev *dev)
return -EINVAL; return -EINVAL;
} }
EXPORT_SYMBOL_GPL(pci_set_cacheline_size);
#ifdef PCI_DISABLE_MWI
int pci_set_mwi(struct pci_dev *dev)
{
return 0;
}
int pci_try_set_mwi(struct pci_dev *dev)
{
return 0;
}
void pci_clear_mwi(struct pci_dev *dev)
{
}
#else
/** /**
* pci_set_mwi - enables memory-write-invalidate PCI transaction * pci_set_mwi - enables memory-write-invalidate PCI transaction
...@@ -2062,6 +2114,7 @@ pci_set_dma_mask(struct pci_dev *dev, u64 mask) ...@@ -2062,6 +2114,7 @@ pci_set_dma_mask(struct pci_dev *dev, u64 mask)
return -EIO; return -EIO;
dev->dma_mask = mask; dev->dma_mask = mask;
dev_dbg(&dev->dev, "using %dbit DMA mask\n", fls64(mask));
return 0; return 0;
} }
...@@ -2073,6 +2126,7 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) ...@@ -2073,6 +2126,7 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
return -EIO; return -EIO;
dev->dev.coherent_dma_mask = mask; dev->dev.coherent_dma_mask = mask;
dev_dbg(&dev->dev, "using %dbit consistent DMA mask\n", fls64(mask));
return 0; return 0;
} }
...@@ -2099,9 +2153,9 @@ static int pcie_flr(struct pci_dev *dev, int probe) ...@@ -2099,9 +2153,9 @@ static int pcie_flr(struct pci_dev *dev, int probe)
int i; int i;
int pos; int pos;
u32 cap; u32 cap;
u16 status; u16 status, control;
pos = pci_find_capability(dev, PCI_CAP_ID_EXP); pos = pci_pcie_cap(dev);
if (!pos) if (!pos)
return -ENOTTY; return -ENOTTY;
...@@ -2126,8 +2180,10 @@ static int pcie_flr(struct pci_dev *dev, int probe) ...@@ -2126,8 +2180,10 @@ static int pcie_flr(struct pci_dev *dev, int probe)
"proceeding with reset anyway\n"); "proceeding with reset anyway\n");
clear: clear:
pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &control);
PCI_EXP_DEVCTL_BCR_FLR); control |= PCI_EXP_DEVCTL_BCR_FLR;
pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, control);
msleep(100); msleep(100);
return 0; return 0;
...@@ -2450,7 +2506,7 @@ int pcie_get_readrq(struct pci_dev *dev) ...@@ -2450,7 +2506,7 @@ int pcie_get_readrq(struct pci_dev *dev)
int ret, cap; int ret, cap;
u16 ctl; u16 ctl;
cap = pci_find_capability(dev, PCI_CAP_ID_EXP); cap = pci_pcie_cap(dev);
if (!cap) if (!cap)
return -EINVAL; return -EINVAL;
...@@ -2480,7 +2536,7 @@ int pcie_set_readrq(struct pci_dev *dev, int rq) ...@@ -2480,7 +2536,7 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
v = (ffs(rq) - 8) << 12; v = (ffs(rq) - 8) << 12;
cap = pci_find_capability(dev, PCI_CAP_ID_EXP); cap = pci_pcie_cap(dev);
if (!cap) if (!cap)
goto out; goto out;
...@@ -2540,7 +2596,7 @@ int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type) ...@@ -2540,7 +2596,7 @@ int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type)
return reg; return reg;
} }
dev_err(&dev->dev, "BAR: invalid resource #%d\n", resno); dev_err(&dev->dev, "BAR %d: invalid resource\n", resno);
return 0; return 0;
} }
...@@ -2590,7 +2646,7 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode, ...@@ -2590,7 +2646,7 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode,
#define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE #define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE
static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0}; static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0};
spinlock_t resource_alignment_lock = SPIN_LOCK_UNLOCKED; static DEFINE_SPINLOCK(resource_alignment_lock);
/** /**
* pci_specified_resource_alignment - get resource alignment specified by user. * pci_specified_resource_alignment - get resource alignment specified by user.
......
...@@ -311,4 +311,6 @@ static inline int pci_resource_alignment(struct pci_dev *dev, ...@@ -311,4 +311,6 @@ static inline int pci_resource_alignment(struct pci_dev *dev,
return resource_alignment(res); return resource_alignment(res);
} }
extern void pci_enable_acs(struct pci_dev *dev);
#endif /* DRIVERS_PCI_H */ #endif /* DRIVERS_PCI_H */
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/stddef.h>
#include "aerdrv.h" #include "aerdrv.h"
struct aer_error_inj { struct aer_error_inj {
...@@ -35,10 +36,12 @@ struct aer_error_inj { ...@@ -35,10 +36,12 @@ struct aer_error_inj {
u32 header_log1; u32 header_log1;
u32 header_log2; u32 header_log2;
u32 header_log3; u32 header_log3;
u16 domain;
}; };
struct aer_error { struct aer_error {
struct list_head list; struct list_head list;
u16 domain;
unsigned int bus; unsigned int bus;
unsigned int devfn; unsigned int devfn;
int pos_cap_err; int pos_cap_err;
...@@ -66,22 +69,27 @@ static LIST_HEAD(pci_bus_ops_list); ...@@ -66,22 +69,27 @@ static LIST_HEAD(pci_bus_ops_list);
/* Protect einjected and pci_bus_ops_list */ /* Protect einjected and pci_bus_ops_list */
static DEFINE_SPINLOCK(inject_lock); static DEFINE_SPINLOCK(inject_lock);
static void aer_error_init(struct aer_error *err, unsigned int bus, static void aer_error_init(struct aer_error *err, u16 domain,
unsigned int devfn, int pos_cap_err) unsigned int bus, unsigned int devfn,
int pos_cap_err)
{ {
INIT_LIST_HEAD(&err->list); INIT_LIST_HEAD(&err->list);
err->domain = domain;
err->bus = bus; err->bus = bus;
err->devfn = devfn; err->devfn = devfn;
err->pos_cap_err = pos_cap_err; err->pos_cap_err = pos_cap_err;
} }
/* inject_lock must be held before calling */ /* inject_lock must be held before calling */
static struct aer_error *__find_aer_error(unsigned int bus, unsigned int devfn) static struct aer_error *__find_aer_error(u16 domain, unsigned int bus,
unsigned int devfn)
{ {
struct aer_error *err; struct aer_error *err;
list_for_each_entry(err, &einjected, list) { list_for_each_entry(err, &einjected, list) {
if (bus == err->bus && devfn == err->devfn) if (domain == err->domain &&
bus == err->bus &&
devfn == err->devfn)
return err; return err;
} }
return NULL; return NULL;
...@@ -90,7 +98,10 @@ static struct aer_error *__find_aer_error(unsigned int bus, unsigned int devfn) ...@@ -90,7 +98,10 @@ static struct aer_error *__find_aer_error(unsigned int bus, unsigned int devfn)
/* inject_lock must be held before calling */ /* inject_lock must be held before calling */
static struct aer_error *__find_aer_error_by_dev(struct pci_dev *dev) static struct aer_error *__find_aer_error_by_dev(struct pci_dev *dev)
{ {
return __find_aer_error(dev->bus->number, dev->devfn); int domain = pci_domain_nr(dev->bus);
if (domain < 0)
return NULL;
return __find_aer_error((u16)domain, dev->bus->number, dev->devfn);
} }
/* inject_lock must be held before calling */ /* inject_lock must be held before calling */
...@@ -172,11 +183,15 @@ static int pci_read_aer(struct pci_bus *bus, unsigned int devfn, int where, ...@@ -172,11 +183,15 @@ static int pci_read_aer(struct pci_bus *bus, unsigned int devfn, int where,
struct aer_error *err; struct aer_error *err;
unsigned long flags; unsigned long flags;
struct pci_ops *ops; struct pci_ops *ops;
int domain;
spin_lock_irqsave(&inject_lock, flags); spin_lock_irqsave(&inject_lock, flags);
if (size != sizeof(u32)) if (size != sizeof(u32))
goto out; goto out;
err = __find_aer_error(bus->number, devfn); domain = pci_domain_nr(bus);
if (domain < 0)
goto out;
err = __find_aer_error((u16)domain, bus->number, devfn);
if (!err) if (!err)
goto out; goto out;
...@@ -200,11 +215,15 @@ int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, int size, ...@@ -200,11 +215,15 @@ int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, int size,
unsigned long flags; unsigned long flags;
int rw1cs; int rw1cs;
struct pci_ops *ops; struct pci_ops *ops;
int domain;
spin_lock_irqsave(&inject_lock, flags); spin_lock_irqsave(&inject_lock, flags);
if (size != sizeof(u32)) if (size != sizeof(u32))
goto out; goto out;
err = __find_aer_error(bus->number, devfn); domain = pci_domain_nr(bus);
if (domain < 0)
goto out;
err = __find_aer_error((u16)domain, bus->number, devfn);
if (!err) if (!err)
goto out; goto out;
...@@ -262,7 +281,7 @@ static int pci_bus_set_aer_ops(struct pci_bus *bus) ...@@ -262,7 +281,7 @@ static int pci_bus_set_aer_ops(struct pci_bus *bus)
static struct pci_dev *pcie_find_root_port(struct pci_dev *dev) static struct pci_dev *pcie_find_root_port(struct pci_dev *dev)
{ {
while (1) { while (1) {
if (!dev->is_pcie) if (!pci_is_pcie(dev))
break; break;
if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
return dev; return dev;
...@@ -305,25 +324,25 @@ static int aer_inject(struct aer_error_inj *einj) ...@@ -305,25 +324,25 @@ static int aer_inject(struct aer_error_inj *einj)
u32 sever; u32 sever;
int ret = 0; int ret = 0;
dev = pci_get_bus_and_slot(einj->bus, devfn); dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn);
if (!dev) if (!dev)
return -EINVAL; return -ENODEV;
rpdev = pcie_find_root_port(dev); rpdev = pcie_find_root_port(dev);
if (!rpdev) { if (!rpdev) {
ret = -EINVAL; ret = -ENOTTY;
goto out_put; goto out_put;
} }
pos_cap_err = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); pos_cap_err = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (!pos_cap_err) { if (!pos_cap_err) {
ret = -EIO; ret = -ENOTTY;
goto out_put; goto out_put;
} }
pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_SEVER, &sever); pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_SEVER, &sever);
rp_pos_cap_err = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ERR); rp_pos_cap_err = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ERR);
if (!rp_pos_cap_err) { if (!rp_pos_cap_err) {
ret = -EIO; ret = -ENOTTY;
goto out_put; goto out_put;
} }
...@@ -344,7 +363,8 @@ static int aer_inject(struct aer_error_inj *einj) ...@@ -344,7 +363,8 @@ static int aer_inject(struct aer_error_inj *einj)
if (!err) { if (!err) {
err = err_alloc; err = err_alloc;
err_alloc = NULL; err_alloc = NULL;
aer_error_init(err, einj->bus, devfn, pos_cap_err); aer_error_init(err, einj->domain, einj->bus, devfn,
pos_cap_err);
list_add(&err->list, &einjected); list_add(&err->list, &einjected);
} }
err->uncor_status |= einj->uncor_status; err->uncor_status |= einj->uncor_status;
...@@ -358,7 +378,8 @@ static int aer_inject(struct aer_error_inj *einj) ...@@ -358,7 +378,8 @@ static int aer_inject(struct aer_error_inj *einj)
if (!rperr) { if (!rperr) {
rperr = rperr_alloc; rperr = rperr_alloc;
rperr_alloc = NULL; rperr_alloc = NULL;
aer_error_init(rperr, rpdev->bus->number, rpdev->devfn, aer_error_init(rperr, pci_domain_nr(rpdev->bus),
rpdev->bus->number, rpdev->devfn,
rp_pos_cap_err); rp_pos_cap_err);
list_add(&rperr->list, &einjected); list_add(&rperr->list, &einjected);
} }
...@@ -411,10 +432,11 @@ static ssize_t aer_inject_write(struct file *filp, const char __user *ubuf, ...@@ -411,10 +432,11 @@ static ssize_t aer_inject_write(struct file *filp, const char __user *ubuf,
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
if (usize < offsetof(struct aer_error_inj, domain) ||
if (usize != sizeof(struct aer_error_inj)) usize > sizeof(einj))
return -EINVAL; return -EINVAL;
memset(&einj, 0, sizeof(einj));
if (copy_from_user(&einj, ubuf, usize)) if (copy_from_user(&einj, ubuf, usize))
return -EFAULT; return -EFAULT;
...@@ -452,7 +474,7 @@ static void __exit aer_inject_exit(void) ...@@ -452,7 +474,7 @@ static void __exit aer_inject_exit(void)
} }
spin_lock_irqsave(&inject_lock, flags); spin_lock_irqsave(&inject_lock, flags);
list_for_each_entry_safe(err, err_next, &pci_bus_ops_list, list) { list_for_each_entry_safe(err, err_next, &einjected, list) {
list_del(&err->list); list_del(&err->list);
kfree(err); kfree(err);
} }
......
...@@ -53,7 +53,7 @@ static struct pci_error_handlers aer_error_handlers = { ...@@ -53,7 +53,7 @@ static struct pci_error_handlers aer_error_handlers = {
static struct pcie_port_service_driver aerdriver = { static struct pcie_port_service_driver aerdriver = {
.name = "aer", .name = "aer",
.port_type = PCIE_RC_PORT, .port_type = PCI_EXP_TYPE_ROOT_PORT,
.service = PCIE_PORT_SERVICE_AER, .service = PCIE_PORT_SERVICE_AER,
.probe = aer_probe, .probe = aer_probe,
...@@ -295,7 +295,7 @@ static void aer_error_resume(struct pci_dev *dev) ...@@ -295,7 +295,7 @@ static void aer_error_resume(struct pci_dev *dev)
u16 reg16; u16 reg16;
/* Clean up Root device status */ /* Clean up Root device status */
pos = pci_find_capability(dev, PCI_CAP_ID_EXP); pos = pci_pcie_cap(dev);
pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &reg16); pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &reg16);
pci_write_config_word(dev, pos + PCI_EXP_DEVSTA, reg16); pci_write_config_word(dev, pos + PCI_EXP_DEVSTA, reg16);
......
...@@ -35,11 +35,14 @@ int pci_enable_pcie_error_reporting(struct pci_dev *dev) ...@@ -35,11 +35,14 @@ int pci_enable_pcie_error_reporting(struct pci_dev *dev)
u16 reg16 = 0; u16 reg16 = 0;
int pos; int pos;
if (dev->aer_firmware_first)
return -EIO;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (!pos) if (!pos)
return -EIO; return -EIO;
pos = pci_find_capability(dev, PCI_CAP_ID_EXP); pos = pci_pcie_cap(dev);
if (!pos) if (!pos)
return -EIO; return -EIO;
...@@ -60,7 +63,10 @@ int pci_disable_pcie_error_reporting(struct pci_dev *dev) ...@@ -60,7 +63,10 @@ int pci_disable_pcie_error_reporting(struct pci_dev *dev)
u16 reg16 = 0; u16 reg16 = 0;
int pos; int pos;
pos = pci_find_capability(dev, PCI_CAP_ID_EXP); if (dev->aer_firmware_first)
return -EIO;
pos = pci_pcie_cap(dev);
if (!pos) if (!pos)
return -EIO; return -EIO;
...@@ -78,48 +84,27 @@ EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting); ...@@ -78,48 +84,27 @@ EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
{ {
int pos; int pos;
u32 status, mask; u32 status;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (!pos) if (!pos)
return -EIO; return -EIO;
pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask); if (status)
if (dev->error_state == pci_channel_io_normal) pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
status &= ~mask; /* Clear corresponding nonfatal bits */
else
status &= mask; /* Clear corresponding fatal bits */
pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status); EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
#if 0
int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
{
int pos;
u32 status;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (!pos)
return -EIO;
pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status);
pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, status);
return 0;
}
#endif /* 0 */
static int set_device_error_reporting(struct pci_dev *dev, void *data) static int set_device_error_reporting(struct pci_dev *dev, void *data)
{ {
bool enable = *((bool *)data); bool enable = *((bool *)data);
if (dev->pcie_type == PCIE_RC_PORT || if ((dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) ||
dev->pcie_type == PCIE_SW_UPSTREAM_PORT || (dev->pcie_type == PCI_EXP_TYPE_UPSTREAM) ||
dev->pcie_type == PCIE_SW_DOWNSTREAM_PORT) { (dev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)) {
if (enable) if (enable)
pci_enable_pcie_error_reporting(dev); pci_enable_pcie_error_reporting(dev);
else else
...@@ -218,7 +203,7 @@ static int find_device_iter(struct pci_dev *dev, void *data) ...@@ -218,7 +203,7 @@ static int find_device_iter(struct pci_dev *dev, void *data)
*/ */
if (atomic_read(&dev->enable_cnt) == 0) if (atomic_read(&dev->enable_cnt) == 0)
return 0; return 0;
pos = pci_find_capability(dev, PCI_CAP_ID_EXP); pos = pci_pcie_cap(dev);
if (!pos) if (!pos)
return 0; return 0;
/* Check if AER is enabled */ /* Check if AER is enabled */
...@@ -431,10 +416,9 @@ static int find_aer_service_iter(struct device *device, void *data) ...@@ -431,10 +416,9 @@ static int find_aer_service_iter(struct device *device, void *data)
result = (struct find_aer_service_data *) data; result = (struct find_aer_service_data *) data;
if (device->bus == &pcie_port_bus_type) { if (device->bus == &pcie_port_bus_type) {
struct pcie_port_data *port_data; struct pcie_device *pcie = to_pcie_device(device);
port_data = pci_get_drvdata(to_pcie_device(device)->port); if (pcie->port->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
if (port_data->port_type == PCIE_SW_DOWNSTREAM_PORT)
result->is_downstream = 1; result->is_downstream = 1;
driver = device->driver; driver = device->driver;
...@@ -612,7 +596,7 @@ void aer_enable_rootport(struct aer_rpc *rpc) ...@@ -612,7 +596,7 @@ void aer_enable_rootport(struct aer_rpc *rpc)
u16 reg16; u16 reg16;
u32 reg32; u32 reg32;
pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); pos = pci_pcie_cap(pdev);
/* Clear PCIE Capability's Device Status */ /* Clear PCIE Capability's Device Status */
pci_read_config_word(pdev, pos+PCI_EXP_DEVSTA, &reg16); pci_read_config_word(pdev, pos+PCI_EXP_DEVSTA, &reg16);
pci_write_config_word(pdev, pos+PCI_EXP_DEVSTA, reg16); pci_write_config_word(pdev, pos+PCI_EXP_DEVSTA, reg16);
...@@ -874,8 +858,22 @@ void aer_delete_rootport(struct aer_rpc *rpc) ...@@ -874,8 +858,22 @@ void aer_delete_rootport(struct aer_rpc *rpc)
*/ */
int aer_init(struct pcie_device *dev) int aer_init(struct pcie_device *dev)
{ {
if (aer_osc_setup(dev) && !forceload) if (dev->port->aer_firmware_first) {
return -ENXIO; dev_printk(KERN_DEBUG, &dev->device,
"PCIe errors handled by platform firmware.\n");
goto out;
}
if (aer_osc_setup(dev))
goto out;
return 0; return 0;
out:
if (forceload) {
dev_printk(KERN_DEBUG, &dev->device,
"aerdrv forceload requested.\n");
dev->port->aer_firmware_first = 0;
return 0;
}
return -ENXIO;
} }
...@@ -51,7 +51,7 @@ static int enable_ecrc_checking(struct pci_dev *dev) ...@@ -51,7 +51,7 @@ static int enable_ecrc_checking(struct pci_dev *dev)
int pos; int pos;
u32 reg32; u32 reg32;
if (!dev->is_pcie) if (!pci_is_pcie(dev))
return -ENODEV; return -ENODEV;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
...@@ -79,7 +79,7 @@ static int disable_ecrc_checking(struct pci_dev *dev) ...@@ -79,7 +79,7 @@ static int disable_ecrc_checking(struct pci_dev *dev)
int pos; int pos;
u32 reg32; u32 reg32;
if (!dev->is_pcie) if (!pci_is_pcie(dev))
return -ENODEV; return -ENODEV;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
......
...@@ -122,7 +122,7 @@ static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable) ...@@ -122,7 +122,7 @@ static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable)
struct pci_bus *linkbus = link->pdev->subordinate; struct pci_bus *linkbus = link->pdev->subordinate;
list_for_each_entry(child, &linkbus->devices, bus_list) { list_for_each_entry(child, &linkbus->devices, bus_list) {
pos = pci_find_capability(child, PCI_CAP_ID_EXP); pos = pci_pcie_cap(child);
if (!pos) if (!pos)
return; return;
pci_read_config_word(child, pos + PCI_EXP_LNKCTL, &reg16); pci_read_config_word(child, pos + PCI_EXP_LNKCTL, &reg16);
...@@ -156,7 +156,7 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) ...@@ -156,7 +156,7 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist)
/* All functions should have the same cap and state, take the worst */ /* All functions should have the same cap and state, take the worst */
list_for_each_entry(child, &linkbus->devices, bus_list) { list_for_each_entry(child, &linkbus->devices, bus_list) {
pos = pci_find_capability(child, PCI_CAP_ID_EXP); pos = pci_pcie_cap(child);
if (!pos) if (!pos)
return; return;
pci_read_config_dword(child, pos + PCI_EXP_LNKCAP, &reg32); pci_read_config_dword(child, pos + PCI_EXP_LNKCAP, &reg32);
...@@ -191,23 +191,23 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) ...@@ -191,23 +191,23 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
* Configuration, so just check one function * Configuration, so just check one function
*/ */
child = list_entry(linkbus->devices.next, struct pci_dev, bus_list); child = list_entry(linkbus->devices.next, struct pci_dev, bus_list);
BUG_ON(!child->is_pcie); BUG_ON(!pci_is_pcie(child));
/* Check downstream component if bit Slot Clock Configuration is 1 */ /* Check downstream component if bit Slot Clock Configuration is 1 */
cpos = pci_find_capability(child, PCI_CAP_ID_EXP); cpos = pci_pcie_cap(child);
pci_read_config_word(child, cpos + PCI_EXP_LNKSTA, &reg16); pci_read_config_word(child, cpos + PCI_EXP_LNKSTA, &reg16);
if (!(reg16 & PCI_EXP_LNKSTA_SLC)) if (!(reg16 & PCI_EXP_LNKSTA_SLC))
same_clock = 0; same_clock = 0;
/* Check upstream component if bit Slot Clock Configuration is 1 */ /* Check upstream component if bit Slot Clock Configuration is 1 */
ppos = pci_find_capability(parent, PCI_CAP_ID_EXP); ppos = pci_pcie_cap(parent);
pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, &reg16); pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, &reg16);
if (!(reg16 & PCI_EXP_LNKSTA_SLC)) if (!(reg16 & PCI_EXP_LNKSTA_SLC))
same_clock = 0; same_clock = 0;
/* Configure downstream component, all functions */ /* Configure downstream component, all functions */
list_for_each_entry(child, &linkbus->devices, bus_list) { list_for_each_entry(child, &linkbus->devices, bus_list) {
cpos = pci_find_capability(child, PCI_CAP_ID_EXP); cpos = pci_pcie_cap(child);
pci_read_config_word(child, cpos + PCI_EXP_LNKCTL, &reg16); pci_read_config_word(child, cpos + PCI_EXP_LNKCTL, &reg16);
child_reg[PCI_FUNC(child->devfn)] = reg16; child_reg[PCI_FUNC(child->devfn)] = reg16;
if (same_clock) if (same_clock)
...@@ -247,7 +247,7 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) ...@@ -247,7 +247,7 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
dev_printk(KERN_ERR, &parent->dev, dev_printk(KERN_ERR, &parent->dev,
"ASPM: Could not configure common clock\n"); "ASPM: Could not configure common clock\n");
list_for_each_entry(child, &linkbus->devices, bus_list) { list_for_each_entry(child, &linkbus->devices, bus_list) {
cpos = pci_find_capability(child, PCI_CAP_ID_EXP); cpos = pci_pcie_cap(child);
pci_write_config_word(child, cpos + PCI_EXP_LNKCTL, pci_write_config_word(child, cpos + PCI_EXP_LNKCTL,
child_reg[PCI_FUNC(child->devfn)]); child_reg[PCI_FUNC(child->devfn)]);
} }
...@@ -300,7 +300,7 @@ static void pcie_get_aspm_reg(struct pci_dev *pdev, ...@@ -300,7 +300,7 @@ static void pcie_get_aspm_reg(struct pci_dev *pdev,
u16 reg16; u16 reg16;
u32 reg32; u32 reg32;
pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); pos = pci_pcie_cap(pdev);
pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &reg32); pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &reg32);
info->support = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10; info->support = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10;
info->latency_encoding_l0s = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12; info->latency_encoding_l0s = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12;
...@@ -420,7 +420,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) ...@@ -420,7 +420,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
child->pcie_type != PCI_EXP_TYPE_LEG_END) child->pcie_type != PCI_EXP_TYPE_LEG_END)
continue; continue;
pos = pci_find_capability(child, PCI_CAP_ID_EXP); pos = pci_pcie_cap(child);
pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, &reg32); pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, &reg32);
/* Calculate endpoint L0s acceptable latency */ /* Calculate endpoint L0s acceptable latency */
encoding = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6; encoding = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6;
...@@ -436,7 +436,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) ...@@ -436,7 +436,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val) static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val)
{ {
u16 reg16; u16 reg16;
int pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); int pos = pci_pcie_cap(pdev);
pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16); pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
reg16 &= ~0x3; reg16 &= ~0x3;
...@@ -503,7 +503,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) ...@@ -503,7 +503,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
* very strange. Disable ASPM for the whole slot * very strange. Disable ASPM for the whole slot
*/ */
list_for_each_entry(child, &pdev->subordinate->devices, bus_list) { list_for_each_entry(child, &pdev->subordinate->devices, bus_list) {
pos = pci_find_capability(child, PCI_CAP_ID_EXP); pos = pci_pcie_cap(child);
if (!pos) if (!pos)
return -EINVAL; return -EINVAL;
/* /*
...@@ -563,7 +563,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) ...@@ -563,7 +563,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
struct pcie_link_state *link; struct pcie_link_state *link;
int blacklist = !!pcie_aspm_sanity_check(pdev); int blacklist = !!pcie_aspm_sanity_check(pdev);
if (aspm_disabled || !pdev->is_pcie || pdev->link_state) if (aspm_disabled || !pci_is_pcie(pdev) || pdev->link_state)
return; return;
if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
...@@ -629,7 +629,8 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) ...@@ -629,7 +629,8 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
struct pci_dev *parent = pdev->bus->self; struct pci_dev *parent = pdev->bus->self;
struct pcie_link_state *link, *root, *parent_link; struct pcie_link_state *link, *root, *parent_link;
if (aspm_disabled || !pdev->is_pcie || !parent || !parent->link_state) if (aspm_disabled || !pci_is_pcie(pdev) ||
!parent || !parent->link_state)
return; return;
if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
(parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) (parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
...@@ -670,7 +671,7 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev) ...@@ -670,7 +671,7 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev)
{ {
struct pcie_link_state *link = pdev->link_state; struct pcie_link_state *link = pdev->link_state;
if (aspm_disabled || !pdev->is_pcie || !link) if (aspm_disabled || !pci_is_pcie(pdev) || !link)
return; return;
if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
(pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) (pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
...@@ -696,7 +697,7 @@ void pci_disable_link_state(struct pci_dev *pdev, int state) ...@@ -696,7 +697,7 @@ void pci_disable_link_state(struct pci_dev *pdev, int state)
struct pci_dev *parent = pdev->bus->self; struct pci_dev *parent = pdev->bus->self;
struct pcie_link_state *link; struct pcie_link_state *link;
if (aspm_disabled || !pdev->is_pcie) if (aspm_disabled || !pci_is_pcie(pdev))
return; return;
if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT || if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
...@@ -841,8 +842,9 @@ void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev) ...@@ -841,8 +842,9 @@ void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
{ {
struct pcie_link_state *link_state = pdev->link_state; struct pcie_link_state *link_state = pdev->link_state;
if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && if (!pci_is_pcie(pdev) ||
pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
return; return;
if (link_state->aspm_support) if (link_state->aspm_support)
...@@ -857,8 +859,9 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev) ...@@ -857,8 +859,9 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
{ {
struct pcie_link_state *link_state = pdev->link_state; struct pcie_link_state *link_state = pdev->link_state;
if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && if (!pci_is_pcie(pdev) ||
pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
return; return;
if (link_state->aspm_support) if (link_state->aspm_support)
......
...@@ -11,31 +11,16 @@ ...@@ -11,31 +11,16 @@
#include <linux/compiler.h> #include <linux/compiler.h>
#if !defined(PCI_CAP_ID_PME) #define PCIE_PORT_DEVICE_MAXSERVICES 4
#define PCI_CAP_ID_PME 1
#endif
#if !defined(PCI_CAP_ID_EXP)
#define PCI_CAP_ID_EXP 0x10
#endif
#define PORT_TYPE_MASK 0xf
#define PORT_TO_SLOT_MASK 0x100
#define SLOT_HP_CAPABLE_MASK 0x40
#define PCIE_CAPABILITIES_REG 0x2
#define PCIE_SLOT_CAPABILITIES_REG 0x14
#define PCIE_PORT_DEVICE_MAXSERVICES 4
#define PCIE_PORT_MSI_VECTOR_MASK 0x1f
/* /*
* According to the PCI Express Base Specification 2.0, the indices of the MSI-X * According to the PCI Express Base Specification 2.0, the indices of
* table entires used by port services must not exceed 31 * the MSI-X table entires used by port services must not exceed 31
*/ */
#define PCIE_PORT_MAX_MSIX_ENTRIES 32 #define PCIE_PORT_MAX_MSIX_ENTRIES 32
#define get_descriptor_id(type, service) (((type - 4) << 4) | service) #define get_descriptor_id(type, service) (((type - 4) << 4) | service)
extern struct bus_type pcie_port_bus_type; extern struct bus_type pcie_port_bus_type;
extern int pcie_port_device_probe(struct pci_dev *dev);
extern int pcie_port_device_register(struct pci_dev *dev); extern int pcie_port_device_register(struct pci_dev *dev);
#ifdef CONFIG_PM #ifdef CONFIG_PM
extern int pcie_port_device_suspend(struct device *dev); extern int pcie_port_device_suspend(struct device *dev);
......
...@@ -26,7 +26,6 @@ EXPORT_SYMBOL_GPL(pcie_port_bus_type); ...@@ -26,7 +26,6 @@ EXPORT_SYMBOL_GPL(pcie_port_bus_type);
static int pcie_port_bus_match(struct device *dev, struct device_driver *drv) static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
{ {
struct pcie_device *pciedev; struct pcie_device *pciedev;
struct pcie_port_data *port_data;
struct pcie_port_service_driver *driver; struct pcie_port_service_driver *driver;
if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type) if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type)
...@@ -38,10 +37,8 @@ static int pcie_port_bus_match(struct device *dev, struct device_driver *drv) ...@@ -38,10 +37,8 @@ static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
if (driver->service != pciedev->service) if (driver->service != pciedev->service)
return 0; return 0;
port_data = pci_get_drvdata(pciedev->port); if ((driver->port_type != PCIE_ANY_PORT) &&
(driver->port_type != pciedev->port->pcie_type))
if (driver->port_type != PCIE_ANY_PORT
&& driver->port_type != port_data->port_type)
return 0; return 0;
return 1; return 1;
......
...@@ -108,9 +108,9 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask) ...@@ -108,9 +108,9 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)
* the value in this field indicates which MSI-X Table entry is * the value in this field indicates which MSI-X Table entry is
* used to generate the interrupt message." * used to generate the interrupt message."
*/ */
pos = pci_find_capability(dev, PCI_CAP_ID_EXP); pos = pci_pcie_cap(dev);
pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, &reg16); pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &reg16);
entry = (reg16 >> 9) & PCIE_PORT_MSI_VECTOR_MASK; entry = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9;
if (entry >= nr_entries) if (entry >= nr_entries)
goto Error; goto Error;
...@@ -177,37 +177,40 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask) ...@@ -177,37 +177,40 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)
} }
/** /**
* assign_interrupt_mode - choose interrupt mode for PCI Express port services * init_service_irqs - initialize irqs for PCI Express port services
* (INTx, MSI-X, MSI) and set up vectors
* @dev: PCI Express port to handle * @dev: PCI Express port to handle
* @vectors: Array of interrupt vectors to populate * @irqs: Array of irqs to populate
* @mask: Bitmask of port capabilities returned by get_port_device_capability() * @mask: Bitmask of port capabilities returned by get_port_device_capability()
* *
* Return value: Interrupt mode associated with the port * Return value: Interrupt mode associated with the port
*/ */
static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask) static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask)
{ {
int irq, interrupt_mode = PCIE_PORT_NO_IRQ; int i, irq;
int i;
/* Try to use MSI-X if supported */ /* Try to use MSI-X if supported */
if (!pcie_port_enable_msix(dev, vectors, mask)) if (!pcie_port_enable_msix(dev, irqs, mask))
return PCIE_PORT_MSIX_MODE; return 0;
/* We're not going to use MSI-X, so try MSI and fall back to INTx */ /* We're not going to use MSI-X, so try MSI and fall back to INTx */
if (!pci_enable_msi(dev)) irq = -1;
interrupt_mode = PCIE_PORT_MSI_MODE; if (!pci_enable_msi(dev) || dev->pin)
irq = dev->irq;
if (interrupt_mode == PCIE_PORT_NO_IRQ && dev->pin)
interrupt_mode = PCIE_PORT_INTx_MODE;
irq = interrupt_mode != PCIE_PORT_NO_IRQ ? dev->irq : -1;
for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++)
vectors[i] = irq; irqs[i] = irq;
irqs[PCIE_PORT_SERVICE_VC_SHIFT] = -1;
vectors[PCIE_PORT_SERVICE_VC_SHIFT] = -1; if (irq < 0)
return -ENODEV;
return 0;
}
return interrupt_mode; static void cleanup_service_irqs(struct pci_dev *dev)
{
if (dev->msix_enabled)
pci_disable_msix(dev);
else if (dev->msi_enabled)
pci_disable_msi(dev);
} }
/** /**
...@@ -226,13 +229,12 @@ static int get_port_device_capability(struct pci_dev *dev) ...@@ -226,13 +229,12 @@ static int get_port_device_capability(struct pci_dev *dev)
u16 reg16; u16 reg16;
u32 reg32; u32 reg32;
pos = pci_find_capability(dev, PCI_CAP_ID_EXP); pos = pci_pcie_cap(dev);
pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, &reg16); pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &reg16);
/* Hot-Plug Capable */ /* Hot-Plug Capable */
if (reg16 & PORT_TO_SLOT_MASK) { if (reg16 & PCI_EXP_FLAGS_SLOT) {
pci_read_config_dword(dev, pci_read_config_dword(dev, pos + PCI_EXP_SLTCAP, &reg32);
pos + PCIE_SLOT_CAPABILITIES_REG, &reg32); if (reg32 & PCI_EXP_SLTCAP_HPC)
if (reg32 & SLOT_HP_CAPABLE_MASK)
services |= PCIE_PORT_SERVICE_HP; services |= PCIE_PORT_SERVICE_HP;
} }
/* AER capable */ /* AER capable */
...@@ -241,80 +243,47 @@ static int get_port_device_capability(struct pci_dev *dev) ...@@ -241,80 +243,47 @@ static int get_port_device_capability(struct pci_dev *dev)
/* VC support */ /* VC support */
if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC)) if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC))
services |= PCIE_PORT_SERVICE_VC; services |= PCIE_PORT_SERVICE_VC;
/* Root ports are capable of generating PME too */
if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
services |= PCIE_PORT_SERVICE_PME;
return services; return services;
} }
/** /**
* pcie_device_init - initialize PCI Express port service device * pcie_device_init - allocate and initialize PCI Express port service device
* @dev: Port service device to initialize * @pdev: PCI Express port to associate the service device with
* @parent: PCI Express port to associate the service device with * @service: Type of service to associate with the service device
* @port_type: Type of the port
* @service_type: Type of service to associate with the service device
* @irq: Interrupt vector to associate with the service device * @irq: Interrupt vector to associate with the service device
*/ */
static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev, static int pcie_device_init(struct pci_dev *pdev, int service, int irq)
int service_type, int irq)
{ {
struct pcie_port_data *port_data = pci_get_drvdata(parent); int retval;
struct pcie_device *pcie;
struct device *device; struct device *device;
int port_type = port_data->port_type;
dev->port = parent; pcie = kzalloc(sizeof(*pcie), GFP_KERNEL);
dev->irq = irq; if (!pcie)
dev->service = service_type; return -ENOMEM;
pcie->port = pdev;
pcie->irq = irq;
pcie->service = service;
/* Initialize generic device interface */ /* Initialize generic device interface */
device = &dev->device; device = &pcie->device;
memset(device, 0, sizeof(struct device));
device->bus = &pcie_port_bus_type; device->bus = &pcie_port_bus_type;
device->driver = NULL;
dev_set_drvdata(device, NULL);
device->release = release_pcie_device; /* callback to free pcie dev */ device->release = release_pcie_device; /* callback to free pcie dev */
dev_set_name(device, "%s:pcie%02x", dev_set_name(device, "%s:pcie%02x",
pci_name(parent), get_descriptor_id(port_type, service_type)); pci_name(pdev),
device->parent = &parent->dev; get_descriptor_id(pdev->pcie_type, service));
} device->parent = &pdev->dev;
/** retval = device_register(device);
* alloc_pcie_device - allocate PCI Express port service device structure if (retval)
* @parent: PCI Express port to associate the service device with kfree(pcie);
* @port_type: Type of the port else
* @service_type: Type of service to associate with the service device get_device(device);
* @irq: Interrupt vector to associate with the service device return retval;
*/
static struct pcie_device* alloc_pcie_device(struct pci_dev *parent,
int service_type, int irq)
{
struct pcie_device *device;
device = kzalloc(sizeof(struct pcie_device), GFP_KERNEL);
if (!device)
return NULL;
pcie_device_init(parent, device, service_type, irq);
return device;
}
/**
* pcie_port_device_probe - check if device is a PCI Express port
* @dev: Device to check
*/
int pcie_port_device_probe(struct pci_dev *dev)
{
int pos, type;
u16 reg;
if (!(pos = pci_find_capability(dev, PCI_CAP_ID_EXP)))
return -ENODEV;
pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, &reg);
type = (reg >> 4) & PORT_TYPE_MASK;
if ( type == PCIE_RC_PORT || type == PCIE_SW_UPSTREAM_PORT ||
type == PCIE_SW_DOWNSTREAM_PORT )
return 0;
return -ENODEV;
} }
/** /**
...@@ -326,77 +295,49 @@ int pcie_port_device_probe(struct pci_dev *dev) ...@@ -326,77 +295,49 @@ int pcie_port_device_probe(struct pci_dev *dev)
*/ */
int pcie_port_device_register(struct pci_dev *dev) int pcie_port_device_register(struct pci_dev *dev)
{ {
struct pcie_port_data *port_data; int status, capabilities, i, nr_service;
int status, capabilities, irq_mode, i, nr_serv; int irqs[PCIE_PORT_DEVICE_MAXSERVICES];
int vectors[PCIE_PORT_DEVICE_MAXSERVICES];
u16 reg16;
port_data = kzalloc(sizeof(*port_data), GFP_KERNEL);
if (!port_data)
return -ENOMEM;
pci_set_drvdata(dev, port_data);
/* Get port type */
pci_read_config_word(dev,
pci_find_capability(dev, PCI_CAP_ID_EXP) +
PCIE_CAPABILITIES_REG, &reg16);
port_data->port_type = (reg16 >> 4) & PORT_TYPE_MASK;
/* Get and check PCI Express port services */
capabilities = get_port_device_capability(dev); capabilities = get_port_device_capability(dev);
/* Root ports are capable of generating PME too */ if (!capabilities)
if (port_data->port_type == PCIE_RC_PORT) return -ENODEV;
capabilities |= PCIE_PORT_SERVICE_PME;
irq_mode = assign_interrupt_mode(dev, vectors, capabilities);
if (irq_mode == PCIE_PORT_NO_IRQ) {
/*
* Don't use service devices that require interrupts if there is
* no way to generate them.
*/
if (!(capabilities & PCIE_PORT_SERVICE_VC)) {
status = -ENODEV;
goto Error;
}
capabilities = PCIE_PORT_SERVICE_VC;
}
port_data->port_irq_mode = irq_mode;
/* Enable PCI Express port device */
status = pci_enable_device(dev); status = pci_enable_device(dev);
if (status) if (status)
goto Error; return status;
pci_set_master(dev); pci_set_master(dev);
/*
* Initialize service irqs. Don't use service devices that
* require interrupts if there is no way to generate them.
*/
status = init_service_irqs(dev, irqs, capabilities);
if (status) {
capabilities &= PCIE_PORT_SERVICE_VC;
if (!capabilities)
goto error_disable;
}
/* Allocate child services if any */ /* Allocate child services if any */
for (i = 0, nr_serv = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) { status = -ENODEV;
struct pcie_device *child; nr_service = 0;
for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
int service = 1 << i; int service = 1 << i;
if (!(capabilities & service)) if (!(capabilities & service))
continue; continue;
if (!pcie_device_init(dev, service, irqs[i]))
child = alloc_pcie_device(dev, service, vectors[i]); nr_service++;
if (!child)
continue;
status = device_register(&child->device);
if (status) {
kfree(child);
continue;
}
get_device(&child->device);
nr_serv++;
}
if (!nr_serv) {
pci_disable_device(dev);
status = -ENODEV;
goto Error;
} }
if (!nr_service)
goto error_cleanup_irqs;
return 0; return 0;
Error: error_cleanup_irqs:
kfree(port_data); cleanup_service_irqs(dev);
error_disable:
pci_disable_device(dev);
return status; return status;
} }
...@@ -464,21 +405,9 @@ static int remove_iter(struct device *dev, void *data) ...@@ -464,21 +405,9 @@ static int remove_iter(struct device *dev, void *data)
*/ */
void pcie_port_device_remove(struct pci_dev *dev) void pcie_port_device_remove(struct pci_dev *dev)
{ {
struct pcie_port_data *port_data = pci_get_drvdata(dev);
device_for_each_child(&dev->dev, NULL, remove_iter); device_for_each_child(&dev->dev, NULL, remove_iter);
cleanup_service_irqs(dev);
pci_disable_device(dev); pci_disable_device(dev);
switch (port_data->port_irq_mode) {
case PCIE_PORT_MSIX_MODE:
pci_disable_msix(dev);
break;
case PCIE_PORT_MSI_MODE:
pci_disable_msi(dev);
break;
}
kfree(port_data);
} }
/** /**
......
...@@ -67,14 +67,16 @@ static struct dev_pm_ops pcie_portdrv_pm_ops = { ...@@ -67,14 +67,16 @@ static struct dev_pm_ops pcie_portdrv_pm_ops = {
* this port device. * this port device.
* *
*/ */
static int __devinit pcie_portdrv_probe (struct pci_dev *dev, static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
const struct pci_device_id *id ) const struct pci_device_id *id)
{ {
int status; int status;
status = pcie_port_device_probe(dev); if (!pci_is_pcie(dev) ||
if (status) ((dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
return status; (dev->pcie_type != PCI_EXP_TYPE_UPSTREAM) &&
(dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)))
return -ENODEV;
if (!dev->irq && dev->pin) { if (!dev->irq && dev->pin) {
dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; " dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; "
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <linux/pci-aspm.h> #include <linux/pci-aspm.h>
#include <acpi/acpi_hest.h>
#include "pci.h" #include "pci.h"
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
...@@ -163,12 +164,12 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -163,12 +164,12 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
{ {
u32 l, sz, mask; u32 l, sz, mask;
mask = type ? ~PCI_ROM_ADDRESS_ENABLE : ~0; mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
res->name = pci_name(dev); res->name = pci_name(dev);
pci_read_config_dword(dev, pos, &l); pci_read_config_dword(dev, pos, &l);
pci_write_config_dword(dev, pos, mask); pci_write_config_dword(dev, pos, l | mask);
pci_read_config_dword(dev, pos, &sz); pci_read_config_dword(dev, pos, &sz);
pci_write_config_dword(dev, pos, l); pci_write_config_dword(dev, pos, l);
...@@ -223,9 +224,13 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -223,9 +224,13 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
goto fail; goto fail;
if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) { if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) {
dev_err(&dev->dev, "can't handle 64-bit BAR\n"); dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n",
pos);
goto fail; goto fail;
} else if ((sizeof(resource_size_t) < 8) && l) { }
res->flags |= IORESOURCE_MEM_64;
if ((sizeof(resource_size_t) < 8) && l) {
/* Address above 32-bit boundary; disable the BAR */ /* Address above 32-bit boundary; disable the BAR */
pci_write_config_dword(dev, pos, 0); pci_write_config_dword(dev, pos, 0);
pci_write_config_dword(dev, pos + 4, 0); pci_write_config_dword(dev, pos + 4, 0);
...@@ -234,14 +239,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -234,14 +239,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
} else { } else {
res->start = l64; res->start = l64;
res->end = l64 + sz64; res->end = l64 + sz64;
dev_printk(KERN_DEBUG, &dev->dev, dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n",
"reg %x %s: %pR\n", pos, pos, res);
(res->flags & IORESOURCE_PREFETCH) ?
"64bit mmio pref" : "64bit mmio",
res);
} }
res->flags |= IORESOURCE_MEM_64;
} else { } else {
sz = pci_size(l, sz, mask); sz = pci_size(l, sz, mask);
...@@ -251,11 +251,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -251,11 +251,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
res->start = l; res->start = l;
res->end = l + sz; res->end = l + sz;
dev_printk(KERN_DEBUG, &dev->dev, "reg %x %s: %pR\n", pos, dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
(res->flags & IORESOURCE_IO) ? "io port" :
((res->flags & IORESOURCE_PREFETCH) ?
"32bit mmio pref" : "32bit mmio"),
res);
} }
out: out:
...@@ -297,8 +293,11 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) ...@@ -297,8 +293,11 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
if (pci_is_root_bus(child)) /* It's a host bus, nothing to read */ if (pci_is_root_bus(child)) /* It's a host bus, nothing to read */
return; return;
dev_info(&dev->dev, "PCI bridge to [bus %02x-%02x]%s\n",
child->secondary, child->subordinate,
dev->transparent ? " (subtractive decode)": "");
if (dev->transparent) { if (dev->transparent) {
dev_info(&dev->dev, "transparent bridge\n");
for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++) for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++)
child->resource[i] = child->parent->resource[i - 3]; child->resource[i] = child->parent->resource[i - 3];
} }
...@@ -323,7 +322,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) ...@@ -323,7 +322,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->start = base; res->start = base;
if (!res->end) if (!res->end)
res->end = limit + 0xfff; res->end = limit + 0xfff;
dev_printk(KERN_DEBUG, &dev->dev, "bridge io port: %pR\n", res); dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
} }
res = child->resource[1]; res = child->resource[1];
...@@ -335,8 +334,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) ...@@ -335,8 +334,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM; res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
res->start = base; res->start = base;
res->end = limit + 0xfffff; res->end = limit + 0xfffff;
dev_printk(KERN_DEBUG, &dev->dev, "bridge 32bit mmio: %pR\n", dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
res);
} }
res = child->resource[2]; res = child->resource[2];
...@@ -375,9 +373,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) ...@@ -375,9 +373,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->flags |= IORESOURCE_MEM_64; res->flags |= IORESOURCE_MEM_64;
res->start = base; res->start = base;
res->end = limit + 0xfffff; res->end = limit + 0xfffff;
dev_printk(KERN_DEBUG, &dev->dev, "bridge %sbit mmio pref: %pR\n", dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
(res->flags & PCI_PREF_RANGE_TYPE_64) ? "64" : "32",
res);
} }
} }
...@@ -651,13 +647,14 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, ...@@ -651,13 +647,14 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
(child->number > bus->subordinate) || (child->number > bus->subordinate) ||
(child->number < bus->number) || (child->number < bus->number) ||
(child->subordinate < bus->number)) { (child->subordinate < bus->number)) {
pr_debug("PCI: Bus #%02x (-#%02x) is %s " dev_info(&child->dev, "[bus %02x-%02x] %s "
"hidden behind%s bridge #%02x (-#%02x)\n", "hidden behind%s bridge %s [bus %02x-%02x]\n",
child->number, child->subordinate, child->number, child->subordinate,
(bus->number > child->subordinate && (bus->number > child->subordinate &&
bus->subordinate < child->number) ? bus->subordinate < child->number) ?
"wholly" : "partially", "wholly" : "partially",
bus->self->transparent ? " transparent" : "", bus->self->transparent ? " transparent" : "",
dev_name(&bus->dev),
bus->number, bus->subordinate); bus->number, bus->subordinate);
} }
bus = bus->parent; bus = bus->parent;
...@@ -693,6 +690,7 @@ static void set_pcie_port_type(struct pci_dev *pdev) ...@@ -693,6 +690,7 @@ static void set_pcie_port_type(struct pci_dev *pdev)
if (!pos) if (!pos)
return; return;
pdev->is_pcie = 1; pdev->is_pcie = 1;
pdev->pcie_cap = pos;
pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16); pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16);
pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4; pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4;
} }
...@@ -703,7 +701,7 @@ static void set_pcie_hotplug_bridge(struct pci_dev *pdev) ...@@ -703,7 +701,7 @@ static void set_pcie_hotplug_bridge(struct pci_dev *pdev)
u16 reg16; u16 reg16;
u32 reg32; u32 reg32;
pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); pos = pci_pcie_cap(pdev);
if (!pos) if (!pos)
return; return;
pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16); pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16);
...@@ -714,6 +712,12 @@ static void set_pcie_hotplug_bridge(struct pci_dev *pdev) ...@@ -714,6 +712,12 @@ static void set_pcie_hotplug_bridge(struct pci_dev *pdev)
pdev->is_hotplug_bridge = 1; pdev->is_hotplug_bridge = 1;
} }
static void set_pci_aer_firmware_first(struct pci_dev *pdev)
{
if (acpi_hest_firmware_first_pci(pdev))
pdev->aer_firmware_first = 1;
}
#define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED) #define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
/** /**
...@@ -731,6 +735,7 @@ int pci_setup_device(struct pci_dev *dev) ...@@ -731,6 +735,7 @@ int pci_setup_device(struct pci_dev *dev)
u32 class; u32 class;
u8 hdr_type; u8 hdr_type;
struct pci_slot *slot; struct pci_slot *slot;
int pos = 0;
if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type)) if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type))
return -EIO; return -EIO;
...@@ -742,6 +747,7 @@ int pci_setup_device(struct pci_dev *dev) ...@@ -742,6 +747,7 @@ int pci_setup_device(struct pci_dev *dev)
dev->multifunction = !!(hdr_type & 0x80); dev->multifunction = !!(hdr_type & 0x80);
dev->error_state = pci_channel_io_normal; dev->error_state = pci_channel_io_normal;
set_pcie_port_type(dev); set_pcie_port_type(dev);
set_pci_aer_firmware_first(dev);
list_for_each_entry(slot, &dev->bus->slots, list) list_for_each_entry(slot, &dev->bus->slots, list)
if (PCI_SLOT(dev->devfn) == slot->number) if (PCI_SLOT(dev->devfn) == slot->number)
...@@ -822,6 +828,11 @@ int pci_setup_device(struct pci_dev *dev) ...@@ -822,6 +828,11 @@ int pci_setup_device(struct pci_dev *dev)
dev->transparent = ((dev->class & 0xff) == 1); dev->transparent = ((dev->class & 0xff) == 1);
pci_read_bases(dev, 2, PCI_ROM_ADDRESS1); pci_read_bases(dev, 2, PCI_ROM_ADDRESS1);
set_pcie_hotplug_bridge(dev); set_pcie_hotplug_bridge(dev);
pos = pci_find_capability(dev, PCI_CAP_ID_SSVID);
if (pos) {
pci_read_config_word(dev, pos + PCI_SSVID_VENDOR_ID, &dev->subsystem_vendor);
pci_read_config_word(dev, pos + PCI_SSVID_DEVICE_ID, &dev->subsystem_device);
}
break; break;
case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */ case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */
...@@ -907,7 +918,7 @@ int pci_cfg_space_size(struct pci_dev *dev) ...@@ -907,7 +918,7 @@ int pci_cfg_space_size(struct pci_dev *dev)
if (class == PCI_CLASS_BRIDGE_HOST) if (class == PCI_CLASS_BRIDGE_HOST)
return pci_cfg_space_size_ext(dev); return pci_cfg_space_size_ext(dev);
pos = pci_find_capability(dev, PCI_CAP_ID_EXP); pos = pci_pcie_cap(dev);
if (!pos) { if (!pos) {
pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
if (!pos) if (!pos)
...@@ -1014,6 +1025,9 @@ static void pci_init_capabilities(struct pci_dev *dev) ...@@ -1014,6 +1025,9 @@ static void pci_init_capabilities(struct pci_dev *dev)
/* Single Root I/O Virtualization */ /* Single Root I/O Virtualization */
pci_iov_init(dev); pci_iov_init(dev);
/* Enable ACS P2P upstream forwarding */
pci_enable_acs(dev);
} }
void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
...@@ -1110,7 +1124,7 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) ...@@ -1110,7 +1124,7 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
unsigned int devfn, pass, max = bus->secondary; unsigned int devfn, pass, max = bus->secondary;
struct pci_dev *dev; struct pci_dev *dev;
pr_debug("PCI: Scanning bus %04x:%02x\n", pci_domain_nr(bus), bus->number); dev_dbg(&bus->dev, "scanning bus\n");
/* Go find them, Rover! */ /* Go find them, Rover! */
for (devfn = 0; devfn < 0x100; devfn += 8) for (devfn = 0; devfn < 0x100; devfn += 8)
...@@ -1124,8 +1138,7 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) ...@@ -1124,8 +1138,7 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
* all PCI-to-PCI bridges on this bus. * all PCI-to-PCI bridges on this bus.
*/ */
if (!bus->is_added) { if (!bus->is_added) {
pr_debug("PCI: Fixups for bus %04x:%02x\n", dev_dbg(&bus->dev, "fixups for bus\n");
pci_domain_nr(bus), bus->number);
pcibios_fixup_bus(bus); pcibios_fixup_bus(bus);
if (pci_is_root_bus(bus)) if (pci_is_root_bus(bus))
bus->is_added = 1; bus->is_added = 1;
...@@ -1145,8 +1158,7 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) ...@@ -1145,8 +1158,7 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
* *
* Return how far we've got finding sub-buses. * Return how far we've got finding sub-buses.
*/ */
pr_debug("PCI: Bus scan for %04x:%02x returning with max=%02x\n", dev_dbg(&bus->dev, "bus scan returning with max=%02x\n", max);
pci_domain_nr(bus), bus->number, max);
return max; return max;
} }
...@@ -1154,7 +1166,7 @@ struct pci_bus * pci_create_bus(struct device *parent, ...@@ -1154,7 +1166,7 @@ struct pci_bus * pci_create_bus(struct device *parent,
int bus, struct pci_ops *ops, void *sysdata) int bus, struct pci_ops *ops, void *sysdata)
{ {
int error; int error;
struct pci_bus *b; struct pci_bus *b, *b2;
struct device *dev; struct device *dev;
b = pci_alloc_bus(); b = pci_alloc_bus();
...@@ -1170,9 +1182,10 @@ struct pci_bus * pci_create_bus(struct device *parent, ...@@ -1170,9 +1182,10 @@ struct pci_bus * pci_create_bus(struct device *parent,
b->sysdata = sysdata; b->sysdata = sysdata;
b->ops = ops; b->ops = ops;
if (pci_find_bus(pci_domain_nr(b), bus)) { b2 = pci_find_bus(pci_domain_nr(b), bus);
if (b2) {
/* If we already got to this bus through a different bridge, ignore it */ /* If we already got to this bus through a different bridge, ignore it */
pr_debug("PCI: Bus %04x:%02x already known\n", pci_domain_nr(b), bus); dev_dbg(&b2->dev, "bus already known\n");
goto err_out; goto err_out;
} }
......
...@@ -357,7 +357,7 @@ static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region, ...@@ -357,7 +357,7 @@ static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
pcibios_bus_to_resource(dev, res, &bus_region); pcibios_bus_to_resource(dev, res, &bus_region);
pci_claim_resource(dev, nr); pci_claim_resource(dev, nr);
dev_info(&dev->dev, "quirk: region %04x-%04x claimed by %s\n", region, region + size - 1, name); dev_info(&dev->dev, "quirk: %pR claimed by %s\n", res, name);
} }
} }
...@@ -1680,6 +1680,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_ ...@@ -1680,6 +1680,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_
*/ */
#define AMD_813X_MISC 0x40 #define AMD_813X_MISC 0x40
#define AMD_813X_NOIOAMODE (1<<0) #define AMD_813X_NOIOAMODE (1<<0)
#define AMD_813X_REV_B1 0x12
#define AMD_813X_REV_B2 0x13 #define AMD_813X_REV_B2 0x13
static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev) static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev)
...@@ -1688,7 +1689,8 @@ static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev) ...@@ -1688,7 +1689,8 @@ static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev)
if (noioapicquirk) if (noioapicquirk)
return; return;
if (dev->revision == AMD_813X_REV_B2) if ((dev->revision == AMD_813X_REV_B1) ||
(dev->revision == AMD_813X_REV_B2))
return; return;
pci_read_config_dword(dev, AMD_813X_MISC, &pci_config_dword); pci_read_config_dword(dev, AMD_813X_MISC, &pci_config_dword);
...@@ -1698,8 +1700,10 @@ static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev) ...@@ -1698,8 +1700,10 @@ static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev)
dev_info(&dev->dev, "disabled boot interrupts on device [%04x:%04x]\n", dev_info(&dev->dev, "disabled boot interrupts on device [%04x:%04x]\n",
dev->vendor, dev->device); dev->vendor, dev->device);
} }
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_amd_813x_boot_interrupt); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_amd_813x_boot_interrupt);
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, quirk_disable_amd_813x_boot_interrupt); DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_amd_813x_boot_interrupt);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, quirk_disable_amd_813x_boot_interrupt);
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, quirk_disable_amd_813x_boot_interrupt);
#define AMD_8111_PCI_IRQ_ROUTING 0x56 #define AMD_8111_PCI_IRQ_ROUTING 0x56
...@@ -2595,9 +2599,37 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) ...@@ -2595,9 +2599,37 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
static int __init pci_apply_final_quirks(void) static int __init pci_apply_final_quirks(void)
{ {
struct pci_dev *dev = NULL; struct pci_dev *dev = NULL;
u8 cls = 0;
u8 tmp;
if (pci_cache_line_size)
printk(KERN_DEBUG "PCI: CLS %u bytes\n",
pci_cache_line_size << 2);
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
pci_fixup_device(pci_fixup_final, dev); pci_fixup_device(pci_fixup_final, dev);
/*
* If arch hasn't set it explicitly yet, use the CLS
* value shared by all PCI devices. If there's a
* mismatch, fall back to the default value.
*/
if (!pci_cache_line_size) {
pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &tmp);
if (!cls)
cls = tmp;
if (!tmp || cls == tmp)
continue;
printk(KERN_DEBUG "PCI: CLS mismatch (%u != %u), "
"using %u bytes\n", cls << 2, tmp << 2,
pci_dfl_cache_line_size << 2);
pci_cache_line_size = pci_dfl_cache_line_size;
}
}
if (!pci_cache_line_size) {
printk(KERN_DEBUG "PCI: CLS %u bytes, default %u\n",
cls << 2, pci_dfl_cache_line_size << 2);
pci_cache_line_size = cls;
} }
return 0; return 0;
......
...@@ -26,14 +26,14 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev) ...@@ -26,14 +26,14 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
{ {
struct pci_dev *tmp = NULL; struct pci_dev *tmp = NULL;
if (pdev->is_pcie) if (pci_is_pcie(pdev))
return NULL; return NULL;
while (1) { while (1) {
if (pci_is_root_bus(pdev->bus)) if (pci_is_root_bus(pdev->bus))
break; break;
pdev = pdev->bus->self; pdev = pdev->bus->self;
/* a p2p bridge */ /* a p2p bridge */
if (!pdev->is_pcie) { if (!pci_is_pcie(pdev)) {
tmp = pdev; tmp = pdev;
continue; continue;
} }
...@@ -149,32 +149,33 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) ...@@ -149,32 +149,33 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn)
} }
/** /**
* pci_get_bus_and_slot - locate PCI device from a given PCI bus & slot * pci_get_domain_bus_and_slot - locate PCI device for a given PCI domain (segment), bus, and slot
* @bus: number of PCI bus on which desired PCI device resides * @domain: PCI domain/segment on which the PCI device resides.
* @devfn: encodes number of PCI slot in which the desired PCI * @bus: PCI bus on which desired PCI device resides
* device resides and the logical device number within that slot * @devfn: encodes number of PCI slot in which the desired PCI device
* in case of multi-function devices. * resides and the logical device number within that slot in case of
* * multi-function devices.
* Note: the bus/slot search is limited to PCI domain (segment) 0.
* *
* Given a PCI bus and slot/function number, the desired PCI device * Given a PCI domain, bus, and slot/function number, the desired PCI
* is located in system global list of PCI devices. If the device * device is located in the list of PCI devices. If the device is
* is found, a pointer to its data structure is returned. If no * found, its reference count is increased and this function returns a
* device is found, %NULL is returned. The returned device has its * pointer to its data structure. The caller must decrement the
* reference count bumped by one. * reference count by calling pci_dev_put(). If no device is found,
* %NULL is returned.
*/ */
struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus,
struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn) unsigned int devfn)
{ {
struct pci_dev *dev = NULL; struct pci_dev *dev = NULL;
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
if (pci_domain_nr(dev->bus) == 0 && if (pci_domain_nr(dev->bus) == domain &&
(dev->bus->number == bus && dev->devfn == devfn)) (dev->bus->number == bus && dev->devfn == devfn))
return dev; return dev;
} }
return NULL; return NULL;
} }
EXPORT_SYMBOL(pci_get_domain_bus_and_slot);
static int match_pci_dev_by_id(struct device *dev, void *data) static int match_pci_dev_by_id(struct device *dev, void *data)
{ {
...@@ -354,5 +355,4 @@ EXPORT_SYMBOL(pci_find_next_bus); ...@@ -354,5 +355,4 @@ EXPORT_SYMBOL(pci_find_next_bus);
EXPORT_SYMBOL(pci_get_device); EXPORT_SYMBOL(pci_get_device);
EXPORT_SYMBOL(pci_get_subsys); EXPORT_SYMBOL(pci_get_subsys);
EXPORT_SYMBOL(pci_get_slot); EXPORT_SYMBOL(pci_get_slot);
EXPORT_SYMBOL(pci_get_bus_and_slot);
EXPORT_SYMBOL(pci_get_class); EXPORT_SYMBOL(pci_get_class);
...@@ -71,53 +71,50 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus) ...@@ -71,53 +71,50 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus)
void pci_setup_cardbus(struct pci_bus *bus) void pci_setup_cardbus(struct pci_bus *bus)
{ {
struct pci_dev *bridge = bus->self; struct pci_dev *bridge = bus->self;
struct resource *res;
struct pci_bus_region region; struct pci_bus_region region;
dev_info(&bridge->dev, "CardBus bridge, secondary bus %04x:%02x\n", dev_info(&bridge->dev, "CardBus bridge to [bus %02x-%02x]\n",
pci_domain_nr(bus), bus->number); bus->secondary, bus->subordinate);
pcibios_resource_to_bus(bridge, &region, bus->resource[0]); res = bus->resource[0];
if (bus->resource[0]->flags & IORESOURCE_IO) { pcibios_resource_to_bus(bridge, &region, res);
if (res->flags & IORESOURCE_IO) {
/* /*
* The IO resource is allocated a range twice as large as it * The IO resource is allocated a range twice as large as it
* would normally need. This allows us to set both IO regs. * would normally need. This allows us to set both IO regs.
*/ */
dev_info(&bridge->dev, " IO window: %#08lx-%#08lx\n", dev_info(&bridge->dev, " bridge window %pR\n", res);
(unsigned long)region.start,
(unsigned long)region.end);
pci_write_config_dword(bridge, PCI_CB_IO_BASE_0, pci_write_config_dword(bridge, PCI_CB_IO_BASE_0,
region.start); region.start);
pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0, pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0,
region.end); region.end);
} }
pcibios_resource_to_bus(bridge, &region, bus->resource[1]); res = bus->resource[1];
if (bus->resource[1]->flags & IORESOURCE_IO) { pcibios_resource_to_bus(bridge, &region, res);
dev_info(&bridge->dev, " IO window: %#08lx-%#08lx\n", if (res->flags & IORESOURCE_IO) {
(unsigned long)region.start, dev_info(&bridge->dev, " bridge window %pR\n", res);
(unsigned long)region.end);
pci_write_config_dword(bridge, PCI_CB_IO_BASE_1, pci_write_config_dword(bridge, PCI_CB_IO_BASE_1,
region.start); region.start);
pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1, pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1,
region.end); region.end);
} }
pcibios_resource_to_bus(bridge, &region, bus->resource[2]); res = bus->resource[2];
if (bus->resource[2]->flags & IORESOURCE_MEM) { pcibios_resource_to_bus(bridge, &region, res);
dev_info(&bridge->dev, " PREFETCH window: %#08lx-%#08lx\n", if (res->flags & IORESOURCE_MEM) {
(unsigned long)region.start, dev_info(&bridge->dev, " bridge window %pR\n", res);
(unsigned long)region.end);
pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0, pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0,
region.start); region.start);
pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0, pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0,
region.end); region.end);
} }
pcibios_resource_to_bus(bridge, &region, bus->resource[3]); res = bus->resource[3];
if (bus->resource[3]->flags & IORESOURCE_MEM) { pcibios_resource_to_bus(bridge, &region, res);
dev_info(&bridge->dev, " MEM window: %#08lx-%#08lx\n", if (res->flags & IORESOURCE_MEM) {
(unsigned long)region.start, dev_info(&bridge->dev, " bridge window %pR\n", res);
(unsigned long)region.end);
pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1, pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1,
region.start); region.start);
pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1, pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1,
...@@ -140,34 +137,33 @@ EXPORT_SYMBOL(pci_setup_cardbus); ...@@ -140,34 +137,33 @@ EXPORT_SYMBOL(pci_setup_cardbus);
static void pci_setup_bridge(struct pci_bus *bus) static void pci_setup_bridge(struct pci_bus *bus)
{ {
struct pci_dev *bridge = bus->self; struct pci_dev *bridge = bus->self;
struct resource *res;
struct pci_bus_region region; struct pci_bus_region region;
u32 l, bu, lu, io_upper16; u32 l, bu, lu, io_upper16;
int pref_mem64;
if (pci_is_enabled(bridge)) if (pci_is_enabled(bridge))
return; return;
dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n", dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n",
pci_domain_nr(bus), bus->number); bus->secondary, bus->subordinate);
/* Set up the top and bottom of the PCI I/O segment for this bus. */ /* Set up the top and bottom of the PCI I/O segment for this bus. */
pcibios_resource_to_bus(bridge, &region, bus->resource[0]); res = bus->resource[0];
if (bus->resource[0]->flags & IORESOURCE_IO) { pcibios_resource_to_bus(bridge, &region, res);
if (res->flags & IORESOURCE_IO) {
pci_read_config_dword(bridge, PCI_IO_BASE, &l); pci_read_config_dword(bridge, PCI_IO_BASE, &l);
l &= 0xffff0000; l &= 0xffff0000;
l |= (region.start >> 8) & 0x00f0; l |= (region.start >> 8) & 0x00f0;
l |= region.end & 0xf000; l |= region.end & 0xf000;
/* Set up upper 16 bits of I/O base/limit. */ /* Set up upper 16 bits of I/O base/limit. */
io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
dev_info(&bridge->dev, " IO window: %#04lx-%#04lx\n", dev_info(&bridge->dev, " bridge window %pR\n", res);
(unsigned long)region.start,
(unsigned long)region.end);
} }
else { else {
/* Clear upper 16 bits of I/O base/limit. */ /* Clear upper 16 bits of I/O base/limit. */
io_upper16 = 0; io_upper16 = 0;
l = 0x00f0; l = 0x00f0;
dev_info(&bridge->dev, " IO window: disabled\n"); dev_info(&bridge->dev, " bridge window [io disabled]\n");
} }
/* Temporarily disable the I/O range before updating PCI_IO_BASE. */ /* Temporarily disable the I/O range before updating PCI_IO_BASE. */
pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff); pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);
...@@ -178,17 +174,16 @@ static void pci_setup_bridge(struct pci_bus *bus) ...@@ -178,17 +174,16 @@ static void pci_setup_bridge(struct pci_bus *bus)
/* Set up the top and bottom of the PCI Memory segment /* Set up the top and bottom of the PCI Memory segment
for this bus. */ for this bus. */
pcibios_resource_to_bus(bridge, &region, bus->resource[1]); res = bus->resource[1];
if (bus->resource[1]->flags & IORESOURCE_MEM) { pcibios_resource_to_bus(bridge, &region, res);
if (res->flags & IORESOURCE_MEM) {
l = (region.start >> 16) & 0xfff0; l = (region.start >> 16) & 0xfff0;
l |= region.end & 0xfff00000; l |= region.end & 0xfff00000;
dev_info(&bridge->dev, " MEM window: %#08lx-%#08lx\n", dev_info(&bridge->dev, " bridge window %pR\n", res);
(unsigned long)region.start,
(unsigned long)region.end);
} }
else { else {
l = 0x0000fff0; l = 0x0000fff0;
dev_info(&bridge->dev, " MEM window: disabled\n"); dev_info(&bridge->dev, " bridge window [mem disabled]\n");
} }
pci_write_config_dword(bridge, PCI_MEMORY_BASE, l); pci_write_config_dword(bridge, PCI_MEMORY_BASE, l);
...@@ -198,34 +193,27 @@ static void pci_setup_bridge(struct pci_bus *bus) ...@@ -198,34 +193,27 @@ static void pci_setup_bridge(struct pci_bus *bus)
pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0); pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
/* Set up PREF base/limit. */ /* Set up PREF base/limit. */
pref_mem64 = 0;
bu = lu = 0; bu = lu = 0;
pcibios_resource_to_bus(bridge, &region, bus->resource[2]); res = bus->resource[2];
if (bus->resource[2]->flags & IORESOURCE_PREFETCH) { pcibios_resource_to_bus(bridge, &region, res);
int width = 8; if (res->flags & IORESOURCE_PREFETCH) {
l = (region.start >> 16) & 0xfff0; l = (region.start >> 16) & 0xfff0;
l |= region.end & 0xfff00000; l |= region.end & 0xfff00000;
if (bus->resource[2]->flags & IORESOURCE_MEM_64) { if (res->flags & IORESOURCE_MEM_64) {
pref_mem64 = 1;
bu = upper_32_bits(region.start); bu = upper_32_bits(region.start);
lu = upper_32_bits(region.end); lu = upper_32_bits(region.end);
width = 16;
} }
dev_info(&bridge->dev, " PREFETCH window: %#0*llx-%#0*llx\n", dev_info(&bridge->dev, " bridge window %pR\n", res);
width, (unsigned long long)region.start,
width, (unsigned long long)region.end);
} }
else { else {
l = 0x0000fff0; l = 0x0000fff0;
dev_info(&bridge->dev, " PREFETCH window: disabled\n"); dev_info(&bridge->dev, " bridge window [mem pref disabled]\n");
} }
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l); pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
if (pref_mem64) { /* Set the upper 32 bits of PREF base & limit. */
/* Set the upper 32 bits of PREF base & limit. */ pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu); pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
}
pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
} }
...@@ -345,6 +333,10 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size) ...@@ -345,6 +333,10 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size)
#endif #endif
size = ALIGN(size + size1, 4096); size = ALIGN(size + size1, 4096);
if (!size) { if (!size) {
if (b_res->start || b_res->end)
dev_info(&bus->self->dev, "disabling bridge window "
"%pR to [bus %02x-%02x] (unused)\n", b_res,
bus->secondary, bus->subordinate);
b_res->flags = 0; b_res->flags = 0;
return; return;
} }
...@@ -390,8 +382,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, ...@@ -390,8 +382,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
align = pci_resource_alignment(dev, r); align = pci_resource_alignment(dev, r);
order = __ffs(align) - 20; order = __ffs(align) - 20;
if (order > 11) { if (order > 11) {
dev_warn(&dev->dev, "BAR %d bad alignment %llx: " dev_warn(&dev->dev, "disabling BAR %d: %pR "
"%pR\n", i, (unsigned long long)align, r); "(bad alignment %#llx)\n", i, r,
(unsigned long long) align);
r->flags = 0; r->flags = 0;
continue; continue;
} }
...@@ -425,6 +418,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, ...@@ -425,6 +418,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
} }
size = ALIGN(size, min_align); size = ALIGN(size, min_align);
if (!size) { if (!size) {
if (b_res->start || b_res->end)
dev_info(&bus->self->dev, "disabling bridge window "
"%pR to [bus %02x-%02x] (unused)\n", b_res,
bus->secondary, bus->subordinate);
b_res->flags = 0; b_res->flags = 0;
return 1; return 1;
} }
...@@ -582,10 +579,7 @@ static void pci_bus_dump_res(struct pci_bus *bus) ...@@ -582,10 +579,7 @@ static void pci_bus_dump_res(struct pci_bus *bus)
if (!res || !res->end) if (!res || !res->end)
continue; continue;
dev_printk(KERN_DEBUG, &bus->dev, "resource %d %s %pR\n", i, dev_printk(KERN_DEBUG, &bus->dev, "resource %d %pR\n", i, res);
(res->flags & IORESOURCE_IO) ? "io: " :
((res->flags & IORESOURCE_PREFETCH)? "pref mem":"mem:"),
res);
} }
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -285,15 +285,10 @@ static void quirk_system_pci_resources(struct pnp_dev *dev) ...@@ -285,15 +285,10 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
* the PCI region, and that might prevent a PCI * the PCI region, and that might prevent a PCI
* driver from requesting its resources. * driver from requesting its resources.
*/ */
dev_warn(&dev->dev, "%s resource " dev_warn(&dev->dev,
"(0x%llx-0x%llx) overlaps %s BAR %d " "disabling %pR because it overlaps "
"(0x%llx-0x%llx), disabling\n", "%s BAR %d %pR\n", res,
pnp_resource_type_name(res), pci_name(pdev), i, &pdev->resource[i]);
(unsigned long long) pnp_start,
(unsigned long long) pnp_end,
pci_name(pdev), i,
(unsigned long long) pci_start,
(unsigned long long) pci_end);
res->flags |= IORESOURCE_DISABLED; res->flags |= IORESOURCE_DISABLED;
} }
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment