Merge branch 'x86/platform' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip into stable/for-linus-3.7

* 'x86/platform' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (9690 commits)
  x86: Document x86_init.paging.pagetable_init()
  x86: xen: Cleanup and remove x86_init.paging.pagetable_setup_done()
  x86: Move paging_init() call to x86_init.paging.pagetable_init()
  x86: Rename pagetable_setup_start() to pagetable_init()
  x86: Remove base argument from x86_init.paging.pagetable_setup_start
  Linux 3.6-rc5
  HID: tpkbd: work even if the new Lenovo Keyboard driver is not configured
  Remove user-triggerable BUG from mpol_to_str
  xen/pciback: Fix proper FLR steps.
  uml: fix compile error in deliver_alarm()
  dj: memory scribble in logi_dj
  Fix order of arguments to compat_put_time[spec|val]
  xen: Use correct masking in xen_swiotlb_alloc_coherent.
  xen: fix logical error in tlb flushing
  xen/p2m: Fix one-off error in checking the P2M tree directory.
  powerpc: Don't use __put_user() in patch_instruction
  powerpc: Make sure IPI handlers see data written by IPI senders
  powerpc: Restore correct DSCR in context switch
  powerpc: Fix DSCR inheritance in copy_thread()
  powerpc: Keep thread.dscr and thread.dscr_inherit in sync
  ...
This commit is contained in:
Konrad Rzeszutek Wilk 2012-09-12 11:14:33 -04:00
commit 25a765b7f0
7984 changed files with 469314 additions and 200010 deletions

View file

@ -49,6 +49,7 @@ obj-$(CONFIG_MN10300) += setup-bus.o
obj-$(CONFIG_MICROBLAZE) += setup-bus.o
obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o
obj-$(CONFIG_SPARC_LEON) += setup-bus.o setup-irq.o
obj-$(CONFIG_M68K) += setup-bus.o setup-irq.o
#
# ACPI Related PCI FW Functions

View file

@ -162,7 +162,8 @@ int pci_user_read_config_##size \
if (ret > 0) \
ret = -EINVAL; \
return ret; \
}
} \
EXPORT_SYMBOL_GPL(pci_user_read_config_##size);
/* Returns 0 on success, negative values indicate error. */
#define PCI_USER_WRITE_CONFIG(size,type) \
@ -181,7 +182,8 @@ int pci_user_write_config_##size \
if (ret > 0) \
ret = -EINVAL; \
return ret; \
}
} \
EXPORT_SYMBOL_GPL(pci_user_write_config_##size);
PCI_USER_READ_CONFIG(byte, u8)
PCI_USER_READ_CONFIG(word, u16)

View file

@ -164,6 +164,8 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
int pci_bus_add_device(struct pci_dev *dev)
{
int retval;
pci_fixup_device(pci_fixup_final, dev);
retval = device_add(&dev->dev);
if (retval)
return retval;

View file

@ -4,18 +4,26 @@
#include <linux/export.h>
#include "pci.h"
unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
int __ref pci_hp_add_bridge(struct pci_dev *dev)
{
unsigned int max;
struct pci_bus *parent = dev->bus;
int pass, busnr, start = parent->busn_res.start;
int end = parent->busn_res.end;
max = pci_scan_child_bus(bus);
for (busnr = start; busnr <= end; busnr++) {
if (!pci_find_bus(pci_domain_nr(parent), busnr))
break;
}
if (busnr-- > end) {
printk(KERN_ERR "No bus number available for hot-added bridge %s\n",
pci_name(dev));
return -1;
}
for (pass = 0; pass < 2; pass++)
busnr = pci_scan_bridge(parent, dev, busnr, pass);
if (!dev->subordinate)
return -1;
/*
* Make the discovered devices available.
*/
pci_bus_add_devices(bus);
return max;
return 0;
}
EXPORT_SYMBOL(pci_do_scan_bus);
EXPORT_SYMBOL_GPL(pci_hp_add_bridge);

View file

@ -89,8 +89,6 @@ struct acpiphp_bridge {
/* PCI-to-PCI bridge device */
struct pci_dev *pci_dev;
spinlock_t res_lock;
};
@ -207,6 +205,6 @@ extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);
extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot);
/* variables */
extern int acpiphp_debug;
extern bool acpiphp_debug;
#endif /* _ACPIPHP_H */

View file

@ -47,8 +47,7 @@
/* name size which is used for entries in pcihpfs */
#define SLOT_NAME_SIZE 21 /* {_SUN} */
static bool debug;
int acpiphp_debug;
bool acpiphp_debug;
/* local variables */
static int num_slots;
@ -62,7 +61,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
module_param(debug, bool, 0644);
module_param_named(debug, acpiphp_debug, bool, 0644);
/* export the attention callback registration methods */
EXPORT_SYMBOL_GPL(acpiphp_register_attention);
@ -379,8 +378,6 @@ static int __init acpiphp_init(void)
if (acpi_pci_disabled)
return 0;
acpiphp_debug = debug;
/* read all the ACPI info from the system */
return init_acpi();
}

View file

@ -100,11 +100,11 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
PCI_PRIMARY_BUS,
&buses);
if (((buses >> 8) & 0xff) != bus->secondary) {
if (((buses >> 8) & 0xff) != bus->busn_res.start) {
buses = (buses & 0xff000000)
| ((unsigned int)(bus->primary) << 0)
| ((unsigned int)(bus->secondary) << 8)
| ((unsigned int)(bus->subordinate) << 16);
| ((unsigned int)(bus->busn_res.start) << 8)
| ((unsigned int)(bus->busn_res.end) << 16);
pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses);
}
return NOTIFY_OK;
@ -132,6 +132,15 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle))
return AE_OK;
status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
if (ACPI_FAILURE(status)) {
warn("can't evaluate _ADR (%#x)\n", status);
return AE_OK;
}
device = (adr >> 16) & 0xffff;
function = adr & 0xffff;
pdev = pbus->self;
if (pdev && pci_is_pcie(pdev)) {
tmp = acpi_find_root_bridge_handle(pdev);
@ -144,10 +153,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
}
}
acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
device = (adr >> 16) & 0xffff;
function = adr & 0xffff;
newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL);
if (!newfunc)
return AE_NO_MEMORY;
@ -391,8 +396,6 @@ static void add_host_bridge(acpi_handle *handle)
bridge->pci_bus = root->bus;
spin_lock_init(&bridge->res_lock);
init_bridge_misc(bridge);
}
@ -425,7 +428,6 @@ static void add_p2p_bridge(acpi_handle *handle)
* (which we access during module unload).
*/
get_device(&bridge->pci_bus->dev);
spin_lock_init(&bridge->res_lock);
init_bridge_misc(bridge);
return;
@ -692,7 +694,7 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
* bus->subordinate value because it could have
* padding in it.
*/
max = bus->secondary;
max = bus->busn_res.start;
list_for_each(tmp, &bus->children) {
n = pci_bus_max_busnr(pci_bus_b(tmp));
@ -878,6 +880,24 @@ static void disable_bridges(struct pci_bus *bus)
}
}
/* return first device in slot, acquiring a reference on it */
static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot)
{
struct pci_bus *bus = slot->bridge->pci_bus;
struct pci_dev *dev;
struct pci_dev *ret = NULL;
down_read(&pci_bus_sem);
list_for_each_entry(dev, &bus->devices, bus_list)
if (PCI_SLOT(dev->devfn) == slot->device) {
ret = pci_dev_get(dev);
break;
}
up_read(&pci_bus_sem);
return ret;
}
/**
* disable_device - disable a slot
* @slot: ACPI PHP slot
@ -893,6 +913,7 @@ static int disable_device(struct acpiphp_slot *slot)
pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0));
if (!pdev)
goto err_exit;
pci_dev_put(pdev);
list_for_each_entry(func, &slot->funcs, sibling) {
if (func->bridge) {
@ -901,18 +922,22 @@ static int disable_device(struct acpiphp_slot *slot)
(u32)1, NULL, NULL);
func->bridge = NULL;
}
}
pdev = pci_get_slot(slot->bridge->pci_bus,
PCI_DEVFN(slot->device, func->function));
if (pdev) {
pci_stop_bus_device(pdev);
if (pdev->subordinate) {
disable_bridges(pdev->subordinate);
pci_disable_device(pdev);
}
__pci_remove_bus_device(pdev);
pci_dev_put(pdev);
/*
* enable_device() enumerates all functions in this device via
* pci_scan_slot(), whether they have associated ACPI hotplug
* methods (_EJ0, etc.) or not. Therefore, we remove all functions
* here.
*/
while ((pdev = dev_in_slot(slot))) {
pci_stop_bus_device(pdev);
if (pdev->subordinate) {
disable_bridges(pdev->subordinate);
pci_disable_device(pdev);
}
__pci_remove_bus_device(pdev);
pci_dev_put(pdev);
}
list_for_each_entry(func, &slot->funcs, sibling) {

View file

@ -225,7 +225,7 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
struct hotplug_slot *hotplug_slot;
struct hotplug_slot_info *info;
char name[SLOT_NAME_SIZE];
int status = -ENOMEM;
int status;
int i;
if (!(controller && bus))
@ -237,18 +237,24 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
*/
for (i = first; i <= last; ++i) {
slot = kzalloc(sizeof (struct slot), GFP_KERNEL);
if (!slot)
if (!slot) {
status = -ENOMEM;
goto error;
}
hotplug_slot =
kzalloc(sizeof (struct hotplug_slot), GFP_KERNEL);
if (!hotplug_slot)
if (!hotplug_slot) {
status = -ENOMEM;
goto error_slot;
}
slot->hotplug_slot = hotplug_slot;
info = kzalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL);
if (!info)
if (!info) {
status = -ENOMEM;
goto error_hpslot;
}
hotplug_slot->info = info;
slot->bus = bus;

View file

@ -285,42 +285,19 @@ int __ref cpci_configure_slot(struct slot *slot)
for (fn = 0; fn < 8; fn++) {
struct pci_dev *dev;
dev = pci_get_slot(parent, PCI_DEVFN(PCI_SLOT(slot->devfn), fn));
dev = pci_get_slot(parent,
PCI_DEVFN(PCI_SLOT(slot->devfn), fn));
if (!dev)
continue;
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
/* Find an unused bus number for the new bridge */
struct pci_bus *child;
unsigned char busnr, start = parent->secondary;
unsigned char end = parent->subordinate;
for (busnr = start; busnr <= end; busnr++) {
if (!pci_find_bus(pci_domain_nr(parent),
busnr))
break;
}
if (busnr >= end) {
err("No free bus for hot-added bridge\n");
pci_dev_put(dev);
continue;
}
child = pci_add_new_bus(parent, dev, busnr);
if (!child) {
err("Cannot add new bus for %s\n",
pci_name(dev));
pci_dev_put(dev);
continue;
}
child->subordinate = pci_do_scan_bus(child);
pci_bus_size_bridges(child);
}
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
pci_hp_add_bridge(dev);
pci_dev_put(dev);
}
pci_bus_assign_resources(parent);
pci_assign_unassigned_bridge_resources(parent->self);
pci_bus_add_devices(parent);
pci_enable_bridges(parent);
dbg("%s - exit", __func__);
return 0;

View file

@ -611,7 +611,7 @@ static int ctrl_slot_setup(struct controller *ctrl,
u32 tempdword;
char name[SLOT_NAME_SIZE];
void __iomem *slot_entry= NULL;
int result = -ENOMEM;
int result;
dbg("%s\n", __func__);
@ -623,19 +623,25 @@ static int ctrl_slot_setup(struct controller *ctrl,
while (number_of_slots) {
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
if (!slot)
if (!slot) {
result = -ENOMEM;
goto error;
}
slot->hotplug_slot = kzalloc(sizeof(*(slot->hotplug_slot)),
GFP_KERNEL);
if (!slot->hotplug_slot)
if (!slot->hotplug_slot) {
result = -ENOMEM;
goto error_slot;
}
hotplug_slot = slot->hotplug_slot;
hotplug_slot->info = kzalloc(sizeof(*(hotplug_slot->info)),
GFP_KERNEL);
if (!hotplug_slot->info)
if (!hotplug_slot->info) {
result = -ENOMEM;
goto error_hpslot;
}
hotplug_slot_info = hotplug_slot->info;
slot->ctrl = ctrl;

View file

@ -83,7 +83,6 @@ static void __iomem *detect_HRT_floating_pointer(void __iomem *begin, void __iom
int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
{
unsigned char bus;
struct pci_bus *child;
int num;
@ -106,9 +105,10 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
}
if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus);
child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus);
pci_do_scan_bus(child);
pci_hp_add_bridge(func->pci_dev);
child = func->pci_dev->subordinate;
if (child)
pci_bus_add_devices(child);
}
pci_dev_put(func->pci_dev);

View file

@ -760,7 +760,7 @@ static u8 bus_structure_fixup(u8 busno)
for (dev->devfn = 0; dev->devfn < 256; dev->devfn += 8) {
if (!pci_read_config_word(dev, PCI_VENDOR_ID, &l) &&
(l != 0x0000) && (l != 0xffff)) {
debug("%s - Inside bus_struture_fixup()\n",
debug("%s - Inside bus_structure_fixup()\n",
__func__);
pci_scan_bus(busno, ibmphp_pci_bus->ops, NULL);
break;
@ -775,7 +775,6 @@ static u8 bus_structure_fixup(u8 busno)
static int ibm_configure_device(struct pci_func *func)
{
unsigned char bus;
struct pci_bus *child;
int num;
int flag = 0; /* this is to make sure we don't double scan the bus,
@ -805,9 +804,10 @@ static int ibm_configure_device(struct pci_func *func)
}
}
if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) {
pci_read_config_byte(func->dev, PCI_SECONDARY_BUS, &bus);
child = pci_add_new_bus(func->dev->bus, func->dev, bus);
pci_do_scan_bus(child);
pci_hp_add_bridge(func->dev);
child = func->dev->subordinate;
if (child)
pci_bus_add_devices(child);
}
return 0;

View file

@ -784,7 +784,7 @@ static int __init ebda_rsrc_controller (void)
hpc_ptr->ctlr_relative_id = ctlr;
hpc_ptr->slot_count = slot_num;
hpc_ptr->bus_count = bus_num;
debug ("now enter ctlr data struture ---\n");
debug ("now enter ctlr data structure ---\n");
debug ("ctlr id: %x\n", ctlr_id);
debug ("ctlr_relative_id: %x\n", hpc_ptr->ctlr_relative_id);
debug ("count of slots controlled by this ctlr: %x\n", slot_num);

View file

@ -109,7 +109,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)
cur_func->function = function;
debug ("inside the loop, cur_func->busno = %x, cur_func->device = %x, cur_func->funcion = %x\n",
debug ("inside the loop, cur_func->busno = %x, cur_func->device = %x, cur_func->function = %x\n",
cur_func->busno, cur_func->device, cur_func->function);
pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id);

View file

@ -149,10 +149,6 @@ int pciehp_get_attention_status(struct slot *slot, u8 *status);
int pciehp_set_attention_status(struct slot *slot, u8 status);
int pciehp_get_latch_status(struct slot *slot, u8 *status);
int pciehp_get_adapter_status(struct slot *slot, u8 *status);
int pciehp_get_max_link_speed(struct slot *slot, enum pci_bus_speed *speed);
int pciehp_get_max_link_width(struct slot *slot, enum pcie_link_width *val);
int pciehp_get_cur_link_speed(struct slot *slot, enum pci_bus_speed *speed);
int pciehp_get_cur_link_width(struct slot *slot, enum pcie_link_width *val);
int pciehp_query_power_fault(struct slot *slot);
void pciehp_green_led_on(struct slot *slot);
void pciehp_green_led_off(struct slot *slot);

View file

@ -705,107 +705,6 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
int pciehp_get_max_lnk_width(struct slot *slot,
enum pcie_link_width *value)
{
struct controller *ctrl = slot->ctrl;
enum pcie_link_width lnk_wdth;
u32 lnk_cap;
int retval = 0;
retval = pciehp_readl(ctrl, PCI_EXP_LNKCAP, &lnk_cap);
if (retval) {
ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__);
return retval;
}
switch ((lnk_cap & PCI_EXP_LNKSTA_NLW) >> 4){
case 0:
lnk_wdth = PCIE_LNK_WIDTH_RESRV;
break;
case 1:
lnk_wdth = PCIE_LNK_X1;
break;
case 2:
lnk_wdth = PCIE_LNK_X2;
break;
case 4:
lnk_wdth = PCIE_LNK_X4;
break;
case 8:
lnk_wdth = PCIE_LNK_X8;
break;
case 12:
lnk_wdth = PCIE_LNK_X12;
break;
case 16:
lnk_wdth = PCIE_LNK_X16;
break;
case 32:
lnk_wdth = PCIE_LNK_X32;
break;
default:
lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;
break;
}
*value = lnk_wdth;
ctrl_dbg(ctrl, "Max link width = %d\n", lnk_wdth);
return retval;
}
int pciehp_get_cur_lnk_width(struct slot *slot,
enum pcie_link_width *value)
{
struct controller *ctrl = slot->ctrl;
enum pcie_link_width lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;
int retval = 0;
u16 lnk_status;
retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
if (retval) {
ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n",
__func__);
return retval;
}
switch ((lnk_status & PCI_EXP_LNKSTA_NLW) >> 4){
case 0:
lnk_wdth = PCIE_LNK_WIDTH_RESRV;
break;
case 1:
lnk_wdth = PCIE_LNK_X1;
break;
case 2:
lnk_wdth = PCIE_LNK_X2;
break;
case 4:
lnk_wdth = PCIE_LNK_X4;
break;
case 8:
lnk_wdth = PCIE_LNK_X8;
break;
case 12:
lnk_wdth = PCIE_LNK_X12;
break;
case 16:
lnk_wdth = PCIE_LNK_X16;
break;
case 32:
lnk_wdth = PCIE_LNK_X32;
break;
default:
lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;
break;
}
*value = lnk_wdth;
ctrl_dbg(ctrl, "Current link width = %d\n", lnk_wdth);
return retval;
}
int pcie_enable_notification(struct controller *ctrl)
{
u16 cmd, mask;

View file

@ -34,29 +34,6 @@
#include "../pci.h"
#include "pciehp.h"
static int __ref pciehp_add_bridge(struct pci_dev *dev)
{
struct pci_bus *parent = dev->bus;
int pass, busnr, start = parent->secondary;
int end = parent->subordinate;
for (busnr = start; busnr <= end; busnr++) {
if (!pci_find_bus(pci_domain_nr(parent), busnr))
break;
}
if (busnr-- > end) {
err("No bus number available for hot-added bridge %s\n",
pci_name(dev));
return -1;
}
for (pass = 0; pass < 2; pass++)
busnr = pci_scan_bridge(parent, dev, busnr, pass);
if (!dev->subordinate)
return -1;
return 0;
}
int pciehp_configure_device(struct slot *p_slot)
{
struct pci_dev *dev;
@ -85,9 +62,8 @@ int pciehp_configure_device(struct slot *p_slot)
if (!dev)
continue;
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
pciehp_add_bridge(dev);
}
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
pci_hp_add_bridge(dev);
pci_dev_put(dev);
}

View file

@ -252,7 +252,7 @@ static int __init init_slots(void)
struct slot *slot;
struct hotplug_slot *hotplug_slot;
struct hotplug_slot_info *info;
int retval = -ENOMEM;
int retval;
int i;
/*
@ -261,17 +261,23 @@ static int __init init_slots(void)
*/
for (i = 0; i < num_slots; ++i) {
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
if (!slot)
if (!slot) {
retval = -ENOMEM;
goto error;
}
hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
if (!hotplug_slot)
if (!hotplug_slot) {
retval = -ENOMEM;
goto error_slot;
}
slot->hotplug_slot = hotplug_slot;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
if (!info) {
retval = -ENOMEM;
goto error_hpslot;
}
hotplug_slot->info = info;
slot->number = i;

View file

@ -397,13 +397,11 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
else
sn_io_slot_fixup(dev);
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
unsigned char sec_bus;
pci_read_config_byte(dev, PCI_SECONDARY_BUS,
&sec_bus);
new_bus = pci_add_new_bus(dev->bus, dev,
sec_bus);
pci_scan_child_bus(new_bus);
new_ppb = 1;
pci_hp_add_bridge(dev);
if (dev->subordinate) {
new_bus = dev->subordinate;
new_ppb = 1;
}
}
pci_dev_put(dev);
}

View file

@ -99,22 +99,28 @@ static int init_slots(struct controller *ctrl)
struct hotplug_slot *hotplug_slot;
struct hotplug_slot_info *info;
char name[SLOT_NAME_SIZE];
int retval = -ENOMEM;
int retval;
int i;
for (i = 0; i < ctrl->num_slots; i++) {
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
if (!slot)
if (!slot) {
retval = -ENOMEM;
goto error;
}
hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
if (!hotplug_slot)
if (!hotplug_slot) {
retval = -ENOMEM;
goto error_slot;
}
slot->hotplug_slot = hotplug_slot;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
if (!info) {
retval = -ENOMEM;
goto error_hpslot;
}
hotplug_slot->info = info;
slot->hp_slot = i;

View file

@ -262,9 +262,6 @@ static int board_added(struct slot *p_slot)
}
if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) {
if (slots_not_empty)
return WRONG_BUS_FREQUENCY;
if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) {
ctrl_err(ctrl, "%s: Issue of set bus speed mode command"
" failed\n", __func__);

View file

@ -37,9 +37,10 @@
int __ref shpchp_configure_device(struct slot *p_slot)
{
struct pci_dev *dev;
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
int num, fn;
struct controller *ctrl = p_slot->ctrl;
struct pci_dev *bridge = ctrl->pci_dev;
struct pci_bus *parent = bridge->subordinate;
int num, fn;
dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
if (dev) {
@ -61,39 +62,23 @@ int __ref shpchp_configure_device(struct slot *p_slot)
if (!dev)
continue;
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
/* Find an unused bus number for the new bridge */
struct pci_bus *child;
unsigned char busnr, start = parent->secondary;
unsigned char end = parent->subordinate;
for (busnr = start; busnr <= end; busnr++) {
if (!pci_find_bus(pci_domain_nr(parent),
busnr))
break;
}
if (busnr > end) {
ctrl_err(ctrl,
"No free bus for hot-added bridge\n");
pci_dev_put(dev);
continue;
}
child = pci_add_new_bus(parent, dev, busnr);
if (!child) {
ctrl_err(ctrl, "Cannot add new bus for %s\n",
pci_name(dev));
pci_dev_put(dev);
continue;
}
child->subordinate = pci_do_scan_bus(child);
pci_bus_size_bridges(child);
}
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
pci_hp_add_bridge(dev);
pci_dev_put(dev);
}
pci_assign_unassigned_bridge_resources(bridge);
for (fn = 0; fn < 8; fn++) {
dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn));
if (!dev)
continue;
pci_configure_slot(dev);
pci_dev_put(dev);
}
pci_bus_assign_resources(parent);
pci_bus_add_devices(parent);
pci_enable_bridges(parent);
return 0;
}

View file

@ -73,13 +73,13 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha
}
}
out += sprintf(out, "Free resources: bus numbers\n");
for (busnr = bus->secondary; busnr <= bus->subordinate; busnr++) {
for (busnr = bus->busn_res.start; busnr <= bus->busn_res.end; busnr++) {
if (!pci_find_bus(pci_domain_nr(bus), busnr))
break;
}
if (busnr < bus->subordinate)
if (busnr < bus->busn_res.end)
out += sprintf(out, "start = %8.8x, length = %8.8x\n",
busnr, (bus->subordinate - busnr));
busnr, (int)(bus->busn_res.end - busnr));
return out - buf;
}

View file

@ -47,7 +47,7 @@ static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr)
if (!child)
return NULL;
child->subordinate = busnr;
pci_bus_insert_busn_res(child, busnr, busnr);
child->dev.parent = bus->bridge;
rc = pci_bus_add_child(child);
if (rc) {
@ -327,7 +327,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
iov->offset = offset;
iov->stride = stride;
if (virtfn_bus(dev, nr_virtfn - 1) > dev->bus->subordinate) {
if (virtfn_bus(dev, nr_virtfn - 1) > dev->bus->busn_res.end) {
dev_err(&dev->dev, "SR-IOV: bus number out of range\n");
return -ENOMEM;
}

View file

@ -48,6 +48,12 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
if (event != ACPI_NOTIFY_DEVICE_WAKE || !pci_dev)
return;
if (pci_dev->current_state == PCI_D3cold) {
pci_wakeup_event(pci_dev);
pm_runtime_resume(&pci_dev->dev);
return;
}
if (!pci_dev->pm_cap || !pci_dev->pme_support
|| pci_check_pme_status(pci_dev)) {
if (pci_dev->pme_poll)
@ -162,6 +168,20 @@ acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
return remove_pm_notifier(dev, pci_acpi_wake_dev);
}
phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
{
acpi_status status = AE_NOT_EXIST;
unsigned long long mcfg_addr;
if (handle)
status = acpi_evaluate_integer(handle, METHOD_NAME__CBA,
NULL, &mcfg_addr);
if (ACPI_FAILURE(status))
return 0;
return (phys_addr_t)mcfg_addr;
}
/*
* _SxD returns the D-state with the highest power
* (lowest D-state number) supported in the S-state "x".
@ -187,9 +207,13 @@ acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev)
{
int acpi_state;
int acpi_state, d_max;
acpi_state = acpi_pm_device_sleep_state(&pdev->dev, NULL);
if (pdev->no_d3cold)
d_max = ACPI_STATE_D3_HOT;
else
d_max = ACPI_STATE_D3_COLD;
acpi_state = acpi_pm_device_sleep_state(&pdev->dev, NULL, d_max);
if (acpi_state < 0)
return PCI_POWER_ERROR;
@ -242,8 +266,8 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
}
if (!error)
dev_printk(KERN_INFO, &dev->dev,
"power state changed by ACPI to D%d\n", state);
dev_info(&dev->dev, "power state changed by ACPI to %s\n",
pci_power_name(state));
return error;
}
@ -296,7 +320,13 @@ static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable)
static int acpi_pci_run_wake(struct pci_dev *dev, bool enable)
{
if (dev->pme_interrupt)
/*
* Per PCI Express Base Specification Revision 2.0 section
* 5.3.3.2 Link Wakeup, platform support is needed for D3cold
* waking up to power on the main link even if there is PME
* support for D3cold
*/
if (dev->pme_interrupt && !dev->runtime_d3cold)
return 0;
if (!acpi_pm_device_run_wake(&dev->dev, enable))

View file

@ -280,8 +280,12 @@ static long local_pci_probe(void *_ddi)
{
struct drv_dev_and_id *ddi = _ddi;
struct device *dev = &ddi->dev->dev;
struct device *parent = dev->parent;
int rc;
/* The parent bridge must be in active state when probing */
if (parent)
pm_runtime_get_sync(parent);
/* Unbound PCI devices are always set to disabled and suspended.
* During probe, the device is set to enabled and active and the
* usage count is incremented. If the driver supports runtime PM,
@ -298,6 +302,8 @@ static long local_pci_probe(void *_ddi)
pm_runtime_set_suspended(dev);
pm_runtime_put_noidle(dev);
}
if (parent)
pm_runtime_put(parent);
return rc;
}
@ -459,16 +465,17 @@ static int pci_restore_standard_config(struct pci_dev *pci_dev)
return 0;
}
static void pci_pm_default_resume_early(struct pci_dev *pci_dev)
{
pci_restore_standard_config(pci_dev);
pci_fixup_device(pci_fixup_resume_early, pci_dev);
}
#endif
#ifdef CONFIG_PM_SLEEP
static void pci_pm_default_resume_early(struct pci_dev *pci_dev)
{
pci_power_up(pci_dev);
pci_restore_state(pci_dev);
pci_fixup_device(pci_fixup_resume_early, pci_dev);
}
/*
* Default "suspend" method for devices that have no driver provided suspend,
* or not even a driver at all (second part).
@ -958,6 +965,13 @@ static int pci_pm_poweroff_noirq(struct device *dev)
if (!pci_dev->state_saved && !pci_is_bridge(pci_dev))
pci_prepare_to_sleep(pci_dev);
/*
* The reason for doing this here is the same as for the analogous code
* in pci_pm_suspend_noirq().
*/
if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI)
pci_write_config_word(pci_dev, PCI_COMMAND, 0);
return 0;
}
@ -1031,10 +1045,13 @@ static int pci_pm_runtime_suspend(struct device *dev)
if (!pm || !pm->runtime_suspend)
return -ENOSYS;
pci_dev->no_d3cold = false;
error = pm->runtime_suspend(dev);
suspend_report_result(pm->runtime_suspend, error);
if (error)
return error;
if (!pci_dev->d3cold_allowed)
pci_dev->no_d3cold = true;
pci_fixup_device(pci_fixup_suspend, pci_dev);
@ -1056,17 +1073,23 @@ static int pci_pm_runtime_suspend(struct device *dev)
static int pci_pm_runtime_resume(struct device *dev)
{
int rc;
struct pci_dev *pci_dev = to_pci_dev(dev);
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
if (!pm || !pm->runtime_resume)
return -ENOSYS;
pci_pm_default_resume_early(pci_dev);
pci_restore_standard_config(pci_dev);
pci_fixup_device(pci_fixup_resume_early, pci_dev);
__pci_enable_wake(pci_dev, PCI_D0, true, false);
pci_fixup_device(pci_fixup_resume, pci_dev);
return pm->runtime_resume(dev);
rc = pm->runtime_resume(dev);
pci_dev->runtime_d3cold = false;
return rc;
}
static int pci_pm_runtime_idle(struct device *dev)

View file

@ -28,6 +28,7 @@
#include <linux/pci-aspm.h>
#include <linux/slab.h>
#include <linux/vgaarb.h>
#include <linux/pm_runtime.h>
#include "pci.h"
static int sysfs_initialized; /* = 0 */
@ -378,6 +379,31 @@ dev_bus_rescan_store(struct device *dev, struct device_attribute *attr,
#endif
#if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI)
static ssize_t d3cold_allowed_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct pci_dev *pdev = to_pci_dev(dev);
unsigned long val;
if (strict_strtoul(buf, 0, &val) < 0)
return -EINVAL;
pdev->d3cold_allowed = !!val;
pm_runtime_resume(dev);
return count;
}
static ssize_t d3cold_allowed_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev = to_pci_dev(dev);
return sprintf (buf, "%u\n", pdev->d3cold_allowed);
}
#endif
struct device_attribute pci_dev_attrs[] = {
__ATTR_RO(resource),
__ATTR_RO(vendor),
@ -401,6 +427,9 @@ struct device_attribute pci_dev_attrs[] = {
#ifdef CONFIG_HOTPLUG
__ATTR(remove, (S_IWUSR|S_IWGRP), NULL, remove_store),
__ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_rescan_store),
#endif
#if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI)
__ATTR(d3cold_allowed, 0644, d3cold_allowed_show, d3cold_allowed_store),
#endif
__ATTR_NULL,
};
@ -429,6 +458,40 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf)
}
struct device_attribute vga_attr = __ATTR_RO(boot_vga);
static void
pci_config_pm_runtime_get(struct pci_dev *pdev)
{
struct device *dev = &pdev->dev;
struct device *parent = dev->parent;
if (parent)
pm_runtime_get_sync(parent);
pm_runtime_get_noresume(dev);
/*
* pdev->current_state is set to PCI_D3cold during suspending,
* so wait until suspending completes
*/
pm_runtime_barrier(dev);
/*
* Only need to resume devices in D3cold, because config
* registers are still accessible for devices suspended but
* not in D3cold.
*/
if (pdev->current_state == PCI_D3cold)
pm_runtime_resume(dev);
}
static void
pci_config_pm_runtime_put(struct pci_dev *pdev)
{
struct device *dev = &pdev->dev;
struct device *parent = dev->parent;
pm_runtime_put(dev);
if (parent)
pm_runtime_put_sync(parent);
}
static ssize_t
pci_read_config(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
@ -455,6 +518,8 @@ pci_read_config(struct file *filp, struct kobject *kobj,
size = count;
}
pci_config_pm_runtime_get(dev);
if ((off & 1) && size) {
u8 val;
pci_user_read_config_byte(dev, off, &val);
@ -500,6 +565,8 @@ pci_read_config(struct file *filp, struct kobject *kobj,
--size;
}
pci_config_pm_runtime_put(dev);
return count;
}
@ -520,6 +587,8 @@ pci_write_config(struct file* filp, struct kobject *kobj,
count = size;
}
pci_config_pm_runtime_get(dev);
if ((off & 1) && size) {
pci_user_write_config_byte(dev, off, data[off - init_off]);
off++;
@ -558,6 +627,8 @@ pci_write_config(struct file* filp, struct kobject *kobj,
--size;
}
pci_config_pm_runtime_put(dev);
return count;
}
@ -1112,7 +1183,7 @@ static struct bin_attribute pcie_config_attr = {
.write = pci_write_config,
};
int __attribute__ ((weak)) pcibios_add_platform_entries(struct pci_dev *dev)
int __weak pcibios_add_platform_entries(struct pci_dev *dev)
{
return 0;
}

View file

@ -110,7 +110,7 @@ unsigned char pci_bus_max_busnr(struct pci_bus* bus)
struct list_head *tmp;
unsigned char max, n;
max = bus->subordinate;
max = bus->busn_res.end;
list_for_each(tmp, &bus->children) {
n = pci_bus_max_busnr(pci_bus_b(tmp));
if(n > max)
@ -136,30 +136,6 @@ void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar)
EXPORT_SYMBOL_GPL(pci_ioremap_bar);
#endif
#if 0
/**
* pci_max_busnr - returns maximum PCI bus number
*
* Returns the highest PCI bus number present in the system global list of
* PCI buses.
*/
unsigned char __devinit
pci_max_busnr(void)
{
struct pci_bus *bus = NULL;
unsigned char max, n;
max = 0;
while ((bus = pci_find_next_bus(bus)) != NULL) {
n = pci_bus_max_busnr(bus);
if(n > max)
max = n;
}
return max;
}
#endif /* 0 */
#define PCI_FIND_CAP_TTL 48
static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
@ -277,6 +253,38 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
return pos;
}
/**
* pci_pcie_cap2 - query for devices' PCI_CAP_ID_EXP v2 capability structure
* @dev: PCI device to check
*
* Like pci_pcie_cap() but also checks that the PCIe capability version is
* >= 2. Note that v1 capability structures could be sparse in that not
* all register fields were required. v2 requires the entire structure to
* be present size wise, while still allowing for non-implemented registers
* to exist but they must be hardwired to 0.
*
* Due to the differences in the versions of capability structures, one
* must be careful not to try and access non-existant registers that may
* exist in early versions - v1 - of Express devices.
*
* Returns the offset of the PCIe capability structure as long as the
* capability version is >= 2; otherwise 0 is returned.
*/
static int pci_pcie_cap2(struct pci_dev *dev)
{
u16 flags;
int pos;
pos = pci_pcie_cap(dev);
if (pos) {
pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags);
if ((flags & PCI_EXP_FLAGS_VERS) < 2)
pos = 0;
}
return pos;
}
/**
* pci_find_ext_capability - Find an extended capability
* @dev: PCI device to query
@ -329,49 +337,6 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
}
EXPORT_SYMBOL_GPL(pci_find_ext_capability);
/**
* pci_bus_find_ext_capability - find an extended capability
* @bus: the PCI bus to query
* @devfn: PCI device to query
* @cap: capability code
*
* Like pci_find_ext_capability() but works for pci devices that do not have a
* pci_dev structure set up yet.
*
* Returns the address of the requested capability structure within the
* device's PCI configuration space or 0 in case the device does not
* support it.
*/
int pci_bus_find_ext_capability(struct pci_bus *bus, unsigned int devfn,
int cap)
{
u32 header;
int ttl;
int pos = PCI_CFG_SPACE_SIZE;
/* minimum 8 bytes per capability */
ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
if (!pci_bus_read_config_dword(bus, devfn, pos, &header))
return 0;
if (header == 0xffffffff || header == 0)
return 0;
while (ttl-- > 0) {
if (PCI_EXT_CAP_ID(header) == cap)
return pos;
pos = PCI_EXT_CAP_NEXT(header);
if (pos < PCI_CFG_SPACE_SIZE)
break;
if (!pci_bus_read_config_dword(bus, devfn, pos, &header))
break;
}
return 0;
}
static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap)
{
int rc, ttl = PCI_FIND_CAP_TTL;
@ -622,7 +587,8 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
dev_info(&dev->dev, "Refused to change power state, "
"currently in D%d\n", dev->current_state);
/* According to section 5.4.1 of the "PCI BUS POWER MANAGEMENT
/*
* According to section 5.4.1 of the "PCI BUS POWER MANAGEMENT
* INTERFACE SPECIFICATION, REV. 1.2", a device transitioning
* from D3hot to D0 _may_ perform an internal reset, thereby
* going to "D0 Uninitialized" rather than "D0 Initialized".
@ -654,6 +620,16 @@ void pci_update_current_state(struct pci_dev *dev, pci_power_t state)
if (dev->pm_cap) {
u16 pmcsr;
/*
* Configuration space is not accessible for device in
* D3cold, so just keep or set D3cold for safety
*/
if (dev->current_state == PCI_D3cold)
return;
if (state == PCI_D3cold) {
dev->current_state = PCI_D3cold;
return;
}
pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
} else {
@ -661,6 +637,19 @@ void pci_update_current_state(struct pci_dev *dev, pci_power_t state)
}
}
/**
* pci_power_up - Put the given device into D0 forcibly
* @dev: PCI device to power up
*/
void pci_power_up(struct pci_dev *dev)
{
if (platform_pci_power_manageable(dev))
platform_pci_set_power_state(dev, PCI_D0);
pci_raw_set_power_state(dev, PCI_D0);
pci_update_current_state(dev, PCI_D0);
}
/**
* pci_platform_power_transition - Use platform to change device power state
* @dev: PCI device to handle.
@ -694,8 +683,50 @@ static int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state)
*/
static void __pci_start_power_transition(struct pci_dev *dev, pci_power_t state)
{
if (state == PCI_D0)
if (state == PCI_D0) {
pci_platform_power_transition(dev, PCI_D0);
/*
* Mandatory power management transition delays, see
* PCI Express Base Specification Revision 2.0 Section
* 6.6.1: Conventional Reset. Do not delay for
* devices powered on/off by corresponding bridge,
* because have already delayed for the bridge.
*/
if (dev->runtime_d3cold) {
msleep(dev->d3cold_delay);
/*
* When powering on a bridge from D3cold, the
* whole hierarchy may be powered on into
* D0uninitialized state, resume them to give
* them a chance to suspend again
*/
pci_wakeup_bus(dev->subordinate);
}
}
}
/**
* __pci_dev_set_current_state - Set current state of a PCI device
* @dev: Device to handle
* @data: pointer to state to be set
*/
static int __pci_dev_set_current_state(struct pci_dev *dev, void *data)
{
pci_power_t state = *(pci_power_t *)data;
dev->current_state = state;
return 0;
}
/**
* __pci_bus_set_current_state - Walk given bus and set current state of devices
* @bus: Top bus of the subtree to walk.
* @state: state to be set
*/
static void __pci_bus_set_current_state(struct pci_bus *bus, pci_power_t state)
{
if (bus)
pci_walk_bus(bus, __pci_dev_set_current_state, &state);
}
/**
@ -707,8 +738,15 @@ static void __pci_start_power_transition(struct pci_dev *dev, pci_power_t state)
*/
int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state)
{
return state >= PCI_D0 ?
pci_platform_power_transition(dev, state) : -EINVAL;
int ret;
if (state <= PCI_D0)
return -EINVAL;
ret = pci_platform_power_transition(dev, state);
/* Power off the bridge may power off the whole hierarchy */
if (!ret && state == PCI_D3cold)
__pci_bus_set_current_state(dev->subordinate, PCI_D3cold);
return ret;
}
EXPORT_SYMBOL_GPL(__pci_complete_power_transition);
@ -732,8 +770,8 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
int error;
/* bound the state we're entering */
if (state > PCI_D3hot)
state = PCI_D3hot;
if (state > PCI_D3cold)
state = PCI_D3cold;
else if (state < PCI_D0)
state = PCI_D0;
else if ((state == PCI_D1 || state == PCI_D2) && pci_no_d1d2(dev))
@ -744,14 +782,23 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
*/
return 0;
/* Check if we're already there */
if (dev->current_state == state)
return 0;
__pci_start_power_transition(dev, state);
/* This device is quirked not to be put into D3, so
don't put it in D3 */
if (state == PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3))
if (state >= PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3))
return 0;
error = pci_raw_set_power_state(dev, state);
/*
* To put device in D3cold, we put device into D3hot in native
* way, then put device into D3cold with platform ops
*/
error = pci_raw_set_power_state(dev, state > PCI_D3hot ?
PCI_D3hot : state);
if (!__pci_complete_power_transition(dev, state))
error = 0;
@ -822,12 +869,6 @@ EXPORT_SYMBOL(pci_choose_state);
((flags & PCI_EXP_FLAGS_VERS) > 1 || \
(type == PCI_EXP_TYPE_ROOT_PORT || \
type == PCI_EXP_TYPE_RC_EC))
#define pcie_cap_has_devctl2(type, flags) \
((flags & PCI_EXP_FLAGS_VERS) > 1)
#define pcie_cap_has_lnkctl2(type, flags) \
((flags & PCI_EXP_FLAGS_VERS) > 1)
#define pcie_cap_has_sltctl2(type, flags) \
((flags & PCI_EXP_FLAGS_VERS) > 1)
static struct pci_cap_saved_state *pci_find_saved_cap(
struct pci_dev *pci_dev, char cap)
@ -870,13 +911,14 @@ static int pci_save_pcie_state(struct pci_dev *dev)
pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
if (pcie_cap_has_rtctl(dev->pcie_type, flags))
pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
if (pcie_cap_has_devctl2(dev->pcie_type, flags))
pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &cap[i++]);
if (pcie_cap_has_lnkctl2(dev->pcie_type, flags))
pci_read_config_word(dev, pos + PCI_EXP_LNKCTL2, &cap[i++]);
if (pcie_cap_has_sltctl2(dev->pcie_type, flags))
pci_read_config_word(dev, pos + PCI_EXP_SLTCTL2, &cap[i++]);
pos = pci_pcie_cap2(dev);
if (!pos)
return 0;
pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &cap[i++]);
pci_read_config_word(dev, pos + PCI_EXP_LNKCTL2, &cap[i++]);
pci_read_config_word(dev, pos + PCI_EXP_SLTCTL2, &cap[i++]);
return 0;
}
@ -903,12 +945,14 @@ static void pci_restore_pcie_state(struct pci_dev *dev)
pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]);
if (pcie_cap_has_rtctl(dev->pcie_type, flags))
pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]);
if (pcie_cap_has_devctl2(dev->pcie_type, flags))
pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, cap[i++]);
if (pcie_cap_has_lnkctl2(dev->pcie_type, flags))
pci_write_config_word(dev, pos + PCI_EXP_LNKCTL2, cap[i++]);
if (pcie_cap_has_sltctl2(dev->pcie_type, flags))
pci_write_config_word(dev, pos + PCI_EXP_SLTCTL2, cap[i++]);
pos = pci_pcie_cap2(dev);
if (!pos)
return;
pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, cap[i++]);
pci_write_config_word(dev, pos + PCI_EXP_LNKCTL2, cap[i++]);
pci_write_config_word(dev, pos + PCI_EXP_SLTCTL2, cap[i++]);
}
@ -1349,7 +1393,7 @@ void pcim_pin_device(struct pci_dev *pdev)
* is the default implementation. Architecture implementations can
* override this.
*/
void __attribute__ ((weak)) pcibios_disable_device (struct pci_dev *dev) {}
void __weak pcibios_disable_device (struct pci_dev *dev) {}
static void do_pci_disable_device(struct pci_dev *dev)
{
@ -1413,8 +1457,8 @@ pci_disable_device(struct pci_dev *dev)
* Sets the PCIe reset state for the device. This is the default
* implementation. Architecture implementations can override this.
*/
int __attribute__ ((weak)) pcibios_set_pcie_reset_state(struct pci_dev *dev,
enum pcie_reset_state state)
int __weak pcibios_set_pcie_reset_state(struct pci_dev *dev,
enum pcie_reset_state state)
{
return -EINVAL;
}
@ -1497,6 +1541,28 @@ void pci_pme_wakeup_bus(struct pci_bus *bus)
pci_walk_bus(bus, pci_pme_wakeup, (void *)true);
}
/**
* pci_wakeup - Wake up a PCI device
* @dev: Device to handle.
* @ign: ignored parameter
*/
static int pci_wakeup(struct pci_dev *pci_dev, void *ign)
{
pci_wakeup_event(pci_dev);
pm_request_resume(&pci_dev->dev);
return 0;
}
/**
* pci_wakeup_bus - Walk given bus and wake up devices on it
* @bus: Top bus of the subtree to walk.
*/
void pci_wakeup_bus(struct pci_bus *bus)
{
if (bus)
pci_walk_bus(bus, pci_wakeup, NULL);
}
/**
* pci_pme_capable - check the capability of PCI device to generate PME#
* @dev: PCI device to handle.
@ -1518,6 +1584,16 @@ static void pci_pme_list_scan(struct work_struct *work)
if (!list_empty(&pci_pme_list)) {
list_for_each_entry_safe(pme_dev, n, &pci_pme_list, list) {
if (pme_dev->dev->pme_poll) {
struct pci_dev *bridge;
bridge = pme_dev->dev->bus->self;
/*
* If bridge is in low power state, the
* configuration space of subordinate devices
* may be not accessible
*/
if (bridge && bridge->current_state != PCI_D0)
continue;
pci_pme_wakeup(pme_dev->dev, NULL);
} else {
list_del(&pme_dev->list);
@ -1744,6 +1820,10 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
if (target_state == PCI_POWER_ERROR)
return -EIO;
/* D3cold during system suspend/hibernate is not supported */
if (target_state > PCI_D3hot)
target_state = PCI_D3hot;
pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev));
error = pci_set_power_state(dev, target_state);
@ -1781,12 +1861,16 @@ int pci_finish_runtime_suspend(struct pci_dev *dev)
if (target_state == PCI_POWER_ERROR)
return -EIO;
dev->runtime_d3cold = target_state == PCI_D3cold;
__pci_enable_wake(dev, target_state, true, pci_dev_run_wake(dev));
error = pci_set_power_state(dev, target_state);
if (error)
if (error) {
__pci_enable_wake(dev, target_state, true, false);
dev->runtime_d3cold = false;
}
return error;
}
@ -1856,6 +1940,8 @@ void pci_pm_init(struct pci_dev *dev)
dev->pm_cap = pm;
dev->d3_delay = PCI_PM_D3_WAIT;
dev->d3cold_delay = PCI_PM_D3COLD_WAIT;
dev->d3cold_allowed = true;
dev->d1_support = false;
dev->d2_support = false;
@ -1983,7 +2069,7 @@ void pci_enable_ari(struct pci_dev *dev)
{
int pos;
u32 cap;
u16 flags, ctrl;
u16 ctrl;
struct pci_dev *bridge;
if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn)
@ -1994,18 +2080,14 @@ void pci_enable_ari(struct pci_dev *dev)
return;
bridge = dev->bus->self;
if (!bridge || !pci_is_pcie(bridge))
if (!bridge)
return;
pos = pci_pcie_cap(bridge);
/* ARI is a PCIe cap v2 feature */
pos = pci_pcie_cap2(bridge);
if (!pos)
return;
/* ARI is a PCIe v2 feature */
pci_read_config_word(bridge, pos + PCI_EXP_FLAGS, &flags);
if ((flags & PCI_EXP_FLAGS_VERS) < 2)
return;
pci_read_config_dword(bridge, pos + PCI_EXP_DEVCAP2, &cap);
if (!(cap & PCI_EXP_DEVCAP2_ARI))
return;
@ -2018,7 +2100,7 @@ void pci_enable_ari(struct pci_dev *dev)
}
/**
* pci_enable_ido - enable ID-based ordering on a device
* pci_enable_ido - enable ID-based Ordering on a device
* @dev: the PCI device
* @type: which types of IDO to enable
*
@ -2031,7 +2113,8 @@ void pci_enable_ido(struct pci_dev *dev, unsigned long type)
int pos;
u16 ctrl;
pos = pci_pcie_cap(dev);
/* ID-based Ordering is a PCIe cap v2 feature */
pos = pci_pcie_cap2(dev);
if (!pos)
return;
@ -2054,10 +2137,8 @@ void pci_disable_ido(struct pci_dev *dev, unsigned long type)
int pos;
u16 ctrl;
if (!pci_is_pcie(dev))
return;
pos = pci_pcie_cap(dev);
/* ID-based Ordering is a PCIe cap v2 feature */
pos = pci_pcie_cap2(dev);
if (!pos)
return;
@ -2096,10 +2177,8 @@ int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type)
u16 ctrl;
int ret;
if (!pci_is_pcie(dev))
return -ENOTSUPP;
pos = pci_pcie_cap(dev);
/* OBFF is a PCIe cap v2 feature */
pos = pci_pcie_cap2(dev);
if (!pos)
return -ENOTSUPP;
@ -2108,7 +2187,7 @@ int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type)
return -ENOTSUPP; /* no OBFF support at all */
/* Make sure the topology supports OBFF as well */
if (dev->bus) {
if (dev->bus->self) {
ret = pci_enable_obff(dev->bus->self, type);
if (ret)
return ret;
@ -2149,10 +2228,8 @@ void pci_disable_obff(struct pci_dev *dev)
int pos;
u16 ctrl;
if (!pci_is_pcie(dev))
return;
pos = pci_pcie_cap(dev);
/* OBFF is a PCIe cap v2 feature */
pos = pci_pcie_cap2(dev);
if (!pos)
return;
@ -2169,15 +2246,13 @@ EXPORT_SYMBOL(pci_disable_obff);
* RETURNS:
* True if @dev supports latency tolerance reporting, false otherwise.
*/
bool pci_ltr_supported(struct pci_dev *dev)
static bool pci_ltr_supported(struct pci_dev *dev)
{
int pos;
u32 cap;
if (!pci_is_pcie(dev))
return false;
pos = pci_pcie_cap(dev);
/* LTR is a PCIe cap v2 feature */
pos = pci_pcie_cap2(dev);
if (!pos)
return false;
@ -2185,7 +2260,6 @@ bool pci_ltr_supported(struct pci_dev *dev)
return cap & PCI_EXP_DEVCAP2_LTR;
}
EXPORT_SYMBOL(pci_ltr_supported);
/**
* pci_enable_ltr - enable latency tolerance reporting
@ -2206,7 +2280,8 @@ int pci_enable_ltr(struct pci_dev *dev)
if (!pci_ltr_supported(dev))
return -ENOTSUPP;
pos = pci_pcie_cap(dev);
/* LTR is a PCIe cap v2 feature */
pos = pci_pcie_cap2(dev);
if (!pos)
return -ENOTSUPP;
@ -2215,7 +2290,7 @@ int pci_enable_ltr(struct pci_dev *dev)
return -EINVAL;
/* Enable upstream ports first */
if (dev->bus) {
if (dev->bus->self) {
ret = pci_enable_ltr(dev->bus->self);
if (ret)
return ret;
@ -2241,7 +2316,8 @@ void pci_disable_ltr(struct pci_dev *dev)
if (!pci_ltr_supported(dev))
return;
pos = pci_pcie_cap(dev);
/* LTR is a PCIe cap v2 feature */
pos = pci_pcie_cap2(dev);
if (!pos)
return;
@ -2359,6 +2435,75 @@ void pci_enable_acs(struct pci_dev *dev)
pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
}
/**
* pci_acs_enabled - test ACS against required flags for a given device
* @pdev: device to test
* @acs_flags: required PCI ACS flags
*
* Return true if the device supports the provided flags. Automatically
* filters out flags that are not implemented on multifunction devices.
*/
bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags)
{
int pos, ret;
u16 ctrl;
ret = pci_dev_specific_acs_enabled(pdev, acs_flags);
if (ret >= 0)
return ret > 0;
if (!pci_is_pcie(pdev))
return false;
/* Filter out flags not applicable to multifunction */
if (pdev->multifunction)
acs_flags &= (PCI_ACS_RR | PCI_ACS_CR |
PCI_ACS_EC | PCI_ACS_DT);
if (pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM ||
pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
pdev->multifunction) {
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ACS);
if (!pos)
return false;
pci_read_config_word(pdev, pos + PCI_ACS_CTRL, &ctrl);
if ((ctrl & acs_flags) != acs_flags)
return false;
}
return true;
}
/**
* pci_acs_path_enable - test ACS flags from start to end in a hierarchy
* @start: starting downstream device
* @end: ending upstream device or NULL to search to the root bus
* @acs_flags: required flags
*
* Walk up a device tree from start to end testing PCI ACS support. If
* any step along the way does not support the required flags, return false.
*/
bool pci_acs_path_enabled(struct pci_dev *start,
struct pci_dev *end, u16 acs_flags)
{
struct pci_dev *pdev, *parent = start;
do {
pdev = parent;
if (!pci_acs_enabled(pdev, acs_flags))
return false;
if (pci_is_root_bus(pdev->bus))
return (end == NULL);
parent = pdev->bus->self;
} while (pdev != end);
return true;
}
/**
* pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge
* @dev: the PCI device
@ -2665,6 +2810,18 @@ static void __pci_set_master(struct pci_dev *dev, bool enable)
dev->is_busmaster = enable;
}
/**
* pcibios_setup - process "pci=" kernel boot arguments
* @str: string used to pass in "pci=" kernel boot arguments
*
* Process kernel boot arguments. This is the default implementation.
* Architecture specific implementations can override this as necessary.
*/
char * __weak __init pcibios_setup(char *str)
{
return str;
}
/**
* pcibios_set_master - enable PCI bus-mastering for device dev
* @dev: the PCI device to enable
@ -2876,6 +3033,9 @@ bool pci_intx_mask_supported(struct pci_dev *dev)
bool mask_supported = false;
u16 orig, new;
if (dev->broken_intx_masking)
return false;
pci_cfg_access_lock(dev);
pci_read_config_word(dev, PCI_COMMAND, &orig);
@ -3395,8 +3555,7 @@ int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc)
o = (cmd & PCI_X_CMD_MAX_READ) >> 2;
if (o != v) {
if (v > o && dev->bus &&
(dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MMRBC))
if (v > o && (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MMRBC))
return -EIO;
cmd &= ~PCI_X_CMD_MAX_READ;
@ -3851,7 +4010,7 @@ static void __devinit pci_no_domains(void)
* greater than 0xff). This is the default implementation. Architecture
* implementations can override this.
*/
int __attribute__ ((weak)) pci_ext_cfg_avail(struct pci_dev *dev)
int __weak pci_ext_cfg_avail(struct pci_dev *dev)
{
return 1;
}

View file

@ -67,9 +67,11 @@ struct pci_platform_pm_ops {
extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops);
extern void pci_update_current_state(struct pci_dev *dev, pci_power_t state);
extern void pci_power_up(struct pci_dev *dev);
extern void pci_disable_enabled_device(struct pci_dev *dev);
extern int pci_finish_runtime_suspend(struct pci_dev *dev);
extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
extern void pci_wakeup_bus(struct pci_bus *bus);
extern void pci_pm_init(struct pci_dev *dev);
extern void platform_pci_wakeup_init(struct pci_dev *dev);
extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
@ -86,13 +88,6 @@ static inline bool pci_is_bridge(struct pci_dev *pci_dev)
return !!(pci_dev->subordinate);
}
extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
extern int pci_user_read_config_dword(struct pci_dev *dev, int where, u32 *val);
extern int pci_user_write_config_byte(struct pci_dev *dev, int where, u8 val);
extern int pci_user_write_config_word(struct pci_dev *dev, int where, u16 val);
extern int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val);
struct pci_vpd_ops {
ssize_t (*read)(struct pci_dev *dev, loff_t pos, size_t count, void *buf);
ssize_t (*write)(struct pci_dev *dev, loff_t pos, size_t count, const void *buf);
@ -124,7 +119,7 @@ static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; }
#endif
/* Functions for PCI Hotplug drivers to use */
extern unsigned int pci_do_scan_bus(struct pci_bus *bus);
int pci_hp_add_bridge(struct pci_dev *dev);
#ifdef HAVE_PCI_LEGACY
extern void pci_create_legacy_files(struct pci_bus *bus);

View file

@ -59,7 +59,7 @@ static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data)
p = (struct acpi_hest_aer_common *)(hest_hdr + 1);
if (p->flags & ACPI_HEST_GLOBAL) {
if ((info->pci_dev->is_pcie &&
if ((pci_is_pcie(info->pci_dev) &&
info->pci_dev->pcie_type == pcie_type) || bridge)
ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
} else

View file

@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/init.h>
#include <linux/pcieport_if.h>
#include <linux/aer.h>
@ -99,6 +100,59 @@ static int pcie_port_resume_noirq(struct device *dev)
return 0;
}
#ifdef CONFIG_PM_RUNTIME
struct d3cold_info {
bool no_d3cold;
unsigned int d3cold_delay;
};
static int pci_dev_d3cold_info(struct pci_dev *pdev, void *data)
{
struct d3cold_info *info = data;
info->d3cold_delay = max_t(unsigned int, pdev->d3cold_delay,
info->d3cold_delay);
if (pdev->no_d3cold)
info->no_d3cold = true;
return 0;
}
static int pcie_port_runtime_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct d3cold_info d3cold_info = {
.no_d3cold = false,
.d3cold_delay = PCI_PM_D3_WAIT,
};
/*
* If any subordinate device disable D3cold, we should not put
* the port into D3cold. The D3cold delay of port should be
* the max of that of all subordinate devices.
*/
pci_walk_bus(pdev->subordinate, pci_dev_d3cold_info, &d3cold_info);
pdev->no_d3cold = d3cold_info.no_d3cold;
pdev->d3cold_delay = d3cold_info.d3cold_delay;
return 0;
}
static int pcie_port_runtime_resume(struct device *dev)
{
return 0;
}
static int pcie_port_runtime_idle(struct device *dev)
{
/* Delay for a short while to prevent too frequent suspend/resume */
pm_schedule_suspend(dev, 10);
return -EBUSY;
}
#else
#define pcie_port_runtime_suspend NULL
#define pcie_port_runtime_resume NULL
#define pcie_port_runtime_idle NULL
#endif
static const struct dev_pm_ops pcie_portdrv_pm_ops = {
.suspend = pcie_port_device_suspend,
.resume = pcie_port_device_resume,
@ -107,6 +161,9 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
.poweroff = pcie_port_device_suspend,
.restore = pcie_port_device_resume,
.resume_noirq = pcie_port_resume_noirq,
.runtime_suspend = pcie_port_runtime_suspend,
.runtime_resume = pcie_port_runtime_resume,
.runtime_idle = pcie_port_runtime_idle,
};
#define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops)
@ -116,6 +173,14 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
#define PCIE_PORTDRV_PM_OPS NULL
#endif /* !PM */
/*
* PCIe port runtime suspend is broken for some chipsets, so use a
* black list to disable runtime PM for these chipsets.
*/
static const struct pci_device_id port_runtime_pm_black_list[] = {
{ /* end: all zeroes */ }
};
/*
* pcie_portdrv_probe - Probe PCI-Express port devices
* @dev: PCI-Express port device being probed
@ -144,12 +209,21 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
return status;
pci_save_state(dev);
/*
* D3cold may not work properly on some PCIe port, so disable
* it by default.
*/
dev->d3cold_allowed = false;
if (!pci_match_id(port_runtime_pm_black_list, dev))
pm_runtime_put_noidle(&dev->dev);
return 0;
}
static void pcie_portdrv_remove(struct pci_dev *dev)
{
if (!pci_match_id(port_runtime_pm_black_list, dev))
pm_runtime_get_noresume(&dev->dev);
pcie_port_device_remove(dev);
pci_disable_device(dev);
}

View file

@ -16,10 +16,47 @@
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
#define CARDBUS_RESERVE_BUSNR 3
struct resource busn_resource = {
.name = "PCI busn",
.start = 0,
.end = 255,
.flags = IORESOURCE_BUS,
};
/* Ugh. Need to stop exporting this to modules. */
LIST_HEAD(pci_root_buses);
EXPORT_SYMBOL(pci_root_buses);
static LIST_HEAD(pci_domain_busn_res_list);
struct pci_domain_busn_res {
struct list_head list;
struct resource res;
int domain_nr;
};
static struct resource *get_pci_domain_busn_res(int domain_nr)
{
struct pci_domain_busn_res *r;
list_for_each_entry(r, &pci_domain_busn_res_list, list)
if (r->domain_nr == domain_nr)
return &r->res;
r = kzalloc(sizeof(*r), GFP_KERNEL);
if (!r)
return NULL;
r->domain_nr = domain_nr;
r->res.start = 0;
r->res.end = 0xff;
r->res.flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED;
list_add_tail(&r->list, &pci_domain_busn_res_list);
return &r->res;
}
static int find_anything(struct device *dev, void *data)
{
return 1;
@ -107,15 +144,13 @@ static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar)
case PCI_BASE_ADDRESS_MEM_TYPE_32:
break;
case PCI_BASE_ADDRESS_MEM_TYPE_1M:
dev_info(&dev->dev, "1M mem BAR treated as 32-bit BAR\n");
/* 1M mem BAR treated as 32-bit BAR */
break;
case PCI_BASE_ADDRESS_MEM_TYPE_64:
flags |= IORESOURCE_MEM_64;
break;
default:
dev_warn(&dev->dev,
"mem unknown type %x treated as 32-bit BAR\n",
mem_type);
/* mem unknown type treated as 32-bit BAR */
break;
}
return flags;
@ -136,9 +171,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
u32 l, sz, mask;
u16 orig_cmd;
struct pci_bus_region region;
bool bar_too_big = false, bar_disabled = false;
mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
/* No printks while decoding is disabled! */
if (!dev->mmio_always_on) {
pci_read_config_word(dev, PCI_COMMAND, &orig_cmd);
pci_write_config_word(dev, PCI_COMMAND,
@ -152,9 +189,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
pci_read_config_dword(dev, pos, &sz);
pci_write_config_dword(dev, pos, l);
if (!dev->mmio_always_on)
pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
/*
* All bits set in sz means the device isn't working properly.
* If the BAR isn't implemented, all bits must be 0. If it's a
@ -206,8 +240,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
goto fail;
if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) {
dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n",
pos);
bar_too_big = true;
goto fail;
}
@ -218,12 +251,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
region.start = 0;
region.end = sz64;
pcibios_bus_to_resource(dev, res, &region);
bar_disabled = true;
} else {
region.start = l64;
region.end = l64 + sz64;
pcibios_bus_to_resource(dev, res, &region);
dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n",
pos, res);
}
} else {
sz = pci_size(l, sz, mask);
@ -234,15 +266,23 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
region.start = l;
region.end = l + sz;
pcibios_bus_to_resource(dev, res, &region);
dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
}
out:
return (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
fail:
res->flags = 0;
goto out;
fail:
res->flags = 0;
out:
if (!dev->mmio_always_on)
pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
if (bar_too_big)
dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", pos);
if (res->flags && !bar_disabled)
dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
return (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
}
static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
@ -269,34 +309,38 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child)
{
struct pci_dev *dev = child->self;
u8 io_base_lo, io_limit_lo;
unsigned long base, limit;
unsigned long io_mask, io_granularity, base, limit;
struct pci_bus_region region;
struct resource *res, res2;
struct resource *res;
io_mask = PCI_IO_RANGE_MASK;
io_granularity = 0x1000;
if (dev->io_window_1k) {
/* Support 1K I/O space granularity */
io_mask = PCI_IO_1K_RANGE_MASK;
io_granularity = 0x400;
}
res = child->resource[0];
pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
base = (io_base_lo & PCI_IO_RANGE_MASK) << 8;
limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8;
base = (io_base_lo & io_mask) << 8;
limit = (io_limit_lo & io_mask) << 8;
if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
u16 io_base_hi, io_limit_hi;
pci_read_config_word(dev, PCI_IO_BASE_UPPER16, &io_base_hi);
pci_read_config_word(dev, PCI_IO_LIMIT_UPPER16, &io_limit_hi);
base |= (io_base_hi << 16);
limit |= (io_limit_hi << 16);
base |= ((unsigned long) io_base_hi << 16);
limit |= ((unsigned long) io_limit_hi << 16);
}
if (base && base <= limit) {
if (base <= limit) {
res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
res2.flags = res->flags;
region.start = base;
region.end = limit + 0xfff;
pcibios_bus_to_resource(dev, &res2, &region);
if (!res->start)
res->start = res2.start;
if (!res->end)
res->end = res2.end;
region.end = limit + io_granularity - 1;
pcibios_bus_to_resource(dev, res, &region);
dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
}
}
@ -312,9 +356,9 @@ static void __devinit pci_read_bridge_mmio(struct pci_bus *child)
res = child->resource[1];
pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo);
pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo);
base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
if (base && base <= limit) {
base = ((unsigned long) mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
limit = ((unsigned long) mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
if (base <= limit) {
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
region.start = base;
region.end = limit + 0xfffff;
@ -334,11 +378,12 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
res = child->resource[2];
pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo);
base = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
limit = (mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
base = ((unsigned long) mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
limit = ((unsigned long) mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
u32 mem_base_hi, mem_limit_hi;
pci_read_config_dword(dev, PCI_PREF_BASE_UPPER32, &mem_base_hi);
pci_read_config_dword(dev, PCI_PREF_LIMIT_UPPER32, &mem_limit_hi);
@ -349,8 +394,8 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
*/
if (mem_base_hi <= mem_limit_hi) {
#if BITS_PER_LONG == 64
base |= ((long) mem_base_hi) << 32;
limit |= ((long) mem_limit_hi) << 32;
base |= ((unsigned long) mem_base_hi) << 32;
limit |= ((unsigned long) mem_limit_hi) << 32;
#else
if (mem_base_hi || mem_limit_hi) {
dev_err(&dev->dev, "can't handle 64-bit "
@ -360,7 +405,7 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
#endif
}
}
if (base && base <= limit) {
if (base <= limit) {
res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) |
IORESOURCE_MEM | IORESOURCE_PREFETCH;
if (res->flags & PCI_PREF_RANGE_TYPE_64)
@ -381,8 +426,8 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
if (pci_is_root_bus(child)) /* It's a host bus, nothing to read */
return;
dev_info(&dev->dev, "PCI bridge to [bus %02x-%02x]%s\n",
child->secondary, child->subordinate,
dev_info(&dev->dev, "PCI bridge to %pR%s\n",
&child->busn_res,
dev->transparent ? " (subtractive decode)" : "");
pci_bus_remove_resources(child);
@ -599,9 +644,9 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
* Set up the primary, secondary and subordinate
* bus numbers.
*/
child->number = child->secondary = busnr;
child->primary = parent->secondary;
child->subordinate = 0xff;
child->number = child->busn_res.start = busnr;
child->primary = parent->busn_res.start;
child->busn_res.end = 0xff;
if (!bridge)
return child;
@ -643,8 +688,8 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
if (!pcibios_assign_all_busses())
return;
while (parent->parent && parent->subordinate < max) {
parent->subordinate = max;
while (parent->parent && parent->busn_res.end < max) {
parent->busn_res.end = max;
pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max);
parent = parent->parent;
}
@ -718,15 +763,15 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
if (!child)
goto out;
child->primary = primary;
child->subordinate = subordinate;
pci_bus_insert_busn_res(child, secondary, subordinate);
child->bridge_ctl = bctl;
}
cmax = pci_scan_child_bus(child);
if (cmax > max)
max = cmax;
if (child->subordinate > max)
max = child->subordinate;
if (child->busn_res.end > max)
max = child->busn_res.end;
} else {
/*
* We need to assign a number to this bus which we always
@ -756,11 +801,12 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
child = pci_add_new_bus(bus, dev, ++max);
if (!child)
goto out;
pci_bus_insert_busn_res(child, max, 0xff);
}
buses = (buses & 0xff000000)
| ((unsigned int)(child->primary) << 0)
| ((unsigned int)(child->secondary) << 8)
| ((unsigned int)(child->subordinate) << 16);
| ((unsigned int)(child->busn_res.start) << 8)
| ((unsigned int)(child->busn_res.end) << 16);
/*
* yenta.c forces a secondary latency timer of 176.
@ -805,8 +851,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
break;
while (parent->parent) {
if ((!pcibios_assign_all_busses()) &&
(parent->subordinate > max) &&
(parent->subordinate <= max+i)) {
(parent->busn_res.end > max) &&
(parent->busn_res.end <= max+i)) {
j = 1;
}
parent = parent->parent;
@ -827,7 +873,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
/*
* Set the subordinate bus number to its real value.
*/
child->subordinate = max;
pci_bus_update_busn_res_end(child, max);
pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
}
@ -837,19 +883,19 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
/* Has only triggered on CardBus, fixup is in yenta_socket */
while (bus->parent) {
if ((child->subordinate > bus->subordinate) ||
(child->number > bus->subordinate) ||
if ((child->busn_res.end > bus->busn_res.end) ||
(child->number > bus->busn_res.end) ||
(child->number < bus->number) ||
(child->subordinate < bus->number)) {
dev_info(&child->dev, "[bus %02x-%02x] %s "
"hidden behind%s bridge %s [bus %02x-%02x]\n",
child->number, child->subordinate,
(bus->number > child->subordinate &&
bus->subordinate < child->number) ?
(child->busn_res.end < bus->number)) {
dev_info(&child->dev, "%pR %s "
"hidden behind%s bridge %s %pR\n",
&child->busn_res,
(bus->number > child->busn_res.end &&
bus->busn_res.end < child->number) ?
"wholly" : "partially",
bus->self->transparent ? " transparent" : "",
dev_name(&bus->dev),
bus->number, bus->subordinate);
&bus->busn_res);
}
bus = bus->parent;
}
@ -1548,7 +1594,7 @@ EXPORT_SYMBOL_GPL(pcie_bus_configure_settings);
unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
{
unsigned int devfn, pass, max = bus->secondary;
unsigned int devfn, pass, max = bus->busn_res.start;
struct pci_dev *dev;
dev_dbg(&bus->dev, "scanning bus\n");
@ -1642,7 +1688,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
/* Create legacy_io and legacy_mem files for this bus */
pci_create_legacy_files(b);
b->number = b->secondary = bus;
b->number = b->busn_res.start = bus;
if (parent)
dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
@ -1654,7 +1700,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
list_move_tail(&window->list, &bridge->windows);
res = window->res;
offset = window->offset;
pci_bus_add_resource(b, res, 0);
if (res->flags & IORESOURCE_BUS)
pci_bus_insert_busn_res(b, bus, res->end);
else
pci_bus_add_resource(b, res, 0);
if (offset) {
if (resource_type(res) == IORESOURCE_IO)
fmt = " (bus address [%#06llx-%#06llx])";
@ -1684,16 +1733,104 @@ err_out:
return NULL;
}
int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
{
struct resource *res = &b->busn_res;
struct resource *parent_res, *conflict;
res->start = bus;
res->end = bus_max;
res->flags = IORESOURCE_BUS;
if (!pci_is_root_bus(b))
parent_res = &b->parent->busn_res;
else {
parent_res = get_pci_domain_busn_res(pci_domain_nr(b));
res->flags |= IORESOURCE_PCI_FIXED;
}
conflict = insert_resource_conflict(parent_res, res);
if (conflict)
dev_printk(KERN_DEBUG, &b->dev,
"busn_res: can not insert %pR under %s%pR (conflicts with %s %pR)\n",
res, pci_is_root_bus(b) ? "domain " : "",
parent_res, conflict->name, conflict);
else
dev_printk(KERN_DEBUG, &b->dev,
"busn_res: %pR is inserted under %s%pR\n",
res, pci_is_root_bus(b) ? "domain " : "",
parent_res);
return conflict == NULL;
}
int pci_bus_update_busn_res_end(struct pci_bus *b, int bus_max)
{
struct resource *res = &b->busn_res;
struct resource old_res = *res;
resource_size_t size;
int ret;
if (res->start > bus_max)
return -EINVAL;
size = bus_max - res->start + 1;
ret = adjust_resource(res, res->start, size);
dev_printk(KERN_DEBUG, &b->dev,
"busn_res: %pR end %s updated to %02x\n",
&old_res, ret ? "can not be" : "is", bus_max);
if (!ret && !res->parent)
pci_bus_insert_busn_res(b, res->start, res->end);
return ret;
}
void pci_bus_release_busn_res(struct pci_bus *b)
{
struct resource *res = &b->busn_res;
int ret;
if (!res->flags || !res->parent)
return;
ret = release_resource(res);
dev_printk(KERN_DEBUG, &b->dev,
"busn_res: %pR %s released\n",
res, ret ? "can not be" : "is");
}
struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata, struct list_head *resources)
{
struct pci_host_bridge_window *window;
bool found = false;
struct pci_bus *b;
int max;
list_for_each_entry(window, resources, list)
if (window->res->flags & IORESOURCE_BUS) {
found = true;
break;
}
b = pci_create_root_bus(parent, bus, ops, sysdata, resources);
if (!b)
return NULL;
b->subordinate = pci_scan_child_bus(b);
if (!found) {
dev_info(&b->dev,
"No busn resource found for root bus, will use [bus %02x-ff]\n",
bus);
pci_bus_insert_busn_res(b, bus, 255);
}
max = pci_scan_child_bus(b);
if (!found)
pci_bus_update_busn_res_end(b, max);
pci_bus_add_devices(b);
return b;
}
@ -1708,9 +1845,10 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
pci_add_resource(&resources, &ioport_resource);
pci_add_resource(&resources, &iomem_resource);
pci_add_resource(&resources, &busn_resource);
b = pci_create_root_bus(parent, bus, ops, sysdata, &resources);
if (b)
b->subordinate = pci_scan_child_bus(b);
pci_scan_child_bus(b);
else
pci_free_resource_list(&resources);
return b;
@ -1725,9 +1863,10 @@ struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops,
pci_add_resource(&resources, &ioport_resource);
pci_add_resource(&resources, &iomem_resource);
pci_add_resource(&resources, &busn_resource);
b = pci_create_root_bus(NULL, bus, ops, sysdata, &resources);
if (b) {
b->subordinate = pci_scan_child_bus(b);
pci_scan_child_bus(b);
pci_bus_add_devices(b);
} else {
pci_free_resource_list(&resources);

View file

@ -253,7 +253,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, quirk_vsfx)
* workaround applied too
* [Info kindly provided by ALi]
*/
static void __init quirk_alimagik(struct pci_dev *dev)
static void __devinit quirk_alimagik(struct pci_dev *dev)
{
if ((pci_pci_problems&PCIPCI_ALIMAGIK)==0) {
dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
@ -789,7 +789,7 @@ static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic);
static void __init quirk_ioapic_rmw(struct pci_dev *dev)
static void __devinit quirk_ioapic_rmw(struct pci_dev *dev)
{
if (dev->devfn == 0 && dev->bus->number == 0)
sis_apic_bug = 1;
@ -801,7 +801,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw);
* Some settings of MMRBC can lead to data corruption so block changes.
* See AMD 8131 HyperTransport PCI-X Tunnel Revision Guide
*/
static void __init quirk_amd_8131_mmrbc(struct pci_dev *dev)
static void __devinit quirk_amd_8131_mmrbc(struct pci_dev *dev)
{
if (dev->subordinate && dev->revision <= 0x12) {
dev_info(&dev->dev, "AMD8131 rev %x detected; "
@ -1039,7 +1039,7 @@ static void quirk_disable_pxb(struct pci_dev *pdev)
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb);
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb);
static void __devinit quirk_amd_ide_mode(struct pci_dev *pdev)
static void quirk_amd_ide_mode(struct pci_dev *pdev)
{
/* set SBX00/Hudson-2 SATA in IDE mode to AHCI mode */
u8 tmp;
@ -1082,7 +1082,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB
/*
* Intel 82801CAM ICH3-M datasheet says IDE modes must be the same
*/
static void __init quirk_ide_samemode(struct pci_dev *pdev)
static void __devinit quirk_ide_samemode(struct pci_dev *pdev)
{
u8 prog;
@ -1121,7 +1121,7 @@ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_VIA, PCI_ANY_ID,
/* This was originally an Alpha specific thing, but it really fits here.
* The i82375 PCI/EISA bridge appears as non-classified. Fix that.
*/
static void __init quirk_eisa_bridge(struct pci_dev *dev)
static void __devinit quirk_eisa_bridge(struct pci_dev *dev)
{
dev->class = PCI_CLASS_BRIDGE_EISA << 8;
}
@ -1155,7 +1155,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_e
*/
static int asus_hides_smbus;
static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
static void __devinit asus_hides_smbus_hostbridge(struct pci_dev *dev)
{
if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK)) {
if (dev->device == PCI_DEVICE_ID_INTEL_82845_HB)
@ -1538,7 +1538,7 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB3
#endif
#ifdef CONFIG_X86_IO_APIC
static void __init quirk_alder_ioapic(struct pci_dev *pdev)
static void __devinit quirk_alder_ioapic(struct pci_dev *pdev)
{
int i;
@ -1777,7 +1777,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS, qui
* but the PIO transfers won't work if BAR0 falls at the odd 8 bytes.
* Re-allocate the region if needed...
*/
static void __init quirk_tc86c001_ide(struct pci_dev *dev)
static void __devinit quirk_tc86c001_ide(struct pci_dev *dev)
{
struct resource *r = &dev->resource[0];
@ -1938,53 +1938,16 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1
static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
{
u16 en1k;
u8 io_base_lo, io_limit_lo;
unsigned long base, limit;
struct resource *res = dev->resource + PCI_BRIDGE_RESOURCES;
pci_read_config_word(dev, 0x40, &en1k);
if (en1k & 0x200) {
dev_info(&dev->dev, "Enable I/O Space to 1KB granularity\n");
pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
base = (io_base_lo & (PCI_IO_RANGE_MASK | 0x0c)) << 8;
limit = (io_limit_lo & (PCI_IO_RANGE_MASK | 0x0c)) << 8;
if (base <= limit) {
res->start = base;
res->end = limit + 0x3ff;
}
dev->io_window_1k = 1;
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io);
/* Fix the IOBL_ADR for 1k I/O space granularity on the Intel P64H2
* The IOBL_ADR gets re-written to 4k boundaries in pci_setup_bridge()
* in drivers/pci/setup-bus.c
*/
static void __devinit quirk_p64h2_1k_io_fix_iobl(struct pci_dev *dev)
{
u16 en1k, iobl_adr, iobl_adr_1k;
struct resource *res = dev->resource + PCI_BRIDGE_RESOURCES;
pci_read_config_word(dev, 0x40, &en1k);
if (en1k & 0x200) {
pci_read_config_word(dev, PCI_IO_BASE, &iobl_adr);
iobl_adr_1k = iobl_adr | (res->start >> 8) | (res->end & 0xfc00);
if (iobl_adr != iobl_adr_1k) {
dev_info(&dev->dev, "Fixing P64H2 IOBL_ADR from 0x%x to 0x%x for 1KB granularity\n",
iobl_adr,iobl_adr_1k);
pci_write_config_word(dev, PCI_IO_BASE, iobl_adr_1k);
}
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io_fix_iobl);
/* Under some circumstances, AER is not linked with extended capabilities.
* Force it to be linked by setting the corresponding control bit in the
* config space.
@ -2104,7 +2067,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
PCI_DEVICE_ID_NX2_5709S,
quirk_brcm_570x_limit_vpd);
static void __devinit quirk_brcm_5719_limit_mrrs(struct pci_dev *dev)
static void quirk_brcm_5719_limit_mrrs(struct pci_dev *dev)
{
u32 rev;
@ -2143,9 +2106,9 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB,
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82875_HB,
quirk_unhide_mch_dev6);
#ifdef CONFIG_TILE
#ifdef CONFIG_TILEPRO
/*
* The Tilera TILEmpower platform needs to set the link speed
* The Tilera TILEmpower tilepro platform needs to set the link speed
* to 2.5GT(Giga-Transfers)/s (Gen 1). The default link speed
* setting is 5GT/s (Gen 2). 0x98 is the Link Control2 PCIe
* capability register of the PEX8624 PCIe switch. The switch
@ -2160,7 +2123,7 @@ static void __devinit quirk_tile_plx_gen1(struct pci_dev *dev)
}
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1);
#endif /* CONFIG_TILE */
#endif /* CONFIG_TILEPRO */
#ifdef CONFIG_PCI_MSI
/* Some chipsets do not support MSI. We cannot easily rely on setting
@ -2169,7 +2132,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1);
* aware of it. Instead of setting the flag on all busses in the
* machine, simply disable MSI globally.
*/
static void __init quirk_disable_all_msi(struct pci_dev *dev)
static void __devinit quirk_disable_all_msi(struct pci_dev *dev)
{
pci_no_msi();
dev_warn(&dev->dev, "MSI quirk detected; MSI disabled\n");
@ -2217,7 +2180,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9601, quirk_amd_780_apc_msi);
/* Go through the list of Hypertransport capabilities and
* return 1 if a HT MSI capability is found and enabled */
static int __devinit msi_ht_cap_enabled(struct pci_dev *dev)
static int msi_ht_cap_enabled(struct pci_dev *dev)
{
int pos, ttl = 48;
@ -2241,7 +2204,7 @@ static int __devinit msi_ht_cap_enabled(struct pci_dev *dev)
}
/* Check the hypertransport MSI mapping to know whether MSI is enabled or not */
static void __devinit quirk_msi_ht_cap(struct pci_dev *dev)
static void quirk_msi_ht_cap(struct pci_dev *dev)
{
if (dev->subordinate && !msi_ht_cap_enabled(dev)) {
dev_warn(&dev->dev, "MSI quirk detected; "
@ -2255,7 +2218,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2
/* The nVidia CK804 chipset may have 2 HT MSI mappings.
* MSI are supported if the MSI capability set in any of these mappings.
*/
static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev)
static void quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev)
{
struct pci_dev *pdev;
@ -2279,7 +2242,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
quirk_nvidia_ck804_msi_ht_cap);
/* Force enable MSI mapping capability on HT bridges */
static void __devinit ht_enable_msi_mapping(struct pci_dev *dev)
static void ht_enable_msi_mapping(struct pci_dev *dev)
{
int pos, ttl = 48;
@ -2359,7 +2322,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
PCI_DEVICE_ID_NVIDIA_MCP55_BRIDGE_V4,
nvbridge_check_legacy_irq_routing);
static int __devinit ht_check_msi_mapping(struct pci_dev *dev)
static int ht_check_msi_mapping(struct pci_dev *dev)
{
int pos, ttl = 48;
int found = 0;
@ -2387,7 +2350,7 @@ static int __devinit ht_check_msi_mapping(struct pci_dev *dev)
return found;
}
static int __devinit host_bridge_with_leaf(struct pci_dev *host_bridge)
static int host_bridge_with_leaf(struct pci_dev *host_bridge)
{
struct pci_dev *dev;
int pos;
@ -2421,7 +2384,7 @@ static int __devinit host_bridge_with_leaf(struct pci_dev *host_bridge)
#define PCI_HT_CAP_SLAVE_CTRL0 4 /* link control */
#define PCI_HT_CAP_SLAVE_CTRL1 8 /* link control to */
static int __devinit is_end_of_ht_chain(struct pci_dev *dev)
static int is_end_of_ht_chain(struct pci_dev *dev)
{
int pos, ctrl_off;
int end = 0;
@ -2445,7 +2408,7 @@ out:
return end;
}
static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev)
static void nv_ht_enable_msi_mapping(struct pci_dev *dev)
{
struct pci_dev *host_bridge;
int pos;
@ -2484,7 +2447,7 @@ out:
pci_dev_put(host_bridge);
}
static void __devinit ht_disable_msi_mapping(struct pci_dev *dev)
static void ht_disable_msi_mapping(struct pci_dev *dev)
{
int pos, ttl = 48;
@ -2504,7 +2467,7 @@ static void __devinit ht_disable_msi_mapping(struct pci_dev *dev)
}
}
static void __devinit __nv_msi_ht_cap_quirk(struct pci_dev *dev, int all)
static void __nv_msi_ht_cap_quirk(struct pci_dev *dev, int all)
{
struct pci_dev *host_bridge;
int pos;
@ -2541,23 +2504,26 @@ static void __devinit __nv_msi_ht_cap_quirk(struct pci_dev *dev, int all)
else
nv_ht_enable_msi_mapping(dev);
}
return;
goto out;
}
/* HT MSI is not enabled */
if (found == 1)
return;
goto out;
/* Host bridge is not to HT, disable HT MSI mapping on this device */
ht_disable_msi_mapping(dev);
out:
pci_dev_put(host_bridge);
}
static void __devinit nv_msi_ht_cap_quirk_all(struct pci_dev *dev)
static void nv_msi_ht_cap_quirk_all(struct pci_dev *dev)
{
return __nv_msi_ht_cap_quirk(dev, 1);
}
static void __devinit nv_msi_ht_cap_quirk_leaf(struct pci_dev *dev)
static void nv_msi_ht_cap_quirk_leaf(struct pci_dev *dev)
{
return __nv_msi_ht_cap_quirk(dev, 0);
}
@ -2879,20 +2845,34 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata);
static void do_one_fixup_debug(void (*fn)(struct pci_dev *dev), struct pci_dev *dev)
static ktime_t fixup_debug_start(struct pci_dev *dev,
void (*fn)(struct pci_dev *dev))
{
ktime_t calltime, delta, rettime;
ktime_t calltime = ktime_set(0, 0);
dev_dbg(&dev->dev, "calling %pF\n", fn);
if (initcall_debug) {
pr_debug("calling %pF @ %i for %s\n",
fn, task_pid_nr(current), dev_name(&dev->dev));
calltime = ktime_get();
}
return calltime;
}
static void fixup_debug_report(struct pci_dev *dev, ktime_t calltime,
void (*fn)(struct pci_dev *dev))
{
ktime_t delta, rettime;
unsigned long long duration;
printk(KERN_DEBUG "calling %pF @ %i for %s\n",
fn, task_pid_nr(current), dev_name(&dev->dev));
calltime = ktime_get();
fn(dev);
rettime = ktime_get();
delta = ktime_sub(rettime, calltime);
duration = (unsigned long long) ktime_to_ns(delta) >> 10;
printk(KERN_DEBUG "pci fixup %pF returned after %lld usecs for %s\n",
fn, duration, dev_name(&dev->dev));
if (initcall_debug) {
rettime = ktime_get();
delta = ktime_sub(rettime, calltime);
duration = (unsigned long long) ktime_to_ns(delta) >> 10;
pr_debug("pci fixup %pF returned after %lld usecs for %s\n",
fn, duration, dev_name(&dev->dev));
}
}
/*
@ -2929,9 +2909,25 @@ static void __devinit disable_igfx_irq(struct pci_dev *dev)
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq);
/*
* Some devices may pass our check in pci_intx_mask_supported if
* PCI_COMMAND_INTX_DISABLE works though they actually do not properly
* support this feature.
*/
static void __devinit quirk_broken_intx_masking(struct pci_dev *dev)
{
dev->broken_intx_masking = 1;
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CHELSIO, 0x0030,
quirk_broken_intx_masking);
DECLARE_PCI_FIXUP_HEADER(0x1814, 0x0601, /* Ralink RT2800 802.11n PCI */
quirk_broken_intx_masking);
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
struct pci_fixup *end)
{
ktime_t calltime;
for (; f < end; f++)
if ((f->class == (u32) (dev->class >> f->class_shift) ||
f->class == (u32) PCI_ANY_ID) &&
@ -2939,11 +2935,9 @@ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
f->vendor == (u16) PCI_ANY_ID) &&
(f->device == dev->device ||
f->device == (u16) PCI_ANY_ID)) {
dev_dbg(&dev->dev, "calling %pF\n", f->hook);
if (initcall_debug)
do_one_fixup_debug(f->hook, dev);
else
f->hook(dev);
calltime = fixup_debug_start(dev, f->hook);
f->hook(dev);
fixup_debug_report(dev, calltime, f->hook);
}
}
@ -2962,6 +2956,7 @@ extern struct pci_fixup __end_pci_fixups_resume_early[];
extern struct pci_fixup __start_pci_fixups_suspend[];
extern struct pci_fixup __end_pci_fixups_suspend[];
static bool pci_apply_fixup_final_quirks;
void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
{
@ -2979,6 +2974,8 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
break;
case pci_fixup_final:
if (!pci_apply_fixup_final_quirks)
return;
start = __start_pci_fixups_final;
end = __end_pci_fixups_final;
break;
@ -3011,6 +3008,7 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
}
EXPORT_SYMBOL(pci_fixup_device);
static int __init pci_apply_final_quirks(void)
{
struct pci_dev *dev = NULL;
@ -3021,6 +3019,7 @@ static int __init pci_apply_final_quirks(void)
printk(KERN_DEBUG "PCI: CLS %u bytes\n",
pci_cache_line_size << 2);
pci_apply_fixup_final_quirks = true;
for_each_pci_dev(dev) {
pci_fixup_device(pci_fixup_final, dev);
/*
@ -3041,6 +3040,7 @@ static int __init pci_apply_final_quirks(void)
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);
@ -3179,3 +3179,87 @@ int pci_dev_specific_reset(struct pci_dev *dev, int probe)
return -ENOTTY;
}
static struct pci_dev *pci_func_0_dma_source(struct pci_dev *dev)
{
if (!PCI_FUNC(dev->devfn))
return pci_dev_get(dev);
return pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
}
static const struct pci_dev_dma_source {
u16 vendor;
u16 device;
struct pci_dev *(*dma_source)(struct pci_dev *dev);
} pci_dev_dma_source[] = {
/*
* https://bugzilla.redhat.com/show_bug.cgi?id=605888
*
* Some Ricoh devices use the function 0 source ID for DMA on
* other functions of a multifunction device. The DMA devices
* is therefore function 0, which will have implications of the
* iommu grouping of these devices.
*/
{ PCI_VENDOR_ID_RICOH, 0xe822, pci_func_0_dma_source },
{ PCI_VENDOR_ID_RICOH, 0xe230, pci_func_0_dma_source },
{ PCI_VENDOR_ID_RICOH, 0xe832, pci_func_0_dma_source },
{ PCI_VENDOR_ID_RICOH, 0xe476, pci_func_0_dma_source },
{ 0 }
};
/*
* IOMMUs with isolation capabilities need to be programmed with the
* correct source ID of a device. In most cases, the source ID matches
* the device doing the DMA, but sometimes hardware is broken and will
* tag the DMA as being sourced from a different device. This function
* allows that translation. Note that the reference count of the
* returned device is incremented on all paths.
*/
struct pci_dev *pci_get_dma_source(struct pci_dev *dev)
{
const struct pci_dev_dma_source *i;
for (i = pci_dev_dma_source; i->dma_source; i++) {
if ((i->vendor == dev->vendor ||
i->vendor == (u16)PCI_ANY_ID) &&
(i->device == dev->device ||
i->device == (u16)PCI_ANY_ID))
return i->dma_source(dev);
}
return pci_dev_get(dev);
}
static const struct pci_dev_acs_enabled {
u16 vendor;
u16 device;
int (*acs_enabled)(struct pci_dev *dev, u16 acs_flags);
} pci_dev_acs_enabled[] = {
{ 0 }
};
int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags)
{
const struct pci_dev_acs_enabled *i;
int ret;
/*
* Allow devices that do not expose standard PCIe ACS capabilities
* or control to indicate their support here. Multi-function express
* devices which do not allow internal peer-to-peer between functions,
* but do not implement PCIe ACS may wish to return true here.
*/
for (i = pci_dev_acs_enabled; i->acs_enabled; i++) {
if ((i->vendor == dev->vendor ||
i->vendor == (u16)PCI_ANY_ID) &&
(i->device == dev->device ||
i->device == (u16)PCI_ANY_ID)) {
ret = i->acs_enabled(dev, acs_flags);
if (ret >= 0)
return ret;
}
}
return -ENOTTY;
}

View file

@ -68,6 +68,7 @@ void pci_remove_bus(struct pci_bus *pci_bus)
down_write(&pci_bus_sem);
list_del(&pci_bus->node);
pci_bus_release_busn_res(pci_bus);
up_write(&pci_bus_sem);
if (!pci_bus->is_added)
return;

View file

@ -15,6 +15,8 @@
#include "pci.h"
DECLARE_RWSEM(pci_bus_sem);
EXPORT_SYMBOL_GPL(pci_bus_sem);
/*
* find the upstream PCIe-to-PCI bridge of a PCI device
* if the device is PCIE, return NULL

View file

@ -265,7 +265,7 @@ out:
* assign_requested_resources_sorted() - satisfy resource requests
*
* @head : head of the list tracking requests for resources
* @failed_list : head of the list tracking requests that could
* @fail_head : head of the list tracking requests that could
* not be allocated
*
* Satisfy resource requests of each element in the list. Add
@ -308,7 +308,7 @@ static void __assign_resources_sorted(struct list_head *head,
* Should not assign requested resources at first.
* they could be adjacent, so later reassign can not reallocate
* them one by one in parent resource window.
* Try to assign requested + add_size at begining
* Try to assign requested + add_size at beginning
* if could do that, could get out early.
* if could not do that, we still try to assign requested at first,
* then try to reassign add_size for some resources.
@ -404,8 +404,8 @@ void pci_setup_cardbus(struct pci_bus *bus)
struct resource *res;
struct pci_bus_region region;
dev_info(&bridge->dev, "CardBus bridge to [bus %02x-%02x]\n",
bus->secondary, bus->subordinate);
dev_info(&bridge->dev, "CardBus bridge to %pR\n",
&bus->busn_res);
res = bus->resource[0];
pcibios_resource_to_bus(bridge, &region, res);
@ -469,16 +469,23 @@ static void pci_setup_bridge_io(struct pci_bus *bus)
struct pci_dev *bridge = bus->self;
struct resource *res;
struct pci_bus_region region;
unsigned long io_mask;
u8 io_base_lo, io_limit_lo;
u32 l, io_upper16;
io_mask = PCI_IO_RANGE_MASK;
if (bridge->io_window_1k)
io_mask = PCI_IO_1K_RANGE_MASK;
/* Set up the top and bottom of the PCI I/O segment for this bus. */
res = bus->resource[0];
pcibios_resource_to_bus(bridge, &region, res);
if (res->flags & IORESOURCE_IO) {
pci_read_config_dword(bridge, PCI_IO_BASE, &l);
l &= 0xffff0000;
l |= (region.start >> 8) & 0x00f0;
l |= region.end & 0xf000;
io_base_lo = (region.start >> 8) & io_mask;
io_limit_lo = (region.end >> 8) & io_mask;
l |= ((u32) io_limit_lo << 8) | io_base_lo;
/* Set up upper 16 bits of I/O base/limit. */
io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
dev_info(&bridge->dev, " bridge window %pR\n", res);
@ -553,8 +560,8 @@ static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type)
{
struct pci_dev *bridge = bus->self;
dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n",
bus->secondary, bus->subordinate);
dev_info(&bridge->dev, "PCI bridge to %pR\n",
&bus->busn_res);
if (type & IORESOURCE_IO)
pci_setup_bridge_io(bus);
@ -699,7 +706,7 @@ static resource_size_t calculate_memsize(resource_size_t size,
* @realloc_head : track the additional io window on this list
*
* Sizing the IO windows of the PCI-PCI bridge is trivial,
* since these windows have 4K granularity and the IO ranges
* since these windows have 1K or 4K granularity and the IO ranges
* of non-bridge PCI devices are limited to 256 bytes.
* We must be careful with the ISA aliasing though.
*/
@ -710,10 +717,17 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
unsigned long size = 0, size0 = 0, size1 = 0;
resource_size_t children_add_size = 0;
resource_size_t min_align = 4096, align;
if (!b_res)
return;
/*
* Per spec, I/O windows are 4K-aligned, but some bridges have an
* extension to support 1K alignment.
*/
if (bus->self->io_window_1k)
min_align = 1024;
list_for_each_entry(dev, &bus->devices, bus_list) {
int i;
@ -731,34 +745,43 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
else
size1 += r_size;
align = pci_resource_alignment(dev, r);
if (align > min_align)
min_align = align;
if (realloc_head)
children_add_size += get_res_add_size(realloc_head, r);
}
}
if (min_align > 4096)
min_align = 4096;
size0 = calculate_iosize(size, min_size, size1,
resource_size(b_res), 4096);
resource_size(b_res), min_align);
if (children_add_size > add_size)
add_size = children_add_size;
size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
calculate_iosize(size, min_size, add_size + size1,
resource_size(b_res), 4096);
resource_size(b_res), min_align);
if (!size0 && !size1) {
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);
"%pR to %pR (unused)\n", b_res,
&bus->busn_res);
b_res->flags = 0;
return;
}
/* Alignment of the IO window is always 4K */
b_res->start = 4096;
b_res->start = min_align;
b_res->end = b_res->start + size0 - 1;
b_res->flags |= IORESOURCE_STARTALIGN;
if (size1 > size0 && realloc_head) {
add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096);
add_to_list(realloc_head, bus->self, b_res, size1-size0,
min_align);
dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window "
"%pR to [bus %02x-%02x] add_size %lx\n", b_res,
bus->secondary, bus->subordinate, size1-size0);
"%pR to %pR add_size %lx\n", b_res,
&bus->busn_res, size1-size0);
}
}
@ -863,8 +886,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
if (!size0 && !size1) {
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);
"%pR to %pR (unused)\n", b_res,
&bus->busn_res);
b_res->flags = 0;
return 1;
}
@ -874,8 +897,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
if (size1 > size0 && realloc_head) {
add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align);
dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window "
"%pR to [bus %02x-%02x] add_size %llx\n", b_res,
bus->secondary, bus->subordinate, (unsigned long long)size1-size0);
"%pR to %pR add_size %llx\n", b_res,
&bus->busn_res, (unsigned long long)size1-size0);
}
return 1;
}

View file

@ -30,6 +30,8 @@
void pci_update_resource(struct pci_dev *dev, int resno)
{
struct pci_bus_region region;
bool disable;
u16 cmd;
u32 new, check, mask;
int reg;
enum pci_bar_type type;
@ -67,6 +69,18 @@ void pci_update_resource(struct pci_dev *dev, int resno)
new |= PCI_ROM_ADDRESS_ENABLE;
}
/*
* We can't update a 64-bit BAR atomically, so when possible,
* disable decoding so that a half-updated BAR won't conflict
* with another device.
*/
disable = (res->flags & IORESOURCE_MEM_64) && !dev->mmio_always_on;
if (disable) {
pci_read_config_word(dev, PCI_COMMAND, &cmd);
pci_write_config_word(dev, PCI_COMMAND,
cmd & ~PCI_COMMAND_MEMORY);
}
pci_write_config_dword(dev, reg, new);
pci_read_config_dword(dev, reg, &check);
@ -84,6 +98,10 @@ void pci_update_resource(struct pci_dev *dev, int resno)
"(high %#08x != %#08x)\n", resno, new, check);
}
}
if (disable)
pci_write_config_word(dev, PCI_COMMAND, cmd);
res->flags &= ~IORESOURCE_UNSET;
dev_dbg(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n",
resno, res, (unsigned long long)region.start,
@ -127,33 +145,6 @@ void pci_disable_bridge_window(struct pci_dev *dev)
pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0xffffffff);
}
static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
int resno, resource_size_t size, resource_size_t align)
{
struct resource *res = dev->resource + resno;
resource_size_t min;
int ret;
min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
/* First, try exact prefetching match.. */
ret = pci_bus_alloc_resource(bus, res, size, align, min,
IORESOURCE_PREFETCH,
pcibios_align_resource, dev);
if (ret < 0 && (res->flags & IORESOURCE_PREFETCH)) {
/*
* That failed.
*
* But a prefetching area can handle a non-prefetching
* window (it will just not perform as well).
*/
ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
pcibios_align_resource, dev);
}
return ret;
}
/*
* Generic function that returns a value indicating that the device's
* original BIOS BAR address was not saved and so is not available for
@ -206,7 +197,35 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
return ret;
}
static int _pci_assign_resource(struct pci_dev *dev, int resno, int size, resource_size_t min_align)
static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
int resno, resource_size_t size, resource_size_t align)
{
struct resource *res = dev->resource + resno;
resource_size_t min;
int ret;
min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
/* First, try exact prefetching match.. */
ret = pci_bus_alloc_resource(bus, res, size, align, min,
IORESOURCE_PREFETCH,
pcibios_align_resource, dev);
if (ret < 0 && (res->flags & IORESOURCE_PREFETCH)) {
/*
* That failed.
*
* But a prefetching area can handle a non-prefetching
* window (it will just not perform as well).
*/
ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
pcibios_align_resource, dev);
}
return ret;
}
static int _pci_assign_resource(struct pci_dev *dev, int resno,
resource_size_t size, resource_size_t min_align)
{
struct resource *res = dev->resource + resno;
struct pci_bus *bus;
@ -238,31 +257,6 @@ static int _pci_assign_resource(struct pci_dev *dev, int resno, int size, resour
return ret;
}
int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsize,
resource_size_t min_align)
{
struct resource *res = dev->resource + resno;
resource_size_t new_size;
int ret;
if (!res->parent) {
dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resource %pR "
"\n", resno, res);
return -EINVAL;
}
/* already aligned with min_align */
new_size = resource_size(res) + addsize;
ret = _pci_assign_resource(dev, resno, new_size, min_align);
if (!ret) {
res->flags &= ~IORESOURCE_STARTALIGN;
dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res);
if (resno < PCI_BRIDGE_RESOURCES)
pci_update_resource(dev, resno);
}
return ret;
}
int pci_assign_resource(struct pci_dev *dev, int resno)
{
struct resource *res = dev->resource + resno;
@ -298,6 +292,31 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
return ret;
}
int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsize,
resource_size_t min_align)
{
struct resource *res = dev->resource + resno;
resource_size_t new_size;
int ret;
if (!res->parent) {
dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resource %pR "
"\n", resno, res);
return -EINVAL;
}
/* already aligned with min_align */
new_size = resource_size(res) + addsize;
ret = _pci_assign_resource(dev, resno, new_size, min_align);
if (!ret) {
res->flags &= ~IORESOURCE_STARTALIGN;
dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res);
if (resno < PCI_BRIDGE_RESOURCES)
pci_update_resource(dev, resno);
}
return ret;
}
int pci_enable_resources(struct pci_dev *dev, int mask)
{
u16 cmd, old_cmd;