Merge branches 'acerhdf', 'acpi-pci-bind', 'bjorn-pci-root', 'bugzilla-12904', 'bugzilla-13121', 'bugzilla-13396', 'bugzilla-13533', 'bugzilla-13612', 'c3_lock', 'hid-cleanups', 'misc-2.6.31', 'pdc-leak-fix', 'pnpacpi', 'power_nocheck', 'thinkpad_acpi', 'video' and 'wmi' into release

This commit is contained in:
39 changed files with 1700 additions and 843 deletions

View file

@ -192,6 +192,22 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"),
},
},
{
.callback = dmi_disable_osi_vista,
.ident = "Sony VGN-NS10J_S",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS10J_S"),
},
},
{
.callback = dmi_disable_osi_vista,
.ident = "Sony VGN-SR290J",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "Sony VGN-SR290J"),
},
},
/*
* BIOS invocation of _OSI(Linux) is almost always a BIOS bug.

View file

@ -140,46 +140,6 @@ struct device *acpi_get_physical_device(acpi_handle handle)
EXPORT_SYMBOL(acpi_get_physical_device);
/* ToDo: When a PCI bridge is found, return the PCI device behind the bridge
* This should work in general, but did not on a Lenovo T61 for the
* graphics card. But this must be fixed when the PCI device is
* bound and the kernel device struct is attached to the acpi device
* Note: A success call will increase reference count by one
* Do call put_device(dev) on the returned device then
*/
struct device *acpi_get_physical_pci_device(acpi_handle handle)
{
struct device *dev;
long long device_id;
acpi_status status;
status =
acpi_evaluate_integer(handle, "_ADR", NULL, &device_id);
if (ACPI_FAILURE(status))
return NULL;
/* We need to attempt to determine whether the _ADR refers to a
PCI device or not. There's no terribly good way to do this,
so the best we can hope for is to assume that there'll never
be a device in the host bridge */
if (device_id >= 0x10000) {
/* It looks like a PCI device. Does it exist? */
dev = acpi_get_physical_device(handle);
} else {
/* It doesn't look like a PCI device. Does its parent
exist? */
acpi_handle phandle;
if (acpi_get_parent(handle, &phandle))
return NULL;
dev = acpi_get_physical_device(phandle);
}
if (!dev)
return NULL;
return dev;
}
EXPORT_SYMBOL(acpi_get_physical_pci_device);
static int acpi_bind_one(struct device *dev, acpi_handle handle)
{
struct acpi_device *acpi_dev;

View file

@ -79,6 +79,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;
static struct workqueue_struct *kacpi_hotplug_wq;
struct acpi_res_list {
resource_size_t start;
@ -192,8 +193,10 @@ acpi_status acpi_os_initialize1(void)
{
kacpid_wq = create_singlethread_workqueue("kacpid");
kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify");
kacpi_hotplug_wq = create_singlethread_workqueue("kacpi_hotplug");
BUG_ON(!kacpid_wq);
BUG_ON(!kacpi_notify_wq);
BUG_ON(!kacpi_hotplug_wq);
return AE_OK;
}
@ -206,6 +209,7 @@ acpi_status acpi_os_terminate(void)
destroy_workqueue(kacpid_wq);
destroy_workqueue(kacpi_notify_wq);
destroy_workqueue(kacpi_hotplug_wq);
return AE_OK;
}
@ -716,6 +720,7 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
acpi_status status = AE_OK;
struct acpi_os_dpc *dpc;
struct workqueue_struct *queue;
work_func_t func;
int ret;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Scheduling function [%p(%p)] for deferred execution.\n",
@ -740,15 +745,17 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
dpc->function = function;
dpc->context = context;
if (!hp) {
INIT_WORK(&dpc->work, acpi_os_execute_deferred);
queue = (type == OSL_NOTIFY_HANDLER) ?
kacpi_notify_wq : kacpid_wq;
ret = queue_work(queue, &dpc->work);
} else {
INIT_WORK(&dpc->work, acpi_os_execute_hp_deferred);
ret = schedule_work(&dpc->work);
}
/*
* We can't run hotplug code in keventd_wq/kacpid_wq/kacpid_notify_wq
* because the hotplug code may call driver .remove() functions,
* which invoke flush_scheduled_work/acpi_os_wait_events_complete
* to flush these workqueues.
*/
queue = hp ? kacpi_hotplug_wq :
(type == OSL_NOTIFY_HANDLER ? kacpi_notify_wq : kacpid_wq);
func = hp ? acpi_os_execute_hp_deferred : acpi_os_execute_deferred;
INIT_WORK(&dpc->work, func);
ret = queue_work(queue, &dpc->work);
if (!ret) {
printk(KERN_ERR PREFIX

View file

@ -24,12 +24,7 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <linux/pm.h>
#include <linux/pci.h>
#include <linux/acpi.h>
#include <acpi/acpi_bus.h>
@ -38,310 +33,76 @@
#define _COMPONENT ACPI_PCI_COMPONENT
ACPI_MODULE_NAME("pci_bind");
struct acpi_pci_data {
struct acpi_pci_id id;
static int acpi_pci_unbind(struct acpi_device *device)
{
struct pci_dev *dev;
dev = acpi_get_pci_dev(device->handle);
if (!dev || !dev->subordinate)
goto out;
acpi_pci_irq_del_prt(dev->subordinate);
device->ops.bind = NULL;
device->ops.unbind = NULL;
out:
pci_dev_put(dev);
return 0;
}
static int acpi_pci_bind(struct acpi_device *device)
{
acpi_status status;
acpi_handle handle;
struct pci_bus *bus;
struct pci_dev *dev;
};
static int acpi_pci_unbind(struct acpi_device *device);
static void acpi_pci_data_handler(acpi_handle handle, u32 function,
void *context)
{
/* TBD: Anything we need to do here? */
return;
}
/**
* acpi_get_pci_id
* ------------------
* This function is used by the ACPI Interpreter (a.k.a. Core Subsystem)
* to resolve PCI information for ACPI-PCI devices defined in the namespace.
* This typically occurs when resolving PCI operation region information.
*/
acpi_status acpi_get_pci_id(acpi_handle handle, struct acpi_pci_id *id)
{
int result = 0;
acpi_status status = AE_OK;
struct acpi_device *device = NULL;
struct acpi_pci_data *data = NULL;
if (!id)
return AE_BAD_PARAMETER;
result = acpi_bus_get_device(handle, &device);
if (result) {
printk(KERN_ERR PREFIX
"Invalid ACPI Bus context for device %s\n",
acpi_device_bid(device));
return AE_NOT_EXIST;
}
status = acpi_get_data(handle, acpi_pci_data_handler, (void **)&data);
if (ACPI_FAILURE(status) || !data) {
ACPI_EXCEPTION((AE_INFO, status,
"Invalid ACPI-PCI context for device %s",
acpi_device_bid(device)));
return status;
}
*id = data->id;
dev = acpi_get_pci_dev(device->handle);
if (!dev)
return 0;
/*
id->segment = data->id.segment;
id->bus = data->id.bus;
id->device = data->id.device;
id->function = data->id.function;
* Install the 'bind' function to facilitate callbacks for
* children of the P2P bridge.
*/
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Device %s has PCI address %04x:%02x:%02x.%d\n",
acpi_device_bid(device), id->segment, id->bus,
id->device, id->function));
return AE_OK;
}
EXPORT_SYMBOL(acpi_get_pci_id);
int acpi_pci_bind(struct acpi_device *device)
{
int result = 0;
acpi_status status;
struct acpi_pci_data *data;
struct acpi_pci_data *pdata;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
acpi_handle handle;
if (!device || !device->parent)
return -EINVAL;
data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
if (ACPI_FAILURE(status)) {
kfree(data);
return -ENODEV;
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n",
(char *)buffer.pointer));
/*
* Segment & Bus
* -------------
* These are obtained via the parent device's ACPI-PCI context.
*/
status = acpi_get_data(device->parent->handle, acpi_pci_data_handler,
(void **)&pdata);
if (ACPI_FAILURE(status) || !pdata || !pdata->bus) {
ACPI_EXCEPTION((AE_INFO, status,
"Invalid ACPI-PCI context for parent device %s",
acpi_device_bid(device->parent)));
result = -ENODEV;
goto end;
}
data->id.segment = pdata->id.segment;
data->id.bus = pdata->bus->number;
/*
* Device & Function
* -----------------
* These are simply obtained from the device's _ADR method. Note
* that a value of zero is valid.
*/
data->id.device = device->pnp.bus_address >> 16;
data->id.function = device->pnp.bus_address & 0xFFFF;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %04x:%02x:%02x.%d\n",
data->id.segment, data->id.bus, data->id.device,
data->id.function));
/*
* TBD: Support slot devices (e.g. function=0xFFFF).
*/
/*
* Locate PCI Device
* -----------------
* Locate matching device in PCI namespace. If it doesn't exist
* this typically means that the device isn't currently inserted
* (e.g. docking station, port replicator, etc.).
*/
data->dev = pci_get_slot(pdata->bus,
PCI_DEVFN(data->id.device, data->id.function));
if (!data->dev) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Device %04x:%02x:%02x.%d not present in PCI namespace\n",
data->id.segment, data->id.bus,
data->id.device, data->id.function));
result = -ENODEV;
goto end;
}
if (!data->dev->bus) {
printk(KERN_ERR PREFIX
"Device %04x:%02x:%02x.%d has invalid 'bus' field\n",
data->id.segment, data->id.bus,
data->id.device, data->id.function);
result = -ENODEV;
goto end;
}
/*
* PCI Bridge?
* -----------
* If so, set the 'bus' field and install the 'bind' function to
* facilitate callbacks for all of its children.
*/
if (data->dev->subordinate) {
if (dev->subordinate) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Device %04x:%02x:%02x.%d is a PCI bridge\n",
data->id.segment, data->id.bus,
data->id.device, data->id.function));
data->bus = data->dev->subordinate;
pci_domain_nr(dev->bus), dev->bus->number,
PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)));
device->ops.bind = acpi_pci_bind;
device->ops.unbind = acpi_pci_unbind;
}
/*
* Attach ACPI-PCI Context
* -----------------------
* Thus binding the ACPI and PCI devices.
*/
status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to attach ACPI-PCI context to device %s",
acpi_device_bid(device)));
result = -ENODEV;
goto end;
}
/*
* PCI Routing Table
* -----------------
* Evaluate and parse _PRT, if exists. This code is independent of
* PCI bridges (above) to allow 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.
* 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(device->handle, METHOD_NAME__PRT, &handle);
if (ACPI_SUCCESS(status)) {
if (data->bus) /* PCI-PCI bridge */
acpi_pci_irq_add_prt(device->handle, data->id.segment,
data->bus->number);
else /* non-bridge PCI device */
acpi_pci_irq_add_prt(device->handle, data->id.segment,
data->id.bus);
}
end:
kfree(buffer.pointer);
if (result) {
pci_dev_put(data->dev);
kfree(data);
}
return result;
}
static int acpi_pci_unbind(struct acpi_device *device)
{
int result = 0;
acpi_status status;
struct acpi_pci_data *data;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
if (!device || !device->parent)
return -EINVAL;
status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
if (ACPI_FAILURE(status))
return -ENODEV;
goto out;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unbinding PCI device [%s]...\n",
(char *) buffer.pointer));
kfree(buffer.pointer);
if (dev->subordinate)
bus = dev->subordinate;
else
bus = dev->bus;
status =
acpi_get_data(device->handle, acpi_pci_data_handler,
(void **)&data);
if (ACPI_FAILURE(status)) {
result = -ENODEV;
goto end;
}
acpi_pci_irq_add_prt(device->handle, bus);
status = acpi_detach_data(device->handle, acpi_pci_data_handler);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to detach data from device %s",
acpi_device_bid(device)));
result = -ENODEV;
goto end;
}
if (data->dev->subordinate) {
acpi_pci_irq_del_prt(data->id.segment, data->bus->number);
}
pci_dev_put(data->dev);
kfree(data);
end:
return result;
out:
pci_dev_put(dev);
return 0;
}
int
acpi_pci_bind_root(struct acpi_device *device,
struct acpi_pci_id *id, struct pci_bus *bus)
int acpi_pci_bind_root(struct acpi_device *device)
{
int result = 0;
acpi_status status;
struct acpi_pci_data *data = NULL;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
if (!device || !id || !bus) {
return -EINVAL;
}
data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->id = *id;
data->bus = bus;
device->ops.bind = acpi_pci_bind;
device->ops.unbind = acpi_pci_unbind;
status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
if (ACPI_FAILURE(status)) {
kfree (data);
return -ENODEV;
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI root bridge [%s] to "
"%04x:%02x\n", (char *)buffer.pointer,
id->segment, id->bus));
status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to attach ACPI-PCI context to device %s",
(char *)buffer.pointer));
result = -ENODEV;
goto end;
}
end:
kfree(buffer.pointer);
if (result != 0)
kfree(data);
return result;
return 0;
}

View file

@ -182,7 +182,7 @@ static void do_prt_fixups(struct acpi_prt_entry *entry,
}
}
static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,
static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,
struct acpi_pci_routing_table *prt)
{
struct acpi_prt_entry *entry;
@ -196,8 +196,8 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,
* 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert
* it here.
*/
entry->id.segment = segment;
entry->id.bus = bus;
entry->id.segment = pci_domain_nr(bus);
entry->id.bus = bus->number;
entry->id.device = (prt->address >> 16) & 0xFFFF;
entry->pin = prt->pin + 1;
@ -242,7 +242,7 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,
return 0;
}
int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
{
acpi_status status;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@ -271,7 +271,7 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
entry = buffer.pointer;
while (entry && (entry->length > 0)) {
acpi_pci_irq_add_entry(handle, segment, bus, entry);
acpi_pci_irq_add_entry(handle, bus, entry);
entry = (struct acpi_pci_routing_table *)
((unsigned long)entry + entry->length);
}
@ -280,16 +280,17 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
return 0;
}
void acpi_pci_irq_del_prt(int segment, int bus)
void acpi_pci_irq_del_prt(struct pci_bus *bus)
{
struct acpi_prt_entry *entry, *tmp;
printk(KERN_DEBUG
"ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
segment, bus);
pci_domain_nr(bus), bus->number);
spin_lock(&acpi_prt_lock);
list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) {
if (segment == entry->id.segment && bus == entry->id.bus) {
if (pci_domain_nr(bus) == entry->id.segment
&& bus->number == entry->id.bus) {
list_del(&entry->list);
kfree(entry);
}

View file

@ -63,9 +63,10 @@ static struct acpi_driver acpi_pci_root_driver = {
struct acpi_pci_root {
struct list_head node;
struct acpi_device * device;
struct acpi_pci_id id;
struct acpi_device *device;
struct pci_bus *bus;
u16 segment;
u8 bus_nr;
u32 osc_support_set; /* _OSC state of support bits */
u32 osc_control_set; /* _OSC state of control bits */
@ -82,7 +83,7 @@ static DEFINE_MUTEX(osc_lock);
int acpi_pci_register_driver(struct acpi_pci_driver *driver)
{
int n = 0;
struct list_head *entry;
struct acpi_pci_root *root;
struct acpi_pci_driver **pptr = &sub_driver;
while (*pptr)
@ -92,9 +93,7 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver)
if (!driver->add)
return 0;
list_for_each(entry, &acpi_pci_roots) {
struct acpi_pci_root *root;
root = list_entry(entry, struct acpi_pci_root, node);
list_for_each_entry(root, &acpi_pci_roots, node) {
driver->add(root->device->handle);
n++;
}
@ -106,7 +105,7 @@ EXPORT_SYMBOL(acpi_pci_register_driver);
void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
{
struct list_head *entry;
struct acpi_pci_root *root;
struct acpi_pci_driver **pptr = &sub_driver;
while (*pptr) {
@ -120,28 +119,48 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
if (!driver->remove)
return;
list_for_each(entry, &acpi_pci_roots) {
struct acpi_pci_root *root;
root = list_entry(entry, struct acpi_pci_root, node);
list_for_each_entry(root, &acpi_pci_roots, node)
driver->remove(root->device->handle);
}
}
EXPORT_SYMBOL(acpi_pci_unregister_driver);
acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus)
{
struct acpi_pci_root *tmp;
struct acpi_pci_root *root;
list_for_each_entry(tmp, &acpi_pci_roots, node) {
if ((tmp->id.segment == (u16) seg) && (tmp->id.bus == (u16) bus))
return tmp->device->handle;
}
list_for_each_entry(root, &acpi_pci_roots, node)
if ((root->segment == (u16) seg) && (root->bus_nr == (u16) bus))
return root->device->handle;
return NULL;
}
EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle);
/**
* acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge
* @handle - the ACPI CA node in question.
*
* Note: we could make this API take a struct acpi_device * instead, but
* for now, it's more convenient to operate on an acpi_handle.
*/
int acpi_is_root_bridge(acpi_handle handle)
{
int ret;
struct acpi_device *device;
ret = acpi_bus_get_device(handle, &device);
if (ret)
return 0;
ret = acpi_match_device_ids(device, root_device_ids);
if (ret)
return 0;
else
return 1;
}
EXPORT_SYMBOL_GPL(acpi_is_root_bridge);
static acpi_status
get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
{
@ -161,19 +180,22 @@ get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
return AE_OK;
}
static acpi_status try_get_root_bridge_busnr(acpi_handle handle, int *busnum)
static acpi_status try_get_root_bridge_busnr(acpi_handle handle,
unsigned long long *bus)
{
acpi_status status;
int busnum;
*busnum = -1;
busnum = -1;
status =
acpi_walk_resources(handle, METHOD_NAME__CRS,
get_root_bridge_busnr_callback, busnum);
get_root_bridge_busnr_callback, &busnum);
if (ACPI_FAILURE(status))
return status;
/* Check if we really get a bus number from _CRS */
if (*busnum == -1)
if (busnum == -1)
return AE_ERROR;
*bus = busnum;
return AE_OK;
}
@ -298,6 +320,7 @@ static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags)
static struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle)
{
struct acpi_pci_root *root;
list_for_each_entry(root, &acpi_pci_roots, node) {
if (root->device->handle == handle)
return root;
@ -305,6 +328,87 @@ static struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle)
return NULL;
}
struct acpi_handle_node {
struct list_head node;
acpi_handle handle;
};
/**
* acpi_get_pci_dev - convert ACPI CA handle to struct pci_dev
* @handle: the handle in question
*
* Given an ACPI CA handle, the desired PCI device is located in the
* list of PCI devices.
*
* If the device is found, its reference count is increased and this
* function returns a pointer to its data structure. The caller must
* decrement the reference count by calling pci_dev_put().
* If no device is found, %NULL is returned.
*/
struct pci_dev *acpi_get_pci_dev(acpi_handle handle)
{
int dev, fn;
unsigned long long adr;
acpi_status status;
acpi_handle phandle;
struct pci_bus *pbus;
struct pci_dev *pdev = NULL;
struct acpi_handle_node *node, *tmp;
struct acpi_pci_root *root;
LIST_HEAD(device_list);
/*
* Walk up the ACPI CA namespace until we reach a PCI root bridge.
*/
phandle = handle;
while (!acpi_is_root_bridge(phandle)) {
node = kzalloc(sizeof(struct acpi_handle_node), GFP_KERNEL);
if (!node)
goto out;
INIT_LIST_HEAD(&node->node);
node->handle = phandle;
list_add(&node->node, &device_list);
status = acpi_get_parent(phandle, &phandle);
if (ACPI_FAILURE(status))
goto out;
}
root = acpi_pci_find_root(phandle);
if (!root)
goto out;
pbus = root->bus;
/*
* Now, walk back down the PCI device tree until we return to our
* original handle. Assumes that everything between the PCI root
* bridge and the device we're looking for must be a P2P bridge.
*/
list_for_each_entry(node, &device_list, node) {
acpi_handle hnd = node->handle;
status = acpi_evaluate_integer(hnd, "_ADR", NULL, &adr);
if (ACPI_FAILURE(status))
goto out;
dev = (adr >> 16) & 0xffff;
fn = adr & 0xffff;
pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn));
if (hnd == handle)
break;
pbus = pdev->subordinate;
pci_dev_put(pdev);
}
out:
list_for_each_entry_safe(node, tmp, &device_list, node)
kfree(node);
return pdev;
}
EXPORT_SYMBOL_GPL(acpi_get_pci_dev);
/**
* acpi_pci_osc_control_set - commit requested control to Firmware
* @handle: acpi_handle for the target ACPI object
@ -363,31 +467,46 @@ EXPORT_SYMBOL(acpi_pci_osc_control_set);
static int __devinit acpi_pci_root_add(struct acpi_device *device)
{
int result = 0;
struct acpi_pci_root *root = NULL;
struct acpi_pci_root *tmp;
acpi_status status = AE_OK;
unsigned long long value = 0;
acpi_handle handle = NULL;
unsigned long long segment, bus;
acpi_status status;
int result;
struct acpi_pci_root *root;
acpi_handle handle;
struct acpi_device *child;
u32 flags, base_flags;
segment = 0;
status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL,
&segment);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
printk(KERN_ERR PREFIX "can't evaluate _SEG\n");
return -ENODEV;
}
if (!device)
return -EINVAL;
/* Check _CRS first, then _BBN. If no _BBN, default to zero. */
bus = 0;
status = try_get_root_bridge_busnr(device->handle, &bus);
if (ACPI_FAILURE(status)) {
status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, &bus);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
printk(KERN_ERR PREFIX
"no bus number in _CRS and can't evaluate _BBN\n");
return -ENODEV;
}
}
root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
if (!root)
return -ENOMEM;
INIT_LIST_HEAD(&root->node);
INIT_LIST_HEAD(&root->node);
root->device = device;
root->segment = segment & 0xFFFF;
root->bus_nr = bus & 0xFF;
strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
device->driver_data = root;
device->ops.bind = acpi_pci_bind;
/*
* All supported architectures that use ACPI have support for
* PCI domains, so we indicate this in _OSC support capabilities.
@ -395,79 +514,6 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
acpi_pci_osc_support(root, flags);
/*
* Segment
* -------
* Obtained via _SEG, if exists, otherwise assumed to be zero (0).
*/
status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL,
&value);
switch (status) {
case AE_OK:
root->id.segment = (u16) value;
break;
case AE_NOT_FOUND:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Assuming segment 0 (no _SEG)\n"));
root->id.segment = 0;
break;
default:
ACPI_EXCEPTION((AE_INFO, status, "Evaluating _SEG"));
result = -ENODEV;
goto end;
}
/*
* Bus
* ---
* Obtained via _BBN, if exists, otherwise assumed to be zero (0).
*/
status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL,
&value);
switch (status) {
case AE_OK:
root->id.bus = (u16) value;
break;
case AE_NOT_FOUND:
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Assuming bus 0 (no _BBN)\n"));
root->id.bus = 0;
break;
default:
ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BBN"));
result = -ENODEV;
goto end;
}
/* Some systems have wrong _BBN */
list_for_each_entry(tmp, &acpi_pci_roots, node) {
if ((tmp->id.segment == root->id.segment)
&& (tmp->id.bus == root->id.bus)) {
int bus = 0;
acpi_status status;
printk(KERN_ERR PREFIX
"Wrong _BBN value, reboot"
" and use option 'pci=noacpi'\n");
status = try_get_root_bridge_busnr(device->handle, &bus);
if (ACPI_FAILURE(status))
break;
if (bus != root->id.bus) {
printk(KERN_INFO PREFIX
"PCI _CRS %d overrides _BBN 0\n", bus);
root->id.bus = bus;
}
break;
}
}
/*
* Device & Function
* -----------------
* Obtained from _ADR (which has already been evaluated for us).
*/
root->id.device = device->pnp.bus_address >> 16;
root->id.function = device->pnp.bus_address & 0xFFFF;
/*
* TBD: Need PCI interface for enumeration/configuration of roots.
*/
@ -477,7 +523,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n",
acpi_device_name(device), acpi_device_bid(device),
root->id.segment, root->id.bus);
root->segment, root->bus_nr);
/*
* Scan the Root Bridge
@ -486,11 +532,11 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
* PCI namespace does not get created until this call is made (and
* thus the root bridge's pci_dev does not exist).
*/
root->bus = pci_acpi_scan_root(device, root->id.segment, root->id.bus);
root->bus = pci_acpi_scan_root(device, segment, bus);
if (!root->bus) {
printk(KERN_ERR PREFIX
"Bus %04x:%02x not present in PCI namespace\n",
root->id.segment, root->id.bus);
root->segment, root->bus_nr);
result = -ENODEV;
goto end;
}
@ -500,7 +546,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
* -----------------------
* Thus binding the ACPI and PCI devices.
*/
result = acpi_pci_bind_root(device, &root->id, root->bus);
result = acpi_pci_bind_root(device);
if (result)
goto end;
@ -511,8 +557,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
*/
status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
if (ACPI_SUCCESS(status))
result = acpi_pci_irq_add_prt(device->handle, root->id.segment,
root->id.bus);
result = acpi_pci_irq_add_prt(device->handle, root->bus);
/*
* Scan and bind all _ADR-Based Devices
@ -531,42 +576,28 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
if (flags != base_flags)
acpi_pci_osc_support(root, flags);
end:
if (result) {
if (!list_empty(&root->node))
list_del(&root->node);
kfree(root);
}
return 0;
end:
if (!list_empty(&root->node))
list_del(&root->node);
kfree(root);
return result;
}
static int acpi_pci_root_start(struct acpi_device *device)
{
struct acpi_pci_root *root;
struct acpi_pci_root *root = acpi_driver_data(device);
list_for_each_entry(root, &acpi_pci_roots, node) {
if (root->device == device) {
pci_bus_add_devices(root->bus);
return 0;
}
}
return -ENODEV;
pci_bus_add_devices(root->bus);
return 0;
}
static int acpi_pci_root_remove(struct acpi_device *device, int type)
{
struct acpi_pci_root *root = NULL;
if (!device || !acpi_driver_data(device))
return -EINVAL;
root = acpi_driver_data(device);
struct acpi_pci_root *root = acpi_driver_data(device);
kfree(root);
return 0;
}

View file

@ -194,7 +194,7 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
{
int result = 0, state;
int result = 0;
int found = 0;
acpi_status status = AE_OK;
struct acpi_power_resource *resource = NULL;
@ -236,18 +236,6 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
if (ACPI_FAILURE(status))
return -ENODEV;
if (!acpi_power_nocheck) {
/*
* If acpi_power_nocheck is set, it is unnecessary to check
* the power state after power transition.
*/
result = acpi_power_get_state(resource->device->handle,
&state);
if (result)
return result;
if (state != ACPI_POWER_RESOURCE_STATE_ON)
return -ENOEXEC;
}
/* Update the power resource's _device_ power state */
resource->device->power.state = ACPI_STATE_D0;
@ -258,7 +246,7 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
{
int result = 0, state;
int result = 0;
acpi_status status = AE_OK;
struct acpi_power_resource *resource = NULL;
struct list_head *node, *next;
@ -293,18 +281,6 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
if (ACPI_FAILURE(status))
return -ENODEV;
if (!acpi_power_nocheck) {
/*
* If acpi_power_nocheck is set, it is unnecessary to check
* the power state after power transition.
*/
result = acpi_power_get_state(handle, &state);
if (result)
return result;
if (state != ACPI_POWER_RESOURCE_STATE_OFF)
return -ENOEXEC;
}
/* Update the power resource's _device_ power state */
resource->device->power.state = ACPI_STATE_D3;

View file

@ -89,7 +89,7 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr);
static const struct acpi_device_id processor_device_ids[] = {
{ACPI_PROCESSOR_OBJECT_HID, 0},
{ACPI_PROCESSOR_HID, 0},
{"ACPI0007", 0},
{"", 0},
};
MODULE_DEVICE_TABLE(acpi, processor_device_ids);
@ -596,7 +596,21 @@ static int acpi_processor_get_info(struct acpi_device *device)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"No bus mastering arbitration control\n"));
if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_HID)) {
if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) {
/* Declared with "Processor" statement; match ProcessorID */
status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX "Evaluating processor object\n");
return -ENODEV;
}
/*
* TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
* >>> 'acpi_get_processor_id(acpi_id, &id)' in
* arch/xxx/acpi.c
*/
pr->acpi_id = object.processor.proc_id;
} else {
/*
* Declared with "Device" statement; match _UID.
* Note that we don't handle string _UIDs yet.
@ -611,20 +625,6 @@ static int acpi_processor_get_info(struct acpi_device *device)
}
device_declaration = 1;
pr->acpi_id = value;
} else {
/* Declared with "Processor" statement; match ProcessorID */
status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX "Evaluating processor object\n");
return -ENODEV;
}
/*
* TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
* >>> 'acpi_get_processor_id(acpi_id, &id)' in
* arch/xxx/acpi.c
*/
pr->acpi_id = object.processor.proc_id;
}
cpu_index = get_cpu_id(pr->handle, device_declaration, pr->acpi_id);
@ -649,7 +649,16 @@ static int acpi_processor_get_info(struct acpi_device *device)
return -ENODEV;
}
}
/*
* On some boxes several processors use the same processor bus id.
* But they are located in different scope. For example:
* \_SB.SCK0.CPU0
* \_SB.SCK1.CPU0
* Rename the processor device bus id. And the new bus id will be
* generated as the following format:
* CPU+CPU ID.
*/
sprintf(acpi_device_bid(device), "CPU%X", pr->id);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
pr->acpi_id));
@ -731,6 +740,8 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
/* _PDC call should be done before doing anything else (if reqd.). */
arch_acpi_processor_init_pdc(pr);
acpi_processor_set_pdc(pr);
arch_acpi_processor_cleanup_pdc(pr);
#ifdef CONFIG_CPU_FREQ
acpi_processor_ppc_has_changed(pr);
#endif

View file

@ -139,7 +139,7 @@ static void acpi_safe_halt(void)
* are affected too. We pick the most conservative approach: we assume
* that the local APIC stops in both C2 and C3.
*/
static void acpi_timer_check_state(int state, struct acpi_processor *pr,
static void lapic_timer_check_state(int state, struct acpi_processor *pr,
struct acpi_processor_cx *cx)
{
struct acpi_processor_power *pwr = &pr->power;
@ -162,7 +162,7 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr,
pr->power.timer_broadcast_on_state = state;
}
static void acpi_propagate_timer_broadcast(struct acpi_processor *pr)
static void lapic_timer_propagate_broadcast(struct acpi_processor *pr)
{
unsigned long reason;
@ -173,7 +173,7 @@ static void acpi_propagate_timer_broadcast(struct acpi_processor *pr)
}
/* Power(C) State timer broadcast control */
static void acpi_state_timer_broadcast(struct acpi_processor *pr,
static void lapic_timer_state_broadcast(struct acpi_processor *pr,
struct acpi_processor_cx *cx,
int broadcast)
{
@ -190,10 +190,10 @@ static void acpi_state_timer_broadcast(struct acpi_processor *pr,
#else
static void acpi_timer_check_state(int state, struct acpi_processor *pr,
static void lapic_timer_check_state(int state, struct acpi_processor *pr,
struct acpi_processor_cx *cstate) { }
static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) { }
static void acpi_state_timer_broadcast(struct acpi_processor *pr,
static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) { }
static void lapic_timer_state_broadcast(struct acpi_processor *pr,
struct acpi_processor_cx *cx,
int broadcast)
{
@ -515,7 +515,8 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx)
static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
struct acpi_processor_cx *cx)
{
static int bm_check_flag;
static int bm_check_flag = -1;
static int bm_control_flag = -1;
if (!cx->address)
@ -545,12 +546,14 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
}
/* All the logic here assumes flags.bm_check is same across all CPUs */
if (!bm_check_flag) {
if (bm_check_flag == -1) {
/* Determine whether bm_check is needed based on CPU */
acpi_processor_power_init_bm_check(&(pr->flags), pr->id);
bm_check_flag = pr->flags.bm_check;
bm_control_flag = pr->flags.bm_control;
} else {
pr->flags.bm_check = bm_check_flag;
pr->flags.bm_control = bm_control_flag;
}
if (pr->flags.bm_check) {
@ -614,29 +617,25 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
switch (cx->type) {
case ACPI_STATE_C1:
cx->valid = 1;
acpi_timer_check_state(i, pr, cx);
break;
case ACPI_STATE_C2:
acpi_processor_power_verify_c2(cx);
if (cx->valid)
acpi_timer_check_state(i, pr, cx);
break;
case ACPI_STATE_C3:
acpi_processor_power_verify_c3(pr, cx);
if (cx->valid)
acpi_timer_check_state(i, pr, cx);
break;
}
if (cx->valid)
tsc_check_state(cx->type);
if (!cx->valid)
continue;
if (cx->valid)
working++;
lapic_timer_check_state(i, pr, cx);
tsc_check_state(cx->type);
working++;
}
acpi_propagate_timer_broadcast(pr);
lapic_timer_propagate_broadcast(pr);
return (working);
}
@ -839,7 +838,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
return 0;
}
acpi_state_timer_broadcast(pr, cx, 1);
lapic_timer_state_broadcast(pr, cx, 1);
kt1 = ktime_get_real();
acpi_idle_do_entry(cx);
kt2 = ktime_get_real();
@ -847,7 +846,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
local_irq_enable();
cx->usage++;
acpi_state_timer_broadcast(pr, cx, 0);
lapic_timer_state_broadcast(pr, cx, 0);
return idle_time;
}
@ -892,7 +891,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
* Must be done before busmaster disable as we might need to
* access HPET !
*/
acpi_state_timer_broadcast(pr, cx, 1);
lapic_timer_state_broadcast(pr, cx, 1);
if (cx->type == ACPI_STATE_C3)
ACPI_FLUSH_CPU_CACHE();
@ -914,7 +913,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
cx->usage++;
acpi_state_timer_broadcast(pr, cx, 0);
lapic_timer_state_broadcast(pr, cx, 0);
cx->time += sleep_ticks;
return idle_time;
}
@ -981,7 +980,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
* Must be done before busmaster disable as we might need to
* access HPET !
*/
acpi_state_timer_broadcast(pr, cx, 1);
lapic_timer_state_broadcast(pr, cx, 1);
kt1 = ktime_get_real();
/*
@ -1026,7 +1025,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
cx->usage++;
acpi_state_timer_broadcast(pr, cx, 0);
lapic_timer_state_broadcast(pr, cx, 0);
cx->time += sleep_ticks;
return idle_time;
}

View file

@ -95,7 +95,7 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha
}
static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
static int acpi_bus_hot_remove_device(void *context)
static void acpi_bus_hot_remove_device(void *context)
{
struct acpi_device *device;
acpi_handle handle = context;
@ -104,10 +104,10 @@ static int acpi_bus_hot_remove_device(void *context)
acpi_status status = AE_OK;
if (acpi_bus_get_device(handle, &device))
return 0;
return;
if (!device)
return 0;
return;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Hot-removing device %s...\n", dev_name(&device->dev)));
@ -115,7 +115,7 @@ static int acpi_bus_hot_remove_device(void *context)
if (acpi_bus_trim(device, 1)) {
printk(KERN_ERR PREFIX
"Removing device failed\n");
return -1;
return;
}
/* power off device */
@ -142,9 +142,10 @@ static int acpi_bus_hot_remove_device(void *context)
*/
status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
if (ACPI_FAILURE(status))
return -ENODEV;
printk(KERN_WARNING PREFIX
"Eject device failed\n");
return 0;
return;
}
static ssize_t
@ -155,7 +156,6 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
acpi_status status;
acpi_object_type type = 0;
struct acpi_device *acpi_device = to_acpi_device(d);
struct task_struct *task;
if ((!count) || (buf[0] != '1')) {
return -EINVAL;
@ -172,11 +172,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
goto err;
}
/* remove the device in another thread to fix the deadlock issue */
task = kthread_run(acpi_bus_hot_remove_device,
acpi_device->handle, "acpi_hot_remove_device");
if (IS_ERR(task))
ret = PTR_ERR(task);
acpi_os_hotplug_execute(acpi_bus_hot_remove_device, acpi_device->handle);
err:
return ret;
}
@ -198,12 +194,12 @@ acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *b
int result;
result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path);
if(result)
if (result)
goto end;
result = sprintf(buf, "%s\n", (char*)path.pointer);
kfree(path.pointer);
end:
end:
return result;
}
static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL);
@ -217,21 +213,21 @@ static int acpi_device_setup_files(struct acpi_device *dev)
/*
* Devices gotten from FADT don't have a "path" attribute
*/
if(dev->handle) {
if (dev->handle) {
result = device_create_file(&dev->dev, &dev_attr_path);
if(result)
if (result)
goto end;
}
if(dev->flags.hardware_id) {
if (dev->flags.hardware_id) {
result = device_create_file(&dev->dev, &dev_attr_hid);
if(result)
if (result)
goto end;
}
if (dev->flags.hardware_id || dev->flags.compatible_ids){
if (dev->flags.hardware_id || dev->flags.compatible_ids) {
result = device_create_file(&dev->dev, &dev_attr_modalias);
if(result)
if (result)
goto end;
}
@ -242,7 +238,7 @@ static int acpi_device_setup_files(struct acpi_device *dev)
status = acpi_get_handle(dev->handle, "_EJ0", &temp);
if (ACPI_SUCCESS(status))
result = device_create_file(&dev->dev, &dev_attr_eject);
end:
end:
return result;
}
@ -262,9 +258,9 @@ static void acpi_device_remove_files(struct acpi_device *dev)
if (dev->flags.hardware_id || dev->flags.compatible_ids)
device_remove_file(&dev->dev, &dev_attr_modalias);
if(dev->flags.hardware_id)
if (dev->flags.hardware_id)
device_remove_file(&dev->dev, &dev_attr_hid);
if(dev->handle)
if (dev->handle)
device_remove_file(&dev->dev, &dev_attr_path);
}
/* --------------------------------------------------------------------------
@ -512,7 +508,7 @@ static int acpi_device_register(struct acpi_device *device,
break;
}
}
if(!found) {
if (!found) {
acpi_device_bus_id = new_bus_id;
strcpy(acpi_device_bus_id->bus_id, device->flags.hardware_id ? device->pnp.hardware_id : "device");
acpi_device_bus_id->instance_no = 0;
@ -530,22 +526,21 @@ static int acpi_device_register(struct acpi_device *device,
if (device->parent)
device->dev.parent = &parent->dev;
device->dev.bus = &acpi_bus_type;
device_initialize(&device->dev);
device->dev.release = &acpi_device_release;
result = device_add(&device->dev);
if(result) {
dev_err(&device->dev, "Error adding device\n");
result = device_register(&device->dev);
if (result) {
dev_err(&device->dev, "Error registering device\n");
goto end;
}
result = acpi_device_setup_files(device);
if(result)
if (result)
printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n",
dev_name(&device->dev));
device->removal_type = ACPI_BUS_REMOVAL_NORMAL;
return 0;
end:
end:
mutex_lock(&acpi_device_lock);
if (device->parent)
list_del(&device->node);
@ -577,7 +572,7 @@ static void acpi_device_unregister(struct acpi_device *device, int type)
* @device: the device to add and initialize
* @driver: driver for the device
*
* Used to initialize a device via its device driver. Called whenever a
* Used to initialize a device via its device driver. Called whenever a
* driver is bound to a device. Invokes the driver's add() ops.
*/
static int
@ -585,7 +580,6 @@ acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver)
{
int result = 0;
if (!device || !driver)
return -EINVAL;
@ -802,7 +796,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
if (!acpi_match_device_ids(device, button_device_ids))
device->wakeup.flags.run_wake = 1;
end:
end:
if (ACPI_FAILURE(status))
device->flags.wake_capable = 0;
return 0;
@ -1070,7 +1064,7 @@ static void acpi_device_set_id(struct acpi_device *device,
break;
}
/*
/*
* \_SB
* ----
* Fix for the system root bus device -- the only root-level device.
@ -1320,7 +1314,7 @@ acpi_add_single_object(struct acpi_device **child,
device->parent->ops.bind(device);
}
end:
end:
if (!result)
*child = device;
else {
@ -1464,7 +1458,6 @@ acpi_bus_add(struct acpi_device **child,
return result;
}
EXPORT_SYMBOL(acpi_bus_add);
int acpi_bus_start(struct acpi_device *device)
@ -1484,7 +1477,6 @@ int acpi_bus_start(struct acpi_device *device)
}
return result;
}
EXPORT_SYMBOL(acpi_bus_start);
int acpi_bus_trim(struct acpi_device *start, int rmdevice)
@ -1542,7 +1534,6 @@ int acpi_bus_trim(struct acpi_device *start, int rmdevice)
}
EXPORT_SYMBOL_GPL(acpi_bus_trim);
static int acpi_bus_scan_fixed(struct acpi_device *root)
{
int result = 0;
@ -1610,6 +1601,6 @@ int __init acpi_scan_init(void)
if (result)
acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
Done:
Done:
return result;
}

View file

@ -76,6 +76,7 @@ MODULE_LICENSE("GPL");
static int brightness_switch_enabled = 1;
module_param(brightness_switch_enabled, bool, 0644);
static int register_count = 0;
static int acpi_video_bus_add(struct acpi_device *device);
static int acpi_video_bus_remove(struct acpi_device *device, int type);
static int acpi_video_resume(struct acpi_device *device);
@ -586,6 +587,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"),
},
},
{
.callback = video_set_bqc_offset,
.ident = "Acer Aspire 7720",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"),
},
},
{}
};
@ -976,6 +985,11 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
device->backlight->props.max_brightness = device->brightness->count-3;
kfree(name);
result = sysfs_create_link(&device->backlight->dev.kobj,
&device->dev->dev.kobj, "device");
if (result)
printk(KERN_ERR PREFIX "Create sysfs link\n");
device->cdev = thermal_cooling_device_register("LCD",
device->dev, &video_cooling_ops);
if (IS_ERR(device->cdev))
@ -1054,15 +1068,15 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
static int acpi_video_bus_check(struct acpi_video_bus *video)
{
acpi_status status = -ENOENT;
struct device *dev;
struct pci_dev *dev;
if (!video)
return -EINVAL;
dev = acpi_get_physical_pci_device(video->device->handle);
dev = acpi_get_pci_dev(video->device->handle);
if (!dev)
return -ENODEV;
put_device(dev);
pci_dev_put(dev);
/* Since there is no HID, CID and so on for VGA driver, we have
* to check well known required nodes.
@ -1990,6 +2004,7 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
status = acpi_remove_notify_handler(device->dev->handle,
ACPI_DEVICE_NOTIFY,
acpi_video_device_notify);
sysfs_remove_link(&device->backlight->dev.kobj, "device");
backlight_device_unregister(device->backlight);
if (device->cdev) {
sysfs_remove_link(&device->dev->dev.kobj,
@ -2318,6 +2333,13 @@ static int __init intel_opregion_present(void)
int acpi_video_register(void)
{
int result = 0;
if (register_count) {
/*
* if the function of acpi_video_register is already called,
* don't register the acpi_vide_bus again and return no error.
*/
return 0;
}
acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir);
if (!acpi_video_dir)
@ -2329,10 +2351,35 @@ int acpi_video_register(void)
return -ENODEV;
}
/*
* When the acpi_video_bus is loaded successfully, increase
* the counter reference.
*/
register_count = 1;
return 0;
}
EXPORT_SYMBOL(acpi_video_register);
void acpi_video_unregister(void)
{
if (!register_count) {
/*
* If the acpi video bus is already unloaded, don't
* unload it again and return directly.
*/
return;
}
acpi_bus_unregister_driver(&acpi_video_bus);
remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
register_count = 0;
return;
}
EXPORT_SYMBOL(acpi_video_unregister);
/*
* This is kind of nasty. Hardware using Intel chipsets may require
* the video opregion code to be run first in order to initialise
@ -2350,16 +2397,12 @@ static int __init acpi_video_init(void)
return acpi_video_register();
}
void acpi_video_exit(void)
static void __exit acpi_video_exit(void)
{
acpi_bus_unregister_driver(&acpi_video_bus);
remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
acpi_video_unregister();
return;
}
EXPORT_SYMBOL(acpi_video_exit);
module_init(acpi_video_init);
module_exit(acpi_video_exit);

View file

@ -10,7 +10,7 @@
* assinged
*
* After PCI devices are glued with ACPI devices
* acpi_get_physical_pci_device() can be called to identify ACPI graphics
* acpi_get_pci_dev() can be called to identify ACPI graphics
* devices for which a real graphics card is plugged in
*
* Now acpi_video_get_capabilities() can be called to check which
@ -36,6 +36,7 @@
#include <linux/acpi.h>
#include <linux/dmi.h>
#include <linux/pci.h>
ACPI_MODULE_NAME("video");
#define _COMPONENT ACPI_VIDEO_COMPONENT
@ -109,7 +110,7 @@ static acpi_status
find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
{
long *cap = context;
struct device *dev;
struct pci_dev *dev;
struct acpi_device *acpi_dev;
const struct acpi_device_id video_ids[] = {
@ -120,10 +121,10 @@ find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
return AE_OK;
if (!acpi_match_device_ids(acpi_dev, video_ids)) {
dev = acpi_get_physical_pci_device(handle);
dev = acpi_get_pci_dev(handle);
if (!dev)
return AE_OK;
put_device(dev);
pci_dev_put(dev);
*cap |= acpi_is_video_device(acpi_dev);
}
return AE_OK;