Merge tag 'pci-v3.9-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci

Pull PCI changes from Bjorn Helgaas:
 "Host bridge hotplug
    - Major overhaul of ACPI host bridge add/start (Rafael Wysocki, Yinghai Lu)
    - Major overhaul of PCI/ACPI binding (Rafael Wysocki, Yinghai Lu)
    - Split out ACPI host bridge and ACPI PCI device hotplug (Yinghai Lu)
    - Stop caching _PRT and make independent of bus numbers (Yinghai Lu)

  PCI device hotplug
    - Clean up cpqphp dead code (Sasha Levin)
    - Disable ARI unless device and upstream bridge support it (Yijing Wang)
    - Initialize all hot-added devices (not functions 0-7) (Yijing Wang)

  Power management
    - Don't touch ASPM if disabled (Joe Lawrence)
    - Fix ASPM link state management (Myron Stowe)

  Miscellaneous
    - Fix PCI_EXP_FLAGS accessor (Alex Williamson)
    - Disable Bus Master in pci_device_shutdown (Konstantin Khlebnikov)
    - Document hotplug resource and MPS parameters (Yijing Wang)
    - Add accessor for PCIe capabilities (Myron Stowe)
    - Drop pciehp suspend/resume messages (Paul Bolle)
    - Make pci_slot built-in only (not a module) (Jiang Liu)
    - Remove unused PCI/ACPI bind ops (Jiang Liu)
    - Removed used pci_root_bus (Bjorn Helgaas)"

* tag 'pci-v3.9-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (51 commits)
  PCI/ACPI: Don't cache _PRT, and don't associate them with bus numbers
  PCI: Fix PCI Express Capability accessors for PCI_EXP_FLAGS
  ACPI / PCI: Make pci_slot built-in only, not a module
  PCI/PM: Clear state_saved during suspend
  PCI: Use atomic_inc_return() rather than atomic_add_return()
  PCI: Catch attempts to disable already-disabled devices
  PCI: Disable Bus Master unconditionally in pci_device_shutdown()
  PCI: acpiphp: Remove dead code for PCI host bridge hotplug
  PCI: acpiphp: Create companion ACPI devices before creating PCI devices
  PCI: Remove unused "rc" in virtfn_add_bus()
  PCI: pciehp: Drop suspend/resume ENTRY messages
  PCI/ASPM: Don't touch ASPM if forcibly disabled
  PCI/ASPM: Deallocate upstream link state even if device is not PCIe
  PCI: Document MPS parameters pci=pcie_bus_safe, pci=pcie_bus_perf, etc
  PCI: Document hpiosize= and hpmemsize= resource reservation parameters
  PCI: Use PCI Express Capability accessor
  PCI: Introduce accessor to retrieve PCIe Capabilities Register
  PCI: Put pci_dev in device tree as early as possible
  PCI: Skip attaching driver in device_add()
  PCI: acpiphp: Keep driver loaded even if no slots found
  ...
This commit is contained in:
Linus Torvalds
2013-02-25 21:18:18 -08:00
46 changed files with 680 additions and 792 deletions

View File

@@ -472,7 +472,7 @@ EXPORT_SYMBOL_GPL(pci_cfg_access_unlock);
static inline int pcie_cap_version(const struct pci_dev *dev)
{
return dev->pcie_flags_reg & PCI_EXP_FLAGS_VERS;
return pcie_caps_reg(dev) & PCI_EXP_FLAGS_VERS;
}
static inline bool pcie_cap_has_devctl(const struct pci_dev *dev)
@@ -497,7 +497,7 @@ static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev)
return pcie_cap_version(dev) > 1 ||
type == PCI_EXP_TYPE_ROOT_PORT ||
(type == PCI_EXP_TYPE_DOWNSTREAM &&
dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT);
pcie_caps_reg(dev) & PCI_EXP_FLAGS_SLOT);
}
static inline bool pcie_cap_has_rtctl(const struct pci_dev *dev)
@@ -515,7 +515,7 @@ static bool pcie_capability_reg_implemented(struct pci_dev *dev, int pos)
return false;
switch (pos) {
case PCI_EXP_FLAGS_TYPE:
case PCI_EXP_FLAGS:
return true;
case PCI_EXP_DEVCAP:
case PCI_EXP_DEVCTL:

View File

@@ -158,69 +158,38 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
return ret;
}
void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { }
/**
* pci_bus_add_device - add a single device
* pci_bus_add_device - start driver for a single device
* @dev: device to add
*
* This adds a single pci device to the global
* device list and adds sysfs and procfs entries
* This adds add sysfs entries and start device drivers
*/
int pci_bus_add_device(struct pci_dev *dev)
{
int retval;
pci_fixup_device(pci_fixup_final, dev);
/*
* Can not put in pci_device_add yet because resources
* are not assigned yet for some devices.
*/
pci_create_sysfs_dev_files(dev);
retval = pcibios_add_device(dev);
if (retval)
return retval;
retval = device_add(&dev->dev);
if (retval)
return retval;
dev->match_driver = true;
retval = device_attach(&dev->dev);
WARN_ON(retval < 0);
dev->is_added = 1;
pci_proc_attach_device(dev);
pci_create_sysfs_dev_files(dev);
return 0;
}
/**
* pci_bus_add_child - add a child bus
* @bus: bus to add
*
* This adds sysfs entries for a single bus
*/
int pci_bus_add_child(struct pci_bus *bus)
{
int retval;
if (bus->bridge)
bus->dev.parent = bus->bridge;
retval = device_register(&bus->dev);
if (retval)
return retval;
bus->is_added = 1;
/* Create legacy_io and legacy_mem files for this bus */
pci_create_legacy_files(bus);
return retval;
}
/**
* pci_bus_add_devices - insert newly discovered PCI devices
* pci_bus_add_devices - start driver for PCI devices
* @bus: bus to check for new devices
*
* Add newly discovered PCI devices (which are on the bus->devices
* list) to the global PCI device list, add the sysfs and procfs
* entries. Where a bridge is found, add the discovered bus to
* the parents list of child buses, and recurse (breadth-first
* to be compatible with 2.4)
*
* Call hotplug for each new devices.
* Start driver for PCI devices and add some sysfs entries.
*/
void pci_bus_add_devices(const struct pci_bus *bus)
{
@@ -233,36 +202,20 @@ void pci_bus_add_devices(const struct pci_bus *bus)
if (dev->is_added)
continue;
retval = pci_bus_add_device(dev);
if (retval)
dev_err(&dev->dev, "Error adding device, continuing\n");
}
list_for_each_entry(dev, &bus->devices, bus_list) {
BUG_ON(!dev->is_added);
child = dev->subordinate;
/*
* If there is an unattached subordinate bus, attach
* it and then scan for unattached PCI devices.
*/
if (!child)
continue;
if (list_empty(&child->node)) {
down_write(&pci_bus_sem);
list_add_tail(&child->node, &dev->bus->children);
up_write(&pci_bus_sem);
}
pci_bus_add_devices(child);
/*
* register the bus with sysfs as the parent is now
* properly registered.
*/
if (child->is_added)
continue;
retval = pci_bus_add_child(child);
if (retval)
dev_err(&dev->dev, "Error adding bus, continuing\n");
child->is_added = 1;
}
}

View File

@@ -79,7 +79,6 @@ struct acpiphp_bridge {
/* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */
struct acpiphp_func *func;
int type;
int nr_slots;
u32 flags;
@@ -146,10 +145,6 @@ struct acpiphp_attention_info
/* PCI bus bridge HID */
#define ACPI_PCI_HOST_HID "PNP0A03"
/* PCI BRIDGE type */
#define BRIDGE_TYPE_HOST 0
#define BRIDGE_TYPE_P2P 1
/* ACPI _STA method value (ignore bit 4; battery present) */
#define ACPI_STA_PRESENT (0x00000001)
#define ACPI_STA_ENABLED (0x00000002)
@@ -158,13 +153,7 @@ struct acpiphp_attention_info
#define ACPI_STA_ALL (0x0000000f)
/* bridge flags */
#define BRIDGE_HAS_STA (0x00000001)
#define BRIDGE_HAS_EJ0 (0x00000002)
#define BRIDGE_HAS_HPP (0x00000004)
#define BRIDGE_HAS_PS0 (0x00000010)
#define BRIDGE_HAS_PS1 (0x00000020)
#define BRIDGE_HAS_PS2 (0x00000040)
#define BRIDGE_HAS_PS3 (0x00000080)
#define BRIDGE_HAS_EJ0 (0x00000001)
/* slot flags */
@@ -193,7 +182,6 @@ extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot);
/* acpiphp_glue.c */
extern int acpiphp_glue_init (void);
extern void acpiphp_glue_exit (void);
extern int acpiphp_get_num_slots (void);
typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);
extern int acpiphp_enable_slot (struct acpiphp_slot *slot);

View File

@@ -50,7 +50,6 @@
bool acpiphp_debug;
/* local variables */
static int num_slots;
static struct acpiphp_attention_info *attention_info;
#define DRIVER_VERSION "0.5"
@@ -272,25 +271,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
return 0;
}
static int __init init_acpi(void)
{
int retval;
/* initialize internal data structure etc. */
retval = acpiphp_glue_init();
/* read initial number of slots */
if (!retval) {
num_slots = acpiphp_get_num_slots();
if (num_slots == 0) {
acpiphp_glue_exit();
retval = -ENODEV;
}
}
return retval;
}
/**
* release_slot - free up the memory used by a slot
* @hotplug_slot: slot to free
@@ -379,7 +359,8 @@ static int __init acpiphp_init(void)
return 0;
/* read all the ACPI info from the system */
return init_acpi();
/* initialize internal data structure etc. */
return acpiphp_glue_init();
}

View File

@@ -325,8 +325,8 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge)
return;
}
/* install notify handler */
if (bridge->type != BRIDGE_TYPE_HOST) {
/* install notify handler for P2P bridges */
if (!pci_is_root_bus(bridge->pci_bus)) {
if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
status = acpi_remove_notify_handler(bridge->func->handle,
ACPI_SYSTEM_NOTIFY,
@@ -369,27 +369,12 @@ static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle
static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge)
{
acpi_handle dummy_handle;
struct acpiphp_func *func;
if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
"_STA", &dummy_handle)))
bridge->flags |= BRIDGE_HAS_STA;
if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
"_EJ0", &dummy_handle)))
"_EJ0", &dummy_handle))) {
bridge->flags |= BRIDGE_HAS_EJ0;
if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
"_PS0", &dummy_handle)))
bridge->flags |= BRIDGE_HAS_PS0;
if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
"_PS3", &dummy_handle)))
bridge->flags |= BRIDGE_HAS_PS3;
/* is this ejectable p2p bridge? */
if (bridge->flags & BRIDGE_HAS_EJ0) {
struct acpiphp_func *func;
dbg("found ejectable p2p bridge\n");
/* make link between PCI bridge and PCI function */
@@ -412,7 +397,6 @@ static void add_host_bridge(struct acpi_pci_root *root)
if (bridge == NULL)
return;
bridge->type = BRIDGE_TYPE_HOST;
bridge->handle = handle;
bridge->pci_bus = root->bus;
@@ -432,7 +416,6 @@ static void add_p2p_bridge(acpi_handle *handle)
return;
}
bridge->type = BRIDGE_TYPE_P2P;
bridge->handle = handle;
config_p2p_bridge_flags(bridge);
@@ -543,13 +526,15 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
acpi_status status;
acpi_handle handle = bridge->handle;
status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
if (!pci_is_root_bus(bridge->pci_bus)) {
status = acpi_remove_notify_handler(handle,
ACPI_SYSTEM_NOTIFY,
handle_hotplug_event_bridge);
if (ACPI_FAILURE(status))
err("failed to remove notify handler\n");
if (ACPI_FAILURE(status))
err("failed to remove notify handler\n");
}
if ((bridge->type != BRIDGE_TYPE_HOST) &&
((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)) {
if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
status = acpi_install_notify_handler(bridge->func->handle,
ACPI_SYSTEM_NOTIFY,
handle_hotplug_event_func,
@@ -630,9 +615,6 @@ static void remove_bridge(struct acpi_pci_root *root)
bridge = acpiphp_handle_to_bridge(handle);
if (bridge)
cleanup_bridge(bridge);
else
acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
handle_hotplug_event_bridge);
}
static int power_on_slot(struct acpiphp_slot *slot)
@@ -793,6 +775,29 @@ static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)
}
}
static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev)
{
struct acpiphp_func *func;
if (!dev->subordinate)
return;
/* quirk, or pcie could set it already */
if (dev->is_hotplug_bridge)
return;
if (PCI_SLOT(dev->devfn) != slot->device)
return;
list_for_each_entry(func, &slot->funcs, sibling) {
if (PCI_FUNC(dev->devfn) == func->function) {
/* check if this bridge has ejectable slots */
if ((detect_ejectable_slots(func->handle) > 0))
dev->is_hotplug_bridge = 1;
break;
}
}
}
/**
* enable_device - enable, configure a slot
* @slot: slot to be enabled
@@ -812,6 +817,9 @@ static int __ref enable_device(struct acpiphp_slot *slot)
if (slot->flags & SLOT_ENABLED)
goto err_exit;
list_for_each_entry(func, &slot->funcs, sibling)
acpiphp_bus_add(func);
num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0));
if (num == 0) {
/* Maybe only part of funcs are added. */
@@ -827,15 +835,14 @@ static int __ref enable_device(struct acpiphp_slot *slot)
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
max = pci_scan_bridge(bus, dev, max, pass);
if (pass && dev->subordinate)
if (pass && dev->subordinate) {
check_hotplug_bridge(slot, dev);
pci_bus_size_bridges(dev->subordinate);
}
}
}
}
list_for_each_entry(func, &slot->funcs, sibling)
acpiphp_bus_add(func);
pci_bus_assign_resources(bus);
acpiphp_sanitize_bus(bus);
acpiphp_set_hpp_values(bus);
@@ -1093,69 +1100,10 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
}
}
/* Program resources in newly inserted bridge */
static int acpiphp_configure_bridge (acpi_handle handle)
{
struct pci_bus *bus;
if (acpi_is_root_bridge(handle)) {
struct acpi_pci_root *root = acpi_pci_find_root(handle);
bus = root->bus;
} else {
struct pci_dev *pdev = acpi_get_pci_dev(handle);
bus = pdev->subordinate;
pci_dev_put(pdev);
}
pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus);
acpiphp_sanitize_bus(bus);
acpiphp_set_hpp_values(bus);
pci_enable_bridges(bus);
return 0;
}
static void handle_bridge_insertion(acpi_handle handle, u32 type)
{
struct acpi_device *device;
if ((type != ACPI_NOTIFY_BUS_CHECK) &&
(type != ACPI_NOTIFY_DEVICE_CHECK)) {
err("unexpected notification type %d\n", type);
return;
}
if (acpi_bus_scan(handle)) {
err("cannot add bridge to acpi list\n");
return;
}
if (acpi_bus_get_device(handle, &device)) {
err("ACPI device object missing\n");
return;
}
if (!acpiphp_configure_bridge(handle))
add_bridge(handle);
else
err("cannot configure and start bridge\n");
}
/*
* ACPI event handlers
*/
static acpi_status
count_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
{
int *count = (int *)context;
struct acpiphp_bridge *bridge;
bridge = acpiphp_handle_to_bridge(handle);
if (bridge)
(*count)++;
return AE_OK ;
}
static acpi_status
check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
{
@@ -1174,83 +1122,33 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
return AE_OK ;
}
struct acpiphp_hp_work {
struct work_struct work;
acpi_handle handle;
u32 type;
void *context;
};
static void alloc_acpiphp_hp_work(acpi_handle handle, u32 type,
void *context,
void (*func)(struct work_struct *work))
{
struct acpiphp_hp_work *hp_work;
int ret;
hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL);
if (!hp_work)
return;
hp_work->handle = handle;
hp_work->type = type;
hp_work->context = context;
INIT_WORK(&hp_work->work, func);
ret = queue_work(kacpi_hotplug_wq, &hp_work->work);
if (!ret)
kfree(hp_work);
}
static void _handle_hotplug_event_bridge(struct work_struct *work)
{
struct acpiphp_bridge *bridge;
char objname[64];
struct acpi_buffer buffer = { .length = sizeof(objname),
.pointer = objname };
struct acpi_device *device;
int num_sub_bridges = 0;
struct acpiphp_hp_work *hp_work;
struct acpi_hp_work *hp_work;
acpi_handle handle;
u32 type;
hp_work = container_of(work, struct acpiphp_hp_work, work);
hp_work = container_of(work, struct acpi_hp_work, work);
handle = hp_work->handle;
type = hp_work->type;
bridge = (struct acpiphp_bridge *)hp_work->context;
acpi_scan_lock_acquire();
if (acpi_bus_get_device(handle, &device)) {
/* This bridge must have just been physically inserted */
handle_bridge_insertion(handle, type);
goto out;
}
bridge = acpiphp_handle_to_bridge(handle);
if (type == ACPI_NOTIFY_BUS_CHECK) {
acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX,
count_sub_bridges, NULL, &num_sub_bridges, NULL);
}
if (!bridge && !num_sub_bridges) {
err("cannot get bridge info\n");
goto out;
}
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
switch (type) {
case ACPI_NOTIFY_BUS_CHECK:
/* bus re-enumerate */
dbg("%s: Bus check notify on %s\n", __func__, objname);
if (bridge) {
dbg("%s: re-enumerating slots under %s\n",
__func__, objname);
acpiphp_check_bridge(bridge);
}
if (num_sub_bridges)
acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL);
dbg("%s: re-enumerating slots under %s\n", __func__, objname);
acpiphp_check_bridge(bridge);
acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL);
break;
case ACPI_NOTIFY_DEVICE_CHECK:
@@ -1267,8 +1165,7 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
case ACPI_NOTIFY_EJECT_REQUEST:
/* request device eject */
dbg("%s: Device eject notify on %s\n", __func__, objname);
if ((bridge->type != BRIDGE_TYPE_HOST) &&
(bridge->flags & BRIDGE_HAS_EJ0)) {
if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
struct acpiphp_slot *slot;
slot = bridge->func->slot;
if (!acpiphp_disable_slot(slot))
@@ -1296,7 +1193,6 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
break;
}
out:
acpi_scan_lock_release();
kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
}
@@ -1320,8 +1216,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type,
* For now just re-add this work to the kacpi_hotplug_wq so we
* don't deadlock on hotplug actions.
*/
alloc_acpiphp_hp_work(handle, type, context,
_handle_hotplug_event_bridge);
alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge);
}
static void _handle_hotplug_event_func(struct work_struct *work)
@@ -1330,22 +1225,19 @@ static void _handle_hotplug_event_func(struct work_struct *work)
char objname[64];
struct acpi_buffer buffer = { .length = sizeof(objname),
.pointer = objname };
struct acpiphp_hp_work *hp_work;
struct acpi_hp_work *hp_work;
acpi_handle handle;
u32 type;
void *context;
hp_work = container_of(work, struct acpiphp_hp_work, work);
hp_work = container_of(work, struct acpi_hp_work, work);
handle = hp_work->handle;
type = hp_work->type;
context = hp_work->context;
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
func = (struct acpiphp_func *)context;
func = (struct acpiphp_func *)hp_work->context;
acpi_scan_lock_acquire();
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
switch (type) {
case ACPI_NOTIFY_BUS_CHECK:
/* bus re-enumerate */
@@ -1399,23 +1291,7 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type,
* For now just re-add this work to the kacpi_hotplug_wq so we
* don't deadlock on hotplug actions.
*/
alloc_acpiphp_hp_work(handle, type, context,
_handle_hotplug_event_func);
}
static acpi_status
find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
{
int *count = (int *)context;
if (!acpi_is_root_bridge(handle))
return AE_OK;
(*count)++;
acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
handle_hotplug_event_bridge, NULL);
return AE_OK ;
alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func);
}
static struct acpi_pci_driver acpi_pci_hp_driver = {
@@ -1428,15 +1304,7 @@ static struct acpi_pci_driver acpi_pci_hp_driver = {
*/
int __init acpiphp_glue_init(void)
{
int num = 0;
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL);
if (num <= 0)
return -1;
else
acpi_pci_register_driver(&acpi_pci_hp_driver);
acpi_pci_register_driver(&acpi_pci_hp_driver);
return 0;
}
@@ -1452,28 +1320,6 @@ void acpiphp_glue_exit(void)
acpi_pci_unregister_driver(&acpi_pci_hp_driver);
}
/**
* acpiphp_get_num_slots - count number of slots in a system
*/
int __init acpiphp_get_num_slots(void)
{
struct acpiphp_bridge *bridge;
int num_slots = 0;
list_for_each_entry(bridge, &bridge_list, list) {
dbg("Bus %04x:%02x has %d slot%s\n",
pci_domain_nr(bridge->pci_bus),
bridge->pci_bus->number, bridge->nr_slots,
bridge->nr_slots == 1 ? "" : "s");
num_slots += bridge->nr_slots;
}
dbg("Total %d slots\n", num_slots);
return num_slots;
}
/**
* acpiphp_enable_slot - power on slot
* @slot: ACPI PHP slot

View File

@@ -252,8 +252,8 @@ int cpci_led_off(struct slot* slot)
int __ref cpci_configure_slot(struct slot *slot)
{
struct pci_dev *dev;
struct pci_bus *parent;
int fn;
dbg("%s - enter", __func__);
@@ -282,18 +282,13 @@ int __ref cpci_configure_slot(struct slot *slot)
}
parent = slot->dev->bus;
for (fn = 0; fn < 8; fn++) {
struct pci_dev *dev;
dev = pci_get_slot(parent,
PCI_DEVFN(PCI_SLOT(slot->devfn), fn));
if (!dev)
list_for_each_entry(dev, &parent->devices, bus_list)
if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))
continue;
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
pci_hp_add_bridge(dev);
pci_dev_put(dev);
}
pci_assign_unassigned_bridge_resources(parent->self);
@@ -305,8 +300,7 @@ int __ref cpci_configure_slot(struct slot *slot)
int cpci_unconfigure_slot(struct slot* slot)
{
int i;
struct pci_dev *dev;
struct pci_dev *dev, *temp;
dbg("%s - enter", __func__);
if (!slot->dev) {
@@ -314,13 +308,12 @@ int cpci_unconfigure_slot(struct slot* slot)
return -ENODEV;
}
for (i = 0; i < 8; i++) {
dev = pci_get_slot(slot->bus,
PCI_DEVFN(PCI_SLOT(slot->devfn), i));
if (dev) {
pci_stop_and_remove_bus_device(dev);
pci_dev_put(dev);
}
list_for_each_entry_safe(dev, temp, &slot->bus->devices, bus_list) {
if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))
continue;
pci_dev_get(dev);
pci_stop_and_remove_bus_device(dev);
pci_dev_put(dev);
}
pci_dev_put(slot->dev);
slot->dev = NULL;

View File

@@ -1900,8 +1900,7 @@ static void interrupt_event_handler(struct controller *ctrl)
dbg("power fault\n");
} else {
/* refresh notification */
if (p_slot)
update_slot_info(ctrl, p_slot);
update_slot_info(ctrl, p_slot);
}
ctrl->event_queue[loop].event_type = 0;
@@ -2520,44 +2519,28 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
/* If we have IO resources copy them and fill in the bridge's
* IO range registers */
if (io_node) {
memcpy(hold_IO_node, io_node, sizeof(struct pci_resource));
io_node->next = NULL;
memcpy(hold_IO_node, io_node, sizeof(struct pci_resource));
io_node->next = NULL;
/* set IO base and Limit registers */
temp_byte = io_node->base >> 8;
rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte);
/* set IO base and Limit registers */
temp_byte = io_node->base >> 8;
rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte);
temp_byte = (io_node->base + io_node->length - 1) >> 8;
rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
} else {
kfree(hold_IO_node);
hold_IO_node = NULL;
}
temp_byte = (io_node->base + io_node->length - 1) >> 8;
rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
/* If we have memory resources copy them and fill in the
* bridge's memory range registers. Otherwise, fill in the
* range registers with values that disable them. */
if (mem_node) {
memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource));
mem_node->next = NULL;
/* Copy the memory resources and fill in the bridge's memory
* range registers.
*/
memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource));
mem_node->next = NULL;
/* set Mem base and Limit registers */
temp_word = mem_node->base >> 16;
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
/* set Mem base and Limit registers */
temp_word = mem_node->base >> 16;
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
temp_word = (mem_node->base + mem_node->length - 1) >> 16;
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
} else {
temp_word = 0xFFFF;
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
temp_word = 0x0000;
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
kfree(hold_mem_node);
hold_mem_node = NULL;
}
temp_word = (mem_node->base + mem_node->length - 1) >> 16;
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource));
p_mem_node->next = NULL;
@@ -2627,7 +2610,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
/* Return unused bus resources
* First use the temporary node to store information for
* the board */
if (hold_bus_node && bus_node && temp_resources.bus_head) {
if (bus_node && temp_resources.bus_head) {
hold_bus_node->length = bus_node->base - hold_bus_node->base;
hold_bus_node->next = func->bus_head;
@@ -2751,7 +2734,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
}
/* If we have prefetchable memory space available and there
* is some left at the end, return the unused portion */
if (hold_p_mem_node && temp_resources.p_mem_head) {
if (temp_resources.p_mem_head) {
p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head),
&hold_p_mem_node, 0x100000);

View File

@@ -293,7 +293,6 @@ static void pciehp_remove(struct pcie_device *dev)
#ifdef CONFIG_PM
static int pciehp_suspend (struct pcie_device *dev)
{
dev_info(&dev->device, "%s ENTRY\n", __func__);
return 0;
}
@@ -303,7 +302,6 @@ static int pciehp_resume (struct pcie_device *dev)
struct slot *slot;
u8 status;
dev_info(&dev->device, "%s ENTRY\n", __func__);
ctrl = get_service_data(dev);
/* reinitialize the chipset's event detection logic */

View File

@@ -39,7 +39,7 @@ int pciehp_configure_device(struct slot *p_slot)
struct pci_dev *dev;
struct pci_dev *bridge = p_slot->ctrl->pcie->port;
struct pci_bus *parent = bridge->subordinate;
int num, fn;
int num;
struct controller *ctrl = p_slot->ctrl;
dev = pci_get_slot(parent, PCI_DEVFN(0, 0));
@@ -57,28 +57,18 @@ int pciehp_configure_device(struct slot *p_slot)
return -ENODEV;
}
for (fn = 0; fn < 8; fn++) {
dev = pci_get_slot(parent, PCI_DEVFN(0, fn));
if (!dev)
continue;
list_for_each_entry(dev, &parent->devices, bus_list)
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
(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(0, fn));
if (!dev)
list_for_each_entry(dev, &parent->devices, bus_list) {
if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
continue;
if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
pci_dev_put(dev);
continue;
}
pci_configure_slot(dev);
pci_dev_put(dev);
}
pci_bus_add_devices(parent);
@@ -89,9 +79,9 @@ int pciehp_configure_device(struct slot *p_slot)
int pciehp_unconfigure_device(struct slot *p_slot)
{
int ret, rc = 0;
int j;
u8 bctl = 0;
u8 presence = 0;
struct pci_dev *dev, *temp;
struct pci_bus *parent = p_slot->ctrl->pcie->port->subordinate;
u16 command;
struct controller *ctrl = p_slot->ctrl;
@@ -102,33 +92,31 @@ int pciehp_unconfigure_device(struct slot *p_slot)
if (ret)
presence = 0;
for (j = 0; j < 8; j++) {
struct pci_dev *temp = pci_get_slot(parent, PCI_DEVFN(0, j));
if (!temp)
continue;
if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) {
pci_dev_get(dev);
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl);
if (bctl & PCI_BRIDGE_CTL_VGA) {
ctrl_err(ctrl,
"Cannot remove display device %s\n",
pci_name(temp));
pci_dev_put(temp);
pci_name(dev));
pci_dev_put(dev);
rc = -EINVAL;
break;
}
}
pci_stop_and_remove_bus_device(temp);
pci_stop_and_remove_bus_device(dev);
/*
* Ensure that no new Requests will be generated from
* the device.
*/
if (presence) {
pci_read_config_word(temp, PCI_COMMAND, &command);
pci_read_config_word(dev, PCI_COMMAND, &command);
command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
command |= PCI_COMMAND_INTX_DISABLE;
pci_write_config_word(temp, PCI_COMMAND, command);
pci_write_config_word(dev, PCI_COMMAND, command);
}
pci_dev_put(temp);
pci_dev_put(dev);
}
return rc;

View File

@@ -334,7 +334,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
struct slot *slot = bss_hotplug_slot->private;
struct pci_bus *new_bus = NULL;
struct pci_dev *dev;
int func, num_funcs;
int num_funcs;
int new_ppb = 0;
int rc;
char *ssdt = NULL;
@@ -381,29 +381,26 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
* to the Linux PCI interface and tell the drivers
* about them.
*/
for (func = 0; func < num_funcs; func++) {
dev = pci_get_slot(slot->pci_bus,
PCI_DEVFN(slot->device_num + 1,
PCI_FUNC(func)));
if (dev) {
/* Need to do slot fixup on PPB before fixup of children
* (PPB's pcidev_info needs to be in pcidev_info list
* before child's SN_PCIDEV_INFO() call to setup
* pdi_host_pcidev_info).
*/
pcibios_fixup_device_resources(dev);
if (SN_ACPI_BASE_SUPPORT())
sn_acpi_slot_fixup(dev);
else
sn_io_slot_fixup(dev);
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
pci_hp_add_bridge(dev);
if (dev->subordinate) {
new_bus = dev->subordinate;
new_ppb = 1;
}
list_for_each_entry(dev, &slot->pci_bus->devices, bus_list) {
if (PCI_SLOT(dev->devfn) != slot->device_num + 1)
continue;
/* Need to do slot fixup on PPB before fixup of children
* (PPB's pcidev_info needs to be in pcidev_info list
* before child's SN_PCIDEV_INFO() call to setup
* pdi_host_pcidev_info).
*/
pcibios_fixup_device_resources(dev);
if (SN_ACPI_BASE_SUPPORT())
sn_acpi_slot_fixup(dev);
else
sn_io_slot_fixup(dev);
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
pci_hp_add_bridge(dev);
if (dev->subordinate) {
new_bus = dev->subordinate;
new_ppb = 1;
}
pci_dev_put(dev);
}
}
@@ -483,8 +480,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
{
struct slot *slot = bss_hotplug_slot->private;
struct pci_dev *dev;
int func;
struct pci_dev *dev, *temp;
int rc;
acpi_owner_id ssdt_id = 0;
@@ -545,15 +541,14 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
}
/* Free the SN resources assigned to the Linux device.*/
for (func = 0; func < 8; func++) {
dev = pci_get_slot(slot->pci_bus,
PCI_DEVFN(slot->device_num + 1,
PCI_FUNC(func)));
if (dev) {
sn_bus_free_data(dev);
pci_stop_and_remove_bus_device(dev);
pci_dev_put(dev);
}
list_for_each_entry_safe(dev, temp, &slot->pci_bus->devices, bus_list) {
if (PCI_SLOT(dev->devfn) != slot->device_num + 1)
continue;
pci_dev_get(dev);
sn_bus_free_data(dev);
pci_stop_and_remove_bus_device(dev);
pci_dev_put(dev);
}
/* Remove the SSDT for the slot from the ACPI namespace */

View File

@@ -40,7 +40,7 @@ int __ref shpchp_configure_device(struct slot *p_slot)
struct controller *ctrl = p_slot->ctrl;
struct pci_dev *bridge = ctrl->pci_dev;
struct pci_bus *parent = bridge->subordinate;
int num, fn;
int num;
dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
if (dev) {
@@ -57,24 +57,20 @@ int __ref shpchp_configure_device(struct slot *p_slot)
return -ENODEV;
}
for (fn = 0; fn < 8; fn++) {
dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn));
if (!dev)
list_for_each_entry(dev, &parent->devices, bus_list) {
if (PCI_SLOT(dev->devfn) != p_slot->device)
continue;
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
(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)
list_for_each_entry(dev, &parent->devices, bus_list) {
if (PCI_SLOT(dev->devfn) != p_slot->device)
continue;
pci_configure_slot(dev);
pci_dev_put(dev);
}
pci_bus_add_devices(parent);
@@ -85,32 +81,32 @@ int __ref shpchp_configure_device(struct slot *p_slot)
int shpchp_unconfigure_device(struct slot *p_slot)
{
int rc = 0;
int j;
u8 bctl = 0;
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
struct pci_dev *dev, *temp;
struct controller *ctrl = p_slot->ctrl;
ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n",
__func__, pci_domain_nr(parent), p_slot->bus, p_slot->device);
for (j = 0; j < 8 ; j++) {
struct pci_dev *temp = pci_get_slot(parent,
(p_slot->device << 3) | j);
if (!temp)
list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) {
if (PCI_SLOT(dev->devfn) != p_slot->device)
continue;
if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
pci_dev_get(dev);
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl);
if (bctl & PCI_BRIDGE_CTL_VGA) {
ctrl_err(ctrl,
"Cannot remove display device %s\n",
pci_name(temp));
pci_dev_put(temp);
pci_name(dev));
pci_dev_put(dev);
rc = -EINVAL;
break;
}
}
pci_stop_and_remove_bus_device(temp);
pci_dev_put(temp);
pci_stop_and_remove_bus_device(dev);
pci_dev_put(dev);
}
return rc;
}

View File

@@ -33,7 +33,6 @@ static inline u8 virtfn_devfn(struct pci_dev *dev, int id)
static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr)
{
int rc;
struct pci_bus *child;
if (bus->number == busnr)
@@ -48,12 +47,7 @@ static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr)
return NULL;
pci_bus_insert_busn_res(child, busnr, busnr);
child->dev.parent = bus->bridge;
rc = pci_bus_add_child(child);
if (rc) {
pci_remove_bus(child);
return NULL;
}
bus->is_added = 1;
return child;
}
@@ -123,8 +117,6 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
virtfn->is_virtfn = 1;
rc = pci_bus_add_device(virtfn);
if (rc)
goto failed1;
sprintf(buf, "virtfn%u", id);
rc = sysfs_create_link(&dev->dev.kobj, &virtfn->dev.kobj, buf);
if (rc)

View File

@@ -302,48 +302,11 @@ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
return 0;
}
static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle)
{
int num;
unsigned int seg, bus;
/*
* The string should be the same as root bridge's name
* Please look at 'pci_scan_bus_parented'
*/
num = sscanf(dev_name(dev), "pci%04x:%02x", &seg, &bus);
if (num != 2)
return -ENODEV;
*handle = acpi_get_pci_rootbridge_handle(seg, bus);
if (!*handle)
return -ENODEV;
return 0;
}
static void pci_acpi_setup(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
acpi_handle handle = ACPI_HANDLE(dev);
struct acpi_device *adev;
acpi_status status;
acpi_handle dummy;
/*
* Evaluate and parse _PRT, if exists. This code allows parsing of
* _PRT objects within the scope of non-bridge devices. Note that
* _PRTs within the scope of a PCI bridge assume the bridge's
* subordinate bus number.
*
* TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
*/
status = acpi_get_handle(handle, METHOD_NAME__PRT, &dummy);
if (ACPI_SUCCESS(status)) {
unsigned char bus;
bus = pci_dev->subordinate ?
pci_dev->subordinate->number : pci_dev->bus->number;
acpi_pci_irq_add_prt(handle, pci_domain_nr(pci_dev->bus), bus);
}
if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
return;
@@ -358,7 +321,6 @@ static void pci_acpi_setup(struct device *dev)
static void pci_acpi_cleanup(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
acpi_handle handle = ACPI_HANDLE(dev);
struct acpi_device *adev;
@@ -367,16 +329,11 @@ static void pci_acpi_cleanup(struct device *dev)
device_set_run_wake(dev, false);
pci_acpi_remove_pm_notifier(adev);
}
if (pci_dev->subordinate)
acpi_pci_irq_del_prt(pci_domain_nr(pci_dev->bus),
pci_dev->subordinate->number);
}
static struct acpi_bus_type acpi_pci_bus = {
.bus = &pci_bus_type,
.find_device = acpi_pci_find_device,
.find_bridge = acpi_pci_find_root_bridge,
.setup = pci_acpi_setup,
.cleanup = pci_acpi_cleanup,
};

View File

@@ -392,7 +392,7 @@ static void pci_device_shutdown(struct device *dev)
* Turn off Bus Master bit on the device to tell it to not
* continue to do DMA
*/
pci_disable_device(pci_dev);
pci_clear_master(pci_dev);
}
#ifdef CONFIG_PM
@@ -628,6 +628,7 @@ static int pci_pm_suspend(struct device *dev)
goto Fixup;
}
pci_dev->state_saved = false;
if (pm->suspend) {
pci_power_t prev = pci_dev->current_state;
int error;
@@ -774,6 +775,7 @@ static int pci_pm_freeze(struct device *dev)
return 0;
}
pci_dev->state_saved = false;
if (pm->freeze) {
int error;
@@ -862,6 +864,7 @@ static int pci_pm_poweroff(struct device *dev)
goto Fixup;
}
pci_dev->state_saved = false;
if (pm->poweroff) {
int error;
@@ -987,6 +990,7 @@ static int pci_pm_runtime_suspend(struct device *dev)
if (!pm || !pm->runtime_suspend)
return -ENOSYS;
pci_dev->state_saved = false;
pci_dev->no_d3cold = false;
error = pm->runtime_suspend(dev);
suspend_report_result(pm->runtime_suspend, error);
@@ -1186,9 +1190,13 @@ pci_dev_driver(const struct pci_dev *dev)
static int pci_bus_match(struct device *dev, struct device_driver *drv)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct pci_driver *pci_drv = to_pci_driver(drv);
struct pci_driver *pci_drv;
const struct pci_device_id *found_id;
if (!pci_dev->match_driver)
return 0;
pci_drv = to_pci_driver(drv);
found_id = pci_match_device(pci_drv, pci_dev);
if (found_id)
return 1;

View File

@@ -1151,8 +1151,7 @@ int pci_reenable_device(struct pci_dev *dev)
return 0;
}
static int __pci_enable_device_flags(struct pci_dev *dev,
resource_size_t flags)
static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags)
{
int err;
int i, bars = 0;
@@ -1169,7 +1168,7 @@ static int __pci_enable_device_flags(struct pci_dev *dev,
dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
}
if (atomic_add_return(1, &dev->enable_cnt) > 1)
if (atomic_inc_return(&dev->enable_cnt) > 1)
return 0; /* already enabled */
/* only skip sriov related */
@@ -1196,7 +1195,7 @@ static int __pci_enable_device_flags(struct pci_dev *dev,
*/
int pci_enable_device_io(struct pci_dev *dev)
{
return __pci_enable_device_flags(dev, IORESOURCE_IO);
return pci_enable_device_flags(dev, IORESOURCE_IO);
}
/**
@@ -1209,7 +1208,7 @@ int pci_enable_device_io(struct pci_dev *dev)
*/
int pci_enable_device_mem(struct pci_dev *dev)
{
return __pci_enable_device_flags(dev, IORESOURCE_MEM);
return pci_enable_device_flags(dev, IORESOURCE_MEM);
}
/**
@@ -1225,7 +1224,7 @@ int pci_enable_device_mem(struct pci_dev *dev)
*/
int pci_enable_device(struct pci_dev *dev)
{
return __pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO);
return pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO);
}
/*
@@ -1396,7 +1395,10 @@ pci_disable_device(struct pci_dev *dev)
if (dr)
dr->enabled = 0;
if (atomic_sub_return(1, &dev->enable_cnt) != 0)
dev_WARN_ONCE(&dev->dev, atomic_read(&dev->enable_cnt) <= 0,
"disabling already-disabled device");
if (atomic_dec_return(&dev->enable_cnt) != 0)
return;
do_pci_disable_device(dev);
@@ -2043,10 +2045,13 @@ void pci_free_cap_save_buffers(struct pci_dev *dev)
}
/**
* pci_enable_ari - enable ARI forwarding if hardware support it
* pci_configure_ari - enable or disable ARI forwarding
* @dev: the PCI device
*
* If @dev and its upstream bridge both support ARI, enable ARI in the
* bridge. Otherwise, disable ARI in the bridge.
*/
void pci_enable_ari(struct pci_dev *dev)
void pci_configure_ari(struct pci_dev *dev)
{
u32 cap;
struct pci_dev *bridge;
@@ -2054,9 +2059,6 @@ void pci_enable_ari(struct pci_dev *dev)
if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn)
return;
if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI))
return;
bridge = dev->bus->self;
if (!bridge)
return;
@@ -2065,8 +2067,15 @@ void pci_enable_ari(struct pci_dev *dev)
if (!(cap & PCI_EXP_DEVCAP2_ARI))
return;
pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_ARI);
bridge->ari_enabled = 1;
if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI)) {
pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2,
PCI_EXP_DEVCTL2_ARI);
bridge->ari_enabled = 1;
} else {
pcie_capability_clear_word(bridge, PCI_EXP_DEVCTL2,
PCI_EXP_DEVCTL2_ARI);
bridge->ari_enabled = 0;
}
}
/**
@@ -3742,18 +3751,6 @@ resource_size_t pci_specified_resource_alignment(struct pci_dev *dev)
return align;
}
/**
* pci_is_reassigndev - check if specified PCI is target device to reassign
* @dev: the PCI device to check
*
* RETURNS: non-zero for PCI device is a target device to reassign,
* or zero is not.
*/
int pci_is_reassigndev(struct pci_dev *dev)
{
return (pci_specified_resource_alignment(dev) != 0);
}
/*
* This function disables memory decoding and releases memory resources
* of the device specified by kernel's boot parameter 'pci=resource_alignment='.
@@ -3768,7 +3765,9 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
resource_size_t align, size;
u16 command;
if (!pci_is_reassigndev(dev))
/* check if specified PCI is target device to reassign */
align = pci_specified_resource_alignment(dev);
if (!align)
return;
if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL &&
@@ -3784,7 +3783,6 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
command &= ~PCI_COMMAND_MEMORY;
pci_write_config_word(dev, PCI_COMMAND, command);
align = pci_specified_resource_alignment(dev);
for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) {
r = &dev->resource[i];
if (!(r->flags & IORESOURCE_MEM))

View File

@@ -203,8 +203,8 @@ extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
struct resource *res, unsigned int reg);
extern int pci_resource_bar(struct pci_dev *dev, int resno,
enum pci_bar_type *type);
extern int pci_bus_add_child(struct pci_bus *bus);
extern void pci_enable_ari(struct pci_dev *dev);
extern void pci_configure_ari(struct pci_dev *dev);
/**
* pci_ari_enabled - query ARI forwarding status
* @bus: the PCI bus

View File

@@ -556,6 +556,9 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
struct pcie_link_state *link;
int blacklist = !!pcie_aspm_sanity_check(pdev);
if (!aspm_support_enabled)
return;
if (!pci_is_pcie(pdev) || pdev->link_state)
return;
if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT &&
@@ -634,10 +637,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
struct pci_dev *parent = pdev->bus->self;
struct pcie_link_state *link, *root, *parent_link;
if (!pci_is_pcie(pdev) || !parent || !parent->link_state)
return;
if ((pci_pcie_type(parent) != PCI_EXP_TYPE_ROOT_PORT) &&
(pci_pcie_type(parent) != PCI_EXP_TYPE_DOWNSTREAM))
if (!parent || !parent->link_state)
return;
down_read(&pci_bus_sem);

View File

@@ -272,7 +272,7 @@ static int get_port_device_capability(struct pci_dev *dev)
/* Hot-Plug Capable */
if ((cap_mask & PCIE_PORT_SERVICE_HP) &&
dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT) {
pcie_caps_reg(dev) & PCI_EXP_FLAGS_SLOT) {
pcie_capability_read_dword(dev, PCI_EXP_SLTCAP, &reg32);
if (reg32 & PCI_EXP_SLTCAP_HPC) {
services |= PCIE_PORT_SERVICE_HP;

View File

@@ -623,6 +623,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
{
struct pci_bus *child;
int i;
int ret;
/*
* Allocate a new bus, and inherit stuff from the parent..
@@ -637,8 +638,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
child->bus_flags = parent->bus_flags;
/* initialize some portions of the bus device, but don't register it
* now as the parent is not properly set up yet. This device will get
* registered later in pci_bus_add_devices()
* now as the parent is not properly set up yet.
*/
child->dev.class = &pcibus_class;
dev_set_name(&child->dev, "%04x:%02x", pci_domain_nr(child), busnr);
@@ -651,11 +651,14 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
child->primary = parent->busn_res.start;
child->busn_res.end = 0xff;
if (!bridge)
return child;
if (!bridge) {
child->dev.parent = parent->bridge;
goto add_dev;
}
child->self = bridge;
child->bridge = get_device(&bridge->dev);
child->dev.parent = child->bridge;
pci_set_bus_of_node(child);
pci_set_bus_speed(child);
@@ -666,6 +669,13 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
}
bridge->subordinate = child;
add_dev:
ret = device_register(&child->dev);
WARN_ON(ret < 0);
/* Create legacy_io and legacy_mem files for this bus */
pci_create_legacy_files(child);
return child;
}
@@ -1285,7 +1295,7 @@ static void pci_init_capabilities(struct pci_dev *dev)
pci_vpd_pci22_init(dev);
/* Alternative Routing-ID Forwarding */
pci_enable_ari(dev);
pci_configure_ari(dev);
/* Single Root I/O Virtualization */
pci_iov_init(dev);
@@ -1296,10 +1306,12 @@ static void pci_init_capabilities(struct pci_dev *dev)
void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
{
int ret;
device_initialize(&dev->dev);
dev->dev.release = pci_release_dev;
pci_dev_get(dev);
set_dev_node(&dev->dev, pcibus_to_node(bus));
dev->dev.dma_mask = &dev->dma_mask;
dev->dev.dma_parms = &dev->dma_parms;
dev->dev.coherent_dma_mask = 0xffffffffull;
@@ -1326,6 +1338,17 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
down_write(&pci_bus_sem);
list_add_tail(&dev->bus_list, &bus->devices);
up_write(&pci_bus_sem);
pci_fixup_device(pci_fixup_final, dev);
ret = pcibios_add_device(dev);
WARN_ON(ret < 0);
/* Notifier could use PCI capabilities */
dev->match_driver = false;
ret = device_add(&dev->dev);
WARN_ON(ret < 0);
pci_proc_attach_device(dev);
}
struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn)
@@ -1348,31 +1371,31 @@ struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn)
}
EXPORT_SYMBOL(pci_scan_single_device);
static unsigned next_ari_fn(struct pci_dev *dev, unsigned fn)
static unsigned next_fn(struct pci_bus *bus, struct pci_dev *dev, unsigned fn)
{
u16 cap;
unsigned pos, next_fn;
int pos;
u16 cap = 0;
unsigned next_fn;
if (!dev)
return 0;
if (pci_ari_enabled(bus)) {
if (!dev)
return 0;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
if (!pos)
return 0;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
if (!pos)
return 0;
pci_read_config_word(dev, pos + 4, &cap);
next_fn = cap >> 8;
if (next_fn <= fn)
return 0;
return next_fn;
}
pci_read_config_word(dev, pos + PCI_ARI_CAP, &cap);
next_fn = PCI_ARI_CAP_NFN(cap);
if (next_fn <= fn)
return 0; /* protect against malformed list */
static unsigned next_trad_fn(struct pci_dev *dev, unsigned fn)
{
return (fn + 1) % 8;
}
return next_fn;
}
/* dev may be NULL for non-contiguous multifunction devices */
if (!dev || dev->multifunction)
return (fn + 1) % 8;
static unsigned no_next_fn(struct pci_dev *dev, unsigned fn)
{
return 0;
}
@@ -1405,7 +1428,6 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
{
unsigned fn, nr = 0;
struct pci_dev *dev;
unsigned (*next_fn)(struct pci_dev *, unsigned) = no_next_fn;
if (only_one_child(bus) && (devfn > 0))
return 0; /* Already scanned the entire slot */
@@ -1416,12 +1438,7 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
if (!dev->is_added)
nr++;
if (pci_ari_enabled(bus))
next_fn = next_ari_fn;
else if (dev->multifunction)
next_fn = next_trad_fn;
for (fn = next_fn(dev, 0); fn > 0; fn = next_fn(dev, fn)) {
for (fn = next_fn(bus, dev, 0); fn > 0; fn = next_fn(bus, dev, fn)) {
dev = pci_scan_single_device(bus, devfn + fn);
if (dev) {
if (!dev->is_added)
@@ -1632,6 +1649,18 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)
return max;
}
/**
* pcibios_root_bridge_prepare - Platform-specific host bridge setup.
* @bridge: Host bridge to set up.
*
* Default empty implementation. Replace with an architecture-specific setup
* routine, if necessary.
*/
int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
{
return 0;
}
struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata, struct list_head *resources)
{
@@ -1644,13 +1673,13 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
char bus_addr[64];
char *fmt;
b = pci_alloc_bus();
if (!b)
return NULL;
b->sysdata = sysdata;
b->ops = ops;
b->number = b->busn_res.start = bus;
b2 = pci_find_bus(pci_domain_nr(b), bus);
if (b2) {
/* If we already got to this bus through a different bridge, ignore it */
@@ -1665,6 +1694,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
bridge->dev.parent = parent;
bridge->dev.release = pci_release_bus_bridge_dev;
dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
error = pcibios_root_bridge_prepare(bridge);
if (error)
goto bridge_dev_reg_err;
error = device_register(&bridge->dev);
if (error)
goto bridge_dev_reg_err;
@@ -1685,8 +1718,6 @@ 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->busn_res.start = bus;
if (parent)
dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
else

View File

@@ -24,7 +24,7 @@ static void pci_stop_dev(struct pci_dev *dev)
if (dev->is_added) {
pci_proc_detach_device(dev);
pci_remove_sysfs_dev_files(dev);
device_unregister(&dev->dev);
device_del(&dev->dev);
dev->is_added = 0;
}
@@ -39,7 +39,7 @@ static void pci_destroy_dev(struct pci_dev *dev)
up_write(&pci_bus_sem);
pci_free_resources(dev);
pci_dev_put(dev);
put_device(&dev->dev);
}
void pci_remove_bus(struct pci_bus *bus)

View File

@@ -319,13 +319,13 @@ int pci_dev_present(const struct pci_device_id *ids)
WARN_ON(in_interrupt());
while (ids->vendor || ids->subvendor || ids->class_mask) {
found = pci_get_dev_by_id(ids, NULL);
if (found)
goto exit;
if (found) {
pci_dev_put(found);
return 1;
}
ids++;
}
exit:
if (found)
return 1;
return 0;
}
EXPORT_SYMBOL(pci_dev_present);

View File

@@ -283,7 +283,7 @@ static void assign_requested_resources_sorted(struct list_head *head,
idx = res - &dev_res->dev->resource[0];
if (resource_size(res) &&
pci_assign_resource(dev_res->dev, idx)) {
if (fail_head && !pci_is_root_bus(dev_res->dev->bus)) {
if (fail_head) {
/*
* if the failed res is for ROM BAR, and it will
* be enabled later, don't add it to the list