Merge tag 'for-3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI update from Bjorn Helgaas: "Host bridge hotplug: - Untangle _PRT from struct pci_bus (Bjorn Helgaas) - Request _OSC control before scanning root bus (Taku Izumi) - Assign resources when adding host bridge (Yinghai Lu) - Remove root bus when removing host bridge (Yinghai Lu) - Remove _PRT during hot remove (Yinghai Lu) SRIOV - Add sysfs knobs to control numVFs (Don Dutile) Power management - Notify devices when power resource turned on (Huang Ying) Bug fixes - Work around broken _SEG on HP xw9300 (Bjorn Helgaas) - Keep runtime PM enabled for unbound PCI devices (Huang Ying) - Fix Optimus dual-GPU runtime D3 suspend issue (Dave Airlie) - Fix xen frontend shutdown issue (David Vrabel) - Work around PLX PCI 9050 BAR alignment erratum (Ian Abbott) Miscellaneous - Add GPL license for drivers/pci/ioapic (Andrew Cooks) - Add standard PCI-X, PCIe ASPM register #defines (Bjorn Helgaas) - NumaChip remote PCI support (Daniel Blueman) - Fix PCIe Link Capabilities Supported Link Speed definition (Jingoo Han) - Convert dev_printk() to dev_info(), etc (Joe Perches) - Add support for non PCI BAR ROM data (Matthew Garrett) - Add x86 support for host bridge translation offset (Mike Yoknis) - Report success only when every driver supports AER (Vijay Pandarathil)" Fix up trivial conflicts. * tag 'for-3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (48 commits) PCI: Use phys_addr_t for physical ROM address x86/PCI: Add NumaChip remote PCI support ath9k: Use standard #defines for PCIe Capability ASPM fields iwlwifi: Use standard #defines for PCIe Capability ASPM fields iwlwifi: collapse wrapper for pcie_capability_read_word() iwlegacy: Use standard #defines for PCIe Capability ASPM fields iwlegacy: collapse wrapper for pcie_capability_read_word() cxgb3: Use standard #defines for PCIe Capability ASPM fields PCI: Add standard PCIe Capability Link ASPM field names PCI/portdrv: Use PCI Express Capability accessors PCI: Use standard PCIe Capability Link register field names x86: Use PCI setup data PCI: Add support for non-BAR ROMs PCI: Add pcibios_add_device EFI: Stash ROMs if they're not in the PCI BAR PCI: Add and use standard PCI-X Capability register names PCI/PM: Keep runtime PM enabled for unbound PCI devices xen-pcifront: Handle backend CLOSED without CLOSING PCI: SRIOV control and status via sysfs (documentation) PCI/AER: Report success only when every device has AER-aware driver ...
This commit is contained in:
@@ -16,6 +16,7 @@ obj-$(CONFIG_STA2X11) += sta2x11-fixup.o
|
||||
obj-$(CONFIG_X86_VISWS) += visws.o
|
||||
|
||||
obj-$(CONFIG_X86_NUMAQ) += numaq_32.o
|
||||
obj-$(CONFIG_X86_NUMACHIP) += numachip.o
|
||||
|
||||
obj-$(CONFIG_X86_INTEL_MID) += mrst.o
|
||||
|
||||
|
@@ -12,6 +12,7 @@ struct pci_root_info {
|
||||
char name[16];
|
||||
unsigned int res_num;
|
||||
struct resource *res;
|
||||
resource_size_t *res_offset;
|
||||
struct pci_sysdata sd;
|
||||
#ifdef CONFIG_PCI_MMCONFIG
|
||||
bool mcfg_added;
|
||||
@@ -22,6 +23,7 @@ struct pci_root_info {
|
||||
};
|
||||
|
||||
static bool pci_use_crs = true;
|
||||
static bool pci_ignore_seg = false;
|
||||
|
||||
static int __init set_use_crs(const struct dmi_system_id *id)
|
||||
{
|
||||
@@ -35,7 +37,14 @@ static int __init set_nouse_crs(const struct dmi_system_id *id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id pci_use_crs_table[] __initconst = {
|
||||
static int __init set_ignore_seg(const struct dmi_system_id *id)
|
||||
{
|
||||
printk(KERN_INFO "PCI: %s detected: ignoring ACPI _SEG\n", id->ident);
|
||||
pci_ignore_seg = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id pci_crs_quirks[] __initconst = {
|
||||
/* http://bugzilla.kernel.org/show_bug.cgi?id=14183 */
|
||||
{
|
||||
.callback = set_use_crs,
|
||||
@@ -98,6 +107,16 @@ static const struct dmi_system_id pci_use_crs_table[] __initconst = {
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "6JET85WW (1.43 )"),
|
||||
},
|
||||
},
|
||||
|
||||
/* https://bugzilla.kernel.org/show_bug.cgi?id=15362 */
|
||||
{
|
||||
.callback = set_ignore_seg,
|
||||
.ident = "HP xw9300",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP xw9300 Workstation"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -108,7 +127,7 @@ void __init pci_acpi_crs_quirks(void)
|
||||
if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year < 2008)
|
||||
pci_use_crs = false;
|
||||
|
||||
dmi_check_system(pci_use_crs_table);
|
||||
dmi_check_system(pci_crs_quirks);
|
||||
|
||||
/*
|
||||
* If the user specifies "pci=use_crs" or "pci=nocrs" explicitly, that
|
||||
@@ -305,6 +324,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
|
||||
res->flags = flags;
|
||||
res->start = start;
|
||||
res->end = end;
|
||||
info->res_offset[info->res_num] = addr.translation_offset;
|
||||
|
||||
if (!pci_use_crs) {
|
||||
dev_printk(KERN_DEBUG, &info->bridge->dev,
|
||||
@@ -374,7 +394,8 @@ static void add_resources(struct pci_root_info *info,
|
||||
"ignoring host bridge window %pR (conflicts with %s %pR)\n",
|
||||
res, conflict->name, conflict);
|
||||
else
|
||||
pci_add_resource(resources, res);
|
||||
pci_add_resource_offset(resources, res,
|
||||
info->res_offset[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,6 +403,8 @@ static void free_pci_root_info_res(struct pci_root_info *info)
|
||||
{
|
||||
kfree(info->res);
|
||||
info->res = NULL;
|
||||
kfree(info->res_offset);
|
||||
info->res_offset = NULL;
|
||||
info->res_num = 0;
|
||||
}
|
||||
|
||||
@@ -432,10 +455,20 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
|
||||
return;
|
||||
|
||||
size = sizeof(*info->res) * info->res_num;
|
||||
info->res_num = 0;
|
||||
info->res = kzalloc(size, GFP_KERNEL);
|
||||
if (!info->res)
|
||||
if (!info->res) {
|
||||
info->res_num = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
size = sizeof(*info->res_offset) * info->res_num;
|
||||
info->res_num = 0;
|
||||
info->res_offset = kzalloc(size, GFP_KERNEL);
|
||||
if (!info->res_offset) {
|
||||
kfree(info->res);
|
||||
info->res = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
|
||||
info);
|
||||
@@ -455,6 +488,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
|
||||
int pxm;
|
||||
#endif
|
||||
|
||||
if (pci_ignore_seg)
|
||||
domain = 0;
|
||||
|
||||
if (domain && !pci_domains_supported) {
|
||||
printk(KERN_WARNING "pci_bus %04x:%02x: "
|
||||
"ignored (multiple domains not supported)\n",
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/pci_x86.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
|
||||
PCI_PROBE_MMCONF;
|
||||
@@ -608,6 +609,35 @@ unsigned int pcibios_assign_all_busses(void)
|
||||
return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
|
||||
}
|
||||
|
||||
int pcibios_add_device(struct pci_dev *dev)
|
||||
{
|
||||
struct setup_data *data;
|
||||
struct pci_setup_rom *rom;
|
||||
u64 pa_data;
|
||||
|
||||
pa_data = boot_params.hdr.setup_data;
|
||||
while (pa_data) {
|
||||
data = phys_to_virt(pa_data);
|
||||
|
||||
if (data->type == SETUP_PCI) {
|
||||
rom = (struct pci_setup_rom *)data;
|
||||
|
||||
if ((pci_domain_nr(dev->bus) == rom->segment) &&
|
||||
(dev->bus->number == rom->bus) &&
|
||||
(PCI_SLOT(dev->devfn) == rom->device) &&
|
||||
(PCI_FUNC(dev->devfn) == rom->function) &&
|
||||
(dev->vendor == rom->vendor) &&
|
||||
(dev->device == rom->devid)) {
|
||||
dev->rom = pa_data +
|
||||
offsetof(struct pci_setup_rom, romdata);
|
||||
dev->romlen = rom->pcilen;
|
||||
}
|
||||
}
|
||||
pa_data = data->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcibios_enable_device(struct pci_dev *dev, int mask)
|
||||
{
|
||||
int err;
|
||||
@@ -626,7 +656,7 @@ void pcibios_disable_device (struct pci_dev *dev)
|
||||
pcibios_disable_irq(dev);
|
||||
}
|
||||
|
||||
int pci_ext_cfg_avail(struct pci_dev *dev)
|
||||
int pci_ext_cfg_avail(void)
|
||||
{
|
||||
if (raw_pci_ext_ops)
|
||||
return 1;
|
||||
|
129
arch/x86/pci/numachip.c
Normal file
129
arch/x86/pci/numachip.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Numascale NumaConnect-specific PCI code
|
||||
*
|
||||
* Copyright (C) 2012 Numascale AS. All rights reserved.
|
||||
*
|
||||
* Send feedback to <support@numascale.com>
|
||||
*
|
||||
* PCI accessor functions derived from mmconfig_64.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <asm/pci_x86.h>
|
||||
|
||||
static u8 limit __read_mostly;
|
||||
|
||||
static inline char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
|
||||
{
|
||||
struct pci_mmcfg_region *cfg = pci_mmconfig_lookup(seg, bus);
|
||||
|
||||
if (cfg && cfg->virt)
|
||||
return cfg->virt + (PCI_MMCFG_BUS_OFFSET(bus) | (devfn << 12));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int pci_mmcfg_read_numachip(unsigned int seg, unsigned int bus,
|
||||
unsigned int devfn, int reg, int len, u32 *value)
|
||||
{
|
||||
char __iomem *addr;
|
||||
|
||||
/* Why do we have this when nobody checks it. How about a BUG()!? -AK */
|
||||
if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
|
||||
err: *value = -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Ensure AMD Northbridges don't decode reads to other devices */
|
||||
if (unlikely(bus == 0 && devfn >= limit)) {
|
||||
*value = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
addr = pci_dev_base(seg, bus, devfn);
|
||||
if (!addr) {
|
||||
rcu_read_unlock();
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (len) {
|
||||
case 1:
|
||||
*value = mmio_config_readb(addr + reg);
|
||||
break;
|
||||
case 2:
|
||||
*value = mmio_config_readw(addr + reg);
|
||||
break;
|
||||
case 4:
|
||||
*value = mmio_config_readl(addr + reg);
|
||||
break;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pci_mmcfg_write_numachip(unsigned int seg, unsigned int bus,
|
||||
unsigned int devfn, int reg, int len, u32 value)
|
||||
{
|
||||
char __iomem *addr;
|
||||
|
||||
/* Why do we have this when nobody checks it. How about a BUG()!? -AK */
|
||||
if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))
|
||||
return -EINVAL;
|
||||
|
||||
/* Ensure AMD Northbridges don't decode writes to other devices */
|
||||
if (unlikely(bus == 0 && devfn >= limit))
|
||||
return 0;
|
||||
|
||||
rcu_read_lock();
|
||||
addr = pci_dev_base(seg, bus, devfn);
|
||||
if (!addr) {
|
||||
rcu_read_unlock();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (len) {
|
||||
case 1:
|
||||
mmio_config_writeb(addr + reg, value);
|
||||
break;
|
||||
case 2:
|
||||
mmio_config_writew(addr + reg, value);
|
||||
break;
|
||||
case 4:
|
||||
mmio_config_writel(addr + reg, value);
|
||||
break;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct pci_raw_ops pci_mmcfg_numachip = {
|
||||
.read = pci_mmcfg_read_numachip,
|
||||
.write = pci_mmcfg_write_numachip,
|
||||
};
|
||||
|
||||
int __init pci_numachip_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 val;
|
||||
|
||||
/* For remote I/O, restrict bus 0 access to the actual number of AMD
|
||||
Northbridges, which starts at device number 0x18 */
|
||||
ret = raw_pci_read(0, 0, PCI_DEVFN(0x18, 0), 0x60, sizeof(val), &val);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* HyperTransport fabric size in bits 6:4 */
|
||||
limit = PCI_DEVFN(0x18 + ((val >> 4) & 7) + 1, 0);
|
||||
|
||||
/* Use NumaChip PCI accessors for non-extended and extended access */
|
||||
raw_pci_ops = raw_pci_ext_ops = &pci_mmcfg_numachip;
|
||||
out:
|
||||
return ret;
|
||||
}
|
Reference in New Issue
Block a user