Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (34 commits) ACPI: processor: push file static MADT pointer into internal map_madt_entry() ACPI: processor: refactor internal map_lsapic_id() ACPI: processor: refactor internal map_x2apic_id() ACPI: processor: refactor internal map_lapic_id() ACPI: processor: driver doesn't need to evaluate _PDC ACPI: processor: remove early _PDC optin quirks ACPI: processor: add internal processor_physically_present() ACPI: processor: move acpi_get_cpuid into processor_core.c ACPI: processor: export acpi_get_cpuid() ACPI: processor: mv processor_pdc.c processor_core.c ACPI: processor: mv processor_core.c processor_driver.c ACPI: plan to delete "acpi=ht" boot option ACPI: remove "acpi=ht" DMI blacklist PNPACPI: add bus number support PNPACPI: add window support resource: add window support resource: add bus number support resource: expand IORESOURCE_TYPE_BITS to make room for bus resource type acpiphp: Execute ACPI _REG method for hotadded devices ACPI video: Be more liberal in validating _BQC behaviour ...
This commit is contained in:
commit
a3d3203e4b
31 changed files with 1515 additions and 1447 deletions
|
@ -582,3 +582,10 @@ Why: The paravirt mmu host support is slower than non-paravirt mmu, both
|
|||
Who: Avi Kivity <avi@redhat.com>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: "acpi=ht" boot option
|
||||
When: 2.6.35
|
||||
Why: Useful in 2003, implementation is a hack.
|
||||
Generally invoked by accident today.
|
||||
Seen as doing more harm than good.
|
||||
Who: Len Brown <len.brown@intel.com>
|
||||
|
|
|
@ -200,10 +200,6 @@ and is between 256 and 4096 characters. It is defined in the file
|
|||
acpi_display_output=video
|
||||
See above.
|
||||
|
||||
acpi_early_pdc_eval [HW,ACPI] Evaluate processor _PDC methods
|
||||
early. Needed on some platforms to properly
|
||||
initialize the EC.
|
||||
|
||||
acpi_irq_balance [HW,ACPI]
|
||||
ACPI will balance active IRQs
|
||||
default in APIC mode
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include <linux/efi.h>
|
||||
#include <linux/mmzone.h>
|
||||
#include <linux/nodemask.h>
|
||||
#include <acpi/processor.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/iosapic.h>
|
||||
#include <asm/machvec.h>
|
||||
|
@ -907,6 +908,8 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu)
|
|||
cpu_set(cpu, cpu_present_map);
|
||||
ia64_cpu_to_sapicid[cpu] = physid;
|
||||
|
||||
acpi_processor_set_pdc(handle);
|
||||
|
||||
*pcpu = cpu;
|
||||
return (0);
|
||||
}
|
||||
|
|
|
@ -490,6 +490,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
|
|||
* ACPI based hotplug support for CPU
|
||||
*/
|
||||
#ifdef CONFIG_ACPI_HOTPLUG_CPU
|
||||
#include <acpi/processor.h>
|
||||
|
||||
static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
|
||||
{
|
||||
|
@ -567,6 +568,8 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
|
|||
goto free_new_map;
|
||||
}
|
||||
|
||||
acpi_processor_set_pdc(handle);
|
||||
|
||||
cpu = cpumask_first(new_map);
|
||||
acpi_map_cpu2node(handle, cpu, physid);
|
||||
|
||||
|
@ -1292,23 +1295,6 @@ static int __init dmi_disable_acpi(const struct dmi_system_id *d)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Limit ACPI to CPU enumeration for HT
|
||||
*/
|
||||
static int __init force_acpi_ht(const struct dmi_system_id *d)
|
||||
{
|
||||
if (!acpi_force) {
|
||||
printk(KERN_NOTICE "%s detected: force use of acpi=ht\n",
|
||||
d->ident);
|
||||
disable_acpi();
|
||||
acpi_ht = 1;
|
||||
} else {
|
||||
printk(KERN_NOTICE
|
||||
"Warning: acpi=force overrules DMI blacklist: acpi=ht\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Force ignoring BIOS IRQ0 pin2 override
|
||||
*/
|
||||
|
@ -1344,82 +1330,6 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {
|
|||
},
|
||||
},
|
||||
|
||||
/*
|
||||
* Boxes that need acpi=ht
|
||||
*/
|
||||
{
|
||||
.callback = force_acpi_ht,
|
||||
.ident = "FSC Primergy T850",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = force_acpi_ht,
|
||||
.ident = "HP VISUALIZE NT Workstation",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = force_acpi_ht,
|
||||
.ident = "Compaq Workstation W8000",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Workstation W8000"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = force_acpi_ht,
|
||||
.ident = "ASUS CUR-DLS",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "CUR-DLS"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = force_acpi_ht,
|
||||
.ident = "ABIT i440BX-W83977",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = force_acpi_ht,
|
||||
.ident = "IBM Bladecenter",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = force_acpi_ht,
|
||||
.ident = "IBM eServer xSeries 360",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "eServer xSeries 360"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = force_acpi_ht,
|
||||
.ident = "IBM eserver xSeries 330",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "eserver xSeries 330"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = force_acpi_ht,
|
||||
.ident = "IBM eserver xSeries 440",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"),
|
||||
},
|
||||
},
|
||||
|
||||
/*
|
||||
* Boxes that need ACPI PCI IRQ routing disabled
|
||||
*/
|
||||
|
@ -1652,8 +1562,10 @@ static int __init parse_acpi(char *arg)
|
|||
}
|
||||
/* Limit ACPI just to boot-time to enable HT */
|
||||
else if (strcmp(arg, "ht") == 0) {
|
||||
if (!acpi_force)
|
||||
if (!acpi_force) {
|
||||
printk(KERN_WARNING "acpi=ht will be removed in Linux-2.6.35\n");
|
||||
disable_acpi();
|
||||
}
|
||||
acpi_ht = 1;
|
||||
}
|
||||
/* acpi=rsdt use RSDT instead of XSDT */
|
||||
|
|
|
@ -32,7 +32,7 @@ acpi-$(CONFIG_ACPI_SLEEP) += proc.o
|
|||
#
|
||||
acpi-y += bus.o glue.o
|
||||
acpi-y += scan.o
|
||||
acpi-y += processor_pdc.o
|
||||
acpi-y += processor_core.o
|
||||
acpi-y += ec.o
|
||||
acpi-$(CONFIG_ACPI_DOCK) += dock.o
|
||||
acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o
|
||||
|
@ -61,7 +61,7 @@ obj-$(CONFIG_ACPI_SBS) += sbs.o
|
|||
obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o
|
||||
|
||||
# processor has its own "processor." module_param namespace
|
||||
processor-y := processor_core.o processor_throttling.o
|
||||
processor-y := processor_driver.o processor_throttling.o
|
||||
processor-y += processor_idle.o processor_thermal.o
|
||||
processor-$(CONFIG_CPU_FREQ) += processor_perflib.o
|
||||
|
||||
|
|
|
@ -375,8 +375,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
|
|||
return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED);
|
||||
}
|
||||
|
||||
/* Must have a valid thread ID */
|
||||
|
||||
/* Must have a valid thread. */
|
||||
if (!walk_state->thread) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Cannot release Mutex [%4.4s], null thread info",
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#define ACPI_BATTERY_DEVICE_NAME "Battery"
|
||||
#define ACPI_BATTERY_NOTIFY_STATUS 0x80
|
||||
#define ACPI_BATTERY_NOTIFY_INFO 0x81
|
||||
#define ACPI_BATTERY_NOTIFY_THRESHOLD 0x82
|
||||
|
||||
#define _COMPONENT ACPI_BATTERY_COMPONENT
|
||||
|
||||
|
@ -88,10 +89,15 @@ static const struct acpi_device_id battery_device_ids[] = {
|
|||
|
||||
MODULE_DEVICE_TABLE(acpi, battery_device_ids);
|
||||
|
||||
/* For buggy DSDTs that report negative 16-bit values for either charging
|
||||
* or discharging current and/or report 0 as 65536 due to bad math.
|
||||
*/
|
||||
#define QUIRK_SIGNED16_CURRENT 0x0001
|
||||
enum {
|
||||
ACPI_BATTERY_ALARM_PRESENT,
|
||||
ACPI_BATTERY_XINFO_PRESENT,
|
||||
/* For buggy DSDTs that report negative 16-bit values for either
|
||||
* charging or discharging current and/or report 0 as 65536
|
||||
* due to bad math.
|
||||
*/
|
||||
ACPI_BATTERY_QUIRK_SIGNED16_CURRENT,
|
||||
};
|
||||
|
||||
struct acpi_battery {
|
||||
struct mutex lock;
|
||||
|
@ -109,6 +115,12 @@ struct acpi_battery {
|
|||
int design_voltage;
|
||||
int design_capacity_warning;
|
||||
int design_capacity_low;
|
||||
int cycle_count;
|
||||
int measurement_accuracy;
|
||||
int max_sampling_time;
|
||||
int min_sampling_time;
|
||||
int max_averaging_interval;
|
||||
int min_averaging_interval;
|
||||
int capacity_granularity_1;
|
||||
int capacity_granularity_2;
|
||||
int alarm;
|
||||
|
@ -118,8 +130,7 @@ struct acpi_battery {
|
|||
char oem_info[32];
|
||||
int state;
|
||||
int power_unit;
|
||||
u8 alarm_present;
|
||||
long quirks;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
|
||||
|
@ -198,6 +209,9 @@ static int acpi_battery_get_property(struct power_supply *psy,
|
|||
case POWER_SUPPLY_PROP_TECHNOLOGY:
|
||||
val->intval = acpi_battery_technology(battery);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CYCLE_COUNT:
|
||||
val->intval = battery->cycle_count;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
|
||||
val->intval = battery->design_voltage * 1000;
|
||||
break;
|
||||
|
@ -239,6 +253,7 @@ static enum power_supply_property charge_battery_props[] = {
|
|||
POWER_SUPPLY_PROP_STATUS,
|
||||
POWER_SUPPLY_PROP_PRESENT,
|
||||
POWER_SUPPLY_PROP_TECHNOLOGY,
|
||||
POWER_SUPPLY_PROP_CYCLE_COUNT,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||
POWER_SUPPLY_PROP_CURRENT_NOW,
|
||||
|
@ -254,6 +269,7 @@ static enum power_supply_property energy_battery_props[] = {
|
|||
POWER_SUPPLY_PROP_STATUS,
|
||||
POWER_SUPPLY_PROP_PRESENT,
|
||||
POWER_SUPPLY_PROP_TECHNOLOGY,
|
||||
POWER_SUPPLY_PROP_CYCLE_COUNT,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||
POWER_SUPPLY_PROP_CURRENT_NOW,
|
||||
|
@ -305,6 +321,28 @@ static struct acpi_offsets info_offsets[] = {
|
|||
{offsetof(struct acpi_battery, oem_info), 1},
|
||||
};
|
||||
|
||||
static struct acpi_offsets extended_info_offsets[] = {
|
||||
{offsetof(struct acpi_battery, power_unit), 0},
|
||||
{offsetof(struct acpi_battery, design_capacity), 0},
|
||||
{offsetof(struct acpi_battery, full_charge_capacity), 0},
|
||||
{offsetof(struct acpi_battery, technology), 0},
|
||||
{offsetof(struct acpi_battery, design_voltage), 0},
|
||||
{offsetof(struct acpi_battery, design_capacity_warning), 0},
|
||||
{offsetof(struct acpi_battery, design_capacity_low), 0},
|
||||
{offsetof(struct acpi_battery, cycle_count), 0},
|
||||
{offsetof(struct acpi_battery, measurement_accuracy), 0},
|
||||
{offsetof(struct acpi_battery, max_sampling_time), 0},
|
||||
{offsetof(struct acpi_battery, min_sampling_time), 0},
|
||||
{offsetof(struct acpi_battery, max_averaging_interval), 0},
|
||||
{offsetof(struct acpi_battery, min_averaging_interval), 0},
|
||||
{offsetof(struct acpi_battery, capacity_granularity_1), 0},
|
||||
{offsetof(struct acpi_battery, capacity_granularity_2), 0},
|
||||
{offsetof(struct acpi_battery, model_number), 1},
|
||||
{offsetof(struct acpi_battery, serial_number), 1},
|
||||
{offsetof(struct acpi_battery, type), 1},
|
||||
{offsetof(struct acpi_battery, oem_info), 1},
|
||||
};
|
||||
|
||||
static int extract_package(struct acpi_battery *battery,
|
||||
union acpi_object *package,
|
||||
struct acpi_offsets *offsets, int num)
|
||||
|
@ -350,22 +388,29 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
|
|||
{
|
||||
int result = -EFAULT;
|
||||
acpi_status status = 0;
|
||||
char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags)?
|
||||
"_BIX" : "_BIF";
|
||||
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
|
||||
if (!acpi_battery_present(battery))
|
||||
return 0;
|
||||
mutex_lock(&battery->lock);
|
||||
status = acpi_evaluate_object(battery->device->handle, "_BIF",
|
||||
NULL, &buffer);
|
||||
status = acpi_evaluate_object(battery->device->handle, name,
|
||||
NULL, &buffer);
|
||||
mutex_unlock(&battery->lock);
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF"));
|
||||
ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name));
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
result = extract_package(battery, buffer.pointer,
|
||||
info_offsets, ARRAY_SIZE(info_offsets));
|
||||
if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
|
||||
result = extract_package(battery, buffer.pointer,
|
||||
extended_info_offsets,
|
||||
ARRAY_SIZE(extended_info_offsets));
|
||||
else
|
||||
result = extract_package(battery, buffer.pointer,
|
||||
info_offsets, ARRAY_SIZE(info_offsets));
|
||||
kfree(buffer.pointer);
|
||||
return result;
|
||||
}
|
||||
|
@ -399,7 +444,7 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
|
|||
battery->update_time = jiffies;
|
||||
kfree(buffer.pointer);
|
||||
|
||||
if ((battery->quirks & QUIRK_SIGNED16_CURRENT) &&
|
||||
if (test_bit(ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, &battery->flags) &&
|
||||
battery->rate_now != -1)
|
||||
battery->rate_now = abs((s16)battery->rate_now);
|
||||
|
||||
|
@ -412,7 +457,8 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery)
|
|||
union acpi_object arg0 = { .type = ACPI_TYPE_INTEGER };
|
||||
struct acpi_object_list arg_list = { 1, &arg0 };
|
||||
|
||||
if (!acpi_battery_present(battery)|| !battery->alarm_present)
|
||||
if (!acpi_battery_present(battery) ||
|
||||
!test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags))
|
||||
return -ENODEV;
|
||||
|
||||
arg0.integer.value = battery->alarm;
|
||||
|
@ -437,10 +483,10 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery)
|
|||
/* See if alarms are supported, and if so, set default */
|
||||
status = acpi_get_handle(battery->device->handle, "_BTP", &handle);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
battery->alarm_present = 0;
|
||||
clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
|
||||
return 0;
|
||||
}
|
||||
battery->alarm_present = 1;
|
||||
set_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
|
||||
if (!battery->alarm)
|
||||
battery->alarm = battery->design_capacity_warning;
|
||||
return acpi_battery_set_alarm(battery);
|
||||
|
@ -510,9 +556,8 @@ static void sysfs_remove_battery(struct acpi_battery *battery)
|
|||
|
||||
static void acpi_battery_quirks(struct acpi_battery *battery)
|
||||
{
|
||||
battery->quirks = 0;
|
||||
if (dmi_name_in_vendors("Acer") && battery->power_unit) {
|
||||
battery->quirks |= QUIRK_SIGNED16_CURRENT;
|
||||
set_bit(ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, &battery->flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -590,6 +635,7 @@ static int acpi_battery_print_info(struct seq_file *seq, int result)
|
|||
seq_printf(seq, "design capacity low: %d %sh\n",
|
||||
battery->design_capacity_low,
|
||||
acpi_battery_units(battery));
|
||||
seq_printf(seq, "cycle count: %i\n", battery->cycle_count);
|
||||
seq_printf(seq, "capacity granularity 1: %d %sh\n",
|
||||
battery->capacity_granularity_1,
|
||||
acpi_battery_units(battery));
|
||||
|
@ -841,6 +887,7 @@ static int acpi_battery_add(struct acpi_device *device)
|
|||
{
|
||||
int result = 0;
|
||||
struct acpi_battery *battery = NULL;
|
||||
acpi_handle handle;
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
|
||||
|
@ -851,6 +898,9 @@ static int acpi_battery_add(struct acpi_device *device)
|
|||
strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
|
||||
device->driver_data = battery;
|
||||
mutex_init(&battery->lock);
|
||||
if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle,
|
||||
"_BIX", &handle)))
|
||||
set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
|
||||
acpi_battery_update(battery);
|
||||
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||
result = acpi_battery_add_fs(device);
|
||||
|
|
|
@ -190,16 +190,16 @@ int acpi_bus_get_power(acpi_handle handle, int *state)
|
|||
* Get the device's power state either directly (via _PSC) or
|
||||
* indirectly (via power resources).
|
||||
*/
|
||||
if (device->power.flags.explicit_get) {
|
||||
if (device->power.flags.power_resources) {
|
||||
result = acpi_power_get_inferred_state(device);
|
||||
if (result)
|
||||
return result;
|
||||
} else if (device->power.flags.explicit_get) {
|
||||
status = acpi_evaluate_integer(device->handle, "_PSC",
|
||||
NULL, &psc);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
device->power.state = (int)psc;
|
||||
} else if (device->power.flags.power_resources) {
|
||||
result = acpi_power_get_inferred_state(device);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
|
||||
*state = device->power.state;
|
||||
|
|
|
@ -76,8 +76,9 @@ enum ec_command {
|
|||
enum {
|
||||
EC_FLAGS_QUERY_PENDING, /* Query is pending */
|
||||
EC_FLAGS_GPE_STORM, /* GPE storm detected */
|
||||
EC_FLAGS_HANDLERS_INSTALLED /* Handlers for GPE and
|
||||
EC_FLAGS_HANDLERS_INSTALLED, /* Handlers for GPE and
|
||||
* OpReg are installed */
|
||||
EC_FLAGS_FROZEN, /* Transactions are suspended */
|
||||
};
|
||||
|
||||
/* If we find an EC via the ECDT, we need to keep a ptr to its context */
|
||||
|
@ -291,6 +292,10 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
|
|||
if (t->rdata)
|
||||
memset(t->rdata, 0, t->rlen);
|
||||
mutex_lock(&ec->lock);
|
||||
if (test_bit(EC_FLAGS_FROZEN, &ec->flags)) {
|
||||
status = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
if (ec->global_lock) {
|
||||
status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
@ -453,6 +458,32 @@ int ec_transaction(u8 command,
|
|||
|
||||
EXPORT_SYMBOL(ec_transaction);
|
||||
|
||||
void acpi_ec_suspend_transactions(void)
|
||||
{
|
||||
struct acpi_ec *ec = first_ec;
|
||||
|
||||
if (!ec)
|
||||
return;
|
||||
|
||||
mutex_lock(&ec->lock);
|
||||
/* Prevent transactions from being carried out */
|
||||
set_bit(EC_FLAGS_FROZEN, &ec->flags);
|
||||
mutex_unlock(&ec->lock);
|
||||
}
|
||||
|
||||
void acpi_ec_resume_transactions(void)
|
||||
{
|
||||
struct acpi_ec *ec = first_ec;
|
||||
|
||||
if (!ec)
|
||||
return;
|
||||
|
||||
mutex_lock(&ec->lock);
|
||||
/* Allow transactions to be carried out again */
|
||||
clear_bit(EC_FLAGS_FROZEN, &ec->flags);
|
||||
mutex_unlock(&ec->lock);
|
||||
}
|
||||
|
||||
static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data)
|
||||
{
|
||||
int result;
|
||||
|
|
|
@ -49,6 +49,8 @@ void acpi_early_processor_set_pdc(void);
|
|||
int acpi_ec_init(void);
|
||||
int acpi_ec_ecdt_probe(void);
|
||||
int acpi_boot_ec_enable(void);
|
||||
void acpi_ec_suspend_transactions(void);
|
||||
void acpi_ec_resume_transactions(void);
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Suspend/Resume
|
||||
|
|
File diff suppressed because it is too large
Load diff
978
drivers/acpi/processor_driver.c
Normal file
978
drivers/acpi/processor_driver.c
Normal file
|
@ -0,0 +1,978 @@
|
|||
/*
|
||||
* acpi_processor.c - ACPI Processor Driver ($Revision: 71 $)
|
||||
*
|
||||
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
|
||||
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
|
||||
* Copyright (C) 2004 Dominik Brodowski <linux@brodo.de>
|
||||
* Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
|
||||
* - Added processor hotplug support
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* TBD:
|
||||
* 1. Make # power states dynamic.
|
||||
* 2. Support duty_cycle values that span bit 4.
|
||||
* 3. Optimize by having scheduler determine business instead of
|
||||
* having us try to calculate it here.
|
||||
* 4. Need C1 timing -- must modify kernel (IRQ handler) to get this.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/cpuidle.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/acpi.h>
|
||||
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
#include <acpi/processor.h>
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
|
||||
#define ACPI_PROCESSOR_CLASS "processor"
|
||||
#define ACPI_PROCESSOR_DEVICE_NAME "Processor"
|
||||
#define ACPI_PROCESSOR_FILE_INFO "info"
|
||||
#define ACPI_PROCESSOR_FILE_THROTTLING "throttling"
|
||||
#define ACPI_PROCESSOR_FILE_LIMIT "limit"
|
||||
#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
|
||||
#define ACPI_PROCESSOR_NOTIFY_POWER 0x81
|
||||
#define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82
|
||||
|
||||
#define ACPI_PROCESSOR_LIMIT_USER 0
|
||||
#define ACPI_PROCESSOR_LIMIT_THERMAL 1
|
||||
|
||||
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
|
||||
ACPI_MODULE_NAME("processor_driver");
|
||||
|
||||
MODULE_AUTHOR("Paul Diefenbaugh");
|
||||
MODULE_DESCRIPTION("ACPI Processor Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int acpi_processor_add(struct acpi_device *device);
|
||||
static int acpi_processor_remove(struct acpi_device *device, int type);
|
||||
#ifdef CONFIG_ACPI_PROCFS
|
||||
static int acpi_processor_info_open_fs(struct inode *inode, struct file *file);
|
||||
#endif
|
||||
static void acpi_processor_notify(struct acpi_device *device, u32 event);
|
||||
static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
|
||||
static int acpi_processor_handle_eject(struct acpi_processor *pr);
|
||||
|
||||
|
||||
static const struct acpi_device_id processor_device_ids[] = {
|
||||
{ACPI_PROCESSOR_OBJECT_HID, 0},
|
||||
{"ACPI0007", 0},
|
||||
{"", 0},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, processor_device_ids);
|
||||
|
||||
static struct acpi_driver acpi_processor_driver = {
|
||||
.name = "processor",
|
||||
.class = ACPI_PROCESSOR_CLASS,
|
||||
.ids = processor_device_ids,
|
||||
.ops = {
|
||||
.add = acpi_processor_add,
|
||||
.remove = acpi_processor_remove,
|
||||
.suspend = acpi_processor_suspend,
|
||||
.resume = acpi_processor_resume,
|
||||
.notify = acpi_processor_notify,
|
||||
},
|
||||
};
|
||||
|
||||
#define INSTALL_NOTIFY_HANDLER 1
|
||||
#define UNINSTALL_NOTIFY_HANDLER 2
|
||||
#ifdef CONFIG_ACPI_PROCFS
|
||||
static const struct file_operations acpi_processor_info_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = acpi_processor_info_open_fs,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
#endif
|
||||
|
||||
DEFINE_PER_CPU(struct acpi_processor *, processors);
|
||||
EXPORT_PER_CPU_SYMBOL(processors);
|
||||
|
||||
struct acpi_processor_errata errata __read_mostly;
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Errata Handling
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
static int acpi_processor_errata_piix4(struct pci_dev *dev)
|
||||
{
|
||||
u8 value1 = 0;
|
||||
u8 value2 = 0;
|
||||
|
||||
|
||||
if (!dev)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Note that 'dev' references the PIIX4 ACPI Controller.
|
||||
*/
|
||||
|
||||
switch (dev->revision) {
|
||||
case 0:
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n"));
|
||||
break;
|
||||
case 1:
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 B-step\n"));
|
||||
break;
|
||||
case 2:
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4E\n"));
|
||||
break;
|
||||
case 3:
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4M\n"));
|
||||
break;
|
||||
default:
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unknown PIIX4\n"));
|
||||
break;
|
||||
}
|
||||
|
||||
switch (dev->revision) {
|
||||
|
||||
case 0: /* PIIX4 A-step */
|
||||
case 1: /* PIIX4 B-step */
|
||||
/*
|
||||
* See specification changes #13 ("Manual Throttle Duty Cycle")
|
||||
* and #14 ("Enabling and Disabling Manual Throttle"), plus
|
||||
* erratum #5 ("STPCLK# Deassertion Time") from the January
|
||||
* 2002 PIIX4 specification update. Applies to only older
|
||||
* PIIX4 models.
|
||||
*/
|
||||
errata.piix4.throttle = 1;
|
||||
|
||||
case 2: /* PIIX4E */
|
||||
case 3: /* PIIX4M */
|
||||
/*
|
||||
* See erratum #18 ("C3 Power State/BMIDE and Type-F DMA
|
||||
* Livelock") from the January 2002 PIIX4 specification update.
|
||||
* Applies to all PIIX4 models.
|
||||
*/
|
||||
|
||||
/*
|
||||
* BM-IDE
|
||||
* ------
|
||||
* Find the PIIX4 IDE Controller and get the Bus Master IDE
|
||||
* Status register address. We'll use this later to read
|
||||
* each IDE controller's DMA status to make sure we catch all
|
||||
* DMA activity.
|
||||
*/
|
||||
dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
|
||||
PCI_DEVICE_ID_INTEL_82371AB,
|
||||
PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
if (dev) {
|
||||
errata.piix4.bmisx = pci_resource_start(dev, 4);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Type-F DMA
|
||||
* ----------
|
||||
* Find the PIIX4 ISA Controller and read the Motherboard
|
||||
* DMA controller's status to see if Type-F (Fast) DMA mode
|
||||
* is enabled (bit 7) on either channel. Note that we'll
|
||||
* disable C3 support if this is enabled, as some legacy
|
||||
* devices won't operate well if fast DMA is disabled.
|
||||
*/
|
||||
dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
|
||||
PCI_DEVICE_ID_INTEL_82371AB_0,
|
||||
PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
if (dev) {
|
||||
pci_read_config_byte(dev, 0x76, &value1);
|
||||
pci_read_config_byte(dev, 0x77, &value2);
|
||||
if ((value1 & 0x80) || (value2 & 0x80))
|
||||
errata.piix4.fdma = 1;
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (errata.piix4.bmisx)
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Bus master activity detection (BM-IDE) erratum enabled\n"));
|
||||
if (errata.piix4.fdma)
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Type-F DMA livelock erratum (C3 disabled)\n"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_processor_errata(struct acpi_processor *pr)
|
||||
{
|
||||
int result = 0;
|
||||
struct pci_dev *dev = NULL;
|
||||
|
||||
|
||||
if (!pr)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* PIIX4
|
||||
*/
|
||||
dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
|
||||
PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID,
|
||||
PCI_ANY_ID, NULL);
|
||||
if (dev) {
|
||||
result = acpi_processor_errata_piix4(dev);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
FS Interface (/proc)
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef CONFIG_ACPI_PROCFS
|
||||
static struct proc_dir_entry *acpi_processor_dir = NULL;
|
||||
|
||||
static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset)
|
||||
{
|
||||
struct acpi_processor *pr = seq->private;
|
||||
|
||||
|
||||
if (!pr)
|
||||
goto end;
|
||||
|
||||
seq_printf(seq, "processor id: %d\n"
|
||||
"acpi id: %d\n"
|
||||
"bus mastering control: %s\n"
|
||||
"power management: %s\n"
|
||||
"throttling control: %s\n"
|
||||
"limit interface: %s\n",
|
||||
pr->id,
|
||||
pr->acpi_id,
|
||||
pr->flags.bm_control ? "yes" : "no",
|
||||
pr->flags.power ? "yes" : "no",
|
||||
pr->flags.throttling ? "yes" : "no",
|
||||
pr->flags.limit ? "yes" : "no");
|
||||
|
||||
end:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_processor_info_open_fs(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, acpi_processor_info_seq_show,
|
||||
PDE(inode)->data);
|
||||
}
|
||||
|
||||
static int __cpuinit acpi_processor_add_fs(struct acpi_device *device)
|
||||
{
|
||||
struct proc_dir_entry *entry = NULL;
|
||||
|
||||
|
||||
if (!acpi_device_dir(device)) {
|
||||
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
|
||||
acpi_processor_dir);
|
||||
if (!acpi_device_dir(device))
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* 'info' [R] */
|
||||
entry = proc_create_data(ACPI_PROCESSOR_FILE_INFO,
|
||||
S_IRUGO, acpi_device_dir(device),
|
||||
&acpi_processor_info_fops,
|
||||
acpi_driver_data(device));
|
||||
if (!entry)
|
||||
return -EIO;
|
||||
|
||||
/* 'throttling' [R/W] */
|
||||
entry = proc_create_data(ACPI_PROCESSOR_FILE_THROTTLING,
|
||||
S_IFREG | S_IRUGO | S_IWUSR,
|
||||
acpi_device_dir(device),
|
||||
&acpi_processor_throttling_fops,
|
||||
acpi_driver_data(device));
|
||||
if (!entry)
|
||||
return -EIO;
|
||||
|
||||
/* 'limit' [R/W] */
|
||||
entry = proc_create_data(ACPI_PROCESSOR_FILE_LIMIT,
|
||||
S_IFREG | S_IRUGO | S_IWUSR,
|
||||
acpi_device_dir(device),
|
||||
&acpi_processor_limit_fops,
|
||||
acpi_driver_data(device));
|
||||
if (!entry)
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
static int acpi_processor_remove_fs(struct acpi_device *device)
|
||||
{
|
||||
|
||||
if (acpi_device_dir(device)) {
|
||||
remove_proc_entry(ACPI_PROCESSOR_FILE_INFO,
|
||||
acpi_device_dir(device));
|
||||
remove_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
|
||||
acpi_device_dir(device));
|
||||
remove_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,
|
||||
acpi_device_dir(device));
|
||||
remove_proc_entry(acpi_device_bid(device), acpi_processor_dir);
|
||||
acpi_device_dir(device) = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int acpi_processor_add_fs(struct acpi_device *device)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int acpi_processor_remove_fs(struct acpi_device *device)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Driver Interface
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
static int acpi_processor_get_info(struct acpi_device *device)
|
||||
{
|
||||
acpi_status status = 0;
|
||||
union acpi_object object = { 0 };
|
||||
struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
|
||||
struct acpi_processor *pr;
|
||||
int cpu_index, device_declaration = 0;
|
||||
static int cpu0_initialized;
|
||||
|
||||
pr = acpi_driver_data(device);
|
||||
if (!pr)
|
||||
return -EINVAL;
|
||||
|
||||
if (num_online_cpus() > 1)
|
||||
errata.smp = TRUE;
|
||||
|
||||
acpi_processor_errata(pr);
|
||||
|
||||
/*
|
||||
* Check to see if we have bus mastering arbitration control. This
|
||||
* is required for proper C3 usage (to maintain cache coherency).
|
||||
*/
|
||||
if (acpi_gbl_FADT.pm2_control_block && acpi_gbl_FADT.pm2_control_length) {
|
||||
pr->flags.bm_control = 1;
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Bus mastering arbitration control present\n"));
|
||||
} else
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"No bus mastering arbitration control\n"));
|
||||
|
||||
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.
|
||||
*/
|
||||
unsigned long long value;
|
||||
status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
|
||||
NULL, &value);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printk(KERN_ERR PREFIX
|
||||
"Evaluating processor _UID [%#x]\n", status);
|
||||
return -ENODEV;
|
||||
}
|
||||
device_declaration = 1;
|
||||
pr->acpi_id = value;
|
||||
}
|
||||
cpu_index = acpi_get_cpuid(pr->handle, device_declaration, pr->acpi_id);
|
||||
|
||||
/* Handle UP system running SMP kernel, with no LAPIC in MADT */
|
||||
if (!cpu0_initialized && (cpu_index == -1) &&
|
||||
(num_online_cpus() == 1)) {
|
||||
cpu_index = 0;
|
||||
}
|
||||
|
||||
cpu0_initialized = 1;
|
||||
|
||||
pr->id = cpu_index;
|
||||
|
||||
/*
|
||||
* Extra Processor objects may be enumerated on MP systems with
|
||||
* less than the max # of CPUs. They should be ignored _iff
|
||||
* they are physically not present.
|
||||
*/
|
||||
if (pr->id == -1) {
|
||||
if (ACPI_FAILURE
|
||||
(acpi_processor_hotadd_init(pr->handle, &pr->id))) {
|
||||
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));
|
||||
|
||||
if (!object.processor.pblk_address)
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n"));
|
||||
else if (object.processor.pblk_length != 6)
|
||||
printk(KERN_ERR PREFIX "Invalid PBLK length [%d]\n",
|
||||
object.processor.pblk_length);
|
||||
else {
|
||||
pr->throttling.address = object.processor.pblk_address;
|
||||
pr->throttling.duty_offset = acpi_gbl_FADT.duty_offset;
|
||||
pr->throttling.duty_width = acpi_gbl_FADT.duty_width;
|
||||
|
||||
pr->pblk = object.processor.pblk_address;
|
||||
|
||||
/*
|
||||
* We don't care about error returns - we just try to mark
|
||||
* these reserved so that nobody else is confused into thinking
|
||||
* that this region might be unused..
|
||||
*
|
||||
* (In particular, allocating the IO range for Cardbus)
|
||||
*/
|
||||
request_region(pr->throttling.address, 6, "ACPI CPU throttle");
|
||||
}
|
||||
|
||||
/*
|
||||
* If ACPI describes a slot number for this CPU, we can use it
|
||||
* ensure we get the right value in the "physical id" field
|
||||
* of /proc/cpuinfo
|
||||
*/
|
||||
status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer);
|
||||
if (ACPI_SUCCESS(status))
|
||||
arch_fix_phys_package_id(pr->id, object.integer.value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DEFINE_PER_CPU(void *, processor_device_array);
|
||||
|
||||
static void acpi_processor_notify(struct acpi_device *device, u32 event)
|
||||
{
|
||||
struct acpi_processor *pr = acpi_driver_data(device);
|
||||
int saved;
|
||||
|
||||
if (!pr)
|
||||
return;
|
||||
|
||||
switch (event) {
|
||||
case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
|
||||
saved = pr->performance_platform_limit;
|
||||
acpi_processor_ppc_has_changed(pr, 1);
|
||||
if (saved == pr->performance_platform_limit)
|
||||
break;
|
||||
acpi_bus_generate_proc_event(device, event,
|
||||
pr->performance_platform_limit);
|
||||
acpi_bus_generate_netlink_event(device->pnp.device_class,
|
||||
dev_name(&device->dev), event,
|
||||
pr->performance_platform_limit);
|
||||
break;
|
||||
case ACPI_PROCESSOR_NOTIFY_POWER:
|
||||
acpi_processor_cst_has_changed(pr);
|
||||
acpi_bus_generate_proc_event(device, event, 0);
|
||||
acpi_bus_generate_netlink_event(device->pnp.device_class,
|
||||
dev_name(&device->dev), event, 0);
|
||||
break;
|
||||
case ACPI_PROCESSOR_NOTIFY_THROTTLING:
|
||||
acpi_processor_tstate_has_changed(pr);
|
||||
acpi_bus_generate_proc_event(device, event, 0);
|
||||
acpi_bus_generate_netlink_event(device->pnp.device_class,
|
||||
dev_name(&device->dev), event, 0);
|
||||
default:
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Unsupported event [0x%x]\n", event));
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int acpi_cpu_soft_notify(struct notifier_block *nfb,
|
||||
unsigned long action, void *hcpu)
|
||||
{
|
||||
unsigned int cpu = (unsigned long)hcpu;
|
||||
struct acpi_processor *pr = per_cpu(processors, cpu);
|
||||
|
||||
if (action == CPU_ONLINE && pr) {
|
||||
acpi_processor_ppc_has_changed(pr, 0);
|
||||
acpi_processor_cst_has_changed(pr);
|
||||
acpi_processor_tstate_has_changed(pr);
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block acpi_cpu_notifier =
|
||||
{
|
||||
.notifier_call = acpi_cpu_soft_notify,
|
||||
};
|
||||
|
||||
static int __cpuinit acpi_processor_add(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_processor *pr = NULL;
|
||||
int result = 0;
|
||||
struct sys_device *sysdev;
|
||||
|
||||
pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
|
||||
if (!pr)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
|
||||
kfree(pr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pr->handle = device->handle;
|
||||
strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
|
||||
device->driver_data = pr;
|
||||
|
||||
result = acpi_processor_get_info(device);
|
||||
if (result) {
|
||||
/* Processor is physically not present */
|
||||
return 0;
|
||||
}
|
||||
|
||||
BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
|
||||
|
||||
/*
|
||||
* Buggy BIOS check
|
||||
* ACPI id of processors can be reported wrongly by the BIOS.
|
||||
* Don't trust it blindly
|
||||
*/
|
||||
if (per_cpu(processor_device_array, pr->id) != NULL &&
|
||||
per_cpu(processor_device_array, pr->id) != device) {
|
||||
printk(KERN_WARNING "BIOS reported wrong ACPI id "
|
||||
"for the processor\n");
|
||||
result = -ENODEV;
|
||||
goto err_free_cpumask;
|
||||
}
|
||||
per_cpu(processor_device_array, pr->id) = device;
|
||||
|
||||
per_cpu(processors, pr->id) = pr;
|
||||
|
||||
result = acpi_processor_add_fs(device);
|
||||
if (result)
|
||||
goto err_free_cpumask;
|
||||
|
||||
sysdev = get_cpu_sysdev(pr->id);
|
||||
if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) {
|
||||
result = -EFAULT;
|
||||
goto err_remove_fs;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
acpi_processor_ppc_has_changed(pr, 0);
|
||||
#endif
|
||||
acpi_processor_get_throttling_info(pr);
|
||||
acpi_processor_get_limit_info(pr);
|
||||
|
||||
|
||||
acpi_processor_power_init(pr, device);
|
||||
|
||||
pr->cdev = thermal_cooling_device_register("Processor", device,
|
||||
&processor_cooling_ops);
|
||||
if (IS_ERR(pr->cdev)) {
|
||||
result = PTR_ERR(pr->cdev);
|
||||
goto err_power_exit;
|
||||
}
|
||||
|
||||
dev_dbg(&device->dev, "registered as cooling_device%d\n",
|
||||
pr->cdev->id);
|
||||
|
||||
result = sysfs_create_link(&device->dev.kobj,
|
||||
&pr->cdev->device.kobj,
|
||||
"thermal_cooling");
|
||||
if (result) {
|
||||
printk(KERN_ERR PREFIX "Create sysfs link\n");
|
||||
goto err_thermal_unregister;
|
||||
}
|
||||
result = sysfs_create_link(&pr->cdev->device.kobj,
|
||||
&device->dev.kobj,
|
||||
"device");
|
||||
if (result) {
|
||||
printk(KERN_ERR PREFIX "Create sysfs link\n");
|
||||
goto err_remove_sysfs;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_remove_sysfs:
|
||||
sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
|
||||
err_thermal_unregister:
|
||||
thermal_cooling_device_unregister(pr->cdev);
|
||||
err_power_exit:
|
||||
acpi_processor_power_exit(pr, device);
|
||||
err_remove_fs:
|
||||
acpi_processor_remove_fs(device);
|
||||
err_free_cpumask:
|
||||
free_cpumask_var(pr->throttling.shared_cpu_map);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int acpi_processor_remove(struct acpi_device *device, int type)
|
||||
{
|
||||
struct acpi_processor *pr = NULL;
|
||||
|
||||
|
||||
if (!device || !acpi_driver_data(device))
|
||||
return -EINVAL;
|
||||
|
||||
pr = acpi_driver_data(device);
|
||||
|
||||
if (pr->id >= nr_cpu_ids)
|
||||
goto free;
|
||||
|
||||
if (type == ACPI_BUS_REMOVAL_EJECT) {
|
||||
if (acpi_processor_handle_eject(pr))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
acpi_processor_power_exit(pr, device);
|
||||
|
||||
sysfs_remove_link(&device->dev.kobj, "sysdev");
|
||||
|
||||
acpi_processor_remove_fs(device);
|
||||
|
||||
if (pr->cdev) {
|
||||
sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
|
||||
sysfs_remove_link(&pr->cdev->device.kobj, "device");
|
||||
thermal_cooling_device_unregister(pr->cdev);
|
||||
pr->cdev = NULL;
|
||||
}
|
||||
|
||||
per_cpu(processors, pr->id) = NULL;
|
||||
per_cpu(processor_device_array, pr->id) = NULL;
|
||||
|
||||
free:
|
||||
free_cpumask_var(pr->throttling.shared_cpu_map);
|
||||
kfree(pr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI_HOTPLUG_CPU
|
||||
/****************************************************************************
|
||||
* Acpi processor hotplug support *
|
||||
****************************************************************************/
|
||||
|
||||
static int is_processor_present(acpi_handle handle)
|
||||
{
|
||||
acpi_status status;
|
||||
unsigned long long sta = 0;
|
||||
|
||||
|
||||
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
|
||||
|
||||
if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* _STA is mandatory for a processor that supports hot plug
|
||||
*/
|
||||
if (status == AE_NOT_FOUND)
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Processor does not support hot plug\n"));
|
||||
else
|
||||
ACPI_EXCEPTION((AE_INFO, status,
|
||||
"Processor Device is not present"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
|
||||
{
|
||||
acpi_handle phandle;
|
||||
struct acpi_device *pdev;
|
||||
|
||||
|
||||
if (acpi_get_parent(handle, &phandle)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (acpi_bus_get_device(phandle, &pdev)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __ref acpi_processor_hotplug_notify(acpi_handle handle,
|
||||
u32 event, void *data)
|
||||
{
|
||||
struct acpi_processor *pr;
|
||||
struct acpi_device *device = NULL;
|
||||
int result;
|
||||
|
||||
|
||||
switch (event) {
|
||||
case ACPI_NOTIFY_BUS_CHECK:
|
||||
case ACPI_NOTIFY_DEVICE_CHECK:
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Processor driver received %s event\n",
|
||||
(event == ACPI_NOTIFY_BUS_CHECK) ?
|
||||
"ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK"));
|
||||
|
||||
if (!is_processor_present(handle))
|
||||
break;
|
||||
|
||||
if (acpi_bus_get_device(handle, &device)) {
|
||||
result = acpi_processor_device_add(handle, &device);
|
||||
if (result)
|
||||
printk(KERN_ERR PREFIX
|
||||
"Unable to add the device\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ACPI_NOTIFY_EJECT_REQUEST:
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"received ACPI_NOTIFY_EJECT_REQUEST\n"));
|
||||
|
||||
if (acpi_bus_get_device(handle, &device)) {
|
||||
printk(KERN_ERR PREFIX
|
||||
"Device don't exist, dropping EJECT\n");
|
||||
break;
|
||||
}
|
||||
pr = acpi_driver_data(device);
|
||||
if (!pr) {
|
||||
printk(KERN_ERR PREFIX
|
||||
"Driver data is NULL, dropping EJECT\n");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Unsupported event [0x%x]\n", event));
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static acpi_status
|
||||
processor_walk_namespace_cb(acpi_handle handle,
|
||||
u32 lvl, void *context, void **rv)
|
||||
{
|
||||
acpi_status status;
|
||||
int *action = context;
|
||||
acpi_object_type type = 0;
|
||||
|
||||
status = acpi_get_type(handle, &type);
|
||||
if (ACPI_FAILURE(status))
|
||||
return (AE_OK);
|
||||
|
||||
if (type != ACPI_TYPE_PROCESSOR)
|
||||
return (AE_OK);
|
||||
|
||||
switch (*action) {
|
||||
case INSTALL_NOTIFY_HANDLER:
|
||||
acpi_install_notify_handler(handle,
|
||||
ACPI_SYSTEM_NOTIFY,
|
||||
acpi_processor_hotplug_notify,
|
||||
NULL);
|
||||
break;
|
||||
case UNINSTALL_NOTIFY_HANDLER:
|
||||
acpi_remove_notify_handler(handle,
|
||||
ACPI_SYSTEM_NOTIFY,
|
||||
acpi_processor_hotplug_notify);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
|
||||
{
|
||||
|
||||
if (!is_processor_present(handle)) {
|
||||
return AE_ERROR;
|
||||
}
|
||||
|
||||
if (acpi_map_lsapic(handle, p_cpu))
|
||||
return AE_ERROR;
|
||||
|
||||
if (arch_register_cpu(*p_cpu)) {
|
||||
acpi_unmap_lsapic(*p_cpu);
|
||||
return AE_ERROR;
|
||||
}
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static int acpi_processor_handle_eject(struct acpi_processor *pr)
|
||||
{
|
||||
if (cpu_online(pr->id))
|
||||
cpu_down(pr->id);
|
||||
|
||||
arch_unregister_cpu(pr->id);
|
||||
acpi_unmap_lsapic(pr->id);
|
||||
return (0);
|
||||
}
|
||||
#else
|
||||
static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
|
||||
{
|
||||
return AE_ERROR;
|
||||
}
|
||||
static int acpi_processor_handle_eject(struct acpi_processor *pr)
|
||||
{
|
||||
return (-EINVAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
void acpi_processor_install_hotplug_notify(void)
|
||||
{
|
||||
#ifdef CONFIG_ACPI_HOTPLUG_CPU
|
||||
int action = INSTALL_NOTIFY_HANDLER;
|
||||
acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
|
||||
ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX,
|
||||
processor_walk_namespace_cb, NULL, &action, NULL);
|
||||
#endif
|
||||
register_hotcpu_notifier(&acpi_cpu_notifier);
|
||||
}
|
||||
|
||||
static
|
||||
void acpi_processor_uninstall_hotplug_notify(void)
|
||||
{
|
||||
#ifdef CONFIG_ACPI_HOTPLUG_CPU
|
||||
int action = UNINSTALL_NOTIFY_HANDLER;
|
||||
acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
|
||||
ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX,
|
||||
processor_walk_namespace_cb, NULL, &action, NULL);
|
||||
#endif
|
||||
unregister_hotcpu_notifier(&acpi_cpu_notifier);
|
||||
}
|
||||
|
||||
/*
|
||||
* We keep the driver loaded even when ACPI is not running.
|
||||
* This is needed for the powernow-k8 driver, that works even without
|
||||
* ACPI, but needs symbols from this driver
|
||||
*/
|
||||
|
||||
static int __init acpi_processor_init(void)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (acpi_disabled)
|
||||
return 0;
|
||||
|
||||
memset(&errata, 0, sizeof(errata));
|
||||
|
||||
#ifdef CONFIG_ACPI_PROCFS
|
||||
acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
|
||||
if (!acpi_processor_dir)
|
||||
return -ENOMEM;
|
||||
#endif
|
||||
result = cpuidle_register_driver(&acpi_idle_driver);
|
||||
if (result < 0)
|
||||
goto out_proc;
|
||||
|
||||
result = acpi_bus_register_driver(&acpi_processor_driver);
|
||||
if (result < 0)
|
||||
goto out_cpuidle;
|
||||
|
||||
acpi_processor_install_hotplug_notify();
|
||||
|
||||
acpi_thermal_cpufreq_init();
|
||||
|
||||
acpi_processor_ppc_init();
|
||||
|
||||
acpi_processor_throttling_init();
|
||||
|
||||
return 0;
|
||||
|
||||
out_cpuidle:
|
||||
cpuidle_unregister_driver(&acpi_idle_driver);
|
||||
|
||||
out_proc:
|
||||
#ifdef CONFIG_ACPI_PROCFS
|
||||
remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit acpi_processor_exit(void)
|
||||
{
|
||||
if (acpi_disabled)
|
||||
return;
|
||||
|
||||
acpi_processor_ppc_exit();
|
||||
|
||||
acpi_thermal_cpufreq_exit();
|
||||
|
||||
acpi_processor_uninstall_hotplug_notify();
|
||||
|
||||
acpi_bus_unregister_driver(&acpi_processor_driver);
|
||||
|
||||
cpuidle_unregister_driver(&acpi_idle_driver);
|
||||
|
||||
#ifdef CONFIG_ACPI_PROCFS
|
||||
remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(acpi_processor_init);
|
||||
module_exit(acpi_processor_exit);
|
||||
|
||||
EXPORT_SYMBOL(acpi_processor_set_thermal_limit);
|
||||
|
||||
MODULE_ALIAS("processor");
|
|
@ -1,209 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Intel Corporation
|
||||
* Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Alex Chiang <achiang@hp.com>
|
||||
* - Unified x86/ia64 implementations
|
||||
* Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
|
||||
* - Added _PDC for platforms with Intel CPUs
|
||||
*/
|
||||
#include <linux/dmi.h>
|
||||
|
||||
#include <acpi/acpi_drivers.h>
|
||||
#include <acpi/processor.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
|
||||
ACPI_MODULE_NAME("processor_pdc");
|
||||
|
||||
static int set_no_mwait(const struct dmi_system_id *id)
|
||||
{
|
||||
printk(KERN_NOTICE PREFIX "%s detected - "
|
||||
"disabling mwait for CPU C-states\n", id->ident);
|
||||
idle_nomwait = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
|
||||
{
|
||||
set_no_mwait, "IFL91 board", {
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL},
|
||||
{
|
||||
set_no_mwait, "Extensa 5220", {
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
|
||||
{},
|
||||
};
|
||||
|
||||
static void acpi_set_pdc_bits(u32 *buf)
|
||||
{
|
||||
buf[0] = ACPI_PDC_REVISION_ID;
|
||||
buf[1] = 1;
|
||||
|
||||
/* Enable coordination with firmware's _TSD info */
|
||||
buf[2] = ACPI_PDC_SMP_T_SWCOORD;
|
||||
|
||||
/* Twiddle arch-specific bits needed for _PDC */
|
||||
arch_acpi_set_pdc_bits(buf);
|
||||
}
|
||||
|
||||
static struct acpi_object_list *acpi_processor_alloc_pdc(void)
|
||||
{
|
||||
struct acpi_object_list *obj_list;
|
||||
union acpi_object *obj;
|
||||
u32 *buf;
|
||||
|
||||
/* allocate and initialize pdc. It will be used later. */
|
||||
obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
|
||||
if (!obj_list) {
|
||||
printk(KERN_ERR "Memory allocation error\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
|
||||
if (!obj) {
|
||||
printk(KERN_ERR "Memory allocation error\n");
|
||||
kfree(obj_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = kmalloc(12, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
printk(KERN_ERR "Memory allocation error\n");
|
||||
kfree(obj);
|
||||
kfree(obj_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
acpi_set_pdc_bits(buf);
|
||||
|
||||
obj->type = ACPI_TYPE_BUFFER;
|
||||
obj->buffer.length = 12;
|
||||
obj->buffer.pointer = (u8 *) buf;
|
||||
obj_list->count = 1;
|
||||
obj_list->pointer = obj;
|
||||
|
||||
return obj_list;
|
||||
}
|
||||
|
||||
/*
|
||||
* _PDC is required for a BIOS-OS handshake for most of the newer
|
||||
* ACPI processor features.
|
||||
*/
|
||||
static int
|
||||
acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
if (idle_nomwait) {
|
||||
/*
|
||||
* If mwait is disabled for CPU C-states, the C2C3_FFH access
|
||||
* mode will be disabled in the parameter of _PDC object.
|
||||
* Of course C1_FFH access mode will also be disabled.
|
||||
*/
|
||||
union acpi_object *obj;
|
||||
u32 *buffer = NULL;
|
||||
|
||||
obj = pdc_in->pointer;
|
||||
buffer = (u32 *)(obj->buffer.pointer);
|
||||
buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
|
||||
|
||||
}
|
||||
status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Could not evaluate _PDC, using legacy perf. control.\n"));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int early_pdc_done;
|
||||
|
||||
void acpi_processor_set_pdc(acpi_handle handle)
|
||||
{
|
||||
struct acpi_object_list *obj_list;
|
||||
|
||||
if (arch_has_acpi_pdc() == false)
|
||||
return;
|
||||
|
||||
if (early_pdc_done)
|
||||
return;
|
||||
|
||||
obj_list = acpi_processor_alloc_pdc();
|
||||
if (!obj_list)
|
||||
return;
|
||||
|
||||
acpi_processor_eval_pdc(handle, obj_list);
|
||||
|
||||
kfree(obj_list->pointer->buffer.pointer);
|
||||
kfree(obj_list->pointer);
|
||||
kfree(obj_list);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_processor_set_pdc);
|
||||
|
||||
static int early_pdc_optin;
|
||||
static int set_early_pdc_optin(const struct dmi_system_id *id)
|
||||
{
|
||||
early_pdc_optin = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int param_early_pdc_optin(char *s)
|
||||
{
|
||||
early_pdc_optin = 1;
|
||||
return 1;
|
||||
}
|
||||
__setup("acpi_early_pdc_eval", param_early_pdc_optin);
|
||||
|
||||
static struct dmi_system_id __cpuinitdata early_pdc_optin_table[] = {
|
||||
{
|
||||
set_early_pdc_optin, "HP Envy", {
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Envy") }, NULL},
|
||||
{
|
||||
set_early_pdc_optin, "HP Pavilion dv6", {
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv6") }, NULL},
|
||||
{
|
||||
set_early_pdc_optin, "HP Pavilion dv7", {
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv7") }, NULL},
|
||||
{},
|
||||
};
|
||||
|
||||
static acpi_status
|
||||
early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
{
|
||||
acpi_processor_set_pdc(handle);
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
void __init acpi_early_processor_set_pdc(void)
|
||||
{
|
||||
/*
|
||||
* Check whether the system is DMI table. If yes, OSPM
|
||||
* should not use mwait for CPU-states.
|
||||
*/
|
||||
dmi_check_system(processor_idle_dmi_table);
|
||||
|
||||
/*
|
||||
* Allow systems to opt-in to early _PDC evaluation.
|
||||
*/
|
||||
dmi_check_system(early_pdc_optin_table);
|
||||
if (!early_pdc_optin)
|
||||
return;
|
||||
|
||||
acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX,
|
||||
early_init_pdc, NULL, NULL, NULL);
|
||||
|
||||
early_pdc_done = 1;
|
||||
}
|
|
@ -1133,9 +1133,6 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
|
|||
int result = 0;
|
||||
struct acpi_processor_throttling *pthrottling;
|
||||
|
||||
if (!pr)
|
||||
return -EINVAL;
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n",
|
||||
pr->throttling.address,
|
||||
|
|
|
@ -217,6 +217,9 @@ static int acpi_sbs_battery_get_property(struct power_supply *psy,
|
|||
case POWER_SUPPLY_PROP_TECHNOLOGY:
|
||||
val->intval = acpi_battery_technology(battery);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CYCLE_COUNT:
|
||||
val->intval = battery->cycle_count;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
|
||||
val->intval = battery->design_voltage *
|
||||
acpi_battery_vscale(battery) * 1000;
|
||||
|
@ -276,6 +279,7 @@ static enum power_supply_property sbs_charge_battery_props[] = {
|
|||
POWER_SUPPLY_PROP_STATUS,
|
||||
POWER_SUPPLY_PROP_PRESENT,
|
||||
POWER_SUPPLY_PROP_TECHNOLOGY,
|
||||
POWER_SUPPLY_PROP_CYCLE_COUNT,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||
POWER_SUPPLY_PROP_CURRENT_NOW,
|
||||
|
@ -560,6 +564,7 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
|
|||
battery->design_voltage * acpi_battery_vscale(battery));
|
||||
seq_printf(seq, "design capacity warning: unknown\n");
|
||||
seq_printf(seq, "design capacity low: unknown\n");
|
||||
seq_printf(seq, "cycle count: %i\n", battery->cycle_count);
|
||||
seq_printf(seq, "capacity granularity 1: unknown\n");
|
||||
seq_printf(seq, "capacity granularity 2: unknown\n");
|
||||
seq_printf(seq, "model number: %s\n", battery->device_name);
|
||||
|
|
|
@ -552,8 +552,17 @@ static void acpi_hibernation_leave(void)
|
|||
hibernate_nvs_restore();
|
||||
}
|
||||
|
||||
static void acpi_pm_enable_gpes(void)
|
||||
static int acpi_pm_pre_restore(void)
|
||||
{
|
||||
acpi_disable_all_gpes();
|
||||
acpi_os_wait_events_complete(NULL);
|
||||
acpi_ec_suspend_transactions();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void acpi_pm_restore_cleanup(void)
|
||||
{
|
||||
acpi_ec_resume_transactions();
|
||||
acpi_enable_all_runtime_gpes();
|
||||
}
|
||||
|
||||
|
@ -565,8 +574,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops = {
|
|||
.prepare = acpi_pm_prepare,
|
||||
.enter = acpi_hibernation_enter,
|
||||
.leave = acpi_hibernation_leave,
|
||||
.pre_restore = acpi_pm_disable_gpes,
|
||||
.restore_cleanup = acpi_pm_enable_gpes,
|
||||
.pre_restore = acpi_pm_pre_restore,
|
||||
.restore_cleanup = acpi_pm_restore_cleanup,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -618,8 +627,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops_old = {
|
|||
.prepare = acpi_pm_disable_gpes,
|
||||
.enter = acpi_hibernation_enter,
|
||||
.leave = acpi_hibernation_leave,
|
||||
.pre_restore = acpi_pm_disable_gpes,
|
||||
.restore_cleanup = acpi_pm_enable_gpes,
|
||||
.pre_restore = acpi_pm_pre_restore,
|
||||
.restore_cleanup = acpi_pm_restore_cleanup,
|
||||
.recover = acpi_pm_finish,
|
||||
};
|
||||
#endif /* CONFIG_HIBERNATION */
|
||||
|
|
|
@ -368,7 +368,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
|||
int valid = 0;
|
||||
int i;
|
||||
|
||||
/* Critical Shutdown (required) */
|
||||
/* Critical Shutdown */
|
||||
if (flag & ACPI_TRIPS_CRITICAL) {
|
||||
status = acpi_evaluate_integer(tz->device->handle,
|
||||
"_CRT", NULL, &tmp);
|
||||
|
@ -379,17 +379,19 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
|||
* Below zero (Celsius) values clearly aren't right for sure..
|
||||
* ... so lets discard those as invalid.
|
||||
*/
|
||||
if (ACPI_FAILURE(status) ||
|
||||
tz->trips.critical.temperature <= 2732) {
|
||||
if (ACPI_FAILURE(status)) {
|
||||
tz->trips.critical.flags.valid = 0;
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"No critical threshold\n"));
|
||||
} else if (tmp <= 2732) {
|
||||
printk(KERN_WARNING FW_BUG "Invalid critical threshold "
|
||||
"(%llu)\n", tmp);
|
||||
tz->trips.critical.flags.valid = 0;
|
||||
ACPI_EXCEPTION((AE_INFO, status,
|
||||
"No or invalid critical threshold"));
|
||||
return -ENODEV;
|
||||
} else {
|
||||
tz->trips.critical.flags.valid = 1;
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Found critical threshold [%lu]\n",
|
||||
tz->trips.critical.temperature));
|
||||
"Found critical threshold [%lu]\n",
|
||||
tz->trips.critical.temperature));
|
||||
}
|
||||
if (tz->trips.critical.flags.valid == 1) {
|
||||
if (crt == -1) {
|
||||
|
@ -575,7 +577,23 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
|||
|
||||
static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
|
||||
{
|
||||
return acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
|
||||
int i, valid, ret = acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
valid = tz->trips.critical.flags.valid |
|
||||
tz->trips.hot.flags.valid |
|
||||
tz->trips.passive.flags.valid;
|
||||
|
||||
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
|
||||
valid |= tz->trips.active[i].flags.valid;
|
||||
|
||||
if (!valid) {
|
||||
printk(KERN_WARNING FW_BUG "No valid trip found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void acpi_thermal_check(void *data)
|
||||
|
|
|
@ -289,51 +289,6 @@ acpi_evaluate_integer(acpi_handle handle,
|
|||
|
||||
EXPORT_SYMBOL(acpi_evaluate_integer);
|
||||
|
||||
#if 0
|
||||
acpi_status
|
||||
acpi_evaluate_string(acpi_handle handle,
|
||||
acpi_string pathname,
|
||||
acpi_object_list * arguments, acpi_string * data)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
acpi_object *element = NULL;
|
||||
acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
|
||||
|
||||
if (!data)
|
||||
return AE_BAD_PARAMETER;
|
||||
|
||||
status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
acpi_util_eval_error(handle, pathname, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
element = (acpi_object *) buffer.pointer;
|
||||
|
||||
if ((element->type != ACPI_TYPE_STRING)
|
||||
|| (element->type != ACPI_TYPE_BUFFER)
|
||||
|| !element->string.length) {
|
||||
acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
|
||||
return AE_BAD_DATA;
|
||||
}
|
||||
|
||||
*data = kzalloc(element->string.length + 1, GFP_KERNEL);
|
||||
if (!data) {
|
||||
printk(KERN_ERR PREFIX "Memory allocation\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(*data, element->string.pointer, element->string.length);
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%s]\n", *data));
|
||||
|
||||
kfree(buffer.pointer);
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
acpi_status
|
||||
acpi_evaluate_reference(acpi_handle handle,
|
||||
acpi_string pathname,
|
||||
|
|
|
@ -327,7 +327,7 @@ static int acpi_video_device_lcd_set_level(struct acpi_video_device *device,
|
|||
int level);
|
||||
static int acpi_video_device_lcd_get_level_current(
|
||||
struct acpi_video_device *device,
|
||||
unsigned long long *level);
|
||||
unsigned long long *level, int init);
|
||||
static int acpi_video_get_next_level(struct acpi_video_device *device,
|
||||
u32 level_current, u32 event);
|
||||
static int acpi_video_switch_brightness(struct acpi_video_device *device,
|
||||
|
@ -345,7 +345,7 @@ static int acpi_video_get_brightness(struct backlight_device *bd)
|
|||
struct acpi_video_device *vd =
|
||||
(struct acpi_video_device *)bl_get_data(bd);
|
||||
|
||||
if (acpi_video_device_lcd_get_level_current(vd, &cur_level))
|
||||
if (acpi_video_device_lcd_get_level_current(vd, &cur_level, 0))
|
||||
return -EINVAL;
|
||||
for (i = 2; i < vd->brightness->count; i++) {
|
||||
if (vd->brightness->levels[i] == cur_level)
|
||||
|
@ -414,7 +414,7 @@ static int video_get_cur_state(struct thermal_cooling_device *cooling_dev, unsig
|
|||
unsigned long long level;
|
||||
int offset;
|
||||
|
||||
if (acpi_video_device_lcd_get_level_current(video, &level))
|
||||
if (acpi_video_device_lcd_get_level_current(video, &level, 0))
|
||||
return -EINVAL;
|
||||
for (offset = 2; offset < video->brightness->count; offset++)
|
||||
if (level == video->brightness->levels[offset]) {
|
||||
|
@ -609,7 +609,7 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
|
|||
|
||||
static int
|
||||
acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
|
||||
unsigned long long *level)
|
||||
unsigned long long *level, int init)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
int i;
|
||||
|
@ -633,10 +633,16 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
|
|||
device->brightness->curr = *level;
|
||||
return 0;
|
||||
}
|
||||
/* BQC returned an invalid level. Stop using it. */
|
||||
ACPI_WARNING((AE_INFO, "%s returned an invalid level",
|
||||
buf));
|
||||
device->cap._BQC = device->cap._BCQ = 0;
|
||||
if (!init) {
|
||||
/*
|
||||
* BQC returned an invalid level.
|
||||
* Stop using it.
|
||||
*/
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"%s returned an invalid level",
|
||||
buf));
|
||||
device->cap._BQC = device->cap._BCQ = 0;
|
||||
}
|
||||
} else {
|
||||
/* Fixme:
|
||||
* should we return an error or ignore this failure?
|
||||
|
@ -892,7 +898,7 @@ acpi_video_init_brightness(struct acpi_video_device *device)
|
|||
if (!device->cap._BQC)
|
||||
goto set_level;
|
||||
|
||||
result = acpi_video_device_lcd_get_level_current(device, &level_old);
|
||||
result = acpi_video_device_lcd_get_level_current(device, &level_old, 1);
|
||||
if (result)
|
||||
goto out_free_levels;
|
||||
|
||||
|
@ -903,7 +909,7 @@ acpi_video_init_brightness(struct acpi_video_device *device)
|
|||
if (result)
|
||||
goto out_free_levels;
|
||||
|
||||
result = acpi_video_device_lcd_get_level_current(device, &level);
|
||||
result = acpi_video_device_lcd_get_level_current(device, &level, 0);
|
||||
if (result)
|
||||
goto out_free_levels;
|
||||
|
||||
|
@ -1996,7 +2002,7 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event)
|
|||
goto out;
|
||||
|
||||
result = acpi_video_device_lcd_get_level_current(device,
|
||||
&level_current);
|
||||
&level_current, 0);
|
||||
if (result)
|
||||
goto out;
|
||||
|
||||
|
|
|
@ -749,6 +749,24 @@ static int acpiphp_bus_trim(acpi_handle handle)
|
|||
return retval;
|
||||
}
|
||||
|
||||
static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)
|
||||
{
|
||||
struct acpiphp_func *func;
|
||||
union acpi_object params[2];
|
||||
struct acpi_object_list arg_list;
|
||||
|
||||
list_for_each_entry(func, &slot->funcs, sibling) {
|
||||
arg_list.count = 2;
|
||||
arg_list.pointer = params;
|
||||
params[0].type = ACPI_TYPE_INTEGER;
|
||||
params[0].integer.value = ACPI_ADR_SPACE_PCI_CONFIG;
|
||||
params[1].type = ACPI_TYPE_INTEGER;
|
||||
params[1].integer.value = 1;
|
||||
/* _REG is optional, we don't care about if there is failure */
|
||||
acpi_evaluate_object(func->handle, "_REG", &arg_list, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* enable_device - enable, configure a slot
|
||||
* @slot: slot to be enabled
|
||||
|
@ -805,6 +823,7 @@ static int __ref enable_device(struct acpiphp_slot *slot)
|
|||
pci_bus_assign_resources(bus);
|
||||
acpiphp_sanitize_bus(bus);
|
||||
acpiphp_set_hpp_values(bus);
|
||||
acpiphp_set_acpi_region(slot);
|
||||
pci_enable_bridges(bus);
|
||||
pci_bus_add_devices(bus);
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ struct sony_laptop_input_s {
|
|||
struct input_dev *key_dev;
|
||||
struct kfifo fifo;
|
||||
spinlock_t fifo_lock;
|
||||
struct workqueue_struct *wq;
|
||||
struct timer_list release_key_timer;
|
||||
};
|
||||
|
||||
static struct sony_laptop_input_s sony_laptop_input = {
|
||||
|
@ -299,20 +299,26 @@ static int sony_laptop_input_keycode_map[] = {
|
|||
};
|
||||
|
||||
/* release buttons after a short delay if pressed */
|
||||
static void do_sony_laptop_release_key(struct work_struct *work)
|
||||
static void do_sony_laptop_release_key(unsigned long unused)
|
||||
{
|
||||
struct sony_laptop_keypress kp;
|
||||
unsigned long flags;
|
||||
|
||||
while (kfifo_out_locked(&sony_laptop_input.fifo, (unsigned char *)&kp,
|
||||
sizeof(kp), &sony_laptop_input.fifo_lock)
|
||||
== sizeof(kp)) {
|
||||
msleep(10);
|
||||
spin_lock_irqsave(&sony_laptop_input.fifo_lock, flags);
|
||||
|
||||
if (kfifo_out(&sony_laptop_input.fifo,
|
||||
(unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) {
|
||||
input_report_key(kp.dev, kp.key, 0);
|
||||
input_sync(kp.dev);
|
||||
}
|
||||
|
||||
/* If there is something in the fifo schedule next release. */
|
||||
if (kfifo_len(&sony_laptop_input.fifo) != 0)
|
||||
mod_timer(&sony_laptop_input.release_key_timer,
|
||||
jiffies + msecs_to_jiffies(10));
|
||||
|
||||
spin_unlock_irqrestore(&sony_laptop_input.fifo_lock, flags);
|
||||
}
|
||||
static DECLARE_WORK(sony_laptop_release_key_work,
|
||||
do_sony_laptop_release_key);
|
||||
|
||||
/* forward event to the input subsystem */
|
||||
static void sony_laptop_report_input_event(u8 event)
|
||||
|
@ -366,13 +372,13 @@ static void sony_laptop_report_input_event(u8 event)
|
|||
/* we emit the scancode so we can always remap the key */
|
||||
input_event(kp.dev, EV_MSC, MSC_SCAN, event);
|
||||
input_sync(kp.dev);
|
||||
kfifo_in_locked(&sony_laptop_input.fifo,
|
||||
(unsigned char *)&kp, sizeof(kp),
|
||||
&sony_laptop_input.fifo_lock);
|
||||
|
||||
if (!work_pending(&sony_laptop_release_key_work))
|
||||
queue_work(sony_laptop_input.wq,
|
||||
&sony_laptop_release_key_work);
|
||||
/* schedule key release */
|
||||
kfifo_in_locked(&sony_laptop_input.fifo,
|
||||
(unsigned char *)&kp, sizeof(kp),
|
||||
&sony_laptop_input.fifo_lock);
|
||||
mod_timer(&sony_laptop_input.release_key_timer,
|
||||
jiffies + msecs_to_jiffies(10));
|
||||
} else
|
||||
dprintk("unknown input event %.2x\n", event);
|
||||
}
|
||||
|
@ -390,27 +396,21 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
|
|||
|
||||
/* kfifo */
|
||||
spin_lock_init(&sony_laptop_input.fifo_lock);
|
||||
error =
|
||||
kfifo_alloc(&sony_laptop_input.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
|
||||
error = kfifo_alloc(&sony_laptop_input.fifo,
|
||||
SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
|
||||
if (error) {
|
||||
printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
|
||||
goto err_dec_users;
|
||||
}
|
||||
|
||||
/* init workqueue */
|
||||
sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop");
|
||||
if (!sony_laptop_input.wq) {
|
||||
printk(KERN_ERR DRV_PFX
|
||||
"Unable to create workqueue.\n");
|
||||
error = -ENXIO;
|
||||
goto err_free_kfifo;
|
||||
}
|
||||
setup_timer(&sony_laptop_input.release_key_timer,
|
||||
do_sony_laptop_release_key, 0);
|
||||
|
||||
/* input keys */
|
||||
key_dev = input_allocate_device();
|
||||
if (!key_dev) {
|
||||
error = -ENOMEM;
|
||||
goto err_destroy_wq;
|
||||
goto err_free_kfifo;
|
||||
}
|
||||
|
||||
key_dev->name = "Sony Vaio Keys";
|
||||
|
@ -419,18 +419,15 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
|
|||
key_dev->dev.parent = &acpi_device->dev;
|
||||
|
||||
/* Initialize the Input Drivers: special keys */
|
||||
set_bit(EV_KEY, key_dev->evbit);
|
||||
set_bit(EV_MSC, key_dev->evbit);
|
||||
set_bit(MSC_SCAN, key_dev->mscbit);
|
||||
input_set_capability(key_dev, EV_MSC, MSC_SCAN);
|
||||
|
||||
__set_bit(EV_KEY, key_dev->evbit);
|
||||
key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]);
|
||||
key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map);
|
||||
key_dev->keycode = &sony_laptop_input_keycode_map;
|
||||
for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) {
|
||||
if (sony_laptop_input_keycode_map[i] != KEY_RESERVED) {
|
||||
set_bit(sony_laptop_input_keycode_map[i],
|
||||
key_dev->keybit);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++)
|
||||
__set_bit(sony_laptop_input_keycode_map[i], key_dev->keybit);
|
||||
__clear_bit(KEY_RESERVED, key_dev->keybit);
|
||||
|
||||
error = input_register_device(key_dev);
|
||||
if (error)
|
||||
|
@ -450,9 +447,8 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
|
|||
jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
|
||||
key_dev->dev.parent = &acpi_device->dev;
|
||||
|
||||
jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
|
||||
jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE);
|
||||
jog_dev->relbit[0] = BIT_MASK(REL_WHEEL);
|
||||
input_set_capability(jog_dev, EV_KEY, BTN_MIDDLE);
|
||||
input_set_capability(jog_dev, EV_REL, REL_WHEEL);
|
||||
|
||||
error = input_register_device(jog_dev);
|
||||
if (error)
|
||||
|
@ -473,9 +469,6 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
|
|||
err_free_keydev:
|
||||
input_free_device(key_dev);
|
||||
|
||||
err_destroy_wq:
|
||||
destroy_workqueue(sony_laptop_input.wq);
|
||||
|
||||
err_free_kfifo:
|
||||
kfifo_free(&sony_laptop_input.fifo);
|
||||
|
||||
|
@ -486,12 +479,23 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
|
|||
|
||||
static void sony_laptop_remove_input(void)
|
||||
{
|
||||
/* cleanup only after the last user has gone */
|
||||
struct sony_laptop_keypress kp = { NULL };
|
||||
|
||||
/* Cleanup only after the last user has gone */
|
||||
if (!atomic_dec_and_test(&sony_laptop_input.users))
|
||||
return;
|
||||
|
||||
/* flush workqueue first */
|
||||
flush_workqueue(sony_laptop_input.wq);
|
||||
del_timer_sync(&sony_laptop_input.release_key_timer);
|
||||
|
||||
/*
|
||||
* Generate key-up events for remaining keys. Note that we don't
|
||||
* need locking since nobody is adding new events to the kfifo.
|
||||
*/
|
||||
while (kfifo_out(&sony_laptop_input.fifo,
|
||||
(unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) {
|
||||
input_report_key(kp.dev, kp.key, 0);
|
||||
input_sync(kp.dev);
|
||||
}
|
||||
|
||||
/* destroy input devs */
|
||||
input_unregister_device(sony_laptop_input.key_dev);
|
||||
|
@ -502,7 +506,6 @@ static void sony_laptop_remove_input(void)
|
|||
sony_laptop_input.jog_dev = NULL;
|
||||
}
|
||||
|
||||
destroy_workqueue(sony_laptop_input.wq);
|
||||
kfifo_free(&sony_laptop_input.fifo);
|
||||
}
|
||||
|
||||
|
|
|
@ -166,6 +166,9 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
|
|||
struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
|
||||
resource_size_t start,
|
||||
resource_size_t end, int flags);
|
||||
struct pnp_resource *pnp_add_bus_resource(struct pnp_dev *dev,
|
||||
resource_size_t start,
|
||||
resource_size_t end);
|
||||
|
||||
extern int pnp_debug;
|
||||
|
||||
|
|
|
@ -278,9 +278,12 @@ static ssize_t pnp_show_current_resources(struct device *dmdev,
|
|||
switch (pnp_resource_type(res)) {
|
||||
case IORESOURCE_IO:
|
||||
case IORESOURCE_MEM:
|
||||
pnp_printf(buffer, " %#llx-%#llx\n",
|
||||
case IORESOURCE_BUS:
|
||||
pnp_printf(buffer, " %#llx-%#llx%s\n",
|
||||
(unsigned long long) res->start,
|
||||
(unsigned long long) res->end);
|
||||
(unsigned long long) res->end,
|
||||
res->flags & IORESOURCE_WINDOW ?
|
||||
" window" : "");
|
||||
break;
|
||||
case IORESOURCE_IRQ:
|
||||
case IORESOURCE_DMA:
|
||||
|
|
|
@ -177,7 +177,8 @@ static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
|
|||
}
|
||||
|
||||
static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
|
||||
u64 len, int io_decode)
|
||||
u64 len, int io_decode,
|
||||
int window)
|
||||
{
|
||||
int flags = 0;
|
||||
u64 end = start + len - 1;
|
||||
|
@ -186,6 +187,8 @@ static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
|
|||
flags |= IORESOURCE_IO_16BIT_ADDR;
|
||||
if (len == 0 || end >= 0x10003)
|
||||
flags |= IORESOURCE_DISABLED;
|
||||
if (window)
|
||||
flags |= IORESOURCE_WINDOW;
|
||||
|
||||
pnp_add_io_resource(dev, start, end, flags);
|
||||
}
|
||||
|
@ -247,7 +250,7 @@ static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,
|
|||
|
||||
static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
|
||||
u64 start, u64 len,
|
||||
int write_protect)
|
||||
int write_protect, int window)
|
||||
{
|
||||
int flags = 0;
|
||||
u64 end = start + len - 1;
|
||||
|
@ -256,15 +259,26 @@ static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
|
|||
flags |= IORESOURCE_DISABLED;
|
||||
if (write_protect == ACPI_READ_WRITE_MEMORY)
|
||||
flags |= IORESOURCE_MEM_WRITEABLE;
|
||||
if (window)
|
||||
flags |= IORESOURCE_WINDOW;
|
||||
|
||||
pnp_add_mem_resource(dev, start, end, flags);
|
||||
}
|
||||
|
||||
static void pnpacpi_parse_allocated_busresource(struct pnp_dev *dev,
|
||||
u64 start, u64 len)
|
||||
{
|
||||
u64 end = start + len - 1;
|
||||
|
||||
pnp_add_bus_resource(dev, start, end);
|
||||
}
|
||||
|
||||
static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
|
||||
struct acpi_resource *res)
|
||||
{
|
||||
struct acpi_resource_address64 addr, *p = &addr;
|
||||
acpi_status status;
|
||||
int window;
|
||||
|
||||
status = acpi_resource_to_address64(res, p);
|
||||
if (!ACPI_SUCCESS(status)) {
|
||||
|
@ -273,37 +287,42 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
|
|||
return;
|
||||
}
|
||||
|
||||
if (p->producer_consumer == ACPI_PRODUCER)
|
||||
return;
|
||||
window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
|
||||
|
||||
if (p->resource_type == ACPI_MEMORY_RANGE)
|
||||
pnpacpi_parse_allocated_memresource(dev,
|
||||
p->minimum, p->address_length,
|
||||
p->info.mem.write_protect);
|
||||
p->info.mem.write_protect, window);
|
||||
else if (p->resource_type == ACPI_IO_RANGE)
|
||||
pnpacpi_parse_allocated_ioresource(dev,
|
||||
p->minimum, p->address_length,
|
||||
p->granularity == 0xfff ? ACPI_DECODE_10 :
|
||||
ACPI_DECODE_16);
|
||||
ACPI_DECODE_16, window);
|
||||
else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
|
||||
pnpacpi_parse_allocated_busresource(dev, p->minimum,
|
||||
p->address_length);
|
||||
}
|
||||
|
||||
static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev,
|
||||
struct acpi_resource *res)
|
||||
{
|
||||
struct acpi_resource_extended_address64 *p = &res->data.ext_address64;
|
||||
int window;
|
||||
|
||||
if (p->producer_consumer == ACPI_PRODUCER)
|
||||
return;
|
||||
window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
|
||||
|
||||
if (p->resource_type == ACPI_MEMORY_RANGE)
|
||||
pnpacpi_parse_allocated_memresource(dev,
|
||||
p->minimum, p->address_length,
|
||||
p->info.mem.write_protect);
|
||||
p->info.mem.write_protect, window);
|
||||
else if (p->resource_type == ACPI_IO_RANGE)
|
||||
pnpacpi_parse_allocated_ioresource(dev,
|
||||
p->minimum, p->address_length,
|
||||
p->granularity == 0xfff ? ACPI_DECODE_10 :
|
||||
ACPI_DECODE_16);
|
||||
ACPI_DECODE_16, window);
|
||||
else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
|
||||
pnpacpi_parse_allocated_busresource(dev, p->minimum,
|
||||
p->address_length);
|
||||
}
|
||||
|
||||
static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
|
||||
|
@ -368,7 +387,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
|
|||
pnpacpi_parse_allocated_ioresource(dev,
|
||||
io->minimum,
|
||||
io->address_length,
|
||||
io->io_decode);
|
||||
io->io_decode, 0);
|
||||
break;
|
||||
|
||||
case ACPI_RESOURCE_TYPE_START_DEPENDENT:
|
||||
|
@ -380,7 +399,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
|
|||
pnpacpi_parse_allocated_ioresource(dev,
|
||||
fixed_io->address,
|
||||
fixed_io->address_length,
|
||||
ACPI_DECODE_10);
|
||||
ACPI_DECODE_10, 0);
|
||||
break;
|
||||
|
||||
case ACPI_RESOURCE_TYPE_VENDOR:
|
||||
|
@ -396,21 +415,21 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
|
|||
pnpacpi_parse_allocated_memresource(dev,
|
||||
memory24->minimum,
|
||||
memory24->address_length,
|
||||
memory24->write_protect);
|
||||
memory24->write_protect, 0);
|
||||
break;
|
||||
case ACPI_RESOURCE_TYPE_MEMORY32:
|
||||
memory32 = &res->data.memory32;
|
||||
pnpacpi_parse_allocated_memresource(dev,
|
||||
memory32->minimum,
|
||||
memory32->address_length,
|
||||
memory32->write_protect);
|
||||
memory32->write_protect, 0);
|
||||
break;
|
||||
case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
|
||||
fixed_memory32 = &res->data.fixed_memory32;
|
||||
pnpacpi_parse_allocated_memresource(dev,
|
||||
fixed_memory32->address,
|
||||
fixed_memory32->address_length,
|
||||
fixed_memory32->write_protect);
|
||||
fixed_memory32->write_protect, 0);
|
||||
break;
|
||||
case ACPI_RESOURCE_TYPE_ADDRESS16:
|
||||
case ACPI_RESOURCE_TYPE_ADDRESS32:
|
||||
|
|
|
@ -470,7 +470,8 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
|
|||
unsigned long pnp_resource_type(struct resource *res)
|
||||
{
|
||||
return res->flags & (IORESOURCE_IO | IORESOURCE_MEM |
|
||||
IORESOURCE_IRQ | IORESOURCE_DMA);
|
||||
IORESOURCE_IRQ | IORESOURCE_DMA |
|
||||
IORESOURCE_BUS);
|
||||
}
|
||||
|
||||
struct resource *pnp_get_resource(struct pnp_dev *dev,
|
||||
|
@ -590,6 +591,30 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
|
|||
return pnp_res;
|
||||
}
|
||||
|
||||
struct pnp_resource *pnp_add_bus_resource(struct pnp_dev *dev,
|
||||
resource_size_t start,
|
||||
resource_size_t end)
|
||||
{
|
||||
struct pnp_resource *pnp_res;
|
||||
struct resource *res;
|
||||
|
||||
pnp_res = pnp_new_resource(dev);
|
||||
if (!pnp_res) {
|
||||
dev_err(&dev->dev, "can't add resource for BUS %#llx-%#llx\n",
|
||||
(unsigned long long) start,
|
||||
(unsigned long long) end);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = &pnp_res->res;
|
||||
res->flags = IORESOURCE_BUS;
|
||||
res->start = start;
|
||||
res->end = end;
|
||||
|
||||
pnp_dbg(&dev->dev, " add %pr\n", res);
|
||||
return pnp_res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine whether the specified resource is a possible configuration
|
||||
* for this device.
|
||||
|
|
|
@ -69,8 +69,10 @@ char *pnp_resource_type_name(struct resource *res)
|
|||
return "irq";
|
||||
case IORESOURCE_DMA:
|
||||
return "dma";
|
||||
case IORESOURCE_BUS:
|
||||
return "bus";
|
||||
}
|
||||
return NULL;
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
|
||||
|
|
|
@ -99,6 +99,7 @@ static struct device_attribute power_supply_attrs[] = {
|
|||
POWER_SUPPLY_ATTR(present),
|
||||
POWER_SUPPLY_ATTR(online),
|
||||
POWER_SUPPLY_ATTR(technology),
|
||||
POWER_SUPPLY_ATTR(cycle_count),
|
||||
POWER_SUPPLY_ATTR(voltage_max),
|
||||
POWER_SUPPLY_ATTR(voltage_min),
|
||||
POWER_SUPPLY_ATTR(voltage_max_design),
|
||||
|
|
|
@ -320,8 +320,16 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
|
|||
|
||||
#endif /* CONFIG_CPU_FREQ */
|
||||
|
||||
/* in processor_pdc.c */
|
||||
/* in processor_core.c */
|
||||
void acpi_processor_set_pdc(acpi_handle handle);
|
||||
#ifdef CONFIG_SMP
|
||||
int acpi_get_cpuid(acpi_handle, int type, u32 acpi_id);
|
||||
#else
|
||||
static inline int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* in processor_throttling.c */
|
||||
int acpi_processor_tstate_has_changed(struct acpi_processor *pr);
|
||||
|
|
|
@ -34,22 +34,24 @@ struct resource_list {
|
|||
*/
|
||||
#define IORESOURCE_BITS 0x000000ff /* Bus-specific bits */
|
||||
|
||||
#define IORESOURCE_TYPE_BITS 0x00000f00 /* Resource type */
|
||||
#define IORESOURCE_TYPE_BITS 0x00001f00 /* Resource type */
|
||||
#define IORESOURCE_IO 0x00000100
|
||||
#define IORESOURCE_MEM 0x00000200
|
||||
#define IORESOURCE_IRQ 0x00000400
|
||||
#define IORESOURCE_DMA 0x00000800
|
||||
#define IORESOURCE_BUS 0x00001000
|
||||
|
||||
#define IORESOURCE_PREFETCH 0x00001000 /* No side effects */
|
||||
#define IORESOURCE_READONLY 0x00002000
|
||||
#define IORESOURCE_CACHEABLE 0x00004000
|
||||
#define IORESOURCE_RANGELENGTH 0x00008000
|
||||
#define IORESOURCE_SHADOWABLE 0x00010000
|
||||
#define IORESOURCE_PREFETCH 0x00002000 /* No side effects */
|
||||
#define IORESOURCE_READONLY 0x00004000
|
||||
#define IORESOURCE_CACHEABLE 0x00008000
|
||||
#define IORESOURCE_RANGELENGTH 0x00010000
|
||||
#define IORESOURCE_SHADOWABLE 0x00020000
|
||||
|
||||
#define IORESOURCE_SIZEALIGN 0x00020000 /* size indicates alignment */
|
||||
#define IORESOURCE_STARTALIGN 0x00040000 /* start field is alignment */
|
||||
#define IORESOURCE_SIZEALIGN 0x00040000 /* size indicates alignment */
|
||||
#define IORESOURCE_STARTALIGN 0x00080000 /* start field is alignment */
|
||||
|
||||
#define IORESOURCE_MEM_64 0x00100000
|
||||
#define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */
|
||||
|
||||
#define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */
|
||||
#define IORESOURCE_DISABLED 0x10000000
|
||||
|
|
|
@ -82,6 +82,7 @@ enum power_supply_property {
|
|||
POWER_SUPPLY_PROP_PRESENT,
|
||||
POWER_SUPPLY_PROP_ONLINE,
|
||||
POWER_SUPPLY_PROP_TECHNOLOGY,
|
||||
POWER_SUPPLY_PROP_CYCLE_COUNT,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_MAX,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_MIN,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
|
||||
|
|
|
@ -609,6 +609,12 @@ static char *resource_string(char *buf, char *end, struct resource *res,
|
|||
.precision = -1,
|
||||
.flags = SPECIAL | SMALL | ZEROPAD,
|
||||
};
|
||||
static const struct printf_spec bus_spec = {
|
||||
.base = 16,
|
||||
.field_width = 2,
|
||||
.precision = -1,
|
||||
.flags = SMALL | ZEROPAD,
|
||||
};
|
||||
static const struct printf_spec dec_spec = {
|
||||
.base = 10,
|
||||
.precision = -1,
|
||||
|
@ -629,7 +635,7 @@ static char *resource_string(char *buf, char *end, struct resource *res,
|
|||
* 64-bit res (sizeof==8): 20 chars in dec, 18 in hex ("0x" + 16) */
|
||||
#define RSRC_BUF_SIZE ((2 * sizeof(resource_size_t)) + 4)
|
||||
#define FLAG_BUF_SIZE (2 * sizeof(res->flags))
|
||||
#define DECODED_BUF_SIZE sizeof("[mem - 64bit pref disabled]")
|
||||
#define DECODED_BUF_SIZE sizeof("[mem - 64bit pref window disabled]")
|
||||
#define RAW_BUF_SIZE sizeof("[mem - flags 0x]")
|
||||
char sym[max(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE,
|
||||
2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)];
|
||||
|
@ -651,6 +657,9 @@ static char *resource_string(char *buf, char *end, struct resource *res,
|
|||
} else if (res->flags & IORESOURCE_DMA) {
|
||||
p = string(p, pend, "dma ", str_spec);
|
||||
specp = &dec_spec;
|
||||
} else if (res->flags & IORESOURCE_BUS) {
|
||||
p = string(p, pend, "bus ", str_spec);
|
||||
specp = &bus_spec;
|
||||
} else {
|
||||
p = string(p, pend, "??? ", str_spec);
|
||||
specp = &mem_spec;
|
||||
|
@ -666,6 +675,8 @@ static char *resource_string(char *buf, char *end, struct resource *res,
|
|||
p = string(p, pend, " 64bit", str_spec);
|
||||
if (res->flags & IORESOURCE_PREFETCH)
|
||||
p = string(p, pend, " pref", str_spec);
|
||||
if (res->flags & IORESOURCE_WINDOW)
|
||||
p = string(p, pend, " window", str_spec);
|
||||
if (res->flags & IORESOURCE_DISABLED)
|
||||
p = string(p, pend, " disabled", str_spec);
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue