Merge branch 'pci/yinghai-root-bus-hotplug' into next

* pci/yinghai-root-bus-hotplug:
  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
  PCI/ACPI: Print info if host bridge notify handler installation fails
  PCI: acpiphp: Move host bridge hotplug to pci_root.c
  PCI/ACPI: acpiphp: Rename alloc_acpiphp_hp_work() to alloc_acpi_hp_work()
  PCI: Make device create/destroy logic symmetric
  PCI: Fix reference count leak in pci_dev_present()
  PCI: Set pci_dev dev_node early so IOAPIC irq_descs are allocated locally
  PCI: Add root bus children dev's res to fail list
  PCI: acpiphp: Add is_hotplug_bridge detection

Conflicts:
	drivers/pci/pci.h
This commit is contained in:
Bjorn Helgaas 2013-01-26 17:35:58 -07:00
commit 939de1d69c
18 changed files with 274 additions and 219 deletions

View File

@ -68,6 +68,7 @@ struct acpi_ec {
extern struct acpi_ec *first_ec;
int acpi_pci_root_init(void);
void acpi_pci_root_hp_init(void);
int acpi_ec_init(void);
int acpi_ec_ecdt_probe(void);
int acpi_boot_ec_enable(void);

View File

@ -84,8 +84,7 @@ static acpi_osd_handler acpi_irq_handler;
static void *acpi_irq_context;
static struct workqueue_struct *kacpid_wq;
static struct workqueue_struct *kacpi_notify_wq;
struct workqueue_struct *kacpi_hotplug_wq;
EXPORT_SYMBOL(kacpi_hotplug_wq);
static struct workqueue_struct *kacpi_hotplug_wq;
/*
* This list of permanent mappings is for memory that may be accessed from
@ -1778,3 +1777,24 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
{
__acpi_os_prepare_sleep = func;
}
void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context,
void (*func)(struct work_struct *work))
{
struct acpi_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);
}
EXPORT_SYMBOL_GPL(alloc_acpi_hp_work);

View File

@ -655,3 +655,133 @@ int __init acpi_pci_root_init(void)
return 0;
}
/* Support root bridge hotplug */
static void handle_root_bridge_insertion(acpi_handle handle)
{
struct acpi_device *device;
if (!acpi_bus_get_device(handle, &device)) {
printk(KERN_DEBUG "acpi device exists...\n");
return;
}
if (acpi_bus_scan(handle))
printk(KERN_ERR "cannot add bridge to acpi list\n");
}
static void handle_root_bridge_removal(struct acpi_device *device)
{
struct acpi_eject_event *ej_event;
ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
if (!ej_event) {
/* Inform firmware the hot-remove operation has error */
(void) acpi_evaluate_hotplug_ost(device->handle,
ACPI_NOTIFY_EJECT_REQUEST,
ACPI_OST_SC_NON_SPECIFIC_FAILURE,
NULL);
return;
}
ej_event->device = device;
ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
acpi_bus_hot_remove_device(ej_event);
}
static void _handle_hotplug_event_root(struct work_struct *work)
{
struct acpi_pci_root *root;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER };
struct acpi_hp_work *hp_work;
acpi_handle handle;
u32 type;
hp_work = container_of(work, struct acpi_hp_work, work);
handle = hp_work->handle;
type = hp_work->type;
root = acpi_pci_find_root(handle);
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
switch (type) {
case ACPI_NOTIFY_BUS_CHECK:
/* bus enumerate */
printk(KERN_DEBUG "%s: Bus check notify on %s\n", __func__,
(char *)buffer.pointer);
if (!root)
handle_root_bridge_insertion(handle);
break;
case ACPI_NOTIFY_DEVICE_CHECK:
/* device check */
printk(KERN_DEBUG "%s: Device check notify on %s\n", __func__,
(char *)buffer.pointer);
if (!root)
handle_root_bridge_insertion(handle);
break;
case ACPI_NOTIFY_EJECT_REQUEST:
/* request device eject */
printk(KERN_DEBUG "%s: Device eject notify on %s\n", __func__,
(char *)buffer.pointer);
if (root)
handle_root_bridge_removal(root->device);
break;
default:
printk(KERN_WARNING "notify_handler: unknown event type 0x%x for %s\n",
type, (char *)buffer.pointer);
break;
}
kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
kfree(buffer.pointer);
}
static void handle_hotplug_event_root(acpi_handle handle, u32 type,
void *context)
{
alloc_acpi_hp_work(handle, type, context,
_handle_hotplug_event_root);
}
static acpi_status __init
find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
{
acpi_status status;
char objname[64];
struct acpi_buffer buffer = { .length = sizeof(objname),
.pointer = objname };
int *count = (int *)context;
if (!acpi_is_root_bridge(handle))
return AE_OK;
(*count)++;
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
handle_hotplug_event_root, NULL);
if (ACPI_FAILURE(status))
printk(KERN_DEBUG "acpi root: %s notify handler is not installed, exit status: %u\n",
objname, (unsigned int)status);
else
printk(KERN_DEBUG "acpi root: %s notify handler is installed\n",
objname);
return AE_OK;
}
void __init acpi_pci_root_hp_init(void)
{
int num = 0;
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL);
printk(KERN_DEBUG "Found %d acpi root devices\n", num);
}

View File

@ -1706,5 +1706,8 @@ int __init acpi_scan_init(void)
}
acpi_update_all_gpes();
acpi_pci_root_hp_init();
return 0;
}

View File

@ -161,68 +161,35 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
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)
{
@ -235,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

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

@ -543,10 +543,13 @@ 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 (bridge->type != BRIDGE_TYPE_HOST) {
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)) {
@ -630,9 +633,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)
@ -797,6 +797,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
@ -831,8 +854,10 @@ 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);
}
}
}
}
@ -1098,18 +1123,12 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
}
/* Program resources in newly inserted bridge */
static int acpiphp_configure_bridge (acpi_handle handle)
static int acpiphp_configure_p2p_bridge(acpi_handle handle)
{
struct pci_bus *bus;
struct pci_dev *pdev = acpi_get_pci_dev(handle);
struct pci_bus *bus = pdev->subordinate;
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_dev_put(pdev);
pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus);
@ -1119,7 +1138,7 @@ static int acpiphp_configure_bridge (acpi_handle handle)
return 0;
}
static void handle_bridge_insertion(acpi_handle handle, u32 type)
static void handle_p2p_bridge_insertion(acpi_handle handle, u32 type)
{
struct acpi_device *device;
@ -1137,8 +1156,8 @@ static void handle_bridge_insertion(acpi_handle handle, u32 type)
err("ACPI device object missing\n");
return;
}
if (!acpiphp_configure_bridge(handle))
add_bridge(handle);
if (!acpiphp_configure_p2p_bridge(handle))
add_p2p_bridge(handle);
else
err("cannot configure and start bridge\n");
@ -1178,34 +1197,6 @@ 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;
@ -1214,17 +1205,17 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
.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;
if (acpi_bus_get_device(handle, &device)) {
/* This bridge must have just been physically inserted */
handle_bridge_insertion(handle, type);
handle_p2p_bridge_insertion(handle, type);
goto out;
}
@ -1321,8 +1312,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)
@ -1331,12 +1321,12 @@ 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;
@ -1397,23 +1387,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 = {
@ -1426,15 +1400,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;
}
@ -1450,28 +1416,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

@ -48,12 +48,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 +118,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

@ -1186,9 +1186,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

@ -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_configure_ari(struct pci_dev *dev);
/**
* pci_ari_enabled - query ARI forwarding status
* @bus: the PCI bus

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;
}
@ -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)
@ -1650,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 */
@ -1695,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

@ -22,7 +22,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;
}
@ -37,7 +37,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

View File

@ -310,6 +310,15 @@ struct acpi_eject_event {
u32 event;
};
struct acpi_hp_work {
struct work_struct work;
acpi_handle handle;
u32 type;
void *context;
};
void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context,
void (*func)(struct work_struct *work));
extern struct kobject *acpi_kobj;
extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int);
void acpi_bus_private_data_handler(acpi_handle, void *);

View File

@ -193,8 +193,6 @@ void acpi_os_fixed_event_count(u32 fixed_event_number);
/*
* Threads and Scheduling
*/
extern struct workqueue_struct *kacpi_hotplug_wq;
acpi_thread_id acpi_os_get_thread_id(void);
acpi_status

View File

@ -286,6 +286,7 @@ struct pci_dev {
unsigned int irq;
struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
bool match_driver; /* Skip attaching driver */
/* These fields are used by common fixups */
unsigned int transparent:1; /* Transparent PCI bridge */
unsigned int multifunction:1;/* Part of multi-function device */