mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-26 00:51:02 +07:00
Merge branch 'release-2.6.27' of git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-acpi-merge-2.6
* 'release-2.6.27' of git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-acpi-merge-2.6: (87 commits) Fix FADT parsing Add the ability to reset the machine using the RESET_REG in ACPI's FADT table. ACPI: use dev_printk when possible PNPACPI: add support for HP vendor-specific CCSR descriptors PNP: avoid legacy IDE IRQs PNP: convert resource options to single linked list ISAPNP: handle independent options following dependent ones PNP: remove extra 0x100 bit from option priority PNP: support optional IRQ resources PNP: rename pnp_register_*_resource() local variables PNPACPI: ignore _PRS interrupt numbers larger than PNP_IRQ_NR PNP: centralize resource option allocations PNP: remove redundant pnp_can_configure() check PNP: make resource assignment functions return 0 (success) or -EBUSY (failure) PNP: in debug resource dump, make empty list obvious PNP: improve resource assignment debug PNP: increase I/O port & memory option address sizes PNP: introduce pnp_irq_mask_t typedef PNP: make resource option structures private to PNP subsystem PNP: define PNP-specific IORESOURCE_IO_* flags alongside IRQ, DMA, MEM ...
This commit is contained in:
commit
4314652bb4
@ -29,46 +29,46 @@ Description:
|
||||
|
||||
$ cd /sys/firmware/acpi/interrupts
|
||||
$ grep . *
|
||||
error:0
|
||||
ff_gbl_lock:0
|
||||
ff_pmtimer:0
|
||||
ff_pwr_btn:0
|
||||
ff_rt_clk:0
|
||||
ff_slp_btn:0
|
||||
gpe00:0
|
||||
gpe01:0
|
||||
gpe02:0
|
||||
gpe03:0
|
||||
gpe04:0
|
||||
gpe05:0
|
||||
gpe06:0
|
||||
gpe07:0
|
||||
gpe08:0
|
||||
gpe09:174
|
||||
gpe0A:0
|
||||
gpe0B:0
|
||||
gpe0C:0
|
||||
gpe0D:0
|
||||
gpe0E:0
|
||||
gpe0F:0
|
||||
gpe10:0
|
||||
gpe11:60
|
||||
gpe12:0
|
||||
gpe13:0
|
||||
gpe14:0
|
||||
gpe15:0
|
||||
gpe16:0
|
||||
gpe17:0
|
||||
gpe18:0
|
||||
gpe19:7
|
||||
gpe1A:0
|
||||
gpe1B:0
|
||||
gpe1C:0
|
||||
gpe1D:0
|
||||
gpe1E:0
|
||||
gpe1F:0
|
||||
gpe_all:241
|
||||
sci:241
|
||||
error: 0
|
||||
ff_gbl_lock: 0 enable
|
||||
ff_pmtimer: 0 invalid
|
||||
ff_pwr_btn: 0 enable
|
||||
ff_rt_clk: 2 disable
|
||||
ff_slp_btn: 0 invalid
|
||||
gpe00: 0 invalid
|
||||
gpe01: 0 enable
|
||||
gpe02: 108 enable
|
||||
gpe03: 0 invalid
|
||||
gpe04: 0 invalid
|
||||
gpe05: 0 invalid
|
||||
gpe06: 0 enable
|
||||
gpe07: 0 enable
|
||||
gpe08: 0 invalid
|
||||
gpe09: 0 invalid
|
||||
gpe0A: 0 invalid
|
||||
gpe0B: 0 invalid
|
||||
gpe0C: 0 invalid
|
||||
gpe0D: 0 invalid
|
||||
gpe0E: 0 invalid
|
||||
gpe0F: 0 invalid
|
||||
gpe10: 0 invalid
|
||||
gpe11: 0 invalid
|
||||
gpe12: 0 invalid
|
||||
gpe13: 0 invalid
|
||||
gpe14: 0 invalid
|
||||
gpe15: 0 invalid
|
||||
gpe16: 0 invalid
|
||||
gpe17: 1084 enable
|
||||
gpe18: 0 enable
|
||||
gpe19: 0 invalid
|
||||
gpe1A: 0 invalid
|
||||
gpe1B: 0 invalid
|
||||
gpe1C: 0 invalid
|
||||
gpe1D: 0 invalid
|
||||
gpe1E: 0 invalid
|
||||
gpe1F: 0 invalid
|
||||
gpe_all: 1192
|
||||
sci: 1194
|
||||
|
||||
sci - The total number of times the ACPI SCI
|
||||
has claimed an interrupt.
|
||||
@ -89,6 +89,13 @@ Description:
|
||||
|
||||
error - an interrupt that can't be accounted for above.
|
||||
|
||||
invalid: it's either a wakeup GPE or a GPE/Fixed Event that
|
||||
doesn't have an event handler.
|
||||
|
||||
disable: the GPE/Fixed Event is valid but disabled.
|
||||
|
||||
enable: the GPE/Fixed Event is valid and enabled.
|
||||
|
||||
Root has permission to clear any of these counters. Eg.
|
||||
# echo 0 > gpe11
|
||||
|
||||
@ -97,3 +104,43 @@ Description:
|
||||
|
||||
None of these counters has an effect on the function
|
||||
of the system, they are simply statistics.
|
||||
|
||||
Besides this, user can also write specific strings to these files
|
||||
to enable/disable/clear ACPI interrupts in user space, which can be
|
||||
used to debug some ACPI interrupt storm issues.
|
||||
|
||||
Note that only writting to VALID GPE/Fixed Event is allowed,
|
||||
i.e. user can only change the status of runtime GPE and
|
||||
Fixed Event with event handler installed.
|
||||
|
||||
Let's take power button fixed event for example, please kill acpid
|
||||
and other user space applications so that the machine won't shutdown
|
||||
when pressing the power button.
|
||||
# cat ff_pwr_btn
|
||||
0
|
||||
# press the power button for 3 times;
|
||||
# cat ff_pwr_btn
|
||||
3
|
||||
# echo disable > ff_pwr_btn
|
||||
# cat ff_pwr_btn
|
||||
disable
|
||||
# press the power button for 3 times;
|
||||
# cat ff_pwr_btn
|
||||
disable
|
||||
# echo enable > ff_pwr_btn
|
||||
# cat ff_pwr_btn
|
||||
4
|
||||
/*
|
||||
* this is because the status bit is set even if the enable bit is cleared,
|
||||
* and it triggers an ACPI fixed event when the enable bit is set again
|
||||
*/
|
||||
# press the power button for 3 times;
|
||||
# cat ff_pwr_btn
|
||||
7
|
||||
# echo disable > ff_pwr_btn
|
||||
# press the power button for 3 times;
|
||||
# echo clear > ff_pwr_btn /* clear the status bit */
|
||||
# echo disable > ff_pwr_btn
|
||||
# cat ff_pwr_btn
|
||||
7
|
||||
|
||||
|
@ -818,7 +818,7 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||
See Documentation/ide/ide.txt.
|
||||
|
||||
idle= [X86]
|
||||
Format: idle=poll or idle=mwait
|
||||
Format: idle=poll or idle=mwait, idle=halt, idle=nomwait
|
||||
Poll forces a polling idle loop that can slightly improves the performance
|
||||
of waking up a idle CPU, but will use a lot of power and make the system
|
||||
run hot. Not recommended.
|
||||
@ -826,6 +826,9 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||
to not use it because it doesn't save as much power as a normal idle
|
||||
loop use the MONITOR/MWAIT idle loop anyways. Performance should be the same
|
||||
as idle=poll.
|
||||
idle=halt. Halt is forced to be used for CPU idle.
|
||||
In such case C2/C3 won't be used again.
|
||||
idle=nomwait. Disable mwait for CPU C-states
|
||||
|
||||
ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem
|
||||
Claim all unknown PCI IDE storage controllers.
|
||||
|
@ -174,8 +174,6 @@ The LED is exposed through the LED subsystem, and can be found in:
|
||||
The mail LED is autodetected, so if you don't have one, the LED device won't
|
||||
be registered.
|
||||
|
||||
If you have a mail LED that is not green, please report this to me.
|
||||
|
||||
Backlight
|
||||
*********
|
||||
|
||||
|
25
MAINTAINERS
25
MAINTAINERS
@ -216,8 +216,8 @@ W: http://code.google.com/p/aceracpi
|
||||
S: Maintained
|
||||
|
||||
ACPI
|
||||
P: Len Brown
|
||||
M: len.brown@intel.com
|
||||
P: Andi Kleen
|
||||
M: ak@linux.intel.com
|
||||
M: lenb@kernel.org
|
||||
L: linux-acpi@vger.kernel.org
|
||||
W: http://www.lesswatts.org/projects/acpi/
|
||||
@ -239,8 +239,8 @@ W: http://www.lesswatts.org/projects/acpi/
|
||||
S: Supported
|
||||
|
||||
ACPI FAN DRIVER
|
||||
P: Len Brown
|
||||
M: len.brown@intel.com
|
||||
P: Zhang Rui
|
||||
M: rui.zhang@intel.com
|
||||
L: linux-acpi@vger.kernel.org
|
||||
W: http://www.lesswatts.org/projects/acpi/
|
||||
S: Supported
|
||||
@ -252,14 +252,14 @@ L: pcihpd-discuss@lists.sourceforge.net
|
||||
S: Supported
|
||||
|
||||
ACPI THERMAL DRIVER
|
||||
P: Len Brown
|
||||
M: len.brown@intel.com
|
||||
P: Zhang Rui
|
||||
M: rui.zhang@intel.com
|
||||
L: linux-acpi@vger.kernel.org
|
||||
W: http://www.lesswatts.org/projects/acpi/
|
||||
S: Supported
|
||||
|
||||
ACPI VIDEO DRIVER
|
||||
P: Rui Zhang
|
||||
P: Zhang Rui
|
||||
M: rui.zhang@intel.com
|
||||
L: linux-acpi@vger.kernel.org
|
||||
W: http://www.lesswatts.org/projects/acpi/
|
||||
@ -1160,6 +1160,11 @@ M: scott@spiteful.org
|
||||
L: pcihpd-discuss@lists.sourceforge.net
|
||||
S: Supported
|
||||
|
||||
COMPAL LAPTOP SUPPORT
|
||||
P: Cezary Jackiewicz
|
||||
M: cezary.jackiewicz@gmail.com
|
||||
S: Maintained
|
||||
|
||||
COMPUTONE INTELLIPORT MULTIPORT CARD
|
||||
P: Michael H. Warfield
|
||||
M: mhw@wittsend.com
|
||||
@ -1787,6 +1792,12 @@ P: David Howells
|
||||
M: dhowells@redhat.com
|
||||
S: Maintained
|
||||
|
||||
FUJITSU LAPTOP EXTRAS
|
||||
P: Jonathan Woithe
|
||||
M: jwoithe@physics.adelaide.edu.au
|
||||
L: linux-acpi@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
FUSE: FILESYSTEM IN USERSPACE
|
||||
P: Miklos Szeredi
|
||||
M: miklos@szeredi.hu
|
||||
|
@ -55,6 +55,10 @@ void (*ia64_mark_idle)(int);
|
||||
|
||||
unsigned long boot_option_idle_override = 0;
|
||||
EXPORT_SYMBOL(boot_option_idle_override);
|
||||
unsigned long idle_halt;
|
||||
EXPORT_SYMBOL(idle_halt);
|
||||
unsigned long idle_nomwait;
|
||||
EXPORT_SYMBOL(idle_nomwait);
|
||||
|
||||
void
|
||||
ia64_do_show_stack (struct unw_frame_info *info, void *arg)
|
||||
|
@ -56,6 +56,12 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c)
|
||||
if (cpu_has(c, X86_FEATURE_ACPI))
|
||||
buf[2] |= ACPI_PDC_T_FFH;
|
||||
|
||||
/*
|
||||
* If mwait/monitor is unsupported, C2/C3_FFH will be disabled
|
||||
*/
|
||||
if (!cpu_has(c, X86_FEATURE_MWAIT))
|
||||
buf[2] &= ~(ACPI_PDC_C_C2C3_FFH);
|
||||
|
||||
obj->type = ACPI_TYPE_BUFFER;
|
||||
obj->buffer.length = 12;
|
||||
obj->buffer.pointer = (u8 *) buf;
|
||||
|
@ -7,6 +7,12 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
unsigned long idle_halt;
|
||||
EXPORT_SYMBOL(idle_halt);
|
||||
unsigned long idle_nomwait;
|
||||
EXPORT_SYMBOL(idle_nomwait);
|
||||
|
||||
struct kmem_cache *task_xstate_cachep;
|
||||
|
||||
@ -325,7 +331,27 @@ static int __init idle_setup(char *str)
|
||||
pm_idle = poll_idle;
|
||||
} else if (!strcmp(str, "mwait"))
|
||||
force_mwait = 1;
|
||||
else
|
||||
else if (!strcmp(str, "halt")) {
|
||||
/*
|
||||
* When the boot option of idle=halt is added, halt is
|
||||
* forced to be used for CPU idle. In such case CPU C2/C3
|
||||
* won't be used again.
|
||||
* To continue to load the CPU idle driver, don't touch
|
||||
* the boot_option_idle_override.
|
||||
*/
|
||||
pm_idle = default_idle;
|
||||
idle_halt = 1;
|
||||
return 0;
|
||||
} else if (!strcmp(str, "nomwait")) {
|
||||
/*
|
||||
* If the boot option of "idle=nomwait" is added,
|
||||
* it means that mwait will be disabled for CPU C2/C3
|
||||
* states. In such case it won't touch the variable
|
||||
* of boot_option_idle_override.
|
||||
*/
|
||||
idle_nomwait = 1;
|
||||
return 0;
|
||||
} else
|
||||
return -1;
|
||||
|
||||
boot_option_idle_override = 1;
|
||||
|
@ -156,10 +156,9 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *memory_affinity)
|
||||
|
||||
num_memory_chunks++;
|
||||
|
||||
printk(KERN_DEBUG "Memory range %08lx to %08lx (type %x)"
|
||||
printk(KERN_DEBUG "Memory range %08lx to %08lx"
|
||||
" in proximity domain %02x %s\n",
|
||||
start_pfn, end_pfn,
|
||||
memory_affinity->memory_type,
|
||||
pxm,
|
||||
((memory_affinity->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) ?
|
||||
"enabled and removable" : "enabled" ) );
|
||||
|
@ -21,7 +21,7 @@ obj-$(CONFIG_X86) += blacklist.o
|
||||
#
|
||||
# ACPI Core Subsystem (Interpreter)
|
||||
#
|
||||
obj-y += osl.o utils.o \
|
||||
obj-y += osl.o utils.o reboot.o\
|
||||
dispatcher/ events/ executer/ hardware/ \
|
||||
namespace/ parser/ resources/ tables/ \
|
||||
utilities/
|
||||
|
@ -377,6 +377,9 @@ static int __init bay_init(void)
|
||||
|
||||
INIT_LIST_HEAD(&drive_bays);
|
||||
|
||||
if (acpi_disabled)
|
||||
return -ENODEV;
|
||||
|
||||
if (acpi_disabled)
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -612,7 +612,7 @@ static int __init acpi_bus_init_irq(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
acpi_native_uint acpi_gbl_permanent_mmap;
|
||||
u8 acpi_gbl_permanent_mmap;
|
||||
|
||||
|
||||
void __init acpi_early_init(void)
|
||||
|
@ -151,7 +151,7 @@ acpi_ds_init_one_object(acpi_handle obj_handle,
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ds_initialize_objects(acpi_native_uint table_index,
|
||||
acpi_ds_initialize_objects(u32 table_index,
|
||||
struct acpi_namespace_node * start_node)
|
||||
{
|
||||
acpi_status status;
|
||||
|
@ -377,7 +377,6 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
|
||||
}
|
||||
|
||||
info->parameters = &this_walk_state->operands[0];
|
||||
info->parameter_type = ACPI_PARAM_ARGS;
|
||||
|
||||
status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node,
|
||||
obj_desc->method.aml_start,
|
||||
|
@ -691,12 +691,6 @@ acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
|
||||
|
||||
status = acpi_ex_resolve_operands(op->common.aml_opcode,
|
||||
ACPI_WALK_OPERANDS, walk_state);
|
||||
|
||||
ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
|
||||
acpi_ps_get_opcode_name(op->common.aml_opcode),
|
||||
walk_state->num_operands,
|
||||
"after AcpiExResolveOperands");
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)",
|
||||
acpi_ps_get_opcode_name(op->common.aml_opcode),
|
||||
@ -785,10 +779,6 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
|
||||
acpi_ps_get_opcode_name(op->common.aml_opcode),
|
||||
1, "after AcpiExResolveOperands");
|
||||
|
||||
obj_desc = acpi_ns_get_attached_object(node);
|
||||
if (!obj_desc) {
|
||||
return_ACPI_STATUS(AE_NOT_EXIST);
|
||||
@ -848,7 +838,7 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
|
||||
union acpi_operand_object **operand;
|
||||
struct acpi_namespace_node *node;
|
||||
union acpi_parse_object *next_op;
|
||||
acpi_native_uint table_index;
|
||||
u32 table_index;
|
||||
struct acpi_table_header *table;
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op);
|
||||
@ -882,10 +872,6 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
|
||||
acpi_ps_get_opcode_name(op->common.aml_opcode),
|
||||
1, "after AcpiExResolveOperands");
|
||||
|
||||
operand = &walk_state->operands[0];
|
||||
|
||||
/* Find the ACPI table */
|
||||
@ -1091,10 +1077,8 @@ acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state,
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
|
||||
acpi_ps_get_opcode_name(op->common.aml_opcode),
|
||||
1, "after AcpiExResolveOperands");
|
||||
|
||||
ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS,
|
||||
acpi_ps_get_opcode_name(op->common.aml_opcode), 1);
|
||||
/*
|
||||
* Get the bank_value operand and save it
|
||||
* (at Top of stack)
|
||||
|
@ -408,14 +408,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
|
||||
[walk_state->
|
||||
num_operands - 1]),
|
||||
walk_state);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS,
|
||||
ACPI_IMODE_EXECUTE,
|
||||
acpi_ps_get_opcode_name
|
||||
(walk_state->opcode),
|
||||
walk_state->num_operands,
|
||||
"after ExResolveOperands");
|
||||
}
|
||||
}
|
||||
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
|
@ -70,7 +70,7 @@ acpi_status
|
||||
acpi_ds_result_pop(union acpi_operand_object **object,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_native_uint index;
|
||||
u32 index;
|
||||
union acpi_generic_state *state;
|
||||
acpi_status status;
|
||||
|
||||
@ -122,7 +122,7 @@ acpi_ds_result_pop(union acpi_operand_object **object,
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
|
||||
"Obj=%p [%s] Index=%X State=%p Num=%X\n", *object,
|
||||
acpi_ut_get_object_type_name(*object),
|
||||
(u32) index, walk_state, walk_state->result_count));
|
||||
index, walk_state, walk_state->result_count));
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
@ -146,7 +146,7 @@ acpi_ds_result_push(union acpi_operand_object * object,
|
||||
{
|
||||
union acpi_generic_state *state;
|
||||
acpi_status status;
|
||||
acpi_native_uint index;
|
||||
u32 index;
|
||||
|
||||
ACPI_FUNCTION_NAME(ds_result_push);
|
||||
|
||||
@ -400,7 +400,7 @@ void
|
||||
acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_native_int i;
|
||||
s32 i;
|
||||
union acpi_operand_object *obj_desc;
|
||||
|
||||
ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete);
|
||||
@ -409,7 +409,7 @@ acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = (acpi_native_int) (pop_count - 1); i >= 0; i--) {
|
||||
for (i = (s32) pop_count - 1; i >= 0; i--) {
|
||||
if (walk_state->num_operands == 0) {
|
||||
return;
|
||||
}
|
||||
@ -615,14 +615,8 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
|
||||
walk_state->pass_number = pass_number;
|
||||
|
||||
if (info) {
|
||||
if (info->parameter_type == ACPI_PARAM_GPE) {
|
||||
walk_state->gpe_event_info =
|
||||
ACPI_CAST_PTR(struct acpi_gpe_event_info,
|
||||
info->parameters);
|
||||
} else {
|
||||
walk_state->params = info->parameters;
|
||||
walk_state->caller_return_desc = &info->return_object;
|
||||
}
|
||||
walk_state->params = info->parameters;
|
||||
walk_state->caller_return_desc = &info->return_object;
|
||||
}
|
||||
|
||||
status = acpi_ps_init_scope(&walk_state->parser_state, op);
|
||||
|
@ -917,6 +917,9 @@ static int __init dock_init(void)
|
||||
|
||||
dock_station = NULL;
|
||||
|
||||
if (acpi_disabled)
|
||||
return 0;
|
||||
|
||||
if (acpi_disabled)
|
||||
return 0;
|
||||
|
||||
|
@ -188,7 +188,7 @@ acpi_status acpi_ev_install_xrupt_handlers(void)
|
||||
|
||||
static acpi_status acpi_ev_fixed_event_initialize(void)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
acpi_status status;
|
||||
|
||||
/*
|
||||
@ -231,7 +231,7 @@ u32 acpi_ev_fixed_event_detect(void)
|
||||
u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
|
||||
u32 fixed_status;
|
||||
u32 fixed_enable;
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_NAME(ev_fixed_event_detect);
|
||||
|
||||
@ -260,7 +260,7 @@ u32 acpi_ev_fixed_event_detect(void)
|
||||
|
||||
/* Found an active (signalled) event */
|
||||
acpi_os_fixed_event_count(i);
|
||||
int_status |= acpi_ev_fixed_event_dispatch((u32) i);
|
||||
int_status |= acpi_ev_fixed_event_dispatch(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,7 +256,7 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* Mark wake-disabled or HW disable, or both */
|
||||
/* Clear the appropriate enabled flags for this GPE */
|
||||
|
||||
switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
|
||||
case ACPI_GPE_TYPE_WAKE:
|
||||
@ -273,13 +273,23 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
|
||||
/* Disable the requested runtime GPE */
|
||||
|
||||
ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
|
||||
|
||||
/* fallthrough */
|
||||
break;
|
||||
|
||||
default:
|
||||
acpi_hw_write_gpe_enable_reg(gpe_event_info);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Even if we don't know the GPE type, make sure that we always
|
||||
* disable it. low_disable_gpe will just clear the enable bit for this
|
||||
* GPE and write it. It will not write out the current GPE enable mask,
|
||||
* since this may inadvertently enable GPEs too early, if a rogue GPE has
|
||||
* come in during ACPICA initialization - possibly as a result of AML or
|
||||
* other code that has enabled the GPE.
|
||||
*/
|
||||
status = acpi_hw_low_disable_gpe(gpe_event_info);
|
||||
return_ACPI_STATUS(status);
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
@ -305,7 +315,7 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
|
||||
{
|
||||
union acpi_operand_object *obj_desc;
|
||||
struct acpi_gpe_block_info *gpe_block;
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
@ -379,8 +389,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
|
||||
u32 status_reg;
|
||||
u32 enable_reg;
|
||||
acpi_cpu_flags flags;
|
||||
acpi_native_uint i;
|
||||
acpi_native_uint j;
|
||||
u32 i;
|
||||
u32 j;
|
||||
|
||||
ACPI_FUNCTION_NAME(ev_gpe_detect);
|
||||
|
||||
@ -462,13 +472,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
|
||||
*/
|
||||
int_status |=
|
||||
acpi_ev_gpe_dispatch(&gpe_block->
|
||||
event_info[(i *
|
||||
ACPI_GPE_REGISTER_WIDTH)
|
||||
+
|
||||
j],
|
||||
(u32) j +
|
||||
gpe_register_info->
|
||||
base_gpe_number);
|
||||
event_info[((acpi_size) i * ACPI_GPE_REGISTER_WIDTH) + j], j + gpe_register_info->base_gpe_number);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -555,10 +559,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
|
||||
*/
|
||||
info->prefix_node =
|
||||
local_gpe_event_info.dispatch.method_node;
|
||||
info->parameters =
|
||||
ACPI_CAST_PTR(union acpi_operand_object *,
|
||||
gpe_event_info);
|
||||
info->parameter_type = ACPI_PARAM_GPE;
|
||||
info->flags = ACPI_IGNORE_RETURN_VALUE;
|
||||
|
||||
status = acpi_ns_evaluate(info);
|
||||
|
@ -189,8 +189,8 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
|
||||
struct acpi_gpe_block_info *gpe_block)
|
||||
{
|
||||
struct acpi_gpe_event_info *gpe_event_info;
|
||||
acpi_native_uint i;
|
||||
acpi_native_uint j;
|
||||
u32 i;
|
||||
u32 j;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ev_delete_gpe_handlers);
|
||||
|
||||
@ -203,7 +203,8 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
|
||||
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
|
||||
gpe_event_info =
|
||||
&gpe_block->
|
||||
event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
|
||||
event_info[((acpi_size) i *
|
||||
ACPI_GPE_REGISTER_WIDTH) + j];
|
||||
|
||||
if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
|
||||
ACPI_GPE_DISPATCH_HANDLER) {
|
||||
@ -744,8 +745,8 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
|
||||
struct acpi_gpe_event_info *gpe_event_info = NULL;
|
||||
struct acpi_gpe_event_info *this_event;
|
||||
struct acpi_gpe_register_info *this_register;
|
||||
acpi_native_uint i;
|
||||
acpi_native_uint j;
|
||||
u32 i;
|
||||
u32 j;
|
||||
acpi_status status;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ev_create_gpe_info_blocks);
|
||||
@ -983,8 +984,8 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
|
||||
struct acpi_gpe_walk_info gpe_info;
|
||||
u32 wake_gpe_count;
|
||||
u32 gpe_enabled_count;
|
||||
acpi_native_uint i;
|
||||
acpi_native_uint j;
|
||||
u32 i;
|
||||
u32 j;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ev_initialize_gpe_block);
|
||||
|
||||
@ -1033,7 +1034,8 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
|
||||
|
||||
gpe_event_info =
|
||||
&gpe_block->
|
||||
event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
|
||||
event_info[((acpi_size) i *
|
||||
ACPI_GPE_REGISTER_WIDTH) + j];
|
||||
|
||||
if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
|
||||
ACPI_GPE_DISPATCH_METHOD)
|
||||
|
@ -575,7 +575,7 @@ acpi_status acpi_ev_release_global_lock(void)
|
||||
|
||||
void acpi_ev_terminate(void)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
acpi_status status;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ev_terminate);
|
||||
@ -589,7 +589,7 @@ void acpi_ev_terminate(void)
|
||||
/* Disable all fixed events */
|
||||
|
||||
for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
|
||||
status = acpi_disable_event((u32) i, 0);
|
||||
status = acpi_disable_event(i, 0);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Could not disable fixed event %d",
|
||||
|
@ -81,7 +81,7 @@ acpi_ev_install_handler(acpi_handle obj_handle,
|
||||
acpi_status acpi_ev_install_region_handlers(void)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ev_install_region_handlers);
|
||||
|
||||
@ -151,7 +151,7 @@ acpi_status acpi_ev_install_region_handlers(void)
|
||||
acpi_status acpi_ev_initialize_op_regions(void)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ev_initialize_op_regions);
|
||||
|
||||
@ -219,7 +219,6 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
|
||||
info->prefix_node = region_obj2->extra.method_REG;
|
||||
info->pathname = NULL;
|
||||
info->parameters = args;
|
||||
info->parameter_type = ACPI_PARAM_ARGS;
|
||||
info->flags = ACPI_IGNORE_RETURN_VALUE;
|
||||
|
||||
/*
|
||||
|
@ -380,7 +380,7 @@ static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
|
||||
acpi_status status;
|
||||
struct acpica_device_id hid;
|
||||
struct acpi_compatible_id_list *cid;
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
|
||||
/*
|
||||
* Get the _HID and check for a PCI Root Bridge
|
||||
|
@ -472,7 +472,6 @@ acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
|
||||
#ifdef ACPI_FUTURE_USAGE
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_get_event_status
|
||||
@ -489,6 +488,7 @@ ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
|
||||
acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
u32 value;
|
||||
|
||||
ACPI_FUNCTION_TRACE(acpi_get_event_status);
|
||||
|
||||
@ -506,7 +506,20 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
|
||||
|
||||
status =
|
||||
acpi_get_register(acpi_gbl_fixed_event_info[event].
|
||||
status_register_id, event_status);
|
||||
enable_register_id, &value);
|
||||
if (ACPI_FAILURE(status))
|
||||
return_ACPI_STATUS(status);
|
||||
|
||||
*event_status = value;
|
||||
|
||||
status =
|
||||
acpi_get_register(acpi_gbl_fixed_event_info[event].
|
||||
status_register_id, &value);
|
||||
if (ACPI_FAILURE(status))
|
||||
return_ACPI_STATUS(status);
|
||||
|
||||
if (value)
|
||||
*event_status |= ACPI_EVENT_FLAG_SET;
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
@ -566,7 +579,6 @@ acpi_get_gpe_status(acpi_handle gpe_device,
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
|
||||
#endif /* ACPI_FUTURE_USAGE */
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_install_gpe_block
|
||||
|
@ -53,7 +53,7 @@ ACPI_MODULE_NAME("exconfig")
|
||||
|
||||
/* Local prototypes */
|
||||
static acpi_status
|
||||
acpi_ex_add_table(acpi_native_uint table_index,
|
||||
acpi_ex_add_table(u32 table_index,
|
||||
struct acpi_namespace_node *parent_node,
|
||||
union acpi_operand_object **ddb_handle);
|
||||
|
||||
@ -73,7 +73,7 @@ acpi_ex_add_table(acpi_native_uint table_index,
|
||||
******************************************************************************/
|
||||
|
||||
static acpi_status
|
||||
acpi_ex_add_table(acpi_native_uint table_index,
|
||||
acpi_ex_add_table(u32 table_index,
|
||||
struct acpi_namespace_node *parent_node,
|
||||
union acpi_operand_object **ddb_handle)
|
||||
{
|
||||
@ -96,7 +96,8 @@ acpi_ex_add_table(acpi_native_uint table_index,
|
||||
|
||||
/* Install the new table into the local data structures */
|
||||
|
||||
obj_desc->reference.object = ACPI_CAST_PTR(void, table_index);
|
||||
obj_desc->reference.object = ACPI_CAST_PTR(void,
|
||||
(unsigned long)table_index);
|
||||
|
||||
/* Add the table to the namespace */
|
||||
|
||||
@ -128,12 +129,12 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
|
||||
{
|
||||
acpi_status status;
|
||||
union acpi_operand_object **operand = &walk_state->operands[0];
|
||||
acpi_native_uint table_index;
|
||||
struct acpi_namespace_node *parent_node;
|
||||
struct acpi_namespace_node *start_node;
|
||||
struct acpi_namespace_node *parameter_node = NULL;
|
||||
union acpi_operand_object *ddb_handle;
|
||||
struct acpi_table_header *table;
|
||||
u32 table_index;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ex_load_table_op);
|
||||
|
||||
@ -280,7 +281,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
|
||||
{
|
||||
union acpi_operand_object *ddb_handle;
|
||||
struct acpi_table_desc table_desc;
|
||||
acpi_native_uint table_index;
|
||||
u32 table_index;
|
||||
acpi_status status;
|
||||
u32 length;
|
||||
|
||||
@ -437,7 +438,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
union acpi_operand_object *table_desc = ddb_handle;
|
||||
acpi_native_uint table_index;
|
||||
u32 table_index;
|
||||
struct acpi_table_header *table;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ex_unload_table);
|
||||
@ -454,9 +455,9 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
|
||||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/* Get the table index from the ddb_handle */
|
||||
/* Get the table index from the ddb_handle (acpi_size for 64-bit case) */
|
||||
|
||||
table_index = (acpi_native_uint) table_desc->reference.object;
|
||||
table_index = (u32) (acpi_size) table_desc->reference.object;
|
||||
|
||||
/* Invoke table handler if present */
|
||||
|
||||
|
@ -288,11 +288,11 @@ acpi_ex_convert_to_ascii(acpi_integer integer,
|
||||
u16 base, u8 * string, u8 data_width)
|
||||
{
|
||||
acpi_integer digit;
|
||||
acpi_native_uint i;
|
||||
acpi_native_uint j;
|
||||
acpi_native_uint k = 0;
|
||||
acpi_native_uint hex_length;
|
||||
acpi_native_uint decimal_length;
|
||||
u32 i;
|
||||
u32 j;
|
||||
u32 k = 0;
|
||||
u32 hex_length;
|
||||
u32 decimal_length;
|
||||
u32 remainder;
|
||||
u8 supress_zeros;
|
||||
|
||||
@ -348,7 +348,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer,
|
||||
|
||||
/* hex_length: 2 ascii hex chars per data byte */
|
||||
|
||||
hex_length = (acpi_native_uint) ACPI_MUL_2(data_width);
|
||||
hex_length = ACPI_MUL_2(data_width);
|
||||
for (i = 0, j = (hex_length - 1); i < hex_length; i++, j--) {
|
||||
|
||||
/* Get one hex digit, most significant digits first */
|
||||
|
@ -45,8 +45,6 @@
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/amlcode.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/acevents.h>
|
||||
#include <acpi/actables.h>
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME("excreate")
|
||||
|
@ -580,25 +580,22 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
acpi_os_printf("Buffer len %X @ %p\n",
|
||||
acpi_os_printf("Buffer length %.2X @ %p\n",
|
||||
obj_desc->buffer.length,
|
||||
obj_desc->buffer.pointer);
|
||||
|
||||
length = obj_desc->buffer.length;
|
||||
if (length > 64) {
|
||||
length = 64;
|
||||
}
|
||||
|
||||
/* Debug only -- dump the buffer contents */
|
||||
|
||||
if (obj_desc->buffer.pointer) {
|
||||
acpi_os_printf("Buffer Contents: ");
|
||||
|
||||
for (index = 0; index < length; index++) {
|
||||
acpi_os_printf(" %02x",
|
||||
obj_desc->buffer.pointer[index]);
|
||||
length = obj_desc->buffer.length;
|
||||
if (length > 128) {
|
||||
length = 128;
|
||||
}
|
||||
acpi_os_printf("\n");
|
||||
|
||||
acpi_os_printf
|
||||
("Buffer Contents: (displaying length 0x%.2X)\n",
|
||||
length);
|
||||
ACPI_DUMP_BUFFER(obj_desc->buffer.pointer, length);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -756,54 +753,42 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
|
||||
*
|
||||
* FUNCTION: acpi_ex_dump_operands
|
||||
*
|
||||
* PARAMETERS: Operands - Operand list
|
||||
* interpreter_mode - Load or Exec
|
||||
* Ident - Identification
|
||||
* num_levels - # of stack entries to dump above line
|
||||
* Note - Output notation
|
||||
* module_name - Caller's module name
|
||||
* line_number - Caller's invocation line number
|
||||
* PARAMETERS: Operands - A list of Operand objects
|
||||
* opcode_name - AML opcode name
|
||||
* num_operands - Operand count for this opcode
|
||||
*
|
||||
* DESCRIPTION: Dump the object stack
|
||||
* DESCRIPTION: Dump the operands associated with the opcode
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_dump_operands(union acpi_operand_object **operands,
|
||||
acpi_interpreter_mode interpreter_mode,
|
||||
char *ident,
|
||||
u32 num_levels,
|
||||
char *note, char *module_name, u32 line_number)
|
||||
const char *opcode_name, u32 num_operands)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
|
||||
ACPI_FUNCTION_NAME(ex_dump_operands);
|
||||
|
||||
if (!ident) {
|
||||
ident = "?";
|
||||
}
|
||||
|
||||
if (!note) {
|
||||
note = "?";
|
||||
if (!opcode_name) {
|
||||
opcode_name = "UNKNOWN";
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
|
||||
"************* Operand Stack Contents (Opcode [%s], %d Operands)\n",
|
||||
ident, num_levels));
|
||||
"**** Start operand dump for opcode [%s], %d operands\n",
|
||||
opcode_name, num_operands));
|
||||
|
||||
if (num_levels == 0) {
|
||||
num_levels = 1;
|
||||
if (num_operands == 0) {
|
||||
num_operands = 1;
|
||||
}
|
||||
|
||||
/* Dump the operand stack starting at the top */
|
||||
/* Dump the individual operands */
|
||||
|
||||
for (i = 0; num_levels > 0; i--, num_levels--) {
|
||||
acpi_ex_dump_operand(operands[i], 0);
|
||||
while (num_operands) {
|
||||
acpi_ex_dump_operand(*operands, 0);
|
||||
operands++;
|
||||
num_operands--;
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
|
||||
"************* Operand Stack dump from %s(%d), %s\n",
|
||||
module_name, line_number, note));
|
||||
"**** End operand dump for [%s]\n", opcode_name));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -153,14 +153,15 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
|
||||
/*
|
||||
* Slack mode only: We will go ahead and allow access to this
|
||||
* field if it is within the region length rounded up to the next
|
||||
* access width boundary.
|
||||
* access width boundary. acpi_size cast for 64-bit compile.
|
||||
*/
|
||||
if (ACPI_ROUND_UP(rgn_desc->region.length,
|
||||
obj_desc->common_field.
|
||||
access_byte_width) >=
|
||||
(obj_desc->common_field.base_byte_offset +
|
||||
(acpi_native_uint) obj_desc->common_field.
|
||||
access_byte_width + field_datum_byte_offset)) {
|
||||
((acpi_size) obj_desc->common_field.
|
||||
base_byte_offset +
|
||||
obj_desc->common_field.access_byte_width +
|
||||
field_datum_byte_offset)) {
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
}
|
||||
|
@ -329,8 +329,8 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
|
||||
|
||||
/* Result of two Strings is a String */
|
||||
|
||||
return_desc = acpi_ut_create_string_object((acpi_size)
|
||||
(operand0->string.
|
||||
return_desc = acpi_ut_create_string_object(((acpi_size)
|
||||
operand0->string.
|
||||
length +
|
||||
local_operand1->
|
||||
string.length));
|
||||
@ -352,8 +352,8 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
|
||||
|
||||
/* Result of two Buffers is a Buffer */
|
||||
|
||||
return_desc = acpi_ut_create_buffer_object((acpi_size)
|
||||
(operand0->buffer.
|
||||
return_desc = acpi_ut_create_buffer_object(((acpi_size)
|
||||
operand0->buffer.
|
||||
length +
|
||||
local_operand1->
|
||||
buffer.length));
|
||||
|
@ -503,11 +503,11 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
|
||||
*/
|
||||
second_desc = obj_desc->common.next_object;
|
||||
second_desc->extra.aml_start =
|
||||
((union acpi_parse_object *)(info->data_register_node))->
|
||||
named.data;
|
||||
ACPI_CAST_PTR(union acpi_parse_object,
|
||||
info->data_register_node)->named.data;
|
||||
second_desc->extra.aml_length =
|
||||
((union acpi_parse_object *)(info->data_register_node))->
|
||||
named.length;
|
||||
ACPI_CAST_PTR(union acpi_parse_object,
|
||||
info->data_register_node)->named.length;
|
||||
|
||||
break;
|
||||
|
||||
|
@ -156,7 +156,7 @@ acpi_ex_system_memory_space_handler(u32 function,
|
||||
/* Create a new mapping starting at the address given */
|
||||
|
||||
mem_info->mapped_logical_address =
|
||||
acpi_os_map_memory((acpi_native_uint) address, window_size);
|
||||
acpi_os_map_memory((acpi_physical_address) address, window_size);
|
||||
if (!mem_info->mapped_logical_address) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Could not map memory at %8.8X%8.8X, size %X",
|
||||
|
@ -698,5 +698,9 @@ acpi_ex_resolve_operands(u16 opcode,
|
||||
}
|
||||
}
|
||||
|
||||
ACPI_DUMP_OPERANDS(walk_state->operands,
|
||||
acpi_ps_get_opcode_name(opcode),
|
||||
walk_state->num_operands);
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
@ -343,12 +343,6 @@ acpi_ex_store(union acpi_operand_object *source_desc,
|
||||
acpi_ut_get_object_type_name(dest_desc),
|
||||
dest_desc));
|
||||
|
||||
ACPI_DUMP_STACK_ENTRY(source_desc);
|
||||
ACPI_DUMP_STACK_ENTRY(dest_desc);
|
||||
ACPI_DUMP_OPERANDS(&dest_desc, ACPI_IMODE_EXECUTE, "ExStore",
|
||||
2,
|
||||
"Target is not a Reference or Constant object");
|
||||
|
||||
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
|
@ -148,7 +148,7 @@ acpi_fan_write_state(struct file *file, const char __user * buffer,
|
||||
int result = 0;
|
||||
struct seq_file *m = file->private_data;
|
||||
struct acpi_device *device = m->private;
|
||||
char state_string[12] = { '\0' };
|
||||
char state_string[3] = { '\0' };
|
||||
|
||||
if (count > sizeof(state_string) - 1)
|
||||
return -EINVAL;
|
||||
@ -157,6 +157,12 @@ acpi_fan_write_state(struct file *file, const char __user * buffer,
|
||||
return -EFAULT;
|
||||
|
||||
state_string[count] = '\0';
|
||||
if ((state_string[0] < '0') || (state_string[0] > '3'))
|
||||
return -EINVAL;
|
||||
if (state_string[1] == '\n')
|
||||
state_string[1] = '\0';
|
||||
if (state_string[1] != '\0')
|
||||
return -EINVAL;
|
||||
|
||||
result = acpi_bus_set_power(device->handle,
|
||||
simple_strtoul(state_string, NULL, 0));
|
||||
|
@ -333,6 +333,9 @@ static int __init acpi_rtc_init(void)
|
||||
{
|
||||
struct device *dev = get_rtc_dev();
|
||||
|
||||
if (acpi_disabled)
|
||||
return 0;
|
||||
|
||||
if (acpi_disabled)
|
||||
return 0;
|
||||
|
||||
|
@ -53,6 +53,54 @@ static acpi_status
|
||||
acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
|
||||
struct acpi_gpe_block_info *gpe_block);
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_hw_low_disable_gpe
|
||||
*
|
||||
* PARAMETERS: gpe_event_info - Info block for the GPE to be disabled
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Disable a single GPE in the enable register.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
|
||||
{
|
||||
struct acpi_gpe_register_info *gpe_register_info;
|
||||
acpi_status status;
|
||||
u32 enable_mask;
|
||||
|
||||
/* Get the info block for the entire GPE register */
|
||||
|
||||
gpe_register_info = gpe_event_info->register_info;
|
||||
if (!gpe_register_info) {
|
||||
return (AE_NOT_EXIST);
|
||||
}
|
||||
|
||||
/* Get current value of the enable register that contains this GPE */
|
||||
|
||||
status = acpi_hw_low_level_read(ACPI_GPE_REGISTER_WIDTH, &enable_mask,
|
||||
&gpe_register_info->enable_address);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
|
||||
/* Clear just the bit that corresponds to this GPE */
|
||||
|
||||
ACPI_CLEAR_BIT(enable_mask,
|
||||
((u32) 1 <<
|
||||
(gpe_event_info->gpe_number -
|
||||
gpe_register_info->base_gpe_number)));
|
||||
|
||||
/* Write the updated enable mask */
|
||||
|
||||
status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, enable_mask,
|
||||
&gpe_register_info->enable_address);
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_hw_write_gpe_enable_reg
|
||||
@ -68,7 +116,7 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info *gpe_event_info)
|
||||
acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)
|
||||
{
|
||||
struct acpi_gpe_register_info *gpe_register_info;
|
||||
acpi_status status;
|
||||
@ -138,7 +186,6 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef ACPI_FUTURE_USAGE
|
||||
acpi_status
|
||||
acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
|
||||
acpi_event_status * event_status)
|
||||
@ -198,7 +245,6 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
|
||||
unlock_and_exit:
|
||||
return (status);
|
||||
}
|
||||
#endif /* ACPI_FUTURE_USAGE */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
|
@ -73,7 +73,7 @@ acpi_ns_dump_one_device(acpi_handle obj_handle,
|
||||
|
||||
void acpi_ns_print_pathname(u32 num_segments, char *pathname)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_NAME(ns_print_pathname);
|
||||
|
||||
@ -515,12 +515,12 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
|
||||
|
||||
if (obj_type > ACPI_TYPE_LOCAL_MAX) {
|
||||
acpi_os_printf
|
||||
("(Ptr to ACPI Object type %X [UNKNOWN])\n",
|
||||
("(Pointer to ACPI Object type %.2X [UNKNOWN])\n",
|
||||
obj_type);
|
||||
bytes_to_dump = 32;
|
||||
} else {
|
||||
acpi_os_printf
|
||||
("(Ptr to ACPI Object type %X [%s])\n",
|
||||
("(Pointer to ACPI Object type %.2X [%s])\n",
|
||||
obj_type, acpi_ut_get_type_name(obj_type));
|
||||
bytes_to_dump =
|
||||
sizeof(union acpi_operand_object);
|
||||
|
@ -138,6 +138,41 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
|
||||
return_ACPI_STATUS(AE_NULL_OBJECT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the number of arguments being passed to the method
|
||||
*/
|
||||
|
||||
info->param_count = 0;
|
||||
if (info->parameters) {
|
||||
while (info->parameters[info->param_count])
|
||||
info->param_count++;
|
||||
}
|
||||
|
||||
/* Error if too few arguments were passed in */
|
||||
|
||||
if (info->param_count < info->obj_desc->method.param_count) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Insufficient arguments - "
|
||||
"method [%4.4s] needs %d, found %d",
|
||||
acpi_ut_get_node_name(info->resolved_node),
|
||||
info->obj_desc->method.param_count,
|
||||
info->param_count));
|
||||
return_ACPI_STATUS(AE_MISSING_ARGUMENTS);
|
||||
}
|
||||
|
||||
/* Just a warning if too many arguments */
|
||||
|
||||
else if (info->param_count >
|
||||
info->obj_desc->method.param_count) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Excess arguments - "
|
||||
"method [%4.4s] needs %d, found %d",
|
||||
acpi_ut_get_node_name(info->
|
||||
resolved_node),
|
||||
info->obj_desc->method.param_count,
|
||||
info->param_count));
|
||||
}
|
||||
|
||||
ACPI_DUMP_PATHNAME(info->resolved_node, "Execute Method:",
|
||||
ACPI_LV_INFO, _COMPONENT);
|
||||
|
||||
|
@ -542,7 +542,6 @@ acpi_ns_init_one_device(acpi_handle obj_handle,
|
||||
info->prefix_node = device_node;
|
||||
info->pathname = METHOD_NAME__INI;
|
||||
info->parameters = NULL;
|
||||
info->parameter_type = ACPI_PARAM_ARGS;
|
||||
info->flags = ACPI_IGNORE_RETURN_VALUE;
|
||||
|
||||
/*
|
||||
|
@ -71,8 +71,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle);
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ns_load_table(acpi_native_uint table_index,
|
||||
struct acpi_namespace_node *node)
|
||||
acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
|
@ -63,13 +63,13 @@ ACPI_MODULE_NAME("nsparse")
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status
|
||||
acpi_ns_one_complete_parse(acpi_native_uint pass_number,
|
||||
acpi_native_uint table_index,
|
||||
struct acpi_namespace_node * start_node)
|
||||
acpi_ns_one_complete_parse(u32 pass_number,
|
||||
u32 table_index,
|
||||
struct acpi_namespace_node *start_node)
|
||||
{
|
||||
union acpi_parse_object *parse_root;
|
||||
acpi_status status;
|
||||
acpi_native_uint aml_length;
|
||||
u32 aml_length;
|
||||
u8 *aml_start;
|
||||
struct acpi_walk_state *walk_state;
|
||||
struct acpi_table_header *table;
|
||||
@ -112,8 +112,8 @@ acpi_ns_one_complete_parse(acpi_native_uint pass_number,
|
||||
aml_start = (u8 *) table + sizeof(struct acpi_table_header);
|
||||
aml_length = table->length - sizeof(struct acpi_table_header);
|
||||
status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL,
|
||||
aml_start, (u32) aml_length,
|
||||
NULL, (u8) pass_number);
|
||||
aml_start, aml_length, NULL,
|
||||
(u8) pass_number);
|
||||
}
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
@ -158,8 +158,7 @@ acpi_ns_one_complete_parse(acpi_native_uint pass_number,
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ns_parse_table(acpi_native_uint table_index,
|
||||
struct acpi_namespace_node *start_node)
|
||||
acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
|
@ -73,9 +73,9 @@ acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ns_report_error(char *module_name,
|
||||
acpi_ns_report_error(const char *module_name,
|
||||
u32 line_number,
|
||||
char *internal_name, acpi_status lookup_status)
|
||||
const char *internal_name, acpi_status lookup_status)
|
||||
{
|
||||
acpi_status status;
|
||||
u32 bad_name;
|
||||
@ -130,11 +130,11 @@ acpi_ns_report_error(char *module_name,
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ns_report_method_error(char *module_name,
|
||||
acpi_ns_report_method_error(const char *module_name,
|
||||
u32 line_number,
|
||||
char *message,
|
||||
const char *message,
|
||||
struct acpi_namespace_node *prefix_node,
|
||||
char *path, acpi_status method_status)
|
||||
const char *path, acpi_status method_status)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_namespace_node *node = prefix_node;
|
||||
@ -167,7 +167,8 @@ acpi_ns_report_method_error(char *module_name,
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ns_print_node_pathname(struct acpi_namespace_node *node, char *message)
|
||||
acpi_ns_print_node_pathname(struct acpi_namespace_node *node,
|
||||
const char *message)
|
||||
{
|
||||
struct acpi_buffer buffer;
|
||||
acpi_status status;
|
||||
@ -296,7 +297,7 @@ u32 acpi_ns_local(acpi_object_type type)
|
||||
|
||||
void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info)
|
||||
{
|
||||
char *next_external_char;
|
||||
const char *next_external_char;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
@ -363,9 +364,9 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
|
||||
{
|
||||
u32 num_segments = info->num_segments;
|
||||
char *internal_name = info->internal_name;
|
||||
char *external_name = info->next_external_char;
|
||||
const char *external_name = info->next_external_char;
|
||||
char *result = NULL;
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ns_build_internal_name);
|
||||
|
||||
@ -400,12 +401,11 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
|
||||
result = &internal_name[i];
|
||||
} else if (num_segments == 2) {
|
||||
internal_name[i] = AML_DUAL_NAME_PREFIX;
|
||||
result = &internal_name[(acpi_native_uint) (i + 1)];
|
||||
result = &internal_name[(acpi_size) i + 1];
|
||||
} else {
|
||||
internal_name[i] = AML_MULTI_NAME_PREFIX_OP;
|
||||
internal_name[(acpi_native_uint) (i + 1)] =
|
||||
(char)num_segments;
|
||||
result = &internal_name[(acpi_native_uint) (i + 2)];
|
||||
internal_name[(acpi_size) i + 1] = (char)num_segments;
|
||||
result = &internal_name[(acpi_size) i + 2];
|
||||
}
|
||||
}
|
||||
|
||||
@ -472,7 +472,8 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
acpi_status acpi_ns_internalize_name(char *external_name, char **converted_name)
|
||||
acpi_status
|
||||
acpi_ns_internalize_name(const char *external_name, char **converted_name)
|
||||
{
|
||||
char *internal_name;
|
||||
struct acpi_namestring_info info;
|
||||
@ -528,15 +529,15 @@ acpi_status acpi_ns_internalize_name(char *external_name, char **converted_name)
|
||||
|
||||
acpi_status
|
||||
acpi_ns_externalize_name(u32 internal_name_length,
|
||||
char *internal_name,
|
||||
const char *internal_name,
|
||||
u32 * converted_name_length, char **converted_name)
|
||||
{
|
||||
acpi_native_uint names_index = 0;
|
||||
acpi_native_uint num_segments = 0;
|
||||
acpi_native_uint required_length;
|
||||
acpi_native_uint prefix_length = 0;
|
||||
acpi_native_uint i = 0;
|
||||
acpi_native_uint j = 0;
|
||||
u32 names_index = 0;
|
||||
u32 num_segments = 0;
|
||||
u32 required_length;
|
||||
u32 prefix_length = 0;
|
||||
u32 i = 0;
|
||||
u32 j = 0;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ns_externalize_name);
|
||||
|
||||
@ -582,9 +583,8 @@ acpi_ns_externalize_name(u32 internal_name_length,
|
||||
/* <count> 4-byte names */
|
||||
|
||||
names_index = prefix_length + 2;
|
||||
num_segments = (acpi_native_uint) (u8)
|
||||
internal_name[(acpi_native_uint)
|
||||
(prefix_length + 1)];
|
||||
num_segments = (u8)
|
||||
internal_name[(acpi_size) prefix_length + 1];
|
||||
break;
|
||||
|
||||
case AML_DUAL_NAME_PREFIX:
|
||||
@ -823,7 +823,7 @@ u32 acpi_ns_opens_scope(acpi_object_type type)
|
||||
|
||||
acpi_status
|
||||
acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
|
||||
char *pathname,
|
||||
const char *pathname,
|
||||
u32 flags, struct acpi_namespace_node **return_node)
|
||||
{
|
||||
union acpi_generic_state scope_info;
|
||||
|
@ -182,7 +182,6 @@ acpi_evaluate_object(acpi_handle handle,
|
||||
}
|
||||
|
||||
info->pathname = pathname;
|
||||
info->parameter_type = ACPI_PARAM_ARGS;
|
||||
|
||||
/* Convert and validate the device handle */
|
||||
|
||||
@ -442,7 +441,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
|
||||
u32 flags;
|
||||
struct acpica_device_id hid;
|
||||
struct acpi_compatible_id_list *cid;
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
int found;
|
||||
|
||||
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
||||
|
@ -120,10 +120,10 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header)
|
||||
struct acpi_srat_mem_affinity *p =
|
||||
(struct acpi_srat_mem_affinity *)header;
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"SRAT Memory (0x%lx length 0x%lx type 0x%x) in proximity domain %d %s%s\n",
|
||||
"SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s\n",
|
||||
(unsigned long)p->base_address,
|
||||
(unsigned long)p->length,
|
||||
p->memory_type, p->proximity_domain,
|
||||
p->proximity_domain,
|
||||
(p->flags & ACPI_SRAT_MEM_ENABLED)?
|
||||
"enabled" : "disabled",
|
||||
(p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)?
|
||||
|
@ -76,7 +76,7 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state)
|
||||
{
|
||||
u8 *aml = parser_state->aml;
|
||||
u32 package_length = 0;
|
||||
acpi_native_uint byte_count;
|
||||
u32 byte_count;
|
||||
u8 byte_zero_mask = 0x3F; /* Default [0:5] */
|
||||
|
||||
ACPI_FUNCTION_TRACE(ps_get_next_package_length);
|
||||
@ -86,7 +86,7 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state)
|
||||
* used to encode the package length, either 0,1,2, or 3
|
||||
*/
|
||||
byte_count = (aml[0] >> 6);
|
||||
parser_state->aml += (byte_count + 1);
|
||||
parser_state->aml += ((acpi_size) byte_count + 1);
|
||||
|
||||
/* Get bytes 3, 2, 1 as needed */
|
||||
|
||||
|
@ -333,9 +333,9 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
|
||||
static void
|
||||
acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
|
||||
if ((info->parameter_type == ACPI_PARAM_ARGS) && (info->parameters)) {
|
||||
if (info->parameters) {
|
||||
|
||||
/* Update reference count for each parameter */
|
||||
|
||||
|
@ -162,7 +162,7 @@ do_prt_fixups(struct acpi_prt_entry *entry, struct acpi_pci_routing_table *prt)
|
||||
!strcmp(prt->source, quirk->source) &&
|
||||
strlen(prt->source) >= strlen(quirk->actual_source)) {
|
||||
printk(KERN_WARNING PREFIX "firmware reports "
|
||||
"%04x:%02x:%02x[%c] connected to %s; "
|
||||
"%04x:%02x:%02x PCI INT %c connected to %s; "
|
||||
"changing to %s\n",
|
||||
entry->id.segment, entry->id.bus,
|
||||
entry->id.device, 'A' + entry->pin,
|
||||
@ -429,7 +429,7 @@ acpi_pci_irq_derive(struct pci_dev *dev,
|
||||
{
|
||||
struct pci_dev *bridge = dev;
|
||||
int irq = -1;
|
||||
u8 bridge_pin = 0;
|
||||
u8 bridge_pin = 0, orig_pin = pin;
|
||||
|
||||
|
||||
if (!dev)
|
||||
@ -463,8 +463,8 @@ acpi_pci_irq_derive(struct pci_dev *dev,
|
||||
}
|
||||
|
||||
if (irq < 0) {
|
||||
printk(KERN_WARNING PREFIX "Unable to derive IRQ for device %s\n",
|
||||
pci_name(dev));
|
||||
dev_warn(&dev->dev, "can't derive routing for PCI INT %c\n",
|
||||
'A' + orig_pin);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -487,6 +487,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
|
||||
int triggering = ACPI_LEVEL_SENSITIVE;
|
||||
int polarity = ACPI_ACTIVE_LOW;
|
||||
char *link = NULL;
|
||||
char link_desc[16];
|
||||
int rc;
|
||||
|
||||
|
||||
@ -503,7 +504,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
|
||||
pin--;
|
||||
|
||||
if (!dev->bus) {
|
||||
printk(KERN_ERR PREFIX "Invalid (NULL) 'bus' field\n");
|
||||
dev_err(&dev->dev, "invalid (NULL) 'bus' field\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -538,8 +539,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
|
||||
* driver reported one, then use it. Exit in any case.
|
||||
*/
|
||||
if (irq < 0) {
|
||||
printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: no GSI",
|
||||
pci_name(dev), ('A' + pin));
|
||||
dev_warn(&dev->dev, "PCI INT %c: no GSI", 'A' + pin);
|
||||
/* Interrupt Line values above 0xF are forbidden */
|
||||
if (dev->irq > 0 && (dev->irq <= 0xF)) {
|
||||
printk(" - using IRQ %d\n", dev->irq);
|
||||
@ -554,21 +554,21 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
|
||||
|
||||
rc = acpi_register_gsi(irq, triggering, polarity);
|
||||
if (rc < 0) {
|
||||
printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: failed "
|
||||
"to register GSI\n", pci_name(dev), ('A' + pin));
|
||||
dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
|
||||
'A' + pin);
|
||||
return rc;
|
||||
}
|
||||
dev->irq = rc;
|
||||
|
||||
printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ",
|
||||
pci_name(dev), 'A' + pin);
|
||||
|
||||
if (link)
|
||||
printk("Link [%s] -> ", link);
|
||||
snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link);
|
||||
else
|
||||
link_desc[0] = '\0';
|
||||
|
||||
printk("GSI %u (%s, %s) -> IRQ %d\n", irq,
|
||||
(triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
|
||||
(polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
|
||||
dev_info(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n",
|
||||
'A' + pin, link_desc, irq,
|
||||
(triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
|
||||
(polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -616,10 +616,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
|
||||
* (e.g. PCI_UNDEFINED_IRQ).
|
||||
*/
|
||||
|
||||
printk(KERN_INFO PREFIX "PCI interrupt for device %s disabled\n",
|
||||
pci_name(dev));
|
||||
|
||||
dev_info(&dev->dev, "PCI INT %c disabled\n", 'A' + pin);
|
||||
acpi_unregister_gsi(gsi);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -118,8 +118,31 @@ static const struct file_operations acpi_processor_info_fops = {
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
struct acpi_processor *processors[NR_CPUS];
|
||||
DEFINE_PER_CPU(struct acpi_processor *, processors);
|
||||
struct acpi_processor_errata errata __read_mostly;
|
||||
static int set_no_mwait(const struct dmi_system_id *id)
|
||||
{
|
||||
printk(KERN_NOTICE PREFIX "%s detected - "
|
||||
"disable mwait for CPU C-stetes\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},
|
||||
{},
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Errata Handling
|
||||
@ -265,7 +288,20 @@ static int acpi_processor_set_pdc(struct acpi_processor *pr)
|
||||
|
||||
if (!pdc_in)
|
||||
return status;
|
||||
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(pr->handle, "_PDC", pdc_in, NULL);
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
@ -614,14 +650,14 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *processor_device_array[NR_CPUS];
|
||||
static DEFINE_PER_CPU(void *, processor_device_array);
|
||||
|
||||
static int __cpuinit acpi_processor_start(struct acpi_device *device)
|
||||
{
|
||||
int result = 0;
|
||||
acpi_status status = AE_OK;
|
||||
struct acpi_processor *pr;
|
||||
|
||||
struct sys_device *sysdev;
|
||||
|
||||
pr = acpi_driver_data(device);
|
||||
|
||||
@ -638,20 +674,24 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
|
||||
* ACPI id of processors can be reported wrongly by the BIOS.
|
||||
* Don't trust it blindly
|
||||
*/
|
||||
if (processor_device_array[pr->id] != NULL &&
|
||||
processor_device_array[pr->id] != device) {
|
||||
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");
|
||||
return -ENODEV;
|
||||
}
|
||||
processor_device_array[pr->id] = device;
|
||||
per_cpu(processor_device_array, pr->id) = device;
|
||||
|
||||
processors[pr->id] = pr;
|
||||
per_cpu(processors, pr->id) = pr;
|
||||
|
||||
result = acpi_processor_add_fs(device);
|
||||
if (result)
|
||||
goto end;
|
||||
|
||||
sysdev = get_cpu_sysdev(pr->id);
|
||||
if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev"))
|
||||
return -EFAULT;
|
||||
|
||||
status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
|
||||
acpi_processor_notify, pr);
|
||||
|
||||
@ -749,7 +789,7 @@ 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 = processors[cpu];
|
||||
struct acpi_processor *pr = per_cpu(processors, cpu);
|
||||
|
||||
if (action == CPU_ONLINE && pr) {
|
||||
acpi_processor_ppc_has_changed(pr);
|
||||
@ -810,6 +850,8 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
|
||||
status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
|
||||
acpi_processor_notify);
|
||||
|
||||
sysfs_remove_link(&device->dev.kobj, "sysdev");
|
||||
|
||||
acpi_processor_remove_fs(device);
|
||||
|
||||
if (pr->cdev) {
|
||||
@ -819,8 +861,8 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
|
||||
pr->cdev = NULL;
|
||||
}
|
||||
|
||||
processors[pr->id] = NULL;
|
||||
processor_device_array[pr->id] = NULL;
|
||||
per_cpu(processors, pr->id) = NULL;
|
||||
per_cpu(processor_device_array, pr->id) = NULL;
|
||||
kfree(pr);
|
||||
|
||||
return 0;
|
||||
@ -1014,9 +1056,9 @@ static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
|
||||
|
||||
static int acpi_processor_handle_eject(struct acpi_processor *pr)
|
||||
{
|
||||
if (cpu_online(pr->id)) {
|
||||
return (-EINVAL);
|
||||
}
|
||||
if (cpu_online(pr->id))
|
||||
cpu_down(pr->id);
|
||||
|
||||
arch_unregister_cpu(pr->id);
|
||||
acpi_unmap_lsapic(pr->id);
|
||||
return (0);
|
||||
@ -1068,8 +1110,6 @@ static int __init acpi_processor_init(void)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
|
||||
memset(&processors, 0, sizeof(processors));
|
||||
memset(&errata, 0, sizeof(errata));
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
@ -1083,6 +1123,11 @@ static int __init acpi_processor_init(void)
|
||||
return -ENOMEM;
|
||||
acpi_processor_dir->owner = THIS_MODULE;
|
||||
|
||||
/*
|
||||
* Check whether the system is DMI table. If yes, OSPM
|
||||
* should not use mwait for CPU-states.
|
||||
*/
|
||||
dmi_check_system(processor_idle_dmi_table);
|
||||
result = cpuidle_register_driver(&acpi_idle_driver);
|
||||
if (result < 0)
|
||||
goto out_proc;
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <linux/pm_qos_params.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/cpuidle.h>
|
||||
#include <linux/cpuidle.h>
|
||||
|
||||
/*
|
||||
* Include the apic definitions for x86 to have the APIC timer related defines
|
||||
@ -57,6 +58,7 @@
|
||||
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/processor.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#define ACPI_PROCESSOR_COMPONENT 0x01000000
|
||||
#define ACPI_PROCESSOR_CLASS "processor"
|
||||
@ -401,7 +403,7 @@ static void acpi_processor_idle(void)
|
||||
*/
|
||||
local_irq_disable();
|
||||
|
||||
pr = processors[smp_processor_id()];
|
||||
pr = __get_cpu_var(processors);
|
||||
if (!pr) {
|
||||
local_irq_enable();
|
||||
return;
|
||||
@ -955,6 +957,21 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
if (cx.type == ACPI_STATE_C1 &&
|
||||
(idle_halt || idle_nomwait)) {
|
||||
/*
|
||||
* In most cases the C1 space_id obtained from
|
||||
* _CST object is FIXED_HARDWARE access mode.
|
||||
* But when the option of idle=halt is added,
|
||||
* the entry_method type should be changed from
|
||||
* CSTATE_FFH to CSTATE_HALT.
|
||||
* When the option of idle=nomwait is added,
|
||||
* the C1 entry_method type should be
|
||||
* CSTATE_HALT.
|
||||
*/
|
||||
cx.entry_method = ACPI_CSTATE_HALT;
|
||||
snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT");
|
||||
}
|
||||
} else {
|
||||
snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI IOPORT 0x%x",
|
||||
cx.address);
|
||||
@ -1431,7 +1448,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
|
||||
struct acpi_processor *pr;
|
||||
struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
|
||||
|
||||
pr = processors[smp_processor_id()];
|
||||
pr = __get_cpu_var(processors);
|
||||
|
||||
if (unlikely(!pr))
|
||||
return 0;
|
||||
@ -1471,7 +1488,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
|
||||
u32 t1, t2;
|
||||
int sleep_ticks = 0;
|
||||
|
||||
pr = processors[smp_processor_id()];
|
||||
pr = __get_cpu_var(processors);
|
||||
|
||||
if (unlikely(!pr))
|
||||
return 0;
|
||||
@ -1549,7 +1566,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
|
||||
u32 t1, t2;
|
||||
int sleep_ticks = 0;
|
||||
|
||||
pr = processors[smp_processor_id()];
|
||||
pr = __get_cpu_var(processors);
|
||||
|
||||
if (unlikely(!pr))
|
||||
return 0;
|
||||
@ -1780,6 +1797,15 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
|
||||
return 0;
|
||||
|
||||
if (!first_run) {
|
||||
if (idle_halt) {
|
||||
/*
|
||||
* When the boot option of "idle=halt" is added, halt
|
||||
* is used for CPU IDLE.
|
||||
* In such case C2/C3 is meaningless. So the max_cstate
|
||||
* is set to one.
|
||||
*/
|
||||
max_cstate = 1;
|
||||
}
|
||||
dmi_check_system(processor_power_dmi_table);
|
||||
max_cstate = acpi_processor_cstate_check(max_cstate);
|
||||
if (max_cstate < ACPI_C_STATES_MAX)
|
||||
|
@ -89,7 +89,7 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb,
|
||||
if (event != CPUFREQ_INCOMPATIBLE)
|
||||
goto out;
|
||||
|
||||
pr = processors[policy->cpu];
|
||||
pr = per_cpu(processors, policy->cpu);
|
||||
if (!pr || !pr->performance)
|
||||
goto out;
|
||||
|
||||
@ -572,7 +572,7 @@ int acpi_processor_preregister_performance(
|
||||
|
||||
/* Call _PSD for all CPUs */
|
||||
for_each_possible_cpu(i) {
|
||||
pr = processors[i];
|
||||
pr = per_cpu(processors, i);
|
||||
if (!pr) {
|
||||
/* Look only at processors in ACPI namespace */
|
||||
continue;
|
||||
@ -603,7 +603,7 @@ int acpi_processor_preregister_performance(
|
||||
* domain info.
|
||||
*/
|
||||
for_each_possible_cpu(i) {
|
||||
pr = processors[i];
|
||||
pr = per_cpu(processors, i);
|
||||
if (!pr)
|
||||
continue;
|
||||
|
||||
@ -624,7 +624,7 @@ int acpi_processor_preregister_performance(
|
||||
|
||||
cpus_clear(covered_cpus);
|
||||
for_each_possible_cpu(i) {
|
||||
pr = processors[i];
|
||||
pr = per_cpu(processors, i);
|
||||
if (!pr)
|
||||
continue;
|
||||
|
||||
@ -651,7 +651,7 @@ int acpi_processor_preregister_performance(
|
||||
if (i == j)
|
||||
continue;
|
||||
|
||||
match_pr = processors[j];
|
||||
match_pr = per_cpu(processors, j);
|
||||
if (!match_pr)
|
||||
continue;
|
||||
|
||||
@ -680,7 +680,7 @@ int acpi_processor_preregister_performance(
|
||||
if (i == j)
|
||||
continue;
|
||||
|
||||
match_pr = processors[j];
|
||||
match_pr = per_cpu(processors, j);
|
||||
if (!match_pr)
|
||||
continue;
|
||||
|
||||
@ -697,7 +697,7 @@ int acpi_processor_preregister_performance(
|
||||
|
||||
err_ret:
|
||||
for_each_possible_cpu(i) {
|
||||
pr = processors[i];
|
||||
pr = per_cpu(processors, i);
|
||||
if (!pr || !pr->performance)
|
||||
continue;
|
||||
|
||||
@ -728,7 +728,7 @@ acpi_processor_register_performance(struct acpi_processor_performance
|
||||
|
||||
mutex_lock(&performance_mutex);
|
||||
|
||||
pr = processors[cpu];
|
||||
pr = per_cpu(processors, cpu);
|
||||
if (!pr) {
|
||||
mutex_unlock(&performance_mutex);
|
||||
return -ENODEV;
|
||||
@ -766,7 +766,7 @@ acpi_processor_unregister_performance(struct acpi_processor_performance
|
||||
|
||||
mutex_lock(&performance_mutex);
|
||||
|
||||
pr = processors[cpu];
|
||||
pr = per_cpu(processors, cpu);
|
||||
if (!pr) {
|
||||
mutex_unlock(&performance_mutex);
|
||||
return;
|
||||
|
@ -71,7 +71,7 @@ static int acpi_processor_update_tsd_coord(void)
|
||||
* coordination between all CPUs.
|
||||
*/
|
||||
for_each_possible_cpu(i) {
|
||||
pr = processors[i];
|
||||
pr = per_cpu(processors, i);
|
||||
if (!pr)
|
||||
continue;
|
||||
|
||||
@ -93,7 +93,7 @@ static int acpi_processor_update_tsd_coord(void)
|
||||
|
||||
cpus_clear(covered_cpus);
|
||||
for_each_possible_cpu(i) {
|
||||
pr = processors[i];
|
||||
pr = per_cpu(processors, i);
|
||||
if (!pr)
|
||||
continue;
|
||||
|
||||
@ -119,7 +119,7 @@ static int acpi_processor_update_tsd_coord(void)
|
||||
if (i == j)
|
||||
continue;
|
||||
|
||||
match_pr = processors[j];
|
||||
match_pr = per_cpu(processors, j);
|
||||
if (!match_pr)
|
||||
continue;
|
||||
|
||||
@ -152,7 +152,7 @@ static int acpi_processor_update_tsd_coord(void)
|
||||
if (i == j)
|
||||
continue;
|
||||
|
||||
match_pr = processors[j];
|
||||
match_pr = per_cpu(processors, j);
|
||||
if (!match_pr)
|
||||
continue;
|
||||
|
||||
@ -172,7 +172,7 @@ static int acpi_processor_update_tsd_coord(void)
|
||||
|
||||
err_ret:
|
||||
for_each_possible_cpu(i) {
|
||||
pr = processors[i];
|
||||
pr = per_cpu(processors, i);
|
||||
if (!pr)
|
||||
continue;
|
||||
|
||||
@ -214,7 +214,7 @@ static int acpi_processor_throttling_notifier(unsigned long event, void *data)
|
||||
struct acpi_processor_throttling *p_throttling;
|
||||
|
||||
cpu = p_tstate->cpu;
|
||||
pr = processors[cpu];
|
||||
pr = per_cpu(processors, cpu);
|
||||
if (!pr) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid pr pointer\n"));
|
||||
return 0;
|
||||
@ -1035,7 +1035,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
|
||||
* cpus.
|
||||
*/
|
||||
for_each_cpu_mask(i, online_throttling_cpus) {
|
||||
match_pr = processors[i];
|
||||
match_pr = per_cpu(processors, i);
|
||||
/*
|
||||
* If the pointer is invalid, we will report the
|
||||
* error message and continue.
|
||||
@ -1232,7 +1232,10 @@ static ssize_t acpi_processor_write_throttling(struct file *file,
|
||||
int result = 0;
|
||||
struct seq_file *m = file->private_data;
|
||||
struct acpi_processor *pr = m->private;
|
||||
char state_string[12] = { '\0' };
|
||||
char state_string[5] = "";
|
||||
char *charp = NULL;
|
||||
size_t state_val = 0;
|
||||
char tmpbuf[5] = "";
|
||||
|
||||
if (!pr || (count > sizeof(state_string) - 1))
|
||||
return -EINVAL;
|
||||
@ -1241,10 +1244,23 @@ static ssize_t acpi_processor_write_throttling(struct file *file,
|
||||
return -EFAULT;
|
||||
|
||||
state_string[count] = '\0';
|
||||
if ((count > 0) && (state_string[count-1] == '\n'))
|
||||
state_string[count-1] = '\0';
|
||||
|
||||
result = acpi_processor_set_throttling(pr,
|
||||
simple_strtoul(state_string,
|
||||
NULL, 0));
|
||||
charp = state_string;
|
||||
if ((state_string[0] == 't') || (state_string[0] == 'T'))
|
||||
charp++;
|
||||
|
||||
state_val = simple_strtoul(charp, NULL, 0);
|
||||
if (state_val >= pr->throttling.state_count)
|
||||
return -EINVAL;
|
||||
|
||||
snprintf(tmpbuf, 5, "%zu", state_val);
|
||||
|
||||
if (strcmp(tmpbuf, charp) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
result = acpi_processor_set_throttling(pr, state_val);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
|
50
drivers/acpi/reboot.c
Normal file
50
drivers/acpi/reboot.c
Normal file
@ -0,0 +1,50 @@
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <acpi/reboot.h>
|
||||
|
||||
void acpi_reboot(void)
|
||||
{
|
||||
struct acpi_generic_address *rr;
|
||||
struct pci_bus *bus0;
|
||||
u8 reset_value;
|
||||
unsigned int devfn;
|
||||
|
||||
if (acpi_disabled)
|
||||
return;
|
||||
|
||||
rr = &acpi_gbl_FADT.reset_register;
|
||||
|
||||
/* Is the reset register supported? */
|
||||
if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) ||
|
||||
rr->bit_width != 8 || rr->bit_offset != 0)
|
||||
return;
|
||||
|
||||
reset_value = acpi_gbl_FADT.reset_value;
|
||||
|
||||
/* The reset register can only exist in I/O, Memory or PCI config space
|
||||
* on a device on bus 0. */
|
||||
switch (rr->space_id) {
|
||||
case ACPI_ADR_SPACE_PCI_CONFIG:
|
||||
/* The reset register can only live on bus 0. */
|
||||
bus0 = pci_find_bus(0, 0);
|
||||
if (!bus0)
|
||||
return;
|
||||
/* Form PCI device/function pair. */
|
||||
devfn = PCI_DEVFN((rr->address >> 32) & 0xffff,
|
||||
(rr->address >> 16) & 0xffff);
|
||||
printk(KERN_DEBUG "Resetting with ACPI PCI RESET_REG.");
|
||||
/* Write the value that resets us. */
|
||||
pci_bus_write_config_byte(bus0, devfn,
|
||||
(rr->address & 0xffff), reset_value);
|
||||
break;
|
||||
|
||||
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
|
||||
case ACPI_ADR_SPACE_SYSTEM_IO:
|
||||
printk(KERN_DEBUG "ACPI MEMORY or I/O RESET_REG.\n");
|
||||
acpi_hw_low_level_write(8, reset_value, rr);
|
||||
break;
|
||||
}
|
||||
/* Wait ten seconds */
|
||||
acpi_os_stall(10000000);
|
||||
}
|
@ -73,7 +73,7 @@ acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length);
|
||||
|
||||
static u8 acpi_rs_count_set_bits(u16 bit_field)
|
||||
{
|
||||
acpi_native_uint bits_set;
|
||||
u8 bits_set;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
@ -84,7 +84,7 @@ static u8 acpi_rs_count_set_bits(u16 bit_field)
|
||||
bit_field &= (u16) (bit_field - 1);
|
||||
}
|
||||
|
||||
return ((u8) bits_set);
|
||||
return bits_set;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -181,9 +181,9 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop through the ACPI_INTERNAL_OBJECTS - Each object
|
||||
* should be a package that in turn contains an
|
||||
* acpi_integer Address, a u8 Pin, a Name and a u8 source_index.
|
||||
* Loop through the ACPI_INTERNAL_OBJECTS - Each object should be a
|
||||
* package that in turn contains an acpi_integer Address, a u8 Pin,
|
||||
* a Name, and a u8 source_index.
|
||||
*/
|
||||
top_object_list = package_object->package.elements;
|
||||
number_of_elements = package_object->package.count;
|
||||
@ -240,9 +240,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
|
||||
/* 1) First subobject: Dereference the PRT.Address */
|
||||
|
||||
obj_desc = sub_object_list[0];
|
||||
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
|
||||
user_prt->address = obj_desc->integer.value;
|
||||
} else {
|
||||
if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"(PRT[%X].Address) Need Integer, found %s",
|
||||
index,
|
||||
@ -250,12 +248,12 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
|
||||
return_ACPI_STATUS(AE_BAD_DATA);
|
||||
}
|
||||
|
||||
user_prt->address = obj_desc->integer.value;
|
||||
|
||||
/* 2) Second subobject: Dereference the PRT.Pin */
|
||||
|
||||
obj_desc = sub_object_list[1];
|
||||
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
|
||||
user_prt->pin = (u32) obj_desc->integer.value;
|
||||
} else {
|
||||
if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"(PRT[%X].Pin) Need Integer, found %s",
|
||||
index,
|
||||
@ -284,6 +282,25 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
|
||||
}
|
||||
}
|
||||
|
||||
user_prt->pin = (u32) obj_desc->integer.value;
|
||||
|
||||
/*
|
||||
* If the BIOS has erroneously reversed the _PRT source_name (index 2)
|
||||
* and the source_index (index 3), fix it. _PRT is important enough to
|
||||
* workaround this BIOS error. This also provides compatibility with
|
||||
* other ACPI implementations.
|
||||
*/
|
||||
obj_desc = sub_object_list[3];
|
||||
if (!obj_desc
|
||||
|| (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) {
|
||||
sub_object_list[3] = sub_object_list[2];
|
||||
sub_object_list[2] = obj_desc;
|
||||
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"(PRT[%X].Source) SourceName and SourceIndex are reversed, fixed",
|
||||
index));
|
||||
}
|
||||
|
||||
/*
|
||||
* 3) Third subobject: Dereference the PRT.source_name
|
||||
* The name may be unresolved (slack mode), so allow a null object
|
||||
@ -364,9 +381,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
|
||||
/* 4) Fourth subobject: Dereference the PRT.source_index */
|
||||
|
||||
obj_desc = sub_object_list[source_index_index];
|
||||
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
|
||||
user_prt->source_index = (u32) obj_desc->integer.value;
|
||||
} else {
|
||||
if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"(PRT[%X].SourceIndex) Need Integer, found %s",
|
||||
index,
|
||||
@ -374,6 +389,8 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
|
||||
return_ACPI_STATUS(AE_BAD_DATA);
|
||||
}
|
||||
|
||||
user_prt->source_index = (u32) obj_desc->integer.value;
|
||||
|
||||
/* Point to the next union acpi_operand_object in the top level package */
|
||||
|
||||
top_object_list++;
|
||||
|
@ -82,7 +82,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
|
||||
|
||||
ACPI_FUNCTION_TRACE(rs_convert_aml_to_resource);
|
||||
|
||||
if (((acpi_native_uint) resource) & 0x3) {
|
||||
if (((acpi_size) resource) & 0x3) {
|
||||
|
||||
/* Each internal resource struct is expected to be 32-bit aligned */
|
||||
|
||||
|
@ -62,7 +62,7 @@ ACPI_MODULE_NAME("rsutils")
|
||||
******************************************************************************/
|
||||
u8 acpi_rs_decode_bitmask(u16 mask, u8 * list)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
u8 i;
|
||||
u8 bit_count;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
@ -71,7 +71,7 @@ u8 acpi_rs_decode_bitmask(u16 mask, u8 * list)
|
||||
|
||||
for (i = 0, bit_count = 0; mask; i++) {
|
||||
if (mask & 0x0001) {
|
||||
list[bit_count] = (u8) i;
|
||||
list[bit_count] = i;
|
||||
bit_count++;
|
||||
}
|
||||
|
||||
@ -96,8 +96,8 @@ u8 acpi_rs_decode_bitmask(u16 mask, u8 * list)
|
||||
|
||||
u16 acpi_rs_encode_bitmask(u8 * list, u8 count)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
acpi_native_uint mask;
|
||||
u32 i;
|
||||
u16 mask;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
@ -107,7 +107,7 @@ u16 acpi_rs_encode_bitmask(u8 * list, u8 count)
|
||||
mask |= (0x1 << list[i]);
|
||||
}
|
||||
|
||||
return ((u16) mask);
|
||||
return mask;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@ -130,7 +130,7 @@ u16 acpi_rs_encode_bitmask(u8 * list, u8 count)
|
||||
void
|
||||
acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
@ -679,7 +679,6 @@ acpi_rs_set_srs_method_data(struct acpi_namespace_node *node,
|
||||
info->prefix_node = node;
|
||||
info->pathname = METHOD_NAME__SRS;
|
||||
info->parameters = args;
|
||||
info->parameter_type = ACPI_PARAM_ARGS;
|
||||
info->flags = ACPI_IGNORE_RETURN_VALUE;
|
||||
|
||||
/*
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/kthread.h>
|
||||
|
||||
#include <acpi/acpi_drivers.h>
|
||||
#include <acpi/acinterp.h> /* for acpi_ex_eisa_id_to_string() */
|
||||
@ -92,17 +94,37 @@ 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_eject_operation(acpi_handle handle, int lockable)
|
||||
static int acpi_bus_hot_remove_device(void *context)
|
||||
{
|
||||
struct acpi_device *device;
|
||||
acpi_handle handle = context;
|
||||
struct acpi_object_list arg_list;
|
||||
union acpi_object arg;
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
/*
|
||||
* TBD: evaluate _PS3?
|
||||
*/
|
||||
if (acpi_bus_get_device(handle, &device))
|
||||
return 0;
|
||||
|
||||
if (lockable) {
|
||||
if (!device)
|
||||
return 0;
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Hot-removing device %s...\n", device->dev.bus_id));
|
||||
|
||||
|
||||
if (acpi_bus_trim(device, 1)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
||||
"Removing device failed\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* power off device */
|
||||
status = acpi_evaluate_object(handle, "_PS3", NULL, NULL);
|
||||
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
|
||||
"Power-off device failed\n"));
|
||||
|
||||
if (device->flags.lockable) {
|
||||
arg_list.count = 1;
|
||||
arg_list.pointer = &arg;
|
||||
arg.type = ACPI_TYPE_INTEGER;
|
||||
@ -118,26 +140,22 @@ static int acpi_eject_operation(acpi_handle handle, int lockable)
|
||||
/*
|
||||
* TBD: _EJD support.
|
||||
*/
|
||||
|
||||
status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (-ENODEV);
|
||||
}
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
acpi_eject_store(struct device *d, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int result;
|
||||
int ret = count;
|
||||
int islockable;
|
||||
acpi_status status;
|
||||
acpi_handle handle;
|
||||
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;
|
||||
@ -154,18 +172,12 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
|
||||
goto err;
|
||||
}
|
||||
|
||||
islockable = acpi_device->flags.lockable;
|
||||
handle = acpi_device->handle;
|
||||
|
||||
result = acpi_bus_trim(acpi_device, 1);
|
||||
|
||||
if (!result)
|
||||
result = acpi_eject_operation(handle, islockable);
|
||||
|
||||
if (result) {
|
||||
ret = -EBUSY;
|
||||
}
|
||||
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);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -61,8 +61,6 @@ static u32 acpi_suspend_states[] = {
|
||||
[PM_SUSPEND_MAX] = ACPI_STATE_S5
|
||||
};
|
||||
|
||||
static int init_8259A_after_S1;
|
||||
|
||||
/**
|
||||
* acpi_suspend_begin - Set the target system sleep state to the state
|
||||
* associated with given @pm_state, if supported.
|
||||
@ -185,13 +183,6 @@ static void acpi_suspend_finish(void)
|
||||
acpi_set_firmware_waking_vector((acpi_physical_address) 0);
|
||||
|
||||
acpi_target_sleep_state = ACPI_STATE_S0;
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
if (init_8259A_after_S1) {
|
||||
printk("Broken toshiba laptop -> kicking interrupts\n");
|
||||
init_8259A(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -231,26 +222,6 @@ static struct platform_suspend_ops acpi_suspend_ops = {
|
||||
.finish = acpi_suspend_finish,
|
||||
.end = acpi_suspend_end,
|
||||
};
|
||||
|
||||
/*
|
||||
* Toshiba fails to preserve interrupts over S1, reinitialization
|
||||
* of 8259 is needed after S1 resume.
|
||||
*/
|
||||
static int __init init_ints_after_s1(const struct dmi_system_id *d)
|
||||
{
|
||||
printk(KERN_WARNING "%s with broken S1 detected.\n", d->ident);
|
||||
init_8259A_after_S1 = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
|
||||
{
|
||||
.callback = init_ints_after_s1,
|
||||
.ident = "Toshiba Satellite 4030cdt",
|
||||
.matches = {DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),},
|
||||
},
|
||||
{},
|
||||
};
|
||||
#endif /* CONFIG_SUSPEND */
|
||||
|
||||
#ifdef CONFIG_HIBERNATION
|
||||
@ -368,8 +339,8 @@ int acpi_suspend(u32 acpi_state)
|
||||
/**
|
||||
* acpi_pm_device_sleep_state - return preferred power state of ACPI device
|
||||
* in the system sleep state given by %acpi_target_sleep_state
|
||||
* @dev: device to examine
|
||||
* @wake: if set, the device should be able to wake up the system
|
||||
* @dev: device to examine; its driver model wakeup flags control
|
||||
* whether it should be able to wake up the system
|
||||
* @d_min_p: used to store the upper limit of allowed states range
|
||||
* Return value: preferred power state of the device on success, -ENODEV on
|
||||
* failure (ie. if there's no 'struct acpi_device' for @dev)
|
||||
@ -387,7 +358,7 @@ int acpi_suspend(u32 acpi_state)
|
||||
* via @wake.
|
||||
*/
|
||||
|
||||
int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p)
|
||||
int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
|
||||
{
|
||||
acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
|
||||
struct acpi_device *adev;
|
||||
@ -426,7 +397,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p)
|
||||
* can wake the system. _S0W may be valid, too.
|
||||
*/
|
||||
if (acpi_target_sleep_state == ACPI_STATE_S0 ||
|
||||
(wake && adev->wakeup.state.enabled &&
|
||||
(device_may_wakeup(dev) && adev->wakeup.state.enabled &&
|
||||
adev->wakeup.sleep_state <= acpi_target_sleep_state)) {
|
||||
acpi_status status;
|
||||
|
||||
@ -472,8 +443,6 @@ int __init acpi_sleep_init(void)
|
||||
u8 type_a, type_b;
|
||||
#ifdef CONFIG_SUSPEND
|
||||
int i = 0;
|
||||
|
||||
dmi_check_system(acpisleep_dmi_table);
|
||||
#endif
|
||||
|
||||
if (acpi_disabled)
|
||||
|
@ -167,7 +167,13 @@ static int acpi_system_sysfs_init(void)
|
||||
#define COUNT_ERROR 2 /* other */
|
||||
#define NUM_COUNTERS_EXTRA 3
|
||||
|
||||
static u32 *all_counters;
|
||||
#define ACPI_EVENT_VALID 0x01
|
||||
struct event_counter {
|
||||
u32 count;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
static struct event_counter *all_counters;
|
||||
static u32 num_gpes;
|
||||
static u32 num_counters;
|
||||
static struct attribute **all_attrs;
|
||||
@ -202,9 +208,44 @@ static int count_num_gpes(void)
|
||||
return count;
|
||||
}
|
||||
|
||||
static int get_gpe_device(int index, acpi_handle *handle)
|
||||
{
|
||||
struct acpi_gpe_xrupt_info *gpe_xrupt_info;
|
||||
struct acpi_gpe_block_info *gpe_block;
|
||||
acpi_cpu_flags flags;
|
||||
struct acpi_namespace_node *node;
|
||||
|
||||
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
|
||||
|
||||
gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
|
||||
while (gpe_xrupt_info) {
|
||||
gpe_block = gpe_xrupt_info->gpe_block_list_head;
|
||||
node = gpe_block->node;
|
||||
while (gpe_block) {
|
||||
index -= gpe_block->register_count *
|
||||
ACPI_GPE_REGISTER_WIDTH;
|
||||
if (index < 0) {
|
||||
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
|
||||
/* return NULL if it's FADT GPE */
|
||||
if (node->type != ACPI_TYPE_DEVICE)
|
||||
*handle = NULL;
|
||||
else
|
||||
*handle = node;
|
||||
return 0;
|
||||
}
|
||||
node = gpe_block->node;
|
||||
gpe_block = gpe_block->next;
|
||||
}
|
||||
gpe_xrupt_info = gpe_xrupt_info->next;
|
||||
}
|
||||
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void delete_gpe_attr_array(void)
|
||||
{
|
||||
u32 *tmp = all_counters;
|
||||
struct event_counter *tmp = all_counters;
|
||||
|
||||
all_counters = NULL;
|
||||
kfree(tmp);
|
||||
@ -230,9 +271,10 @@ void acpi_os_gpe_count(u32 gpe_number)
|
||||
return;
|
||||
|
||||
if (gpe_number < num_gpes)
|
||||
all_counters[gpe_number]++;
|
||||
all_counters[gpe_number].count++;
|
||||
else
|
||||
all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR]++;
|
||||
all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR].
|
||||
count++;
|
||||
|
||||
return;
|
||||
}
|
||||
@ -243,44 +285,144 @@ void acpi_os_fixed_event_count(u32 event_number)
|
||||
return;
|
||||
|
||||
if (event_number < ACPI_NUM_FIXED_EVENTS)
|
||||
all_counters[num_gpes + event_number]++;
|
||||
all_counters[num_gpes + event_number].count++;
|
||||
else
|
||||
all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR]++;
|
||||
all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR].
|
||||
count++;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int get_status(u32 index, acpi_event_status *status, acpi_handle *handle)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS)
|
||||
goto end;
|
||||
|
||||
if (index < num_gpes) {
|
||||
result = get_gpe_device(index, handle);
|
||||
if (result) {
|
||||
ACPI_EXCEPTION((AE_INFO, AE_NOT_FOUND,
|
||||
"Invalid GPE 0x%x\n", index));
|
||||
goto end;
|
||||
}
|
||||
result = acpi_get_gpe_status(*handle, index,
|
||||
ACPI_NOT_ISR, status);
|
||||
} else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS))
|
||||
result = acpi_get_event_status(index - num_gpes, status);
|
||||
|
||||
/*
|
||||
* sleep/power button GPE/Fixed Event is enabled after acpi_system_init,
|
||||
* check the status at runtime and mark it as valid once it's enabled
|
||||
*/
|
||||
if (!result && (*status & ACPI_EVENT_FLAG_ENABLED))
|
||||
all_counters[index].flags |= ACPI_EVENT_VALID;
|
||||
end:
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t counter_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI] =
|
||||
int index = attr - counter_attrs;
|
||||
int size;
|
||||
acpi_handle handle;
|
||||
acpi_event_status status;
|
||||
int result = 0;
|
||||
|
||||
all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI].count =
|
||||
acpi_irq_handled;
|
||||
all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE] =
|
||||
all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE].count =
|
||||
acpi_gpe_count;
|
||||
|
||||
return sprintf(buf, "%d\n", all_counters[attr - counter_attrs]);
|
||||
size = sprintf(buf, "%8d", all_counters[index].count);
|
||||
|
||||
/* "gpe_all" or "sci" */
|
||||
if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS)
|
||||
goto end;
|
||||
|
||||
result = get_status(index, &status, &handle);
|
||||
if (result)
|
||||
goto end;
|
||||
|
||||
if (!(all_counters[index].flags & ACPI_EVENT_VALID))
|
||||
size += sprintf(buf + size, " invalid");
|
||||
else if (status & ACPI_EVENT_FLAG_ENABLED)
|
||||
size += sprintf(buf + size, " enable");
|
||||
else
|
||||
size += sprintf(buf + size, " disable");
|
||||
|
||||
end:
|
||||
size += sprintf(buf + size, "\n");
|
||||
return result ? result : size;
|
||||
}
|
||||
|
||||
/*
|
||||
* counter_set() sets the specified counter.
|
||||
* setting the total "sci" file to any value clears all counters.
|
||||
* enable/disable/clear a gpe/fixed event in user space.
|
||||
*/
|
||||
static ssize_t counter_set(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
int index = attr - counter_attrs;
|
||||
acpi_event_status status;
|
||||
acpi_handle handle;
|
||||
int result = 0;
|
||||
|
||||
if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) {
|
||||
int i;
|
||||
for (i = 0; i < num_counters; ++i)
|
||||
all_counters[i] = 0;
|
||||
all_counters[i].count = 0;
|
||||
acpi_gpe_count = 0;
|
||||
acpi_irq_handled = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* show the event status for both GPEs and Fixed Events */
|
||||
result = get_status(index, &status, &handle);
|
||||
if (result)
|
||||
goto end;
|
||||
|
||||
if (!(all_counters[index].flags & ACPI_EVENT_VALID)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
|
||||
"Can not change Invalid GPE/Fixed Event status\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (index < num_gpes) {
|
||||
if (!strcmp(buf, "disable\n") &&
|
||||
(status & ACPI_EVENT_FLAG_ENABLED))
|
||||
result = acpi_disable_gpe(handle, index, ACPI_NOT_ISR);
|
||||
else if (!strcmp(buf, "enable\n") &&
|
||||
!(status & ACPI_EVENT_FLAG_ENABLED))
|
||||
result = acpi_enable_gpe(handle, index, ACPI_NOT_ISR);
|
||||
else if (!strcmp(buf, "clear\n") &&
|
||||
(status & ACPI_EVENT_FLAG_SET))
|
||||
result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR);
|
||||
else
|
||||
all_counters[index].count = strtoul(buf, NULL, 0);
|
||||
} else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) {
|
||||
int event = index - num_gpes;
|
||||
if (!strcmp(buf, "disable\n") &&
|
||||
(status & ACPI_EVENT_FLAG_ENABLED))
|
||||
result = acpi_disable_event(event, ACPI_NOT_ISR);
|
||||
else if (!strcmp(buf, "enable\n") &&
|
||||
!(status & ACPI_EVENT_FLAG_ENABLED))
|
||||
result = acpi_enable_event(event, ACPI_NOT_ISR);
|
||||
else if (!strcmp(buf, "clear\n") &&
|
||||
(status & ACPI_EVENT_FLAG_SET))
|
||||
result = acpi_clear_event(event);
|
||||
else
|
||||
all_counters[index].count = strtoul(buf, NULL, 0);
|
||||
} else
|
||||
all_counters[index] = strtoul(buf, NULL, 0);
|
||||
all_counters[index].count = strtoul(buf, NULL, 0);
|
||||
|
||||
return size;
|
||||
if (ACPI_FAILURE(result))
|
||||
result = -EINVAL;
|
||||
end:
|
||||
return result ? result : size;
|
||||
}
|
||||
|
||||
void acpi_irq_stats_init(void)
|
||||
@ -298,7 +440,8 @@ void acpi_irq_stats_init(void)
|
||||
if (all_attrs == NULL)
|
||||
return;
|
||||
|
||||
all_counters = kzalloc(sizeof(u32) * (num_counters), GFP_KERNEL);
|
||||
all_counters = kzalloc(sizeof(struct event_counter) * (num_counters),
|
||||
GFP_KERNEL);
|
||||
if (all_counters == NULL)
|
||||
goto fail;
|
||||
|
||||
|
@ -124,7 +124,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
|
||||
|
||||
static void inline
|
||||
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
|
||||
u8 bit_width, u64 address)
|
||||
u8 byte_width, u64 address)
|
||||
{
|
||||
|
||||
/*
|
||||
@ -136,7 +136,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
|
||||
/* All other fields are byte-wide */
|
||||
|
||||
generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO;
|
||||
generic_address->bit_width = bit_width;
|
||||
generic_address->bit_width = byte_width << 3;
|
||||
generic_address->bit_offset = 0;
|
||||
generic_address->access_width = 0;
|
||||
}
|
||||
@ -155,7 +155,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags)
|
||||
void acpi_tb_parse_fadt(u32 table_index, u8 flags)
|
||||
{
|
||||
u32 length;
|
||||
struct acpi_table_header *table;
|
||||
@ -280,7 +280,7 @@ static void acpi_tb_convert_fadt(void)
|
||||
{
|
||||
u8 pm1_register_length;
|
||||
struct acpi_generic_address *target;
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
|
||||
/* Update the local FADT table header length */
|
||||
|
||||
@ -343,9 +343,11 @@ static void acpi_tb_convert_fadt(void)
|
||||
*
|
||||
* The PM event blocks are split into two register blocks, first is the
|
||||
* PM Status Register block, followed immediately by the PM Enable Register
|
||||
* block. Each is of length (pm1_event_length/2)
|
||||
* block. Each is of length (xpm1x_event_block.bit_width/2)
|
||||
*/
|
||||
pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length);
|
||||
WARN_ON(ACPI_MOD_16(acpi_gbl_FADT.xpm1a_event_block.bit_width));
|
||||
pm1_register_length = (u8) ACPI_DIV_16(acpi_gbl_FADT
|
||||
.xpm1a_event_block.bit_width);
|
||||
|
||||
/* The PM1A register block is required */
|
||||
|
||||
@ -360,14 +362,17 @@ static void acpi_tb_convert_fadt(void)
|
||||
/* The PM1B register block is optional, ignore if not present */
|
||||
|
||||
if (acpi_gbl_FADT.xpm1b_event_block.address) {
|
||||
WARN_ON(ACPI_MOD_16(acpi_gbl_FADT.xpm1b_event_block.bit_width));
|
||||
pm1_register_length = (u8) ACPI_DIV_16(acpi_gbl_FADT
|
||||
.xpm1b_event_block
|
||||
.bit_width);
|
||||
acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
|
||||
pm1_register_length,
|
||||
(acpi_gbl_FADT.xpm1b_event_block.
|
||||
address + pm1_register_length));
|
||||
/* Don't forget to copy space_id of the GAS */
|
||||
acpi_gbl_xpm1b_enable.space_id =
|
||||
acpi_gbl_FADT.xpm1a_event_block.space_id;
|
||||
|
||||
acpi_gbl_FADT.xpm1b_event_block.space_id;
|
||||
}
|
||||
}
|
||||
|
||||
@ -396,7 +401,7 @@ static void acpi_tb_validate_fadt(void)
|
||||
u32 *address32;
|
||||
struct acpi_generic_address *address64;
|
||||
u8 length;
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
|
||||
/* Examine all of the 64-bit extended address fields (X fields) */
|
||||
|
||||
|
@ -65,10 +65,9 @@ ACPI_MODULE_NAME("tbfind")
|
||||
******************************************************************************/
|
||||
acpi_status
|
||||
acpi_tb_find_table(char *signature,
|
||||
char *oem_id,
|
||||
char *oem_table_id, acpi_native_uint * table_index)
|
||||
char *oem_id, char *oem_table_id, u32 *table_index)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
acpi_status status;
|
||||
struct acpi_table_header header;
|
||||
|
||||
|
@ -107,11 +107,10 @@ acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc)
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_tb_add_table(struct acpi_table_desc *table_desc,
|
||||
acpi_native_uint * table_index)
|
||||
acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
acpi_native_uint length;
|
||||
u32 i;
|
||||
u32 length;
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_add_table);
|
||||
@ -207,8 +206,8 @@ acpi_status acpi_tb_resize_root_table_list(void)
|
||||
|
||||
/* Increase the Table Array size */
|
||||
|
||||
tables = ACPI_ALLOCATE_ZEROED((acpi_gbl_root_table_list.size +
|
||||
ACPI_ROOT_TABLE_SIZE_INCREMENT)
|
||||
tables = ACPI_ALLOCATE_ZEROED(((acpi_size) acpi_gbl_root_table_list.
|
||||
size + ACPI_ROOT_TABLE_SIZE_INCREMENT)
|
||||
* sizeof(struct acpi_table_desc));
|
||||
if (!tables) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
@ -220,7 +219,7 @@ acpi_status acpi_tb_resize_root_table_list(void)
|
||||
|
||||
if (acpi_gbl_root_table_list.tables) {
|
||||
ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
|
||||
acpi_gbl_root_table_list.size *
|
||||
(acpi_size) acpi_gbl_root_table_list.size *
|
||||
sizeof(struct acpi_table_desc));
|
||||
|
||||
if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
|
||||
@ -253,7 +252,7 @@ acpi_status acpi_tb_resize_root_table_list(void)
|
||||
acpi_status
|
||||
acpi_tb_store_table(acpi_physical_address address,
|
||||
struct acpi_table_header *table,
|
||||
u32 length, u8 flags, acpi_native_uint * table_index)
|
||||
u32 length, u8 flags, u32 *table_index)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
@ -334,7 +333,7 @@ void acpi_tb_delete_table(struct acpi_table_desc *table_desc)
|
||||
|
||||
void acpi_tb_terminate(void)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_terminate);
|
||||
|
||||
@ -374,7 +373,7 @@ void acpi_tb_terminate(void)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void acpi_tb_delete_namespace_by_owner(acpi_native_uint table_index)
|
||||
void acpi_tb_delete_namespace_by_owner(u32 table_index)
|
||||
{
|
||||
acpi_owner_id owner_id;
|
||||
|
||||
@ -403,7 +402,7 @@ void acpi_tb_delete_namespace_by_owner(acpi_native_uint table_index)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_tb_allocate_owner_id(acpi_native_uint table_index)
|
||||
acpi_status acpi_tb_allocate_owner_id(u32 table_index)
|
||||
{
|
||||
acpi_status status = AE_BAD_PARAMETER;
|
||||
|
||||
@ -431,7 +430,7 @@ acpi_status acpi_tb_allocate_owner_id(acpi_native_uint table_index)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_tb_release_owner_id(acpi_native_uint table_index)
|
||||
acpi_status acpi_tb_release_owner_id(u32 table_index)
|
||||
{
|
||||
acpi_status status = AE_BAD_PARAMETER;
|
||||
|
||||
@ -462,8 +461,7 @@ acpi_status acpi_tb_release_owner_id(acpi_native_uint table_index)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_tb_get_owner_id(acpi_native_uint table_index, acpi_owner_id * owner_id)
|
||||
acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id)
|
||||
{
|
||||
acpi_status status = AE_BAD_PARAMETER;
|
||||
|
||||
@ -490,7 +488,7 @@ acpi_tb_get_owner_id(acpi_native_uint table_index, acpi_owner_id * owner_id)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u8 acpi_tb_is_table_loaded(acpi_native_uint table_index)
|
||||
u8 acpi_tb_is_table_loaded(u32 table_index)
|
||||
{
|
||||
u8 is_loaded = FALSE;
|
||||
|
||||
@ -518,7 +516,7 @@ u8 acpi_tb_is_table_loaded(acpi_native_uint table_index)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void acpi_tb_set_table_loaded_flag(acpi_native_uint table_index, u8 is_loaded)
|
||||
void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded)
|
||||
{
|
||||
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
|
@ -49,8 +49,8 @@ ACPI_MODULE_NAME("tbutils")
|
||||
|
||||
/* Local prototypes */
|
||||
static acpi_physical_address
|
||||
acpi_tb_get_root_table_entry(u8 * table_entry,
|
||||
acpi_native_uint table_entry_size);
|
||||
acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_check_xsdt
|
||||
@ -238,7 +238,7 @@ acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length)
|
||||
u8 acpi_tb_checksum(u8 *buffer, u32 length)
|
||||
{
|
||||
u8 sum = 0;
|
||||
u8 *end = buffer + length;
|
||||
@ -268,7 +268,7 @@ u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length)
|
||||
|
||||
void
|
||||
acpi_tb_install_table(acpi_physical_address address,
|
||||
u8 flags, char *signature, acpi_native_uint table_index)
|
||||
u8 flags, char *signature, u32 table_index)
|
||||
{
|
||||
struct acpi_table_header *table;
|
||||
|
||||
@ -336,8 +336,7 @@ acpi_tb_install_table(acpi_physical_address address,
|
||||
******************************************************************************/
|
||||
|
||||
static acpi_physical_address
|
||||
acpi_tb_get_root_table_entry(u8 * table_entry,
|
||||
acpi_native_uint table_entry_size)
|
||||
acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size)
|
||||
{
|
||||
u64 address64;
|
||||
|
||||
@ -395,8 +394,8 @@ acpi_status __init
|
||||
acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
|
||||
{
|
||||
struct acpi_table_rsdp *rsdp;
|
||||
acpi_native_uint table_entry_size;
|
||||
acpi_native_uint i;
|
||||
u32 table_entry_size;
|
||||
u32 i;
|
||||
u32 table_count;
|
||||
struct acpi_table_header *table;
|
||||
acpi_physical_address address;
|
||||
|
@ -125,7 +125,7 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array,
|
||||
/* Root Table Array has been statically allocated by the host */
|
||||
|
||||
ACPI_MEMSET(initial_table_array, 0,
|
||||
initial_table_count *
|
||||
(acpi_size) initial_table_count *
|
||||
sizeof(struct acpi_table_desc));
|
||||
|
||||
acpi_gbl_root_table_list.tables = initial_table_array;
|
||||
@ -183,9 +183,9 @@ acpi_status acpi_reallocate_root_table(void)
|
||||
return_ACPI_STATUS(AE_SUPPORT);
|
||||
}
|
||||
|
||||
new_size =
|
||||
(acpi_gbl_root_table_list.count +
|
||||
ACPI_ROOT_TABLE_SIZE_INCREMENT) * sizeof(struct acpi_table_desc);
|
||||
new_size = ((acpi_size) acpi_gbl_root_table_list.count +
|
||||
ACPI_ROOT_TABLE_SIZE_INCREMENT) *
|
||||
sizeof(struct acpi_table_desc);
|
||||
|
||||
/* Create new array and copy the old array */
|
||||
|
||||
@ -222,7 +222,7 @@ acpi_status acpi_reallocate_root_table(void)
|
||||
acpi_status acpi_load_table(struct acpi_table_header *table_ptr)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_native_uint table_index;
|
||||
u32 table_index;
|
||||
struct acpi_table_desc table_desc;
|
||||
|
||||
if (!table_ptr)
|
||||
@ -264,11 +264,10 @@ ACPI_EXPORT_SYMBOL(acpi_load_table)
|
||||
*****************************************************************************/
|
||||
acpi_status
|
||||
acpi_get_table_header(char *signature,
|
||||
acpi_native_uint instance,
|
||||
struct acpi_table_header * out_table_header)
|
||||
u32 instance, struct acpi_table_header *out_table_header)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
acpi_native_uint j;
|
||||
u32 i;
|
||||
u32 j;
|
||||
struct acpi_table_header *header;
|
||||
|
||||
/* Parameter validation */
|
||||
@ -378,10 +377,10 @@ ACPI_EXPORT_SYMBOL(acpi_unload_table_id)
|
||||
*****************************************************************************/
|
||||
acpi_status
|
||||
acpi_get_table(char *signature,
|
||||
acpi_native_uint instance, struct acpi_table_header **out_table)
|
||||
u32 instance, struct acpi_table_header **out_table)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
acpi_native_uint j;
|
||||
u32 i;
|
||||
u32 j;
|
||||
acpi_status status;
|
||||
|
||||
/* Parameter validation */
|
||||
@ -435,8 +434,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_table)
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status
|
||||
acpi_get_table_by_index(acpi_native_uint table_index,
|
||||
struct acpi_table_header ** table)
|
||||
acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
@ -493,7 +491,7 @@ static acpi_status acpi_tb_load_namespace(void)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_table_header *table;
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_load_namespace);
|
||||
|
||||
|
@ -118,7 +118,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_find_root_pointer(acpi_native_uint * table_address)
|
||||
acpi_status acpi_find_root_pointer(acpi_size *table_address)
|
||||
{
|
||||
u8 *table_ptr;
|
||||
u8 *mem_rover;
|
||||
@ -153,7 +153,7 @@ acpi_status acpi_find_root_pointer(acpi_native_uint * table_address)
|
||||
* 1b) Search EBDA paragraphs (EBDA is required to be a
|
||||
* minimum of 1_k length)
|
||||
*/
|
||||
table_ptr = acpi_os_map_memory((acpi_native_uint)
|
||||
table_ptr = acpi_os_map_memory((acpi_physical_address)
|
||||
physical_address,
|
||||
ACPI_EBDA_WINDOW_SIZE);
|
||||
if (!table_ptr) {
|
||||
|
@ -309,7 +309,8 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line)
|
||||
void *acpi_ut_allocate(acpi_size size,
|
||||
u32 component, const char *module, u32 line)
|
||||
{
|
||||
void *allocation;
|
||||
|
||||
@ -353,7 +354,7 @@ void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line)
|
||||
******************************************************************************/
|
||||
|
||||
void *acpi_ut_allocate_zeroed(acpi_size size,
|
||||
u32 component, char *module, u32 line)
|
||||
u32 component, const char *module, u32 line)
|
||||
{
|
||||
void *allocation;
|
||||
|
||||
|
@ -572,7 +572,7 @@ acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
|
||||
acpi_status status = AE_OK;
|
||||
union acpi_operand_object *package_object;
|
||||
union acpi_operand_object **package_elements;
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage);
|
||||
|
||||
@ -599,7 +599,7 @@ acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
|
||||
|
||||
/* Truncate package and delete it */
|
||||
|
||||
package_object->package.count = (u32) i;
|
||||
package_object->package.count = i;
|
||||
package_elements[i] = NULL;
|
||||
acpi_ut_remove_reference(package_object);
|
||||
return_ACPI_STATUS(status);
|
||||
|
@ -157,7 +157,8 @@ void ACPI_INTERNAL_VAR_XFACE
|
||||
acpi_ut_debug_print(u32 requested_debug_level,
|
||||
u32 line_number,
|
||||
const char *function_name,
|
||||
char *module_name, u32 component_id, char *format, ...)
|
||||
const char *module_name,
|
||||
u32 component_id, const char *format, ...)
|
||||
{
|
||||
acpi_thread_id thread_id;
|
||||
va_list args;
|
||||
@ -228,7 +229,8 @@ void ACPI_INTERNAL_VAR_XFACE
|
||||
acpi_ut_debug_print_raw(u32 requested_debug_level,
|
||||
u32 line_number,
|
||||
const char *function_name,
|
||||
char *module_name, u32 component_id, char *format, ...)
|
||||
const char *module_name,
|
||||
u32 component_id, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
@ -261,7 +263,8 @@ ACPI_EXPORT_SYMBOL(acpi_ut_debug_print_raw)
|
||||
******************************************************************************/
|
||||
void
|
||||
acpi_ut_trace(u32 line_number,
|
||||
const char *function_name, char *module_name, u32 component_id)
|
||||
const char *function_name,
|
||||
const char *module_name, u32 component_id)
|
||||
{
|
||||
|
||||
acpi_gbl_nesting_level++;
|
||||
@ -293,7 +296,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_trace)
|
||||
void
|
||||
acpi_ut_trace_ptr(u32 line_number,
|
||||
const char *function_name,
|
||||
char *module_name, u32 component_id, void *pointer)
|
||||
const char *module_name, u32 component_id, void *pointer)
|
||||
{
|
||||
acpi_gbl_nesting_level++;
|
||||
acpi_ut_track_stack_ptr();
|
||||
@ -324,7 +327,7 @@ acpi_ut_trace_ptr(u32 line_number,
|
||||
void
|
||||
acpi_ut_trace_str(u32 line_number,
|
||||
const char *function_name,
|
||||
char *module_name, u32 component_id, char *string)
|
||||
const char *module_name, u32 component_id, char *string)
|
||||
{
|
||||
|
||||
acpi_gbl_nesting_level++;
|
||||
@ -356,7 +359,7 @@ acpi_ut_trace_str(u32 line_number,
|
||||
void
|
||||
acpi_ut_trace_u32(u32 line_number,
|
||||
const char *function_name,
|
||||
char *module_name, u32 component_id, u32 integer)
|
||||
const char *module_name, u32 component_id, u32 integer)
|
||||
{
|
||||
|
||||
acpi_gbl_nesting_level++;
|
||||
@ -386,7 +389,8 @@ acpi_ut_trace_u32(u32 line_number,
|
||||
|
||||
void
|
||||
acpi_ut_exit(u32 line_number,
|
||||
const char *function_name, char *module_name, u32 component_id)
|
||||
const char *function_name,
|
||||
const char *module_name, u32 component_id)
|
||||
{
|
||||
|
||||
acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
|
||||
@ -417,7 +421,8 @@ ACPI_EXPORT_SYMBOL(acpi_ut_exit)
|
||||
void
|
||||
acpi_ut_status_exit(u32 line_number,
|
||||
const char *function_name,
|
||||
char *module_name, u32 component_id, acpi_status status)
|
||||
const char *module_name,
|
||||
u32 component_id, acpi_status status)
|
||||
{
|
||||
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
@ -458,7 +463,8 @@ ACPI_EXPORT_SYMBOL(acpi_ut_status_exit)
|
||||
void
|
||||
acpi_ut_value_exit(u32 line_number,
|
||||
const char *function_name,
|
||||
char *module_name, u32 component_id, acpi_integer value)
|
||||
const char *module_name,
|
||||
u32 component_id, acpi_integer value)
|
||||
{
|
||||
|
||||
acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
|
||||
@ -490,7 +496,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_value_exit)
|
||||
void
|
||||
acpi_ut_ptr_exit(u32 line_number,
|
||||
const char *function_name,
|
||||
char *module_name, u32 component_id, u8 * ptr)
|
||||
const char *module_name, u32 component_id, u8 *ptr)
|
||||
{
|
||||
|
||||
acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
|
||||
@ -519,8 +525,8 @@ acpi_ut_ptr_exit(u32 line_number,
|
||||
|
||||
void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
|
||||
{
|
||||
acpi_native_uint i = 0;
|
||||
acpi_native_uint j;
|
||||
u32 i = 0;
|
||||
u32 j;
|
||||
u32 temp32;
|
||||
u8 buf_char;
|
||||
|
||||
@ -539,7 +545,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
|
||||
|
||||
/* Print current offset */
|
||||
|
||||
acpi_os_printf("%6.4X: ", (u32) i);
|
||||
acpi_os_printf("%6.4X: ", i);
|
||||
|
||||
/* Print 16 hex chars */
|
||||
|
||||
@ -549,7 +555,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
|
||||
/* Dump fill spaces */
|
||||
|
||||
acpi_os_printf("%*s", ((display * 2) + 1), " ");
|
||||
j += (acpi_native_uint) display;
|
||||
j += display;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -557,32 +563,38 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
|
||||
case DB_BYTE_DISPLAY:
|
||||
default: /* Default is BYTE display */
|
||||
|
||||
acpi_os_printf("%02X ", buffer[i + j]);
|
||||
acpi_os_printf("%02X ",
|
||||
buffer[(acpi_size) i + j]);
|
||||
break;
|
||||
|
||||
case DB_WORD_DISPLAY:
|
||||
|
||||
ACPI_MOVE_16_TO_32(&temp32, &buffer[i + j]);
|
||||
ACPI_MOVE_16_TO_32(&temp32,
|
||||
&buffer[(acpi_size) i + j]);
|
||||
acpi_os_printf("%04X ", temp32);
|
||||
break;
|
||||
|
||||
case DB_DWORD_DISPLAY:
|
||||
|
||||
ACPI_MOVE_32_TO_32(&temp32, &buffer[i + j]);
|
||||
ACPI_MOVE_32_TO_32(&temp32,
|
||||
&buffer[(acpi_size) i + j]);
|
||||
acpi_os_printf("%08X ", temp32);
|
||||
break;
|
||||
|
||||
case DB_QWORD_DISPLAY:
|
||||
|
||||
ACPI_MOVE_32_TO_32(&temp32, &buffer[i + j]);
|
||||
ACPI_MOVE_32_TO_32(&temp32,
|
||||
&buffer[(acpi_size) i + j]);
|
||||
acpi_os_printf("%08X", temp32);
|
||||
|
||||
ACPI_MOVE_32_TO_32(&temp32, &buffer[i + j + 4]);
|
||||
ACPI_MOVE_32_TO_32(&temp32,
|
||||
&buffer[(acpi_size) i + j +
|
||||
4]);
|
||||
acpi_os_printf("%08X ", temp32);
|
||||
break;
|
||||
}
|
||||
|
||||
j += (acpi_native_uint) display;
|
||||
j += display;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -596,7 +608,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
|
||||
return;
|
||||
}
|
||||
|
||||
buf_char = buffer[i + j];
|
||||
buf_char = buffer[(acpi_size) i + j];
|
||||
if (ACPI_IS_PRINT(buf_char)) {
|
||||
acpi_os_printf("%c", buf_char);
|
||||
} else {
|
||||
|
@ -442,7 +442,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action)
|
||||
union acpi_generic_state *state_list = NULL;
|
||||
union acpi_operand_object *next_object = NULL;
|
||||
union acpi_generic_state *state;
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR(ut_update_object_reference, object);
|
||||
|
||||
|
@ -97,7 +97,7 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
|
||||
acpi_status status;
|
||||
union acpi_operand_object *string_desc;
|
||||
union acpi_operand_object *return_desc;
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ut_osi_implementation);
|
||||
|
||||
@ -217,7 +217,6 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
|
||||
|
||||
info->prefix_node = prefix_node;
|
||||
info->pathname = path;
|
||||
info->parameter_type = ACPI_PARAM_ARGS;
|
||||
|
||||
/* Evaluate the object/method */
|
||||
|
||||
@ -514,7 +513,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node * device_node,
|
||||
u32 count;
|
||||
u32 size;
|
||||
struct acpi_compatible_id_list *cid_list;
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ut_execute_CID);
|
||||
|
||||
|
@ -64,7 +64,7 @@ ACPI_MODULE_NAME("utmisc")
|
||||
******************************************************************************/
|
||||
const char *acpi_ut_validate_exception(acpi_status status)
|
||||
{
|
||||
acpi_status sub_status;
|
||||
u32 sub_status;
|
||||
const char *exception = NULL;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
@ -85,32 +85,28 @@ const char *acpi_ut_validate_exception(acpi_status status)
|
||||
case AE_CODE_PROGRAMMER:
|
||||
|
||||
if (sub_status <= AE_CODE_PGM_MAX) {
|
||||
exception =
|
||||
acpi_gbl_exception_names_pgm[sub_status - 1];
|
||||
exception = acpi_gbl_exception_names_pgm[sub_status];
|
||||
}
|
||||
break;
|
||||
|
||||
case AE_CODE_ACPI_TABLES:
|
||||
|
||||
if (sub_status <= AE_CODE_TBL_MAX) {
|
||||
exception =
|
||||
acpi_gbl_exception_names_tbl[sub_status - 1];
|
||||
exception = acpi_gbl_exception_names_tbl[sub_status];
|
||||
}
|
||||
break;
|
||||
|
||||
case AE_CODE_AML:
|
||||
|
||||
if (sub_status <= AE_CODE_AML_MAX) {
|
||||
exception =
|
||||
acpi_gbl_exception_names_aml[sub_status - 1];
|
||||
exception = acpi_gbl_exception_names_aml[sub_status];
|
||||
}
|
||||
break;
|
||||
|
||||
case AE_CODE_CONTROL:
|
||||
|
||||
if (sub_status <= AE_CODE_CTRL_MAX) {
|
||||
exception =
|
||||
acpi_gbl_exception_names_ctrl[sub_status - 1];
|
||||
exception = acpi_gbl_exception_names_ctrl[sub_status];
|
||||
}
|
||||
break;
|
||||
|
||||
@ -165,9 +161,9 @@ u8 acpi_ut_is_aml_table(struct acpi_table_header *table)
|
||||
|
||||
acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
acpi_native_uint j;
|
||||
acpi_native_uint k;
|
||||
u32 i;
|
||||
u32 j;
|
||||
u32 k;
|
||||
acpi_status status;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ut_allocate_owner_id);
|
||||
@ -273,7 +269,7 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr)
|
||||
{
|
||||
acpi_owner_id owner_id = *owner_id_ptr;
|
||||
acpi_status status;
|
||||
acpi_native_uint index;
|
||||
u32 index;
|
||||
u32 bit;
|
||||
|
||||
ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id);
|
||||
@ -593,7 +589,7 @@ acpi_ut_display_init_pathname(u8 type,
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u8 acpi_ut_valid_acpi_char(char character, acpi_native_uint position)
|
||||
u8 acpi_ut_valid_acpi_char(char character, u32 position)
|
||||
{
|
||||
|
||||
if (!((character >= 'A' && character <= 'Z') ||
|
||||
@ -628,7 +624,7 @@ u8 acpi_ut_valid_acpi_char(char character, acpi_native_uint position)
|
||||
|
||||
u8 acpi_ut_valid_acpi_name(u32 name)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
@ -657,7 +653,7 @@ u8 acpi_ut_valid_acpi_name(u32 name)
|
||||
|
||||
acpi_name acpi_ut_repair_name(char *name)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
u32 i;
|
||||
char new_name[ACPI_NAME_SIZE];
|
||||
|
||||
for (i = 0; i < ACPI_NAME_SIZE; i++) {
|
||||
@ -1024,7 +1020,7 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
|
||||
******************************************************************************/
|
||||
|
||||
void ACPI_INTERNAL_VAR_XFACE
|
||||
acpi_ut_error(char *module_name, u32 line_number, char *format, ...)
|
||||
acpi_ut_error(const char *module_name, u32 line_number, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
@ -1037,8 +1033,8 @@ acpi_ut_error(char *module_name, u32 line_number, char *format, ...)
|
||||
}
|
||||
|
||||
void ACPI_INTERNAL_VAR_XFACE
|
||||
acpi_ut_exception(char *module_name,
|
||||
u32 line_number, acpi_status status, char *format, ...)
|
||||
acpi_ut_exception(const char *module_name,
|
||||
u32 line_number, acpi_status status, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
@ -1054,7 +1050,8 @@ acpi_ut_exception(char *module_name,
|
||||
EXPORT_SYMBOL(acpi_ut_exception);
|
||||
|
||||
void ACPI_INTERNAL_VAR_XFACE
|
||||
acpi_ut_warning(char *module_name, u32 line_number, char *format, ...)
|
||||
acpi_ut_warning(const char *module_name,
|
||||
u32 line_number, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
@ -1067,7 +1064,7 @@ acpi_ut_warning(char *module_name, u32 line_number, char *format, ...)
|
||||
}
|
||||
|
||||
void ACPI_INTERNAL_VAR_XFACE
|
||||
acpi_ut_info(char *module_name, u32 line_number, char *format, ...)
|
||||
acpi_ut_info(const char *module_name, u32 line_number, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
|
@ -218,7 +218,7 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
|
||||
* the mutex ordering rule. This indicates a coding error somewhere in
|
||||
* the ACPI subsystem code.
|
||||
*/
|
||||
for (i = mutex_id; i < ACPI_MAX_MUTEX; i++) {
|
||||
for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
|
||||
if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
|
||||
if (i == mutex_id) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
@ -315,7 +315,7 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
|
||||
* ordering rule. This indicates a coding error somewhere in
|
||||
* the ACPI subsystem code.
|
||||
*/
|
||||
for (i = mutex_id; i < ACPI_MAX_MUTEX; i++) {
|
||||
for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
|
||||
if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
|
||||
if (i == mutex_id) {
|
||||
continue;
|
||||
|
@ -83,7 +83,8 @@ acpi_ut_get_element_length(u8 object_type,
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
union acpi_operand_object *acpi_ut_create_internal_object_dbg(char *module_name,
|
||||
union acpi_operand_object *acpi_ut_create_internal_object_dbg(const char
|
||||
*module_name,
|
||||
u32 line_number,
|
||||
u32 component_id,
|
||||
acpi_object_type
|
||||
@ -175,8 +176,8 @@ union acpi_operand_object *acpi_ut_create_package_object(u32 count)
|
||||
* Create the element array. Count+1 allows the array to be null
|
||||
* terminated.
|
||||
*/
|
||||
package_elements = ACPI_ALLOCATE_ZEROED((acpi_size)
|
||||
(count + 1) * sizeof(void *));
|
||||
package_elements = ACPI_ALLOCATE_ZEROED(((acpi_size) count +
|
||||
1) * sizeof(void *));
|
||||
if (!package_elements) {
|
||||
acpi_ut_remove_reference(package_desc);
|
||||
return_PTR(NULL);
|
||||
@ -347,7 +348,7 @@ u8 acpi_ut_valid_internal_object(void *object)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void *acpi_ut_allocate_object_desc_dbg(char *module_name,
|
||||
void *acpi_ut_allocate_object_desc_dbg(const char *module_name,
|
||||
u32 line_number, u32 component_id)
|
||||
{
|
||||
union acpi_operand_object *object;
|
||||
|
@ -631,6 +631,76 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
|
||||
* device : video output device (LCD, CRT, ..)
|
||||
*
|
||||
* Return Value:
|
||||
* Maximum brightness level
|
||||
*
|
||||
* Allocate and initialize device->brightness.
|
||||
*/
|
||||
|
||||
static int
|
||||
acpi_video_init_brightness(struct acpi_video_device *device)
|
||||
{
|
||||
union acpi_object *obj = NULL;
|
||||
int i, max_level = 0, count = 0;
|
||||
union acpi_object *o;
|
||||
struct acpi_video_device_brightness *br = NULL;
|
||||
|
||||
if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available "
|
||||
"LCD brightness level\n"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (obj->package.count < 2)
|
||||
goto out;
|
||||
|
||||
br = kzalloc(sizeof(*br), GFP_KERNEL);
|
||||
if (!br) {
|
||||
printk(KERN_ERR "can't allocate memory\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
br->levels = kmalloc(obj->package.count * sizeof *(br->levels),
|
||||
GFP_KERNEL);
|
||||
if (!br->levels)
|
||||
goto out_free;
|
||||
|
||||
for (i = 0; i < obj->package.count; i++) {
|
||||
o = (union acpi_object *)&obj->package.elements[i];
|
||||
if (o->type != ACPI_TYPE_INTEGER) {
|
||||
printk(KERN_ERR PREFIX "Invalid data\n");
|
||||
continue;
|
||||
}
|
||||
br->levels[count] = (u32) o->integer.value;
|
||||
|
||||
if (br->levels[count] > max_level)
|
||||
max_level = br->levels[count];
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count < 2)
|
||||
goto out_free_levels;
|
||||
|
||||
br->count = count;
|
||||
device->brightness = br;
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "found %d brightness levels\n", count));
|
||||
kfree(obj);
|
||||
return max_level;
|
||||
|
||||
out_free_levels:
|
||||
kfree(br->levels);
|
||||
out_free:
|
||||
kfree(br);
|
||||
out:
|
||||
device->brightness = NULL;
|
||||
kfree(obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Arg:
|
||||
* device : video output device (LCD, CRT, ..)
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Find out all required AML methods defined under the output
|
||||
@ -640,10 +710,7 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
|
||||
static void acpi_video_device_find_cap(struct acpi_video_device *device)
|
||||
{
|
||||
acpi_handle h_dummy1;
|
||||
int i;
|
||||
u32 max_level = 0;
|
||||
union acpi_object *obj = NULL;
|
||||
struct acpi_video_device_brightness *br = NULL;
|
||||
|
||||
|
||||
memset(&device->cap, 0, sizeof(device->cap));
|
||||
@ -672,53 +739,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
|
||||
device->cap._DSS = 1;
|
||||
}
|
||||
|
||||
if (ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
|
||||
|
||||
if (obj->package.count >= 2) {
|
||||
int count = 0;
|
||||
union acpi_object *o;
|
||||
|
||||
br = kzalloc(sizeof(*br), GFP_KERNEL);
|
||||
if (!br) {
|
||||
printk(KERN_ERR "can't allocate memory\n");
|
||||
} else {
|
||||
br->levels = kmalloc(obj->package.count *
|
||||
sizeof *(br->levels), GFP_KERNEL);
|
||||
if (!br->levels)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < obj->package.count; i++) {
|
||||
o = (union acpi_object *)&obj->package.
|
||||
elements[i];
|
||||
if (o->type != ACPI_TYPE_INTEGER) {
|
||||
printk(KERN_ERR PREFIX "Invalid data\n");
|
||||
continue;
|
||||
}
|
||||
br->levels[count] = (u32) o->integer.value;
|
||||
|
||||
if (br->levels[count] > max_level)
|
||||
max_level = br->levels[count];
|
||||
count++;
|
||||
}
|
||||
out:
|
||||
if (count < 2) {
|
||||
kfree(br->levels);
|
||||
kfree(br);
|
||||
} else {
|
||||
br->count = count;
|
||||
device->brightness = br;
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"found %d brightness levels\n",
|
||||
count));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available LCD brightness level\n"));
|
||||
}
|
||||
|
||||
kfree(obj);
|
||||
max_level = acpi_video_init_brightness(device);
|
||||
|
||||
if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){
|
||||
int result;
|
||||
@ -1695,6 +1716,8 @@ static void
|
||||
acpi_video_switch_brightness(struct acpi_video_device *device, int event)
|
||||
{
|
||||
unsigned long level_current, level_next;
|
||||
if (!device->brightness)
|
||||
return;
|
||||
acpi_video_device_lcd_get_level_current(device, &level_current);
|
||||
level_next = acpi_video_get_next_level(device, level_current, event);
|
||||
acpi_video_device_lcd_set_level(device, level_next);
|
||||
|
@ -58,6 +58,55 @@ struct apm_queue {
|
||||
apm_event_t events[APM_MAX_EVENTS];
|
||||
};
|
||||
|
||||
/*
|
||||
* thread states (for threads using a writable /dev/apm_bios fd):
|
||||
*
|
||||
* SUSPEND_NONE: nothing happening
|
||||
* SUSPEND_PENDING: suspend event queued for thread and pending to be read
|
||||
* SUSPEND_READ: suspend event read, pending acknowledgement
|
||||
* SUSPEND_ACKED: acknowledgement received from thread (via ioctl),
|
||||
* waiting for resume
|
||||
* SUSPEND_ACKTO: acknowledgement timeout
|
||||
* SUSPEND_DONE: thread had acked suspend and is now notified of
|
||||
* resume
|
||||
*
|
||||
* SUSPEND_WAIT: this thread invoked suspend and is waiting for resume
|
||||
*
|
||||
* A thread migrates in one of three paths:
|
||||
* NONE -1-> PENDING -2-> READ -3-> ACKED -4-> DONE -5-> NONE
|
||||
* -6-> ACKTO -7-> NONE
|
||||
* NONE -8-> WAIT -9-> NONE
|
||||
*
|
||||
* While in PENDING or READ, the thread is accounted for in the
|
||||
* suspend_acks_pending counter.
|
||||
*
|
||||
* The transitions are invoked as follows:
|
||||
* 1: suspend event is signalled from the core PM code
|
||||
* 2: the suspend event is read from the fd by the userspace thread
|
||||
* 3: userspace thread issues the APM_IOC_SUSPEND ioctl (as ack)
|
||||
* 4: core PM code signals that we have resumed
|
||||
* 5: APM_IOC_SUSPEND ioctl returns
|
||||
*
|
||||
* 6: the notifier invoked from the core PM code timed out waiting
|
||||
* for all relevant threds to enter ACKED state and puts those
|
||||
* that haven't into ACKTO
|
||||
* 7: those threads issue APM_IOC_SUSPEND ioctl too late,
|
||||
* get an error
|
||||
*
|
||||
* 8: userspace thread issues the APM_IOC_SUSPEND ioctl (to suspend),
|
||||
* ioctl code invokes pm_suspend()
|
||||
* 9: pm_suspend() returns indicating resume
|
||||
*/
|
||||
enum apm_suspend_state {
|
||||
SUSPEND_NONE,
|
||||
SUSPEND_PENDING,
|
||||
SUSPEND_READ,
|
||||
SUSPEND_ACKED,
|
||||
SUSPEND_ACKTO,
|
||||
SUSPEND_WAIT,
|
||||
SUSPEND_DONE,
|
||||
};
|
||||
|
||||
/*
|
||||
* The per-file APM data
|
||||
*/
|
||||
@ -69,13 +118,7 @@ struct apm_user {
|
||||
unsigned int reader: 1;
|
||||
|
||||
int suspend_result;
|
||||
unsigned int suspend_state;
|
||||
#define SUSPEND_NONE 0 /* no suspend pending */
|
||||
#define SUSPEND_PENDING 1 /* suspend pending read */
|
||||
#define SUSPEND_READ 2 /* suspend read, pending ack */
|
||||
#define SUSPEND_ACKED 3 /* suspend acked */
|
||||
#define SUSPEND_WAIT 4 /* waiting for suspend */
|
||||
#define SUSPEND_DONE 5 /* suspend completed */
|
||||
enum apm_suspend_state suspend_state;
|
||||
|
||||
struct apm_queue queue;
|
||||
};
|
||||
@ -83,7 +126,8 @@ struct apm_user {
|
||||
/*
|
||||
* Local variables
|
||||
*/
|
||||
static int suspends_pending;
|
||||
static atomic_t suspend_acks_pending = ATOMIC_INIT(0);
|
||||
static atomic_t userspace_notification_inhibit = ATOMIC_INIT(0);
|
||||
static int apm_disabled;
|
||||
static struct task_struct *kapmd_tsk;
|
||||
|
||||
@ -166,78 +210,6 @@ static void queue_event(apm_event_t event)
|
||||
wake_up_interruptible(&apm_waitqueue);
|
||||
}
|
||||
|
||||
/*
|
||||
* queue_suspend_event - queue an APM suspend event.
|
||||
*
|
||||
* Check that we're in a state where we can suspend. If not,
|
||||
* return -EBUSY. Otherwise, queue an event to all "writer"
|
||||
* users. If there are no "writer" users, return '1' to
|
||||
* indicate that we can immediately suspend.
|
||||
*/
|
||||
static int queue_suspend_event(apm_event_t event, struct apm_user *sender)
|
||||
{
|
||||
struct apm_user *as;
|
||||
int ret = 1;
|
||||
|
||||
mutex_lock(&state_lock);
|
||||
down_read(&user_list_lock);
|
||||
|
||||
/*
|
||||
* If a thread is still processing, we can't suspend, so reject
|
||||
* the request.
|
||||
*/
|
||||
list_for_each_entry(as, &apm_user_list, list) {
|
||||
if (as != sender && as->reader && as->writer && as->suser &&
|
||||
as->suspend_state != SUSPEND_NONE) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(as, &apm_user_list, list) {
|
||||
if (as != sender && as->reader && as->writer && as->suser) {
|
||||
as->suspend_state = SUSPEND_PENDING;
|
||||
suspends_pending++;
|
||||
queue_add_event(&as->queue, event);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
out:
|
||||
up_read(&user_list_lock);
|
||||
mutex_unlock(&state_lock);
|
||||
wake_up_interruptible(&apm_waitqueue);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void apm_suspend(void)
|
||||
{
|
||||
struct apm_user *as;
|
||||
int err = pm_suspend(PM_SUSPEND_MEM);
|
||||
|
||||
/*
|
||||
* Anyone on the APM queues will think we're still suspended.
|
||||
* Send a message so everyone knows we're now awake again.
|
||||
*/
|
||||
queue_event(APM_NORMAL_RESUME);
|
||||
|
||||
/*
|
||||
* Finally, wake up anyone who is sleeping on the suspend.
|
||||
*/
|
||||
mutex_lock(&state_lock);
|
||||
down_read(&user_list_lock);
|
||||
list_for_each_entry(as, &apm_user_list, list) {
|
||||
if (as->suspend_state == SUSPEND_WAIT ||
|
||||
as->suspend_state == SUSPEND_ACKED) {
|
||||
as->suspend_result = err;
|
||||
as->suspend_state = SUSPEND_DONE;
|
||||
}
|
||||
}
|
||||
up_read(&user_list_lock);
|
||||
mutex_unlock(&state_lock);
|
||||
|
||||
wake_up(&apm_suspend_waitqueue);
|
||||
}
|
||||
|
||||
static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
struct apm_user *as = fp->private_data;
|
||||
@ -308,25 +280,22 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
|
||||
|
||||
as->suspend_result = -EINTR;
|
||||
|
||||
if (as->suspend_state == SUSPEND_READ) {
|
||||
int pending;
|
||||
|
||||
switch (as->suspend_state) {
|
||||
case SUSPEND_READ:
|
||||
/*
|
||||
* If we read a suspend command from /dev/apm_bios,
|
||||
* then the corresponding APM_IOC_SUSPEND ioctl is
|
||||
* interpreted as an acknowledge.
|
||||
*/
|
||||
as->suspend_state = SUSPEND_ACKED;
|
||||
suspends_pending--;
|
||||
pending = suspends_pending == 0;
|
||||
atomic_dec(&suspend_acks_pending);
|
||||
mutex_unlock(&state_lock);
|
||||
|
||||
/*
|
||||
* If there are no further acknowledges required,
|
||||
* suspend the system.
|
||||
* suspend_acks_pending changed, the notifier needs to
|
||||
* be woken up for this
|
||||
*/
|
||||
if (pending)
|
||||
apm_suspend();
|
||||
wake_up(&apm_suspend_waitqueue);
|
||||
|
||||
/*
|
||||
* Wait for the suspend/resume to complete. If there
|
||||
@ -342,35 +311,21 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
|
||||
* try_to_freeze() in freezer_count() will not trigger
|
||||
*/
|
||||
freezer_count();
|
||||
} else {
|
||||
break;
|
||||
case SUSPEND_ACKTO:
|
||||
as->suspend_result = -ETIMEDOUT;
|
||||
mutex_unlock(&state_lock);
|
||||
break;
|
||||
default:
|
||||
as->suspend_state = SUSPEND_WAIT;
|
||||
mutex_unlock(&state_lock);
|
||||
|
||||
/*
|
||||
* Otherwise it is a request to suspend the system.
|
||||
* Queue an event for all readers, and expect an
|
||||
* acknowledge from all writers who haven't already
|
||||
* acknowledged.
|
||||
* Just invoke pm_suspend(), we'll handle it from
|
||||
* there via the notifier.
|
||||
*/
|
||||
err = queue_suspend_event(APM_USER_SUSPEND, as);
|
||||
if (err < 0) {
|
||||
/*
|
||||
* Avoid taking the lock here - this
|
||||
* should be fine.
|
||||
*/
|
||||
as->suspend_state = SUSPEND_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err > 0)
|
||||
apm_suspend();
|
||||
|
||||
/*
|
||||
* Wait for the suspend/resume to complete. If there
|
||||
* are pending acknowledges, we wait here for them.
|
||||
*/
|
||||
wait_event_freezable(apm_suspend_waitqueue,
|
||||
as->suspend_state == SUSPEND_DONE);
|
||||
as->suspend_result = pm_suspend(PM_SUSPEND_MEM);
|
||||
}
|
||||
|
||||
mutex_lock(&state_lock);
|
||||
@ -386,7 +341,6 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
|
||||
static int apm_release(struct inode * inode, struct file * filp)
|
||||
{
|
||||
struct apm_user *as = filp->private_data;
|
||||
int pending = 0;
|
||||
|
||||
filp->private_data = NULL;
|
||||
|
||||
@ -396,18 +350,15 @@ static int apm_release(struct inode * inode, struct file * filp)
|
||||
|
||||
/*
|
||||
* We are now unhooked from the chain. As far as new
|
||||
* events are concerned, we no longer exist. However, we
|
||||
* need to balance suspends_pending, which means the
|
||||
* possibility of sleeping.
|
||||
* events are concerned, we no longer exist.
|
||||
*/
|
||||
mutex_lock(&state_lock);
|
||||
if (as->suspend_state != SUSPEND_NONE) {
|
||||
suspends_pending -= 1;
|
||||
pending = suspends_pending == 0;
|
||||
}
|
||||
if (as->suspend_state == SUSPEND_PENDING ||
|
||||
as->suspend_state == SUSPEND_READ)
|
||||
atomic_dec(&suspend_acks_pending);
|
||||
mutex_unlock(&state_lock);
|
||||
if (pending)
|
||||
apm_suspend();
|
||||
|
||||
wake_up(&apm_suspend_waitqueue);
|
||||
|
||||
kfree(as);
|
||||
return 0;
|
||||
@ -545,7 +496,6 @@ static int kapmd(void *arg)
|
||||
{
|
||||
do {
|
||||
apm_event_t event;
|
||||
int ret;
|
||||
|
||||
wait_event_interruptible(kapmd_wait,
|
||||
!queue_empty(&kapmd_queue) || kthread_should_stop());
|
||||
@ -570,20 +520,13 @@ static int kapmd(void *arg)
|
||||
|
||||
case APM_USER_SUSPEND:
|
||||
case APM_SYS_SUSPEND:
|
||||
ret = queue_suspend_event(event, NULL);
|
||||
if (ret < 0) {
|
||||
/*
|
||||
* We were busy. Try again in 50ms.
|
||||
*/
|
||||
queue_add_event(&kapmd_queue, event);
|
||||
msleep(50);
|
||||
}
|
||||
if (ret > 0)
|
||||
apm_suspend();
|
||||
pm_suspend(PM_SUSPEND_MEM);
|
||||
break;
|
||||
|
||||
case APM_CRITICAL_SUSPEND:
|
||||
apm_suspend();
|
||||
atomic_inc(&userspace_notification_inhibit);
|
||||
pm_suspend(PM_SUSPEND_MEM);
|
||||
atomic_dec(&userspace_notification_inhibit);
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
@ -591,6 +534,120 @@ static int kapmd(void *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apm_suspend_notifier(struct notifier_block *nb,
|
||||
unsigned long event,
|
||||
void *dummy)
|
||||
{
|
||||
struct apm_user *as;
|
||||
int err;
|
||||
|
||||
/* short-cut emergency suspends */
|
||||
if (atomic_read(&userspace_notification_inhibit))
|
||||
return NOTIFY_DONE;
|
||||
|
||||
switch (event) {
|
||||
case PM_SUSPEND_PREPARE:
|
||||
/*
|
||||
* Queue an event to all "writer" users that we want
|
||||
* to suspend and need their ack.
|
||||
*/
|
||||
mutex_lock(&state_lock);
|
||||
down_read(&user_list_lock);
|
||||
|
||||
list_for_each_entry(as, &apm_user_list, list) {
|
||||
if (as->suspend_state != SUSPEND_WAIT && as->reader &&
|
||||
as->writer && as->suser) {
|
||||
as->suspend_state = SUSPEND_PENDING;
|
||||
atomic_inc(&suspend_acks_pending);
|
||||
queue_add_event(&as->queue, APM_USER_SUSPEND);
|
||||
}
|
||||
}
|
||||
|
||||
up_read(&user_list_lock);
|
||||
mutex_unlock(&state_lock);
|
||||
wake_up_interruptible(&apm_waitqueue);
|
||||
|
||||
/*
|
||||
* Wait for the the suspend_acks_pending variable to drop to
|
||||
* zero, meaning everybody acked the suspend event (or the
|
||||
* process was killed.)
|
||||
*
|
||||
* If the app won't answer within a short while we assume it
|
||||
* locked up and ignore it.
|
||||
*/
|
||||
err = wait_event_interruptible_timeout(
|
||||
apm_suspend_waitqueue,
|
||||
atomic_read(&suspend_acks_pending) == 0,
|
||||
5*HZ);
|
||||
|
||||
/* timed out */
|
||||
if (err == 0) {
|
||||
/*
|
||||
* Move anybody who timed out to "ack timeout" state.
|
||||
*
|
||||
* We could time out and the userspace does the ACK
|
||||
* right after we time out but before we enter the
|
||||
* locked section here, but that's fine.
|
||||
*/
|
||||
mutex_lock(&state_lock);
|
||||
down_read(&user_list_lock);
|
||||
list_for_each_entry(as, &apm_user_list, list) {
|
||||
if (as->suspend_state == SUSPEND_PENDING ||
|
||||
as->suspend_state == SUSPEND_READ) {
|
||||
as->suspend_state = SUSPEND_ACKTO;
|
||||
atomic_dec(&suspend_acks_pending);
|
||||
}
|
||||
}
|
||||
up_read(&user_list_lock);
|
||||
mutex_unlock(&state_lock);
|
||||
}
|
||||
|
||||
/* let suspend proceed */
|
||||
if (err >= 0)
|
||||
return NOTIFY_OK;
|
||||
|
||||
/* interrupted by signal */
|
||||
return NOTIFY_BAD;
|
||||
|
||||
case PM_POST_SUSPEND:
|
||||
/*
|
||||
* Anyone on the APM queues will think we're still suspended.
|
||||
* Send a message so everyone knows we're now awake again.
|
||||
*/
|
||||
queue_event(APM_NORMAL_RESUME);
|
||||
|
||||
/*
|
||||
* Finally, wake up anyone who is sleeping on the suspend.
|
||||
*/
|
||||
mutex_lock(&state_lock);
|
||||
down_read(&user_list_lock);
|
||||
list_for_each_entry(as, &apm_user_list, list) {
|
||||
if (as->suspend_state == SUSPEND_ACKED) {
|
||||
/*
|
||||
* TODO: maybe grab error code, needs core
|
||||
* changes to push the error to the notifier
|
||||
* chain (could use the second parameter if
|
||||
* implemented)
|
||||
*/
|
||||
as->suspend_result = 0;
|
||||
as->suspend_state = SUSPEND_DONE;
|
||||
}
|
||||
}
|
||||
up_read(&user_list_lock);
|
||||
mutex_unlock(&state_lock);
|
||||
|
||||
wake_up(&apm_suspend_waitqueue);
|
||||
return NOTIFY_OK;
|
||||
|
||||
default:
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
static struct notifier_block apm_notif_block = {
|
||||
.notifier_call = apm_suspend_notifier,
|
||||
};
|
||||
|
||||
static int __init apm_init(void)
|
||||
{
|
||||
int ret;
|
||||
@ -604,7 +661,7 @@ static int __init apm_init(void)
|
||||
if (IS_ERR(kapmd_tsk)) {
|
||||
ret = PTR_ERR(kapmd_tsk);
|
||||
kapmd_tsk = NULL;
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
wake_up_process(kapmd_tsk);
|
||||
|
||||
@ -613,16 +670,27 @@ static int __init apm_init(void)
|
||||
#endif
|
||||
|
||||
ret = misc_register(&apm_device);
|
||||
if (ret != 0) {
|
||||
remove_proc_entry("apm", NULL);
|
||||
kthread_stop(kapmd_tsk);
|
||||
}
|
||||
if (ret)
|
||||
goto out_stop;
|
||||
|
||||
ret = register_pm_notifier(&apm_notif_block);
|
||||
if (ret)
|
||||
goto out_unregister;
|
||||
|
||||
return 0;
|
||||
|
||||
out_unregister:
|
||||
misc_deregister(&apm_device);
|
||||
out_stop:
|
||||
remove_proc_entry("apm", NULL);
|
||||
kthread_stop(kapmd_tsk);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit apm_exit(void)
|
||||
{
|
||||
unregister_pm_notifier(&apm_notif_block);
|
||||
misc_deregister(&apm_device);
|
||||
remove_proc_entry("apm", NULL);
|
||||
|
||||
|
@ -179,17 +179,29 @@ config FUJITSU_LAPTOP
|
||||
tristate "Fujitsu Laptop Extras"
|
||||
depends on X86
|
||||
depends on ACPI
|
||||
depends on INPUT
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
---help---
|
||||
This is a driver for laptops built by Fujitsu:
|
||||
|
||||
* P2xxx/P5xxx/S6xxx/S7xxx series Lifebooks
|
||||
* Possibly other Fujitsu laptop models
|
||||
* Tested with S6410 and S7020
|
||||
|
||||
It adds support for LCD brightness control.
|
||||
It adds support for LCD brightness control and some hotkeys.
|
||||
|
||||
If you have a Fujitsu laptop, say Y or M here.
|
||||
|
||||
config FUJITSU_LAPTOP_DEBUG
|
||||
bool "Verbose debug mode for Fujitsu Laptop Extras"
|
||||
depends on FUJITSU_LAPTOP
|
||||
default n
|
||||
---help---
|
||||
Enables extra debug output from the fujitsu extras driver, at the
|
||||
expense of a slight increase in driver size.
|
||||
|
||||
If you are not sure, say N here.
|
||||
|
||||
config TC1100_WMI
|
||||
tristate "HP Compaq TC1100 Tablet WMI Extras (EXPERIMENTAL)"
|
||||
depends on X86 && !X86_64
|
||||
@ -219,6 +231,23 @@ config MSI_LAPTOP
|
||||
|
||||
If you have an MSI S270 laptop, say Y or M here.
|
||||
|
||||
config COMPAL_LAPTOP
|
||||
tristate "Compal Laptop Extras"
|
||||
depends on X86
|
||||
depends on ACPI_EC
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
---help---
|
||||
This is a driver for laptops built by Compal:
|
||||
|
||||
Compal FL90/IFL90
|
||||
Compal FL91/IFL91
|
||||
Compal FL92/JFL92
|
||||
Compal FT00/IFT00
|
||||
|
||||
It adds support for Bluetooth, WLAN and LCD brightness control.
|
||||
|
||||
If you have an Compal FL9x/IFL9x/FT00 laptop, say Y or M here.
|
||||
|
||||
config SONY_LAPTOP
|
||||
tristate "Sony Laptop Extras"
|
||||
depends on X86 && ACPI
|
||||
|
@ -5,10 +5,11 @@ obj- := misc.o # Dummy rule to force built-in.o to be made
|
||||
|
||||
obj-$(CONFIG_IBM_ASM) += ibmasm/
|
||||
obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/
|
||||
obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
|
||||
obj-$(CONFIG_ACER_WMI) += acer-wmi.o
|
||||
obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
|
||||
obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o
|
||||
obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
|
||||
obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o
|
||||
obj-$(CONFIG_ACER_WMI) += acer-wmi.o
|
||||
obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o
|
||||
obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
|
||||
obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o
|
||||
|
@ -22,18 +22,18 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define ACER_WMI_VERSION "0.1"
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/i8042.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include <acpi/acpi_drivers.h>
|
||||
|
||||
@ -87,6 +87,7 @@ struct acer_quirks {
|
||||
* Acer ACPI method GUIDs
|
||||
*/
|
||||
#define AMW0_GUID1 "67C3371D-95A3-4C37-BB61-DD47B491DAAB"
|
||||
#define AMW0_GUID2 "431F16ED-0C2B-444C-B267-27DEB140CF9C"
|
||||
#define WMID_GUID1 "6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3"
|
||||
#define WMID_GUID2 "95764E09-FB56-4e83-B31A-37761F60994A"
|
||||
|
||||
@ -150,6 +151,12 @@ struct acer_data {
|
||||
int brightness;
|
||||
};
|
||||
|
||||
struct acer_debug {
|
||||
struct dentry *root;
|
||||
struct dentry *devices;
|
||||
u32 wmid_devices;
|
||||
};
|
||||
|
||||
/* Each low-level interface must define at least some of the following */
|
||||
struct wmi_interface {
|
||||
/* The WMI device type */
|
||||
@ -160,6 +167,9 @@ struct wmi_interface {
|
||||
|
||||
/* Private data for the current interface */
|
||||
struct acer_data data;
|
||||
|
||||
/* debugfs entries associated with this interface */
|
||||
struct acer_debug debug;
|
||||
};
|
||||
|
||||
/* The static interface pointer, points to the currently detected interface */
|
||||
@ -174,7 +184,7 @@ static struct wmi_interface *interface;
|
||||
struct quirk_entry {
|
||||
u8 wireless;
|
||||
u8 mailled;
|
||||
u8 brightness;
|
||||
s8 brightness;
|
||||
u8 bluetooth;
|
||||
};
|
||||
|
||||
@ -198,6 +208,10 @@ static int dmi_matched(const struct dmi_system_id *dmi)
|
||||
static struct quirk_entry quirk_unknown = {
|
||||
};
|
||||
|
||||
static struct quirk_entry quirk_acer_aspire_1520 = {
|
||||
.brightness = -1,
|
||||
};
|
||||
|
||||
static struct quirk_entry quirk_acer_travelmate_2490 = {
|
||||
.mailled = 1,
|
||||
};
|
||||
@ -207,7 +221,29 @@ static struct quirk_entry quirk_medion_md_98300 = {
|
||||
.wireless = 1,
|
||||
};
|
||||
|
||||
static struct quirk_entry quirk_fujitsu_amilo_li_1718 = {
|
||||
.wireless = 2,
|
||||
};
|
||||
|
||||
static struct dmi_system_id acer_quirks[] = {
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "Acer Aspire 1360",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"),
|
||||
},
|
||||
.driver_data = &quirk_acer_aspire_1520,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "Acer Aspire 1520",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1520"),
|
||||
},
|
||||
.driver_data = &quirk_acer_aspire_1520,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "Acer Aspire 3100",
|
||||
@ -298,6 +334,15 @@ static struct dmi_system_id acer_quirks[] = {
|
||||
},
|
||||
.driver_data = &quirk_acer_travelmate_2490,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "Fujitsu Siemens Amilo Li 1718",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Li 1718"),
|
||||
},
|
||||
.driver_data = &quirk_fujitsu_amilo_li_1718,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "Medion MD 98300",
|
||||
@ -393,6 +438,12 @@ struct wmi_interface *iface)
|
||||
return AE_ERROR;
|
||||
*value = result & 0x1;
|
||||
return AE_OK;
|
||||
case 2:
|
||||
err = ec_read(0x71, &result);
|
||||
if (err)
|
||||
return AE_ERROR;
|
||||
*value = result & 0x1;
|
||||
return AE_OK;
|
||||
default:
|
||||
err = ec_read(0xA, &result);
|
||||
if (err)
|
||||
@ -506,6 +557,15 @@ static acpi_status AMW0_set_capabilities(void)
|
||||
struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
union acpi_object *obj;
|
||||
|
||||
/*
|
||||
* On laptops with this strange GUID (non Acer), normal probing doesn't
|
||||
* work.
|
||||
*/
|
||||
if (wmi_has_guid(AMW0_GUID2)) {
|
||||
interface->capability |= ACER_CAP_WIRELESS;
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
args.eax = ACER_AMW0_WRITE;
|
||||
args.ecx = args.edx = 0;
|
||||
|
||||
@ -552,7 +612,8 @@ static acpi_status AMW0_set_capabilities(void)
|
||||
* appear to use the same EC register for brightness, even if they
|
||||
* differ for wireless, etc
|
||||
*/
|
||||
interface->capability |= ACER_CAP_BRIGHTNESS;
|
||||
if (quirks->brightness >= 0)
|
||||
interface->capability |= ACER_CAP_BRIGHTNESS;
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
@ -807,7 +868,15 @@ static int read_brightness(struct backlight_device *bd)
|
||||
|
||||
static int update_bl_status(struct backlight_device *bd)
|
||||
{
|
||||
set_u32(bd->props.brightness, ACER_CAP_BRIGHTNESS);
|
||||
int intensity = bd->props.brightness;
|
||||
|
||||
if (bd->props.power != FB_BLANK_UNBLANK)
|
||||
intensity = 0;
|
||||
if (bd->props.fb_blank != FB_BLANK_UNBLANK)
|
||||
intensity = 0;
|
||||
|
||||
set_u32(intensity, ACER_CAP_BRIGHTNESS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -829,8 +898,9 @@ static int __devinit acer_backlight_init(struct device *dev)
|
||||
|
||||
acer_backlight_device = bd;
|
||||
|
||||
bd->props.power = FB_BLANK_UNBLANK;
|
||||
bd->props.brightness = max_brightness;
|
||||
bd->props.max_brightness = max_brightness;
|
||||
bd->props.brightness = read_brightness(NULL);
|
||||
backlight_update_status(bd);
|
||||
return 0;
|
||||
}
|
||||
@ -893,6 +963,28 @@ static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
|
||||
static DEVICE_ATTR(interface, S_IWUGO | S_IRUGO | S_IWUSR,
|
||||
show_interface, NULL);
|
||||
|
||||
/*
|
||||
* debugfs functions
|
||||
*/
|
||||
static u32 get_wmid_devices(void)
|
||||
{
|
||||
struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
union acpi_object *obj;
|
||||
acpi_status status;
|
||||
|
||||
status = wmi_query_block(WMID_GUID2, 1, &out);
|
||||
if (ACPI_FAILURE(status))
|
||||
return 0;
|
||||
|
||||
obj = (union acpi_object *) out.pointer;
|
||||
if (obj && obj->type == ACPI_TYPE_BUFFER &&
|
||||
obj->buffer.length == sizeof(u32)) {
|
||||
return *((u32 *) obj->buffer.pointer);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Platform device
|
||||
*/
|
||||
@ -1052,12 +1144,40 @@ static int create_sysfs(void)
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void remove_debugfs(void)
|
||||
{
|
||||
debugfs_remove(interface->debug.devices);
|
||||
debugfs_remove(interface->debug.root);
|
||||
}
|
||||
|
||||
static int create_debugfs(void)
|
||||
{
|
||||
interface->debug.root = debugfs_create_dir("acer-wmi", NULL);
|
||||
if (!interface->debug.root) {
|
||||
printk(ACER_ERR "Failed to create debugfs directory");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
interface->debug.devices = debugfs_create_u32("devices", S_IRUGO,
|
||||
interface->debug.root,
|
||||
&interface->debug.wmid_devices);
|
||||
if (!interface->debug.devices)
|
||||
goto error_debugfs;
|
||||
|
||||
return 0;
|
||||
|
||||
error_debugfs:
|
||||
remove_debugfs();
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int __init acer_wmi_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
printk(ACER_INFO "Acer Laptop ACPI-WMI Extras version %s\n",
|
||||
ACER_WMI_VERSION);
|
||||
printk(ACER_INFO "Acer Laptop ACPI-WMI Extras\n");
|
||||
|
||||
find_quirks();
|
||||
|
||||
/*
|
||||
* Detect which ACPI-WMI interface we're using.
|
||||
@ -1092,8 +1212,6 @@ static int __init acer_wmi_init(void)
|
||||
if (wmi_has_guid(AMW0_GUID1))
|
||||
AMW0_find_mailled();
|
||||
|
||||
find_quirks();
|
||||
|
||||
if (!interface) {
|
||||
printk(ACER_ERR "No or unsupported WMI interface, unable to "
|
||||
"load\n");
|
||||
@ -1111,6 +1229,13 @@ static int __init acer_wmi_init(void)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (wmi_has_guid(WMID_GUID2)) {
|
||||
interface->debug.wmid_devices = get_wmid_devices();
|
||||
err = create_debugfs();
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Override any initial settings with values from the commandline */
|
||||
acer_commandline_init();
|
||||
|
||||
|
404
drivers/misc/compal-laptop.c
Normal file
404
drivers/misc/compal-laptop.c
Normal file
@ -0,0 +1,404 @@
|
||||
/*-*-linux-c-*-*/
|
||||
|
||||
/*
|
||||
Copyright (C) 2008 Cezary Jackiewicz <cezary.jackiewicz (at) gmail.com>
|
||||
|
||||
based on MSI driver
|
||||
|
||||
Copyright (C) 2006 Lennart Poettering <mzxreary (at) 0pointer (dot) de>
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* comapl-laptop.c - Compal laptop support.
|
||||
*
|
||||
* This driver exports a few files in /sys/devices/platform/compal-laptop/:
|
||||
*
|
||||
* wlan - wlan subsystem state: contains 0 or 1 (rw)
|
||||
*
|
||||
* bluetooth - Bluetooth subsystem state: contains 0 or 1 (rw)
|
||||
*
|
||||
* raw - raw value taken from embedded controller register (ro)
|
||||
*
|
||||
* In addition to these platform device attributes the driver
|
||||
* registers itself in the Linux backlight control subsystem and is
|
||||
* available to userspace under /sys/class/backlight/compal-laptop/.
|
||||
*
|
||||
* This driver might work on other laptops produced by Compal. If you
|
||||
* want to try it you can pass force=1 as argument to the module which
|
||||
* will force it to load even when the DMI data doesn't identify the
|
||||
* laptop as FL9x.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/autoconf.h>
|
||||
|
||||
#define COMPAL_DRIVER_VERSION "0.2.6"
|
||||
|
||||
#define COMPAL_LCD_LEVEL_MAX 8
|
||||
|
||||
#define COMPAL_EC_COMMAND_WIRELESS 0xBB
|
||||
#define COMPAL_EC_COMMAND_LCD_LEVEL 0xB9
|
||||
|
||||
#define KILLSWITCH_MASK 0x10
|
||||
#define WLAN_MASK 0x01
|
||||
#define BT_MASK 0x02
|
||||
|
||||
static int force;
|
||||
module_param(force, bool, 0);
|
||||
MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
|
||||
|
||||
/* Hardware access */
|
||||
|
||||
static int set_lcd_level(int level)
|
||||
{
|
||||
if (level < 0 || level >= COMPAL_LCD_LEVEL_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
ec_write(COMPAL_EC_COMMAND_LCD_LEVEL, level);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_lcd_level(void)
|
||||
{
|
||||
u8 result;
|
||||
|
||||
ec_read(COMPAL_EC_COMMAND_LCD_LEVEL, &result);
|
||||
|
||||
return (int) result;
|
||||
}
|
||||
|
||||
static int set_wlan_state(int state)
|
||||
{
|
||||
u8 result, value;
|
||||
|
||||
ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
|
||||
|
||||
if ((result & KILLSWITCH_MASK) == 0)
|
||||
return -EINVAL;
|
||||
else {
|
||||
if (state)
|
||||
value = (u8) (result | WLAN_MASK);
|
||||
else
|
||||
value = (u8) (result & ~WLAN_MASK);
|
||||
ec_write(COMPAL_EC_COMMAND_WIRELESS, value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_bluetooth_state(int state)
|
||||
{
|
||||
u8 result, value;
|
||||
|
||||
ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
|
||||
|
||||
if ((result & KILLSWITCH_MASK) == 0)
|
||||
return -EINVAL;
|
||||
else {
|
||||
if (state)
|
||||
value = (u8) (result | BT_MASK);
|
||||
else
|
||||
value = (u8) (result & ~BT_MASK);
|
||||
ec_write(COMPAL_EC_COMMAND_WIRELESS, value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_wireless_state(int *wlan, int *bluetooth)
|
||||
{
|
||||
u8 result;
|
||||
|
||||
ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
|
||||
|
||||
if (wlan) {
|
||||
if ((result & KILLSWITCH_MASK) == 0)
|
||||
*wlan = 0;
|
||||
else
|
||||
*wlan = result & WLAN_MASK;
|
||||
}
|
||||
|
||||
if (bluetooth) {
|
||||
if ((result & KILLSWITCH_MASK) == 0)
|
||||
*bluetooth = 0;
|
||||
else
|
||||
*bluetooth = (result & BT_MASK) >> 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Backlight device stuff */
|
||||
|
||||
static int bl_get_brightness(struct backlight_device *b)
|
||||
{
|
||||
return get_lcd_level();
|
||||
}
|
||||
|
||||
|
||||
static int bl_update_status(struct backlight_device *b)
|
||||
{
|
||||
return set_lcd_level(b->props.brightness);
|
||||
}
|
||||
|
||||
static struct backlight_ops compalbl_ops = {
|
||||
.get_brightness = bl_get_brightness,
|
||||
.update_status = bl_update_status,
|
||||
};
|
||||
|
||||
static struct backlight_device *compalbl_device;
|
||||
|
||||
/* Platform device */
|
||||
|
||||
static ssize_t show_wlan(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int ret, enabled;
|
||||
|
||||
ret = get_wireless_state(&enabled, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%i\n", enabled);
|
||||
}
|
||||
|
||||
static ssize_t show_raw(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
u8 result;
|
||||
|
||||
ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
|
||||
|
||||
return sprintf(buf, "%i\n", result);
|
||||
}
|
||||
|
||||
static ssize_t show_bluetooth(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int ret, enabled;
|
||||
|
||||
ret = get_wireless_state(NULL, &enabled);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%i\n", enabled);
|
||||
}
|
||||
|
||||
static ssize_t store_wlan_state(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int state, ret;
|
||||
|
||||
if (sscanf(buf, "%i", &state) != 1 || (state < 0 || state > 1))
|
||||
return -EINVAL;
|
||||
|
||||
ret = set_wlan_state(state);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t store_bluetooth_state(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int state, ret;
|
||||
|
||||
if (sscanf(buf, "%i", &state) != 1 || (state < 0 || state > 1))
|
||||
return -EINVAL;
|
||||
|
||||
ret = set_bluetooth_state(state);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(bluetooth, 0644, show_bluetooth, store_bluetooth_state);
|
||||
static DEVICE_ATTR(wlan, 0644, show_wlan, store_wlan_state);
|
||||
static DEVICE_ATTR(raw, 0444, show_raw, NULL);
|
||||
|
||||
static struct attribute *compal_attributes[] = {
|
||||
&dev_attr_bluetooth.attr,
|
||||
&dev_attr_wlan.attr,
|
||||
&dev_attr_raw.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group compal_attribute_group = {
|
||||
.attrs = compal_attributes
|
||||
};
|
||||
|
||||
static struct platform_driver compal_driver = {
|
||||
.driver = {
|
||||
.name = "compal-laptop",
|
||||
.owner = THIS_MODULE,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device *compal_device;
|
||||
|
||||
/* Initialization */
|
||||
|
||||
static int dmi_check_cb(const struct dmi_system_id *id)
|
||||
{
|
||||
printk(KERN_INFO "compal-laptop: Identified laptop model '%s'.\n",
|
||||
id->ident);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dmi_system_id __initdata compal_dmi_table[] = {
|
||||
{
|
||||
.ident = "FL90/IFL90",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "IFL90"),
|
||||
DMI_MATCH(DMI_BOARD_VERSION, "IFT00"),
|
||||
},
|
||||
.callback = dmi_check_cb
|
||||
},
|
||||
{
|
||||
.ident = "FL90/IFL90",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "IFL90"),
|
||||
DMI_MATCH(DMI_BOARD_VERSION, "REFERENCE"),
|
||||
},
|
||||
.callback = dmi_check_cb
|
||||
},
|
||||
{
|
||||
.ident = "FL91/IFL91",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "IFL91"),
|
||||
DMI_MATCH(DMI_BOARD_VERSION, "IFT00"),
|
||||
},
|
||||
.callback = dmi_check_cb
|
||||
},
|
||||
{
|
||||
.ident = "FL92/JFL92",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "JFL92"),
|
||||
DMI_MATCH(DMI_BOARD_VERSION, "IFT00"),
|
||||
},
|
||||
.callback = dmi_check_cb
|
||||
},
|
||||
{
|
||||
.ident = "FT00/IFT00",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "IFT00"),
|
||||
DMI_MATCH(DMI_BOARD_VERSION, "IFT00"),
|
||||
},
|
||||
.callback = dmi_check_cb
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static int __init compal_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (acpi_disabled)
|
||||
return -ENODEV;
|
||||
|
||||
if (!force && !dmi_check_system(compal_dmi_table))
|
||||
return -ENODEV;
|
||||
|
||||
/* Register backlight stuff */
|
||||
|
||||
compalbl_device = backlight_device_register("compal-laptop", NULL, NULL,
|
||||
&compalbl_ops);
|
||||
if (IS_ERR(compalbl_device))
|
||||
return PTR_ERR(compalbl_device);
|
||||
|
||||
compalbl_device->props.max_brightness = COMPAL_LCD_LEVEL_MAX-1;
|
||||
|
||||
ret = platform_driver_register(&compal_driver);
|
||||
if (ret)
|
||||
goto fail_backlight;
|
||||
|
||||
/* Register platform stuff */
|
||||
|
||||
compal_device = platform_device_alloc("compal-laptop", -1);
|
||||
if (!compal_device) {
|
||||
ret = -ENOMEM;
|
||||
goto fail_platform_driver;
|
||||
}
|
||||
|
||||
ret = platform_device_add(compal_device);
|
||||
if (ret)
|
||||
goto fail_platform_device1;
|
||||
|
||||
ret = sysfs_create_group(&compal_device->dev.kobj,
|
||||
&compal_attribute_group);
|
||||
if (ret)
|
||||
goto fail_platform_device2;
|
||||
|
||||
printk(KERN_INFO "compal-laptop: driver "COMPAL_DRIVER_VERSION
|
||||
" successfully loaded.\n");
|
||||
|
||||
return 0;
|
||||
|
||||
fail_platform_device2:
|
||||
|
||||
platform_device_del(compal_device);
|
||||
|
||||
fail_platform_device1:
|
||||
|
||||
platform_device_put(compal_device);
|
||||
|
||||
fail_platform_driver:
|
||||
|
||||
platform_driver_unregister(&compal_driver);
|
||||
|
||||
fail_backlight:
|
||||
|
||||
backlight_device_unregister(compalbl_device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit compal_cleanup(void)
|
||||
{
|
||||
|
||||
sysfs_remove_group(&compal_device->dev.kobj, &compal_attribute_group);
|
||||
platform_device_unregister(compal_device);
|
||||
platform_driver_unregister(&compal_driver);
|
||||
backlight_device_unregister(compalbl_device);
|
||||
|
||||
printk(KERN_INFO "compal-laptop: driver unloaded.\n");
|
||||
}
|
||||
|
||||
module_init(compal_init);
|
||||
module_exit(compal_cleanup);
|
||||
|
||||
MODULE_AUTHOR("Cezary Jackiewicz");
|
||||
MODULE_DESCRIPTION("Compal Laptop Support");
|
||||
MODULE_VERSION(COMPAL_DRIVER_VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
MODULE_ALIAS("dmi:*:rnIFL90:rvrIFT00:*");
|
||||
MODULE_ALIAS("dmi:*:rnIFL90:rvrREFERENCE:*");
|
||||
MODULE_ALIAS("dmi:*:rnIFL91:rvrIFT00:*");
|
||||
MODULE_ALIAS("dmi:*:rnJFL92:rvrIFT00:*");
|
||||
MODULE_ALIAS("dmi:*:rnIFT00:rvrIFT00:*");
|
@ -87,7 +87,7 @@ enum {
|
||||
CM_ASL_LID
|
||||
};
|
||||
|
||||
const char *cm_getv[] = {
|
||||
static const char *cm_getv[] = {
|
||||
"WLDG", NULL, NULL, NULL,
|
||||
"CAMG", NULL, NULL, NULL,
|
||||
NULL, "PBLG", NULL, NULL,
|
||||
@ -96,7 +96,7 @@ const char *cm_getv[] = {
|
||||
"CRDG", "LIDG"
|
||||
};
|
||||
|
||||
const char *cm_setv[] = {
|
||||
static const char *cm_setv[] = {
|
||||
"WLDS", NULL, NULL, NULL,
|
||||
"CAMS", NULL, NULL, NULL,
|
||||
"SDSP", "PBLS", "HDPS", NULL,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -293,13 +293,11 @@ EXPORT_SYMBOL(pci_osc_control_set);
|
||||
* choose highest power _SxD or any lower power
|
||||
*/
|
||||
|
||||
static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev,
|
||||
pm_message_t state)
|
||||
static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev)
|
||||
{
|
||||
int acpi_state;
|
||||
|
||||
acpi_state = acpi_pm_device_sleep_state(&pdev->dev,
|
||||
device_may_wakeup(&pdev->dev), NULL);
|
||||
acpi_state = acpi_pm_device_sleep_state(&pdev->dev, NULL);
|
||||
if (acpi_state < 0)
|
||||
return PCI_POWER_ERROR;
|
||||
|
||||
|
@ -508,7 +508,7 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
|
||||
pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev);
|
||||
|
||||
/**
|
||||
* pci_choose_state - Choose the power state of a PCI device
|
||||
@ -528,7 +528,7 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
|
||||
return PCI_D0;
|
||||
|
||||
if (platform_pci_choose_state) {
|
||||
ret = platform_pci_choose_state(dev, state);
|
||||
ret = platform_pci_choose_state(dev);
|
||||
if (ret != PCI_POWER_ERROR)
|
||||
return ret;
|
||||
}
|
||||
|
@ -6,8 +6,7 @@ extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
|
||||
extern void pci_cleanup_rom(struct pci_dev *dev);
|
||||
|
||||
/* Firmware callbacks */
|
||||
extern pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev,
|
||||
pm_message_t state);
|
||||
extern pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev);
|
||||
extern int (*platform_pci_set_power_state)(struct pci_dev *dev,
|
||||
pci_power_t state);
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
|
||||
* Bjorn Helgaas <bjorn.helgaas@hp.com>
|
||||
*/
|
||||
|
||||
extern spinlock_t pnp_lock;
|
||||
void *pnp_alloc(long size);
|
||||
|
||||
@ -19,22 +24,118 @@ void pnp_remove_card(struct pnp_card *card);
|
||||
int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev);
|
||||
void pnp_remove_card_device(struct pnp_dev *dev);
|
||||
|
||||
struct pnp_option *pnp_build_option(int priority);
|
||||
struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev);
|
||||
struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
|
||||
int priority);
|
||||
int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option,
|
||||
struct pnp_irq *data);
|
||||
int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option,
|
||||
struct pnp_dma *data);
|
||||
int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option,
|
||||
struct pnp_port *data);
|
||||
int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option,
|
||||
struct pnp_mem *data);
|
||||
struct pnp_port {
|
||||
resource_size_t min; /* min base number */
|
||||
resource_size_t max; /* max base number */
|
||||
resource_size_t align; /* align boundary */
|
||||
resource_size_t size; /* size of range */
|
||||
unsigned char flags; /* port flags */
|
||||
};
|
||||
|
||||
#define PNP_IRQ_NR 256
|
||||
typedef struct { DECLARE_BITMAP(bits, PNP_IRQ_NR); } pnp_irq_mask_t;
|
||||
|
||||
struct pnp_irq {
|
||||
pnp_irq_mask_t map; /* bitmap for IRQ lines */
|
||||
unsigned char flags; /* IRQ flags */
|
||||
};
|
||||
|
||||
struct pnp_dma {
|
||||
unsigned char map; /* bitmask for DMA channels */
|
||||
unsigned char flags; /* DMA flags */
|
||||
};
|
||||
|
||||
struct pnp_mem {
|
||||
resource_size_t min; /* min base number */
|
||||
resource_size_t max; /* max base number */
|
||||
resource_size_t align; /* align boundary */
|
||||
resource_size_t size; /* size of range */
|
||||
unsigned char flags; /* memory flags */
|
||||
};
|
||||
|
||||
#define PNP_OPTION_DEPENDENT 0x80000000
|
||||
#define PNP_OPTION_SET_MASK 0xffff
|
||||
#define PNP_OPTION_SET_SHIFT 12
|
||||
#define PNP_OPTION_PRIORITY_MASK 0xfff
|
||||
#define PNP_OPTION_PRIORITY_SHIFT 0
|
||||
|
||||
#define PNP_RES_PRIORITY_PREFERRED 0
|
||||
#define PNP_RES_PRIORITY_ACCEPTABLE 1
|
||||
#define PNP_RES_PRIORITY_FUNCTIONAL 2
|
||||
#define PNP_RES_PRIORITY_INVALID PNP_OPTION_PRIORITY_MASK
|
||||
|
||||
struct pnp_option {
|
||||
struct list_head list;
|
||||
unsigned int flags; /* independent/dependent, set, priority */
|
||||
|
||||
unsigned long type; /* IORESOURCE_{IO,MEM,IRQ,DMA} */
|
||||
union {
|
||||
struct pnp_port port;
|
||||
struct pnp_irq irq;
|
||||
struct pnp_dma dma;
|
||||
struct pnp_mem mem;
|
||||
} u;
|
||||
};
|
||||
|
||||
int pnp_register_irq_resource(struct pnp_dev *dev, unsigned int option_flags,
|
||||
pnp_irq_mask_t *map, unsigned char flags);
|
||||
int pnp_register_dma_resource(struct pnp_dev *dev, unsigned int option_flags,
|
||||
unsigned char map, unsigned char flags);
|
||||
int pnp_register_port_resource(struct pnp_dev *dev, unsigned int option_flags,
|
||||
resource_size_t min, resource_size_t max,
|
||||
resource_size_t align, resource_size_t size,
|
||||
unsigned char flags);
|
||||
int pnp_register_mem_resource(struct pnp_dev *dev, unsigned int option_flags,
|
||||
resource_size_t min, resource_size_t max,
|
||||
resource_size_t align, resource_size_t size,
|
||||
unsigned char flags);
|
||||
|
||||
static inline int pnp_option_is_dependent(struct pnp_option *option)
|
||||
{
|
||||
return option->flags & PNP_OPTION_DEPENDENT ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline unsigned int pnp_option_set(struct pnp_option *option)
|
||||
{
|
||||
return (option->flags >> PNP_OPTION_SET_SHIFT) & PNP_OPTION_SET_MASK;
|
||||
}
|
||||
|
||||
static inline unsigned int pnp_option_priority(struct pnp_option *option)
|
||||
{
|
||||
return (option->flags >> PNP_OPTION_PRIORITY_SHIFT) &
|
||||
PNP_OPTION_PRIORITY_MASK;
|
||||
}
|
||||
|
||||
static inline unsigned int pnp_new_dependent_set(struct pnp_dev *dev,
|
||||
int priority)
|
||||
{
|
||||
unsigned int flags;
|
||||
|
||||
if (priority > PNP_RES_PRIORITY_FUNCTIONAL) {
|
||||
dev_warn(&dev->dev, "invalid dependent option priority %d "
|
||||
"clipped to %d", priority,
|
||||
PNP_RES_PRIORITY_INVALID);
|
||||
priority = PNP_RES_PRIORITY_INVALID;
|
||||
}
|
||||
|
||||
flags = PNP_OPTION_DEPENDENT |
|
||||
((dev->num_dependent_sets & PNP_OPTION_SET_MASK) <<
|
||||
PNP_OPTION_SET_SHIFT) |
|
||||
((priority & PNP_OPTION_PRIORITY_MASK) <<
|
||||
PNP_OPTION_PRIORITY_SHIFT);
|
||||
|
||||
dev->num_dependent_sets++;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
char *pnp_option_priority_name(struct pnp_option *option);
|
||||
void dbg_pnp_show_option(struct pnp_dev *dev, struct pnp_option *option);
|
||||
|
||||
void pnp_init_resources(struct pnp_dev *dev);
|
||||
|
||||
void pnp_fixup_device(struct pnp_dev *dev);
|
||||
void pnp_free_option(struct pnp_option *option);
|
||||
void pnp_free_options(struct pnp_dev *dev);
|
||||
int __pnp_add_device(struct pnp_dev *dev);
|
||||
void __pnp_remove_device(struct pnp_dev *dev);
|
||||
|
||||
@ -43,29 +144,18 @@ int pnp_check_mem(struct pnp_dev *dev, struct resource *res);
|
||||
int pnp_check_irq(struct pnp_dev *dev, struct resource *res);
|
||||
int pnp_check_dma(struct pnp_dev *dev, struct resource *res);
|
||||
|
||||
char *pnp_resource_type_name(struct resource *res);
|
||||
void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc);
|
||||
|
||||
void pnp_init_resource(struct resource *res);
|
||||
|
||||
struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev,
|
||||
unsigned int type, unsigned int num);
|
||||
|
||||
#define PNP_MAX_PORT 40
|
||||
#define PNP_MAX_MEM 24
|
||||
#define PNP_MAX_IRQ 2
|
||||
#define PNP_MAX_DMA 2
|
||||
void pnp_free_resources(struct pnp_dev *dev);
|
||||
int pnp_resource_type(struct resource *res);
|
||||
|
||||
struct pnp_resource {
|
||||
struct list_head list;
|
||||
struct resource res;
|
||||
unsigned int index; /* ISAPNP config register index */
|
||||
};
|
||||
|
||||
struct pnp_resource_table {
|
||||
struct pnp_resource port[PNP_MAX_PORT];
|
||||
struct pnp_resource mem[PNP_MAX_MEM];
|
||||
struct pnp_resource dma[PNP_MAX_DMA];
|
||||
struct pnp_resource irq[PNP_MAX_IRQ];
|
||||
};
|
||||
void pnp_free_resource(struct pnp_resource *pnp_res);
|
||||
|
||||
struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
|
||||
int flags);
|
||||
|
@ -99,14 +99,28 @@ static void pnp_free_ids(struct pnp_dev *dev)
|
||||
}
|
||||
}
|
||||
|
||||
void pnp_free_resource(struct pnp_resource *pnp_res)
|
||||
{
|
||||
list_del(&pnp_res->list);
|
||||
kfree(pnp_res);
|
||||
}
|
||||
|
||||
void pnp_free_resources(struct pnp_dev *dev)
|
||||
{
|
||||
struct pnp_resource *pnp_res, *tmp;
|
||||
|
||||
list_for_each_entry_safe(pnp_res, tmp, &dev->resources, list) {
|
||||
pnp_free_resource(pnp_res);
|
||||
}
|
||||
}
|
||||
|
||||
static void pnp_release_device(struct device *dmdev)
|
||||
{
|
||||
struct pnp_dev *dev = to_pnp_dev(dmdev);
|
||||
|
||||
pnp_free_option(dev->independent);
|
||||
pnp_free_option(dev->dependent);
|
||||
pnp_free_ids(dev);
|
||||
kfree(dev->res);
|
||||
pnp_free_resources(dev);
|
||||
pnp_free_options(dev);
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
@ -119,12 +133,8 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
dev->res = kzalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
|
||||
if (!dev->res) {
|
||||
kfree(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&dev->resources);
|
||||
INIT_LIST_HEAD(&dev->options);
|
||||
dev->protocol = protocol;
|
||||
dev->number = id;
|
||||
dev->dma_mask = DMA_24BIT_MASK;
|
||||
@ -140,7 +150,6 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid
|
||||
|
||||
dev_id = pnp_add_id(dev, pnpid);
|
||||
if (!dev_id) {
|
||||
kfree(dev->res);
|
||||
kfree(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
*
|
||||
* Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela <perex@perex.cz>
|
||||
* Copyright 2002 Adam Belay <ambx1@neo.rr.com>
|
||||
* Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
|
||||
* Bjorn Helgaas <bjorn.helgaas@hp.com>
|
||||
*/
|
||||
|
||||
#include <linux/pnp.h>
|
||||
@ -53,11 +55,13 @@ static int pnp_printf(pnp_info_buffer_t * buffer, char *fmt, ...)
|
||||
static void pnp_print_port(pnp_info_buffer_t * buffer, char *space,
|
||||
struct pnp_port *port)
|
||||
{
|
||||
pnp_printf(buffer,
|
||||
"%sport 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decoding\n",
|
||||
space, port->min, port->max,
|
||||
port->align ? (port->align - 1) : 0, port->size,
|
||||
port->flags & PNP_PORT_FLAG_16BITADDR ? 16 : 10);
|
||||
pnp_printf(buffer, "%sport %#llx-%#llx, align %#llx, size %#llx, "
|
||||
"%i-bit address decoding\n", space,
|
||||
(unsigned long long) port->min,
|
||||
(unsigned long long) port->max,
|
||||
port->align ? ((unsigned long long) port->align - 1) : 0,
|
||||
(unsigned long long) port->size,
|
||||
port->flags & IORESOURCE_IO_16BIT_ADDR ? 16 : 10);
|
||||
}
|
||||
|
||||
static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space,
|
||||
@ -67,7 +71,7 @@ static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space,
|
||||
|
||||
pnp_printf(buffer, "%sirq ", space);
|
||||
for (i = 0; i < PNP_IRQ_NR; i++)
|
||||
if (test_bit(i, irq->map)) {
|
||||
if (test_bit(i, irq->map.bits)) {
|
||||
if (!first) {
|
||||
pnp_printf(buffer, ",");
|
||||
} else {
|
||||
@ -78,7 +82,7 @@ static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space,
|
||||
else
|
||||
pnp_printf(buffer, "%i", i);
|
||||
}
|
||||
if (bitmap_empty(irq->map, PNP_IRQ_NR))
|
||||
if (bitmap_empty(irq->map.bits, PNP_IRQ_NR))
|
||||
pnp_printf(buffer, "<none>");
|
||||
if (irq->flags & IORESOURCE_IRQ_HIGHEDGE)
|
||||
pnp_printf(buffer, " High-Edge");
|
||||
@ -88,6 +92,8 @@ static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space,
|
||||
pnp_printf(buffer, " High-Level");
|
||||
if (irq->flags & IORESOURCE_IRQ_LOWLEVEL)
|
||||
pnp_printf(buffer, " Low-Level");
|
||||
if (irq->flags & IORESOURCE_IRQ_OPTIONAL)
|
||||
pnp_printf(buffer, " (optional)");
|
||||
pnp_printf(buffer, "\n");
|
||||
}
|
||||
|
||||
@ -148,8 +154,11 @@ static void pnp_print_mem(pnp_info_buffer_t * buffer, char *space,
|
||||
{
|
||||
char *s;
|
||||
|
||||
pnp_printf(buffer, "%sMemory 0x%x-0x%x, align 0x%x, size 0x%x",
|
||||
space, mem->min, mem->max, mem->align, mem->size);
|
||||
pnp_printf(buffer, "%sMemory %#llx-%#llx, align %#llx, size %#llx",
|
||||
space, (unsigned long long) mem->min,
|
||||
(unsigned long long) mem->max,
|
||||
(unsigned long long) mem->align,
|
||||
(unsigned long long) mem->size);
|
||||
if (mem->flags & IORESOURCE_MEM_WRITEABLE)
|
||||
pnp_printf(buffer, ", writeable");
|
||||
if (mem->flags & IORESOURCE_MEM_CACHEABLE)
|
||||
@ -177,65 +186,58 @@ static void pnp_print_mem(pnp_info_buffer_t * buffer, char *space,
|
||||
}
|
||||
|
||||
static void pnp_print_option(pnp_info_buffer_t * buffer, char *space,
|
||||
struct pnp_option *option, int dep)
|
||||
struct pnp_option *option)
|
||||
{
|
||||
char *s;
|
||||
struct pnp_port *port;
|
||||
struct pnp_irq *irq;
|
||||
struct pnp_dma *dma;
|
||||
struct pnp_mem *mem;
|
||||
|
||||
if (dep) {
|
||||
switch (option->priority) {
|
||||
case PNP_RES_PRIORITY_PREFERRED:
|
||||
s = "preferred";
|
||||
break;
|
||||
case PNP_RES_PRIORITY_ACCEPTABLE:
|
||||
s = "acceptable";
|
||||
break;
|
||||
case PNP_RES_PRIORITY_FUNCTIONAL:
|
||||
s = "functional";
|
||||
break;
|
||||
default:
|
||||
s = "invalid";
|
||||
}
|
||||
pnp_printf(buffer, "Dependent: %02i - Priority %s\n", dep, s);
|
||||
switch (option->type) {
|
||||
case IORESOURCE_IO:
|
||||
pnp_print_port(buffer, space, &option->u.port);
|
||||
break;
|
||||
case IORESOURCE_MEM:
|
||||
pnp_print_mem(buffer, space, &option->u.mem);
|
||||
break;
|
||||
case IORESOURCE_IRQ:
|
||||
pnp_print_irq(buffer, space, &option->u.irq);
|
||||
break;
|
||||
case IORESOURCE_DMA:
|
||||
pnp_print_dma(buffer, space, &option->u.dma);
|
||||
break;
|
||||
}
|
||||
|
||||
for (port = option->port; port; port = port->next)
|
||||
pnp_print_port(buffer, space, port);
|
||||
for (irq = option->irq; irq; irq = irq->next)
|
||||
pnp_print_irq(buffer, space, irq);
|
||||
for (dma = option->dma; dma; dma = dma->next)
|
||||
pnp_print_dma(buffer, space, dma);
|
||||
for (mem = option->mem; mem; mem = mem->next)
|
||||
pnp_print_mem(buffer, space, mem);
|
||||
}
|
||||
|
||||
static ssize_t pnp_show_options(struct device *dmdev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct pnp_dev *dev = to_pnp_dev(dmdev);
|
||||
struct pnp_option *independent = dev->independent;
|
||||
struct pnp_option *dependent = dev->dependent;
|
||||
int ret, dep = 1;
|
||||
pnp_info_buffer_t *buffer;
|
||||
struct pnp_option *option;
|
||||
int ret, dep = 0, set = 0;
|
||||
char *indent;
|
||||
|
||||
pnp_info_buffer_t *buffer = (pnp_info_buffer_t *)
|
||||
pnp_alloc(sizeof(pnp_info_buffer_t));
|
||||
buffer = pnp_alloc(sizeof(pnp_info_buffer_t));
|
||||
if (!buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
buffer->len = PAGE_SIZE;
|
||||
buffer->buffer = buf;
|
||||
buffer->curr = buffer->buffer;
|
||||
if (independent)
|
||||
pnp_print_option(buffer, "", independent, 0);
|
||||
|
||||
while (dependent) {
|
||||
pnp_print_option(buffer, " ", dependent, dep);
|
||||
dependent = dependent->next;
|
||||
dep++;
|
||||
list_for_each_entry(option, &dev->options, list) {
|
||||
if (pnp_option_is_dependent(option)) {
|
||||
indent = " ";
|
||||
if (!dep || pnp_option_set(option) != set) {
|
||||
set = pnp_option_set(option);
|
||||
dep = 1;
|
||||
pnp_printf(buffer, "Dependent: %02i - "
|
||||
"Priority %s\n", set,
|
||||
pnp_option_priority_name(option));
|
||||
}
|
||||
} else {
|
||||
dep = 0;
|
||||
indent = "";
|
||||
}
|
||||
pnp_print_option(buffer, indent, option);
|
||||
}
|
||||
|
||||
ret = (buffer->curr - buf);
|
||||
kfree(buffer);
|
||||
return ret;
|
||||
@ -248,79 +250,59 @@ static ssize_t pnp_show_current_resources(struct device *dmdev,
|
||||
char *buf)
|
||||
{
|
||||
struct pnp_dev *dev = to_pnp_dev(dmdev);
|
||||
struct resource *res;
|
||||
int i, ret;
|
||||
pnp_info_buffer_t *buffer;
|
||||
struct pnp_resource *pnp_res;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
if (!dev)
|
||||
return -EINVAL;
|
||||
|
||||
buffer = (pnp_info_buffer_t *) pnp_alloc(sizeof(pnp_info_buffer_t));
|
||||
buffer = pnp_alloc(sizeof(pnp_info_buffer_t));
|
||||
if (!buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
buffer->len = PAGE_SIZE;
|
||||
buffer->buffer = buf;
|
||||
buffer->curr = buffer->buffer;
|
||||
|
||||
pnp_printf(buffer, "state = ");
|
||||
if (dev->active)
|
||||
pnp_printf(buffer, "active\n");
|
||||
else
|
||||
pnp_printf(buffer, "disabled\n");
|
||||
pnp_printf(buffer, "state = %s\n", dev->active ? "active" : "disabled");
|
||||
|
||||
for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
|
||||
if (pnp_resource_valid(res)) {
|
||||
pnp_printf(buffer, "io");
|
||||
if (res->flags & IORESOURCE_DISABLED)
|
||||
pnp_printf(buffer, " disabled\n");
|
||||
else
|
||||
pnp_printf(buffer, " 0x%llx-0x%llx\n",
|
||||
(unsigned long long) res->start,
|
||||
(unsigned long long) res->end);
|
||||
}
|
||||
}
|
||||
for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
|
||||
if (pnp_resource_valid(res)) {
|
||||
pnp_printf(buffer, "mem");
|
||||
if (res->flags & IORESOURCE_DISABLED)
|
||||
pnp_printf(buffer, " disabled\n");
|
||||
else
|
||||
pnp_printf(buffer, " 0x%llx-0x%llx\n",
|
||||
(unsigned long long) res->start,
|
||||
(unsigned long long) res->end);
|
||||
}
|
||||
}
|
||||
for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) {
|
||||
if (pnp_resource_valid(res)) {
|
||||
pnp_printf(buffer, "irq");
|
||||
if (res->flags & IORESOURCE_DISABLED)
|
||||
pnp_printf(buffer, " disabled\n");
|
||||
else
|
||||
pnp_printf(buffer, " %lld\n",
|
||||
(unsigned long long) res->start);
|
||||
}
|
||||
}
|
||||
for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) {
|
||||
if (pnp_resource_valid(res)) {
|
||||
pnp_printf(buffer, "dma");
|
||||
if (res->flags & IORESOURCE_DISABLED)
|
||||
pnp_printf(buffer, " disabled\n");
|
||||
else
|
||||
pnp_printf(buffer, " %lld\n",
|
||||
(unsigned long long) res->start);
|
||||
list_for_each_entry(pnp_res, &dev->resources, list) {
|
||||
res = &pnp_res->res;
|
||||
|
||||
pnp_printf(buffer, pnp_resource_type_name(res));
|
||||
|
||||
if (res->flags & IORESOURCE_DISABLED) {
|
||||
pnp_printf(buffer, " disabled\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (pnp_resource_type(res)) {
|
||||
case IORESOURCE_IO:
|
||||
case IORESOURCE_MEM:
|
||||
pnp_printf(buffer, " %#llx-%#llx\n",
|
||||
(unsigned long long) res->start,
|
||||
(unsigned long long) res->end);
|
||||
break;
|
||||
case IORESOURCE_IRQ:
|
||||
case IORESOURCE_DMA:
|
||||
pnp_printf(buffer, " %lld\n",
|
||||
(unsigned long long) res->start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = (buffer->curr - buf);
|
||||
kfree(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
|
||||
const char *ubuf, size_t count)
|
||||
static ssize_t pnp_set_current_resources(struct device *dmdev,
|
||||
struct device_attribute *attr,
|
||||
const char *ubuf, size_t count)
|
||||
{
|
||||
struct pnp_dev *dev = to_pnp_dev(dmdev);
|
||||
struct pnp_resource *pnp_res;
|
||||
char *buf = (void *)ubuf;
|
||||
int retval = 0;
|
||||
resource_size_t start, end;
|
||||
@ -368,7 +350,6 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
|
||||
goto done;
|
||||
}
|
||||
if (!strnicmp(buf, "set", 3)) {
|
||||
int nport = 0, nmem = 0, nirq = 0, ndma = 0;
|
||||
if (dev->active)
|
||||
goto done;
|
||||
buf += 3;
|
||||
@ -391,10 +372,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
|
||||
end = simple_strtoul(buf, &buf, 0);
|
||||
} else
|
||||
end = start;
|
||||
pnp_res = pnp_add_io_resource(dev, start, end,
|
||||
0);
|
||||
if (pnp_res)
|
||||
pnp_res->index = nport++;
|
||||
pnp_add_io_resource(dev, start, end, 0);
|
||||
continue;
|
||||
}
|
||||
if (!strnicmp(buf, "mem", 3)) {
|
||||
@ -411,10 +389,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
|
||||
end = simple_strtoul(buf, &buf, 0);
|
||||
} else
|
||||
end = start;
|
||||
pnp_res = pnp_add_mem_resource(dev, start, end,
|
||||
0);
|
||||
if (pnp_res)
|
||||
pnp_res->index = nmem++;
|
||||
pnp_add_mem_resource(dev, start, end, 0);
|
||||
continue;
|
||||
}
|
||||
if (!strnicmp(buf, "irq", 3)) {
|
||||
@ -422,9 +397,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
|
||||
while (isspace(*buf))
|
||||
++buf;
|
||||
start = simple_strtoul(buf, &buf, 0);
|
||||
pnp_res = pnp_add_irq_resource(dev, start, 0);
|
||||
if (pnp_res)
|
||||
pnp_res->index = nirq++;
|
||||
pnp_add_irq_resource(dev, start, 0);
|
||||
continue;
|
||||
}
|
||||
if (!strnicmp(buf, "dma", 3)) {
|
||||
@ -432,9 +405,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
|
||||
while (isspace(*buf))
|
||||
++buf;
|
||||
start = simple_strtoul(buf, &buf, 0);
|
||||
pnp_res = pnp_add_dma_resource(dev, start, 0);
|
||||
if (pnp_res)
|
||||
pnp_res->index = ndma++;
|
||||
pnp_add_dma_resource(dev, start, 0);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
@ -429,154 +429,135 @@ static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card,
|
||||
* Add IRQ resource to resources list.
|
||||
*/
|
||||
static void __init isapnp_parse_irq_resource(struct pnp_dev *dev,
|
||||
struct pnp_option *option,
|
||||
unsigned int option_flags,
|
||||
int size)
|
||||
{
|
||||
unsigned char tmp[3];
|
||||
struct pnp_irq *irq;
|
||||
unsigned long bits;
|
||||
pnp_irq_mask_t map;
|
||||
unsigned char flags = IORESOURCE_IRQ_HIGHEDGE;
|
||||
|
||||
isapnp_peek(tmp, size);
|
||||
irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
|
||||
if (!irq)
|
||||
return;
|
||||
bits = (tmp[1] << 8) | tmp[0];
|
||||
bitmap_copy(irq->map, &bits, 16);
|
||||
|
||||
bitmap_zero(map.bits, PNP_IRQ_NR);
|
||||
bitmap_copy(map.bits, &bits, 16);
|
||||
|
||||
if (size > 2)
|
||||
irq->flags = tmp[2];
|
||||
else
|
||||
irq->flags = IORESOURCE_IRQ_HIGHEDGE;
|
||||
pnp_register_irq_resource(dev, option, irq);
|
||||
flags = tmp[2];
|
||||
|
||||
pnp_register_irq_resource(dev, option_flags, &map, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add DMA resource to resources list.
|
||||
*/
|
||||
static void __init isapnp_parse_dma_resource(struct pnp_dev *dev,
|
||||
struct pnp_option *option,
|
||||
unsigned int option_flags,
|
||||
int size)
|
||||
{
|
||||
unsigned char tmp[2];
|
||||
struct pnp_dma *dma;
|
||||
|
||||
isapnp_peek(tmp, size);
|
||||
dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
|
||||
if (!dma)
|
||||
return;
|
||||
dma->map = tmp[0];
|
||||
dma->flags = tmp[1];
|
||||
pnp_register_dma_resource(dev, option, dma);
|
||||
pnp_register_dma_resource(dev, option_flags, tmp[0], tmp[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add port resource to resources list.
|
||||
*/
|
||||
static void __init isapnp_parse_port_resource(struct pnp_dev *dev,
|
||||
struct pnp_option *option,
|
||||
unsigned int option_flags,
|
||||
int size)
|
||||
{
|
||||
unsigned char tmp[7];
|
||||
struct pnp_port *port;
|
||||
resource_size_t min, max, align, len;
|
||||
unsigned char flags;
|
||||
|
||||
isapnp_peek(tmp, size);
|
||||
port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
|
||||
if (!port)
|
||||
return;
|
||||
port->min = (tmp[2] << 8) | tmp[1];
|
||||
port->max = (tmp[4] << 8) | tmp[3];
|
||||
port->align = tmp[5];
|
||||
port->size = tmp[6];
|
||||
port->flags = tmp[0] ? PNP_PORT_FLAG_16BITADDR : 0;
|
||||
pnp_register_port_resource(dev, option, port);
|
||||
min = (tmp[2] << 8) | tmp[1];
|
||||
max = (tmp[4] << 8) | tmp[3];
|
||||
align = tmp[5];
|
||||
len = tmp[6];
|
||||
flags = tmp[0] ? IORESOURCE_IO_16BIT_ADDR : 0;
|
||||
pnp_register_port_resource(dev, option_flags,
|
||||
min, max, align, len, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add fixed port resource to resources list.
|
||||
*/
|
||||
static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev,
|
||||
struct pnp_option *option,
|
||||
unsigned int option_flags,
|
||||
int size)
|
||||
{
|
||||
unsigned char tmp[3];
|
||||
struct pnp_port *port;
|
||||
resource_size_t base, len;
|
||||
|
||||
isapnp_peek(tmp, size);
|
||||
port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
|
||||
if (!port)
|
||||
return;
|
||||
port->min = port->max = (tmp[1] << 8) | tmp[0];
|
||||
port->size = tmp[2];
|
||||
port->align = 0;
|
||||
port->flags = PNP_PORT_FLAG_FIXED;
|
||||
pnp_register_port_resource(dev, option, port);
|
||||
base = (tmp[1] << 8) | tmp[0];
|
||||
len = tmp[2];
|
||||
pnp_register_port_resource(dev, option_flags, base, base, 0, len,
|
||||
IORESOURCE_IO_FIXED);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add memory resource to resources list.
|
||||
*/
|
||||
static void __init isapnp_parse_mem_resource(struct pnp_dev *dev,
|
||||
struct pnp_option *option,
|
||||
unsigned int option_flags,
|
||||
int size)
|
||||
{
|
||||
unsigned char tmp[9];
|
||||
struct pnp_mem *mem;
|
||||
resource_size_t min, max, align, len;
|
||||
unsigned char flags;
|
||||
|
||||
isapnp_peek(tmp, size);
|
||||
mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
|
||||
if (!mem)
|
||||
return;
|
||||
mem->min = ((tmp[2] << 8) | tmp[1]) << 8;
|
||||
mem->max = ((tmp[4] << 8) | tmp[3]) << 8;
|
||||
mem->align = (tmp[6] << 8) | tmp[5];
|
||||
mem->size = ((tmp[8] << 8) | tmp[7]) << 8;
|
||||
mem->flags = tmp[0];
|
||||
pnp_register_mem_resource(dev, option, mem);
|
||||
min = ((tmp[2] << 8) | tmp[1]) << 8;
|
||||
max = ((tmp[4] << 8) | tmp[3]) << 8;
|
||||
align = (tmp[6] << 8) | tmp[5];
|
||||
len = ((tmp[8] << 8) | tmp[7]) << 8;
|
||||
flags = tmp[0];
|
||||
pnp_register_mem_resource(dev, option_flags,
|
||||
min, max, align, len, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add 32-bit memory resource to resources list.
|
||||
*/
|
||||
static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev,
|
||||
struct pnp_option *option,
|
||||
unsigned int option_flags,
|
||||
int size)
|
||||
{
|
||||
unsigned char tmp[17];
|
||||
struct pnp_mem *mem;
|
||||
resource_size_t min, max, align, len;
|
||||
unsigned char flags;
|
||||
|
||||
isapnp_peek(tmp, size);
|
||||
mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
|
||||
if (!mem)
|
||||
return;
|
||||
mem->min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
|
||||
mem->max = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];
|
||||
mem->align =
|
||||
(tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9];
|
||||
mem->size =
|
||||
(tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13];
|
||||
mem->flags = tmp[0];
|
||||
pnp_register_mem_resource(dev, option, mem);
|
||||
min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
|
||||
max = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];
|
||||
align = (tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9];
|
||||
len = (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13];
|
||||
flags = tmp[0];
|
||||
pnp_register_mem_resource(dev, option_flags,
|
||||
min, max, align, len, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add 32-bit fixed memory resource to resources list.
|
||||
*/
|
||||
static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev,
|
||||
struct pnp_option *option,
|
||||
unsigned int option_flags,
|
||||
int size)
|
||||
{
|
||||
unsigned char tmp[9];
|
||||
struct pnp_mem *mem;
|
||||
resource_size_t base, len;
|
||||
unsigned char flags;
|
||||
|
||||
isapnp_peek(tmp, size);
|
||||
mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
|
||||
if (!mem)
|
||||
return;
|
||||
mem->min = mem->max =
|
||||
(tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
|
||||
mem->size = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];
|
||||
mem->align = 0;
|
||||
mem->flags = tmp[0];
|
||||
pnp_register_mem_resource(dev, option, mem);
|
||||
base = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
|
||||
len = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];
|
||||
flags = tmp[0];
|
||||
pnp_register_mem_resource(dev, option_flags, base, base, 0, len, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -604,20 +585,16 @@ isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size)
|
||||
static int __init isapnp_create_device(struct pnp_card *card,
|
||||
unsigned short size)
|
||||
{
|
||||
int number = 0, skip = 0, priority = 0, compat = 0;
|
||||
int number = 0, skip = 0, priority, compat = 0;
|
||||
unsigned char type, tmp[17];
|
||||
struct pnp_option *option;
|
||||
unsigned int option_flags;
|
||||
struct pnp_dev *dev;
|
||||
u32 eisa_id;
|
||||
char id[8];
|
||||
|
||||
if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
|
||||
return 1;
|
||||
option = pnp_register_independent_option(dev);
|
||||
if (!option) {
|
||||
kfree(dev);
|
||||
return 1;
|
||||
}
|
||||
option_flags = 0;
|
||||
pnp_add_card_device(card, dev);
|
||||
|
||||
while (1) {
|
||||
@ -634,16 +611,11 @@ static int __init isapnp_create_device(struct pnp_card *card,
|
||||
return 1;
|
||||
size = 0;
|
||||
skip = 0;
|
||||
option = pnp_register_independent_option(dev);
|
||||
if (!option) {
|
||||
kfree(dev);
|
||||
return 1;
|
||||
}
|
||||
option_flags = 0;
|
||||
pnp_add_card_device(card, dev);
|
||||
} else {
|
||||
skip = 1;
|
||||
}
|
||||
priority = 0;
|
||||
compat = 0;
|
||||
break;
|
||||
case _STAG_COMPATDEVID:
|
||||
@ -660,44 +632,42 @@ static int __init isapnp_create_device(struct pnp_card *card,
|
||||
case _STAG_IRQ:
|
||||
if (size < 2 || size > 3)
|
||||
goto __skip;
|
||||
isapnp_parse_irq_resource(dev, option, size);
|
||||
isapnp_parse_irq_resource(dev, option_flags, size);
|
||||
size = 0;
|
||||
break;
|
||||
case _STAG_DMA:
|
||||
if (size != 2)
|
||||
goto __skip;
|
||||
isapnp_parse_dma_resource(dev, option, size);
|
||||
isapnp_parse_dma_resource(dev, option_flags, size);
|
||||
size = 0;
|
||||
break;
|
||||
case _STAG_STARTDEP:
|
||||
if (size > 1)
|
||||
goto __skip;
|
||||
priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE;
|
||||
priority = PNP_RES_PRIORITY_ACCEPTABLE;
|
||||
if (size > 0) {
|
||||
isapnp_peek(tmp, size);
|
||||
priority = 0x100 | tmp[0];
|
||||
priority = tmp[0];
|
||||
size = 0;
|
||||
}
|
||||
option = pnp_register_dependent_option(dev, priority);
|
||||
if (!option)
|
||||
return 1;
|
||||
option_flags = pnp_new_dependent_set(dev, priority);
|
||||
break;
|
||||
case _STAG_ENDDEP:
|
||||
if (size != 0)
|
||||
goto __skip;
|
||||
priority = 0;
|
||||
dev_dbg(&dev->dev, "end dependent options\n");
|
||||
option_flags = 0;
|
||||
break;
|
||||
case _STAG_IOPORT:
|
||||
if (size != 7)
|
||||
goto __skip;
|
||||
isapnp_parse_port_resource(dev, option, size);
|
||||
isapnp_parse_port_resource(dev, option_flags, size);
|
||||
size = 0;
|
||||
break;
|
||||
case _STAG_FIXEDIO:
|
||||
if (size != 3)
|
||||
goto __skip;
|
||||
isapnp_parse_fixed_port_resource(dev, option, size);
|
||||
isapnp_parse_fixed_port_resource(dev, option_flags,
|
||||
size);
|
||||
size = 0;
|
||||
break;
|
||||
case _STAG_VENDOR:
|
||||
@ -705,7 +675,7 @@ static int __init isapnp_create_device(struct pnp_card *card,
|
||||
case _LTAG_MEMRANGE:
|
||||
if (size != 9)
|
||||
goto __skip;
|
||||
isapnp_parse_mem_resource(dev, option, size);
|
||||
isapnp_parse_mem_resource(dev, option_flags, size);
|
||||
size = 0;
|
||||
break;
|
||||
case _LTAG_ANSISTR:
|
||||
@ -720,13 +690,14 @@ static int __init isapnp_create_device(struct pnp_card *card,
|
||||
case _LTAG_MEM32RANGE:
|
||||
if (size != 17)
|
||||
goto __skip;
|
||||
isapnp_parse_mem32_resource(dev, option, size);
|
||||
isapnp_parse_mem32_resource(dev, option_flags, size);
|
||||
size = 0;
|
||||
break;
|
||||
case _LTAG_FIXEDMEM32RANGE:
|
||||
if (size != 9)
|
||||
goto __skip;
|
||||
isapnp_parse_fixed_mem32_resource(dev, option, size);
|
||||
isapnp_parse_fixed_mem32_resource(dev, option_flags,
|
||||
size);
|
||||
size = 0;
|
||||
break;
|
||||
case _STAG_END:
|
||||
@ -928,7 +899,6 @@ EXPORT_SYMBOL(isapnp_write_byte);
|
||||
|
||||
static int isapnp_get_resources(struct pnp_dev *dev)
|
||||
{
|
||||
struct pnp_resource *pnp_res;
|
||||
int i, ret;
|
||||
|
||||
dev_dbg(&dev->dev, "get resources\n");
|
||||
@ -940,35 +910,23 @@ static int isapnp_get_resources(struct pnp_dev *dev)
|
||||
|
||||
for (i = 0; i < ISAPNP_MAX_PORT; i++) {
|
||||
ret = isapnp_read_word(ISAPNP_CFG_PORT + (i << 1));
|
||||
if (ret) {
|
||||
pnp_res = pnp_add_io_resource(dev, ret, ret, 0);
|
||||
if (pnp_res)
|
||||
pnp_res->index = i;
|
||||
}
|
||||
pnp_add_io_resource(dev, ret, ret,
|
||||
ret == 0 ? IORESOURCE_DISABLED : 0);
|
||||
}
|
||||
for (i = 0; i < ISAPNP_MAX_MEM; i++) {
|
||||
ret = isapnp_read_word(ISAPNP_CFG_MEM + (i << 3)) << 8;
|
||||
if (ret) {
|
||||
pnp_res = pnp_add_mem_resource(dev, ret, ret, 0);
|
||||
if (pnp_res)
|
||||
pnp_res->index = i;
|
||||
}
|
||||
pnp_add_mem_resource(dev, ret, ret,
|
||||
ret == 0 ? IORESOURCE_DISABLED : 0);
|
||||
}
|
||||
for (i = 0; i < ISAPNP_MAX_IRQ; i++) {
|
||||
ret = isapnp_read_word(ISAPNP_CFG_IRQ + (i << 1)) >> 8;
|
||||
if (ret) {
|
||||
pnp_res = pnp_add_irq_resource(dev, ret, 0);
|
||||
if (pnp_res)
|
||||
pnp_res->index = i;
|
||||
}
|
||||
pnp_add_irq_resource(dev, ret,
|
||||
ret == 0 ? IORESOURCE_DISABLED : 0);
|
||||
}
|
||||
for (i = 0; i < ISAPNP_MAX_DMA; i++) {
|
||||
ret = isapnp_read_byte(ISAPNP_CFG_DMA + i);
|
||||
if (ret != 4) {
|
||||
pnp_res = pnp_add_dma_resource(dev, ret, 0);
|
||||
if (pnp_res)
|
||||
pnp_res->index = i;
|
||||
}
|
||||
pnp_add_dma_resource(dev, ret,
|
||||
ret == 4 ? IORESOURCE_DISABLED : 0);
|
||||
}
|
||||
|
||||
__end:
|
||||
@ -978,62 +936,45 @@ static int isapnp_get_resources(struct pnp_dev *dev)
|
||||
|
||||
static int isapnp_set_resources(struct pnp_dev *dev)
|
||||
{
|
||||
struct pnp_resource *pnp_res;
|
||||
struct resource *res;
|
||||
int tmp, index;
|
||||
int tmp;
|
||||
|
||||
dev_dbg(&dev->dev, "set resources\n");
|
||||
isapnp_cfg_begin(dev->card->number, dev->number);
|
||||
dev->active = 1;
|
||||
for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) {
|
||||
pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, tmp);
|
||||
if (!pnp_res)
|
||||
continue;
|
||||
res = &pnp_res->res;
|
||||
if (pnp_resource_valid(res)) {
|
||||
index = pnp_res->index;
|
||||
res = pnp_get_resource(dev, IORESOURCE_IO, tmp);
|
||||
if (pnp_resource_enabled(res)) {
|
||||
dev_dbg(&dev->dev, " set io %d to %#llx\n",
|
||||
index, (unsigned long long) res->start);
|
||||
isapnp_write_word(ISAPNP_CFG_PORT + (index << 1),
|
||||
tmp, (unsigned long long) res->start);
|
||||
isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1),
|
||||
res->start);
|
||||
}
|
||||
}
|
||||
for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) {
|
||||
pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, tmp);
|
||||
if (!pnp_res)
|
||||
continue;
|
||||
res = &pnp_res->res;
|
||||
if (pnp_resource_valid(res)) {
|
||||
res = pnp_get_resource(dev, IORESOURCE_IRQ, tmp);
|
||||
if (pnp_resource_enabled(res)) {
|
||||
int irq = res->start;
|
||||
if (irq == 2)
|
||||
irq = 9;
|
||||
index = pnp_res->index;
|
||||
dev_dbg(&dev->dev, " set irq %d to %d\n", index, irq);
|
||||
isapnp_write_byte(ISAPNP_CFG_IRQ + (index << 1), irq);
|
||||
dev_dbg(&dev->dev, " set irq %d to %d\n", tmp, irq);
|
||||
isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq);
|
||||
}
|
||||
}
|
||||
for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) {
|
||||
pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, tmp);
|
||||
if (!pnp_res)
|
||||
continue;
|
||||
res = &pnp_res->res;
|
||||
if (pnp_resource_valid(res)) {
|
||||
index = pnp_res->index;
|
||||
res = pnp_get_resource(dev, IORESOURCE_DMA, tmp);
|
||||
if (pnp_resource_enabled(res)) {
|
||||
dev_dbg(&dev->dev, " set dma %d to %lld\n",
|
||||
index, (unsigned long long) res->start);
|
||||
isapnp_write_byte(ISAPNP_CFG_DMA + index, res->start);
|
||||
tmp, (unsigned long long) res->start);
|
||||
isapnp_write_byte(ISAPNP_CFG_DMA + tmp, res->start);
|
||||
}
|
||||
}
|
||||
for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) {
|
||||
pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, tmp);
|
||||
if (!pnp_res)
|
||||
continue;
|
||||
res = &pnp_res->res;
|
||||
if (pnp_resource_valid(res)) {
|
||||
index = pnp_res->index;
|
||||
res = pnp_get_resource(dev, IORESOURCE_MEM, tmp);
|
||||
if (pnp_resource_enabled(res)) {
|
||||
dev_dbg(&dev->dev, " set mem %d to %#llx\n",
|
||||
index, (unsigned long long) res->start);
|
||||
isapnp_write_word(ISAPNP_CFG_MEM + (index << 3),
|
||||
tmp, (unsigned long long) res->start);
|
||||
isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3),
|
||||
(res->start >> 8) & 0xffff);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
*
|
||||
* based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
|
||||
* Copyright 2003 Adam Belay <ambx1@neo.rr.com>
|
||||
* Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
|
||||
* Bjorn Helgaas <bjorn.helgaas@hp.com>
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
@ -19,82 +21,64 @@ DEFINE_MUTEX(pnp_res_mutex);
|
||||
|
||||
static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
|
||||
{
|
||||
struct pnp_resource *pnp_res;
|
||||
struct resource *res;
|
||||
struct resource *res, local_res;
|
||||
|
||||
pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, idx);
|
||||
if (!pnp_res) {
|
||||
dev_err(&dev->dev, "too many I/O port resources\n");
|
||||
/* pretend we were successful so at least the manager won't try again */
|
||||
return 1;
|
||||
}
|
||||
|
||||
res = &pnp_res->res;
|
||||
|
||||
/* check if this resource has been manually set, if so skip */
|
||||
if (!(res->flags & IORESOURCE_AUTO)) {
|
||||
res = pnp_get_resource(dev, IORESOURCE_IO, idx);
|
||||
if (res) {
|
||||
dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx "
|
||||
"flags %#lx\n", idx, (unsigned long long) res->start,
|
||||
(unsigned long long) res->end, res->flags);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set the initial values */
|
||||
pnp_res->index = idx;
|
||||
res->flags |= rule->flags | IORESOURCE_IO;
|
||||
res->flags &= ~IORESOURCE_UNSET;
|
||||
res = &local_res;
|
||||
res->flags = rule->flags | IORESOURCE_AUTO;
|
||||
res->start = 0;
|
||||
res->end = 0;
|
||||
|
||||
if (!rule->size) {
|
||||
res->flags |= IORESOURCE_DISABLED;
|
||||
dev_dbg(&dev->dev, " io %d disabled\n", idx);
|
||||
return 1; /* skip disabled resource requests */
|
||||
goto __add;
|
||||
}
|
||||
|
||||
res->start = rule->min;
|
||||
res->end = res->start + rule->size - 1;
|
||||
|
||||
/* run through until pnp_check_port is happy */
|
||||
while (!pnp_check_port(dev, res)) {
|
||||
res->start += rule->align;
|
||||
res->end = res->start + rule->size - 1;
|
||||
if (res->start > rule->max || !rule->align) {
|
||||
dev_dbg(&dev->dev, " couldn't assign io %d\n", idx);
|
||||
return 0;
|
||||
dev_dbg(&dev->dev, " couldn't assign io %d "
|
||||
"(min %#llx max %#llx)\n", idx,
|
||||
(unsigned long long) rule->min,
|
||||
(unsigned long long) rule->max);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
dev_dbg(&dev->dev, " assign io %d %#llx-%#llx\n", idx,
|
||||
(unsigned long long) res->start, (unsigned long long) res->end);
|
||||
return 1;
|
||||
|
||||
__add:
|
||||
pnp_add_io_resource(dev, res->start, res->end, res->flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
|
||||
{
|
||||
struct pnp_resource *pnp_res;
|
||||
struct resource *res;
|
||||
struct resource *res, local_res;
|
||||
|
||||
pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, idx);
|
||||
if (!pnp_res) {
|
||||
dev_err(&dev->dev, "too many memory resources\n");
|
||||
/* pretend we were successful so at least the manager won't try again */
|
||||
return 1;
|
||||
}
|
||||
|
||||
res = &pnp_res->res;
|
||||
|
||||
/* check if this resource has been manually set, if so skip */
|
||||
if (!(res->flags & IORESOURCE_AUTO)) {
|
||||
res = pnp_get_resource(dev, IORESOURCE_MEM, idx);
|
||||
if (res) {
|
||||
dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx "
|
||||
"flags %#lx\n", idx, (unsigned long long) res->start,
|
||||
(unsigned long long) res->end, res->flags);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set the initial values */
|
||||
pnp_res->index = idx;
|
||||
res->flags |= rule->flags | IORESOURCE_MEM;
|
||||
res->flags &= ~IORESOURCE_UNSET;
|
||||
res = &local_res;
|
||||
res->flags = rule->flags | IORESOURCE_AUTO;
|
||||
res->start = 0;
|
||||
res->end = 0;
|
||||
|
||||
/* convert pnp flags to standard Linux flags */
|
||||
if (!(rule->flags & IORESOURCE_MEM_WRITEABLE))
|
||||
res->flags |= IORESOURCE_READONLY;
|
||||
if (rule->flags & IORESOURCE_MEM_CACHEABLE)
|
||||
@ -107,30 +91,32 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
|
||||
if (!rule->size) {
|
||||
res->flags |= IORESOURCE_DISABLED;
|
||||
dev_dbg(&dev->dev, " mem %d disabled\n", idx);
|
||||
return 1; /* skip disabled resource requests */
|
||||
goto __add;
|
||||
}
|
||||
|
||||
res->start = rule->min;
|
||||
res->end = res->start + rule->size - 1;
|
||||
|
||||
/* run through until pnp_check_mem is happy */
|
||||
while (!pnp_check_mem(dev, res)) {
|
||||
res->start += rule->align;
|
||||
res->end = res->start + rule->size - 1;
|
||||
if (res->start > rule->max || !rule->align) {
|
||||
dev_dbg(&dev->dev, " couldn't assign mem %d\n", idx);
|
||||
return 0;
|
||||
dev_dbg(&dev->dev, " couldn't assign mem %d "
|
||||
"(min %#llx max %#llx)\n", idx,
|
||||
(unsigned long long) rule->min,
|
||||
(unsigned long long) rule->max);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
dev_dbg(&dev->dev, " assign mem %d %#llx-%#llx\n", idx,
|
||||
(unsigned long long) res->start, (unsigned long long) res->end);
|
||||
return 1;
|
||||
|
||||
__add:
|
||||
pnp_add_mem_resource(dev, res->start, res->end, res->flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
|
||||
{
|
||||
struct pnp_resource *pnp_res;
|
||||
struct resource *res;
|
||||
struct resource *res, local_res;
|
||||
int i;
|
||||
|
||||
/* IRQ priority: this table is good for i386 */
|
||||
@ -138,59 +124,57 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
|
||||
5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
|
||||
};
|
||||
|
||||
pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, idx);
|
||||
if (!pnp_res) {
|
||||
dev_err(&dev->dev, "too many IRQ resources\n");
|
||||
/* pretend we were successful so at least the manager won't try again */
|
||||
return 1;
|
||||
}
|
||||
|
||||
res = &pnp_res->res;
|
||||
|
||||
/* check if this resource has been manually set, if so skip */
|
||||
if (!(res->flags & IORESOURCE_AUTO)) {
|
||||
res = pnp_get_resource(dev, IORESOURCE_IRQ, idx);
|
||||
if (res) {
|
||||
dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n",
|
||||
idx, (int) res->start, res->flags);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set the initial values */
|
||||
pnp_res->index = idx;
|
||||
res->flags |= rule->flags | IORESOURCE_IRQ;
|
||||
res->flags &= ~IORESOURCE_UNSET;
|
||||
res = &local_res;
|
||||
res->flags = rule->flags | IORESOURCE_AUTO;
|
||||
res->start = -1;
|
||||
res->end = -1;
|
||||
|
||||
if (bitmap_empty(rule->map, PNP_IRQ_NR)) {
|
||||
if (bitmap_empty(rule->map.bits, PNP_IRQ_NR)) {
|
||||
res->flags |= IORESOURCE_DISABLED;
|
||||
dev_dbg(&dev->dev, " irq %d disabled\n", idx);
|
||||
return 1; /* skip disabled resource requests */
|
||||
goto __add;
|
||||
}
|
||||
|
||||
/* TBD: need check for >16 IRQ */
|
||||
res->start = find_next_bit(rule->map, PNP_IRQ_NR, 16);
|
||||
res->start = find_next_bit(rule->map.bits, PNP_IRQ_NR, 16);
|
||||
if (res->start < PNP_IRQ_NR) {
|
||||
res->end = res->start;
|
||||
dev_dbg(&dev->dev, " assign irq %d %d\n", idx,
|
||||
(int) res->start);
|
||||
return 1;
|
||||
goto __add;
|
||||
}
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (test_bit(xtab[i], rule->map)) {
|
||||
if (test_bit(xtab[i], rule->map.bits)) {
|
||||
res->start = res->end = xtab[i];
|
||||
if (pnp_check_irq(dev, res)) {
|
||||
dev_dbg(&dev->dev, " assign irq %d %d\n", idx,
|
||||
(int) res->start);
|
||||
return 1;
|
||||
}
|
||||
if (pnp_check_irq(dev, res))
|
||||
goto __add;
|
||||
}
|
||||
}
|
||||
|
||||
if (rule->flags & IORESOURCE_IRQ_OPTIONAL) {
|
||||
res->start = -1;
|
||||
res->end = -1;
|
||||
res->flags |= IORESOURCE_DISABLED;
|
||||
dev_dbg(&dev->dev, " irq %d disabled (optional)\n", idx);
|
||||
goto __add;
|
||||
}
|
||||
|
||||
dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx);
|
||||
return -EBUSY;
|
||||
|
||||
__add:
|
||||
pnp_add_irq_resource(dev, res->start, res->flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
|
||||
static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
|
||||
{
|
||||
struct pnp_resource *pnp_res;
|
||||
struct resource *res;
|
||||
struct resource *res, local_res;
|
||||
int i;
|
||||
|
||||
/* DMA priority: this table is good for i386 */
|
||||
@ -198,231 +182,99 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
|
||||
1, 3, 5, 6, 7, 0, 2, 4
|
||||
};
|
||||
|
||||
pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, idx);
|
||||
if (!pnp_res) {
|
||||
dev_err(&dev->dev, "too many DMA resources\n");
|
||||
return;
|
||||
}
|
||||
|
||||
res = &pnp_res->res;
|
||||
|
||||
/* check if this resource has been manually set, if so skip */
|
||||
if (!(res->flags & IORESOURCE_AUTO)) {
|
||||
res = pnp_get_resource(dev, IORESOURCE_DMA, idx);
|
||||
if (res) {
|
||||
dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n",
|
||||
idx, (int) res->start, res->flags);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set the initial values */
|
||||
pnp_res->index = idx;
|
||||
res->flags |= rule->flags | IORESOURCE_DMA;
|
||||
res->flags &= ~IORESOURCE_UNSET;
|
||||
res = &local_res;
|
||||
res->flags = rule->flags | IORESOURCE_AUTO;
|
||||
res->start = -1;
|
||||
res->end = -1;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (rule->map & (1 << xtab[i])) {
|
||||
res->start = res->end = xtab[i];
|
||||
if (pnp_check_dma(dev, res)) {
|
||||
dev_dbg(&dev->dev, " assign dma %d %d\n", idx,
|
||||
(int) res->start);
|
||||
return;
|
||||
}
|
||||
if (pnp_check_dma(dev, res))
|
||||
goto __add;
|
||||
}
|
||||
}
|
||||
#ifdef MAX_DMA_CHANNELS
|
||||
res->start = res->end = MAX_DMA_CHANNELS;
|
||||
#endif
|
||||
res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
|
||||
res->flags |= IORESOURCE_DISABLED;
|
||||
dev_dbg(&dev->dev, " disable dma %d\n", idx);
|
||||
|
||||
__add:
|
||||
pnp_add_dma_resource(dev, res->start, res->flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pnp_init_resource(struct resource *res)
|
||||
{
|
||||
unsigned long type;
|
||||
|
||||
type = res->flags & (IORESOURCE_IO | IORESOURCE_MEM |
|
||||
IORESOURCE_IRQ | IORESOURCE_DMA);
|
||||
|
||||
res->name = NULL;
|
||||
res->flags = type | IORESOURCE_AUTO | IORESOURCE_UNSET;
|
||||
if (type == IORESOURCE_IRQ || type == IORESOURCE_DMA) {
|
||||
res->start = -1;
|
||||
res->end = -1;
|
||||
} else {
|
||||
res->start = 0;
|
||||
res->end = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pnp_init_resources - Resets a resource table to default values.
|
||||
* @table: pointer to the desired resource table
|
||||
*/
|
||||
void pnp_init_resources(struct pnp_dev *dev)
|
||||
{
|
||||
struct resource *res;
|
||||
int idx;
|
||||
|
||||
for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
|
||||
res = &dev->res->irq[idx].res;
|
||||
res->flags = IORESOURCE_IRQ;
|
||||
pnp_init_resource(res);
|
||||
}
|
||||
for (idx = 0; idx < PNP_MAX_DMA; idx++) {
|
||||
res = &dev->res->dma[idx].res;
|
||||
res->flags = IORESOURCE_DMA;
|
||||
pnp_init_resource(res);
|
||||
}
|
||||
for (idx = 0; idx < PNP_MAX_PORT; idx++) {
|
||||
res = &dev->res->port[idx].res;
|
||||
res->flags = IORESOURCE_IO;
|
||||
pnp_init_resource(res);
|
||||
}
|
||||
for (idx = 0; idx < PNP_MAX_MEM; idx++) {
|
||||
res = &dev->res->mem[idx].res;
|
||||
res->flags = IORESOURCE_MEM;
|
||||
pnp_init_resource(res);
|
||||
}
|
||||
pnp_free_resources(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* pnp_clean_resources - clears resources that were not manually set
|
||||
* @res: the resources to clean
|
||||
*/
|
||||
static void pnp_clean_resource_table(struct pnp_dev *dev)
|
||||
{
|
||||
struct resource *res;
|
||||
int idx;
|
||||
struct pnp_resource *pnp_res, *tmp;
|
||||
|
||||
for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
|
||||
res = &dev->res->irq[idx].res;
|
||||
if (res->flags & IORESOURCE_AUTO) {
|
||||
res->flags = IORESOURCE_IRQ;
|
||||
pnp_init_resource(res);
|
||||
}
|
||||
}
|
||||
for (idx = 0; idx < PNP_MAX_DMA; idx++) {
|
||||
res = &dev->res->dma[idx].res;
|
||||
if (res->flags & IORESOURCE_AUTO) {
|
||||
res->flags = IORESOURCE_DMA;
|
||||
pnp_init_resource(res);
|
||||
}
|
||||
}
|
||||
for (idx = 0; idx < PNP_MAX_PORT; idx++) {
|
||||
res = &dev->res->port[idx].res;
|
||||
if (res->flags & IORESOURCE_AUTO) {
|
||||
res->flags = IORESOURCE_IO;
|
||||
pnp_init_resource(res);
|
||||
}
|
||||
}
|
||||
for (idx = 0; idx < PNP_MAX_MEM; idx++) {
|
||||
res = &dev->res->mem[idx].res;
|
||||
if (res->flags & IORESOURCE_AUTO) {
|
||||
res->flags = IORESOURCE_MEM;
|
||||
pnp_init_resource(res);
|
||||
}
|
||||
list_for_each_entry_safe(pnp_res, tmp, &dev->resources, list) {
|
||||
if (pnp_res->res.flags & IORESOURCE_AUTO)
|
||||
pnp_free_resource(pnp_res);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pnp_assign_resources - assigns resources to the device based on the specified dependent number
|
||||
* @dev: pointer to the desired device
|
||||
* @depnum: the dependent function number
|
||||
*
|
||||
* Only set depnum to 0 if the device does not have dependent options.
|
||||
* @set: the dependent function number
|
||||
*/
|
||||
static int pnp_assign_resources(struct pnp_dev *dev, int depnum)
|
||||
static int pnp_assign_resources(struct pnp_dev *dev, int set)
|
||||
{
|
||||
struct pnp_port *port;
|
||||
struct pnp_mem *mem;
|
||||
struct pnp_irq *irq;
|
||||
struct pnp_dma *dma;
|
||||
struct pnp_option *option;
|
||||
int nport = 0, nmem = 0, nirq = 0, ndma = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (!pnp_can_configure(dev))
|
||||
return -ENODEV;
|
||||
|
||||
dbg_pnp_show_resources(dev, "before pnp_assign_resources");
|
||||
dev_dbg(&dev->dev, "pnp_assign_resources, try dependent set %d\n", set);
|
||||
mutex_lock(&pnp_res_mutex);
|
||||
pnp_clean_resource_table(dev);
|
||||
if (dev->independent) {
|
||||
dev_dbg(&dev->dev, "assigning independent options\n");
|
||||
port = dev->independent->port;
|
||||
mem = dev->independent->mem;
|
||||
irq = dev->independent->irq;
|
||||
dma = dev->independent->dma;
|
||||
while (port) {
|
||||
if (!pnp_assign_port(dev, port, nport))
|
||||
goto fail;
|
||||
nport++;
|
||||
port = port->next;
|
||||
}
|
||||
while (mem) {
|
||||
if (!pnp_assign_mem(dev, mem, nmem))
|
||||
goto fail;
|
||||
nmem++;
|
||||
mem = mem->next;
|
||||
}
|
||||
while (irq) {
|
||||
if (!pnp_assign_irq(dev, irq, nirq))
|
||||
goto fail;
|
||||
nirq++;
|
||||
irq = irq->next;
|
||||
}
|
||||
while (dma) {
|
||||
pnp_assign_dma(dev, dma, ndma);
|
||||
ndma++;
|
||||
dma = dma->next;
|
||||
|
||||
list_for_each_entry(option, &dev->options, list) {
|
||||
if (pnp_option_is_dependent(option) &&
|
||||
pnp_option_set(option) != set)
|
||||
continue;
|
||||
|
||||
switch (option->type) {
|
||||
case IORESOURCE_IO:
|
||||
ret = pnp_assign_port(dev, &option->u.port, nport++);
|
||||
break;
|
||||
case IORESOURCE_MEM:
|
||||
ret = pnp_assign_mem(dev, &option->u.mem, nmem++);
|
||||
break;
|
||||
case IORESOURCE_IRQ:
|
||||
ret = pnp_assign_irq(dev, &option->u.irq, nirq++);
|
||||
break;
|
||||
case IORESOURCE_DMA:
|
||||
ret = pnp_assign_dma(dev, &option->u.dma, ndma++);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (depnum) {
|
||||
struct pnp_option *dep;
|
||||
int i;
|
||||
|
||||
dev_dbg(&dev->dev, "assigning dependent option %d\n", depnum);
|
||||
for (i = 1, dep = dev->dependent; i < depnum;
|
||||
i++, dep = dep->next)
|
||||
if (!dep)
|
||||
goto fail;
|
||||
port = dep->port;
|
||||
mem = dep->mem;
|
||||
irq = dep->irq;
|
||||
dma = dep->dma;
|
||||
while (port) {
|
||||
if (!pnp_assign_port(dev, port, nport))
|
||||
goto fail;
|
||||
nport++;
|
||||
port = port->next;
|
||||
}
|
||||
while (mem) {
|
||||
if (!pnp_assign_mem(dev, mem, nmem))
|
||||
goto fail;
|
||||
nmem++;
|
||||
mem = mem->next;
|
||||
}
|
||||
while (irq) {
|
||||
if (!pnp_assign_irq(dev, irq, nirq))
|
||||
goto fail;
|
||||
nirq++;
|
||||
irq = irq->next;
|
||||
}
|
||||
while (dma) {
|
||||
pnp_assign_dma(dev, dma, ndma);
|
||||
ndma++;
|
||||
dma = dma->next;
|
||||
}
|
||||
} else if (dev->dependent)
|
||||
goto fail;
|
||||
|
||||
mutex_unlock(&pnp_res_mutex);
|
||||
dbg_pnp_show_resources(dev, "after pnp_assign_resources");
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
pnp_clean_resource_table(dev);
|
||||
mutex_unlock(&pnp_res_mutex);
|
||||
dbg_pnp_show_resources(dev, "after pnp_assign_resources (failed)");
|
||||
return 0;
|
||||
if (ret < 0) {
|
||||
dev_dbg(&dev->dev, "pnp_assign_resources failed (%d)\n", ret);
|
||||
pnp_clean_resource_table(dev);
|
||||
} else
|
||||
dbg_pnp_show_resources(dev, "pnp_assign_resources succeeded");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -431,29 +283,25 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum)
|
||||
*/
|
||||
int pnp_auto_config_dev(struct pnp_dev *dev)
|
||||
{
|
||||
struct pnp_option *dep;
|
||||
int i = 1;
|
||||
int i, ret;
|
||||
|
||||
if (!pnp_can_configure(dev)) {
|
||||
dev_dbg(&dev->dev, "configuration not supported\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!dev->dependent) {
|
||||
if (pnp_assign_resources(dev, 0))
|
||||
ret = pnp_assign_resources(dev, 0);
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
|
||||
for (i = 1; i < dev->num_dependent_sets; i++) {
|
||||
ret = pnp_assign_resources(dev, i);
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
} else {
|
||||
dep = dev->dependent;
|
||||
do {
|
||||
if (pnp_assign_resources(dev, i))
|
||||
return 0;
|
||||
dep = dep->next;
|
||||
i++;
|
||||
} while (dep);
|
||||
}
|
||||
|
||||
dev_err(&dev->dev, "unable to assign resources\n");
|
||||
return -EBUSY;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,9 +117,7 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
|
||||
{
|
||||
int power_state;
|
||||
|
||||
power_state = acpi_pm_device_sleep_state(&dev->dev,
|
||||
device_may_wakeup(&dev->dev),
|
||||
NULL);
|
||||
power_state = acpi_pm_device_sleep_state(&dev->dev, NULL);
|
||||
if (power_state < 0)
|
||||
power_state = (state.event == PM_EVENT_ON) ?
|
||||
ACPI_STATE_D0 : ACPI_STATE_D3;
|
||||
|
@ -3,6 +3,8 @@
|
||||
*
|
||||
* Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr>
|
||||
* Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com>
|
||||
* Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
|
||||
* Bjorn Helgaas <bjorn.helgaas@hp.com>
|
||||
*
|
||||
* 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
|
||||
@ -98,8 +100,10 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
|
||||
int irq, flags;
|
||||
int p, t;
|
||||
|
||||
if (!valid_IRQ(gsi))
|
||||
if (!valid_IRQ(gsi)) {
|
||||
pnp_add_irq_resource(dev, gsi, IORESOURCE_DISABLED);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* in IO-APIC mode, use overrided attribute. Two reasons:
|
||||
@ -178,13 +182,68 @@ static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
|
||||
u64 end = start + len - 1;
|
||||
|
||||
if (io_decode == ACPI_DECODE_16)
|
||||
flags |= PNP_PORT_FLAG_16BITADDR;
|
||||
flags |= IORESOURCE_IO_16BIT_ADDR;
|
||||
if (len == 0 || end >= 0x10003)
|
||||
flags |= IORESOURCE_DISABLED;
|
||||
|
||||
pnp_add_io_resource(dev, start, end, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Device CSRs that do not appear in PCI config space should be described
|
||||
* via ACPI. This would normally be done with Address Space Descriptors
|
||||
* marked as "consumer-only," but old versions of Windows and Linux ignore
|
||||
* the producer/consumer flag, so HP invented a vendor-defined resource to
|
||||
* describe the location and size of CSR space.
|
||||
*/
|
||||
static struct acpi_vendor_uuid hp_ccsr_uuid = {
|
||||
.subtype = 2,
|
||||
.data = { 0xf9, 0xad, 0xe9, 0x69, 0x4f, 0x92, 0x5f, 0xab, 0xf6, 0x4a,
|
||||
0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad },
|
||||
};
|
||||
|
||||
static int vendor_resource_matches(struct pnp_dev *dev,
|
||||
struct acpi_resource_vendor_typed *vendor,
|
||||
struct acpi_vendor_uuid *match,
|
||||
int expected_len)
|
||||
{
|
||||
int uuid_len = sizeof(vendor->uuid);
|
||||
u8 uuid_subtype = vendor->uuid_subtype;
|
||||
u8 *uuid = vendor->uuid;
|
||||
int actual_len;
|
||||
|
||||
/* byte_length includes uuid_subtype and uuid */
|
||||
actual_len = vendor->byte_length - uuid_len - 1;
|
||||
|
||||
if (uuid_subtype == match->subtype &&
|
||||
uuid_len == sizeof(match->data) &&
|
||||
memcmp(uuid, match->data, uuid_len) == 0) {
|
||||
if (expected_len && expected_len != actual_len) {
|
||||
dev_err(&dev->dev, "wrong vendor descriptor size; "
|
||||
"expected %d, found %d bytes\n",
|
||||
expected_len, actual_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,
|
||||
struct acpi_resource_vendor_typed *vendor)
|
||||
{
|
||||
if (vendor_resource_matches(dev, vendor, &hp_ccsr_uuid, 16)) {
|
||||
u64 start, length;
|
||||
|
||||
memcpy(&start, vendor->byte_data, sizeof(start));
|
||||
memcpy(&length, vendor->byte_data + 8, sizeof(length));
|
||||
|
||||
pnp_add_mem_resource(dev, start, start + length - 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
|
||||
u64 start, u64 len,
|
||||
int write_protect)
|
||||
@ -235,6 +294,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
|
||||
struct acpi_resource_dma *dma;
|
||||
struct acpi_resource_io *io;
|
||||
struct acpi_resource_fixed_io *fixed_io;
|
||||
struct acpi_resource_vendor_typed *vendor_typed;
|
||||
struct acpi_resource_memory24 *memory24;
|
||||
struct acpi_resource_memory32 *memory32;
|
||||
struct acpi_resource_fixed_memory32 *fixed_memory32;
|
||||
@ -248,24 +308,39 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
|
||||
* _CRS, but some firmware violates this, so parse them all.
|
||||
*/
|
||||
irq = &res->data.irq;
|
||||
for (i = 0; i < irq->interrupt_count; i++) {
|
||||
pnpacpi_parse_allocated_irqresource(dev,
|
||||
irq->interrupts[i],
|
||||
irq->triggering,
|
||||
irq->polarity,
|
||||
irq->sharable);
|
||||
if (irq->interrupt_count == 0)
|
||||
pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
|
||||
else {
|
||||
for (i = 0; i < irq->interrupt_count; i++) {
|
||||
pnpacpi_parse_allocated_irqresource(dev,
|
||||
irq->interrupts[i],
|
||||
irq->triggering,
|
||||
irq->polarity,
|
||||
irq->sharable);
|
||||
}
|
||||
|
||||
/*
|
||||
* The IRQ encoder puts a single interrupt in each
|
||||
* descriptor, so if a _CRS descriptor has more than
|
||||
* one interrupt, we won't be able to re-encode it.
|
||||
*/
|
||||
if (pnp_can_write(dev) && irq->interrupt_count > 1) {
|
||||
dev_warn(&dev->dev, "multiple interrupts in "
|
||||
"_CRS descriptor; configuration can't "
|
||||
"be changed\n");
|
||||
dev->capabilities &= ~PNP_WRITE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_RESOURCE_TYPE_DMA:
|
||||
dma = &res->data.dma;
|
||||
if (dma->channel_count > 0) {
|
||||
if (dma->channel_count > 0 && dma->channels[0] != (u8) -1)
|
||||
flags = dma_flags(dma->type, dma->bus_master,
|
||||
dma->transfer);
|
||||
if (dma->channels[0] == (u8) -1)
|
||||
flags |= IORESOURCE_DISABLED;
|
||||
pnp_add_dma_resource(dev, dma->channels[0], flags);
|
||||
}
|
||||
else
|
||||
flags = IORESOURCE_DISABLED;
|
||||
pnp_add_dma_resource(dev, dma->channels[0], flags);
|
||||
break;
|
||||
|
||||
case ACPI_RESOURCE_TYPE_IO:
|
||||
@ -289,6 +364,8 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
|
||||
break;
|
||||
|
||||
case ACPI_RESOURCE_TYPE_VENDOR:
|
||||
vendor_typed = &res->data.vendor_typed;
|
||||
pnpacpi_parse_allocated_vendor(dev, vendor_typed);
|
||||
break;
|
||||
|
||||
case ACPI_RESOURCE_TYPE_END_TAG:
|
||||
@ -331,12 +408,29 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
|
||||
if (extended_irq->producer_consumer == ACPI_PRODUCER)
|
||||
return AE_OK;
|
||||
|
||||
for (i = 0; i < extended_irq->interrupt_count; i++) {
|
||||
pnpacpi_parse_allocated_irqresource(dev,
|
||||
extended_irq->interrupts[i],
|
||||
extended_irq->triggering,
|
||||
extended_irq->polarity,
|
||||
extended_irq->sharable);
|
||||
if (extended_irq->interrupt_count == 0)
|
||||
pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
|
||||
else {
|
||||
for (i = 0; i < extended_irq->interrupt_count; i++) {
|
||||
pnpacpi_parse_allocated_irqresource(dev,
|
||||
extended_irq->interrupts[i],
|
||||
extended_irq->triggering,
|
||||
extended_irq->polarity,
|
||||
extended_irq->sharable);
|
||||
}
|
||||
|
||||
/*
|
||||
* The IRQ encoder puts a single interrupt in each
|
||||
* descriptor, so if a _CRS descriptor has more than
|
||||
* one interrupt, we won't be able to re-encode it.
|
||||
*/
|
||||
if (pnp_can_write(dev) &&
|
||||
extended_irq->interrupt_count > 1) {
|
||||
dev_warn(&dev->dev, "multiple interrupts in "
|
||||
"_CRS descriptor; configuration can't "
|
||||
"be changed\n");
|
||||
dev->capabilities &= ~PNP_WRITE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -373,179 +467,147 @@ int pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
|
||||
}
|
||||
|
||||
static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
|
||||
struct pnp_option *option,
|
||||
unsigned int option_flags,
|
||||
struct acpi_resource_dma *p)
|
||||
{
|
||||
int i;
|
||||
struct pnp_dma *dma;
|
||||
unsigned char map = 0, flags;
|
||||
|
||||
if (p->channel_count == 0)
|
||||
return;
|
||||
dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
|
||||
if (!dma)
|
||||
return;
|
||||
|
||||
for (i = 0; i < p->channel_count; i++)
|
||||
dma->map |= 1 << p->channels[i];
|
||||
map |= 1 << p->channels[i];
|
||||
|
||||
dma->flags = dma_flags(p->type, p->bus_master, p->transfer);
|
||||
|
||||
pnp_register_dma_resource(dev, option, dma);
|
||||
flags = dma_flags(p->type, p->bus_master, p->transfer);
|
||||
pnp_register_dma_resource(dev, option_flags, map, flags);
|
||||
}
|
||||
|
||||
static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
|
||||
struct pnp_option *option,
|
||||
unsigned int option_flags,
|
||||
struct acpi_resource_irq *p)
|
||||
{
|
||||
int i;
|
||||
struct pnp_irq *irq;
|
||||
pnp_irq_mask_t map;
|
||||
unsigned char flags;
|
||||
|
||||
if (p->interrupt_count == 0)
|
||||
return;
|
||||
irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
|
||||
if (!irq)
|
||||
return;
|
||||
|
||||
bitmap_zero(map.bits, PNP_IRQ_NR);
|
||||
for (i = 0; i < p->interrupt_count; i++)
|
||||
if (p->interrupts[i])
|
||||
__set_bit(p->interrupts[i], irq->map);
|
||||
irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
|
||||
__set_bit(p->interrupts[i], map.bits);
|
||||
|
||||
pnp_register_irq_resource(dev, option, irq);
|
||||
flags = irq_flags(p->triggering, p->polarity, p->sharable);
|
||||
pnp_register_irq_resource(dev, option_flags, &map, flags);
|
||||
}
|
||||
|
||||
static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
|
||||
struct pnp_option *option,
|
||||
unsigned int option_flags,
|
||||
struct acpi_resource_extended_irq *p)
|
||||
{
|
||||
int i;
|
||||
struct pnp_irq *irq;
|
||||
pnp_irq_mask_t map;
|
||||
unsigned char flags;
|
||||
|
||||
if (p->interrupt_count == 0)
|
||||
return;
|
||||
irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
|
||||
if (!irq)
|
||||
return;
|
||||
|
||||
for (i = 0; i < p->interrupt_count; i++)
|
||||
if (p->interrupts[i])
|
||||
__set_bit(p->interrupts[i], irq->map);
|
||||
irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
|
||||
bitmap_zero(map.bits, PNP_IRQ_NR);
|
||||
for (i = 0; i < p->interrupt_count; i++) {
|
||||
if (p->interrupts[i]) {
|
||||
if (p->interrupts[i] < PNP_IRQ_NR)
|
||||
__set_bit(p->interrupts[i], map.bits);
|
||||
else
|
||||
dev_err(&dev->dev, "ignoring IRQ %d option "
|
||||
"(too large for %d entry bitmap)\n",
|
||||
p->interrupts[i], PNP_IRQ_NR);
|
||||
}
|
||||
}
|
||||
|
||||
pnp_register_irq_resource(dev, option, irq);
|
||||
flags = irq_flags(p->triggering, p->polarity, p->sharable);
|
||||
pnp_register_irq_resource(dev, option_flags, &map, flags);
|
||||
}
|
||||
|
||||
static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
|
||||
struct pnp_option *option,
|
||||
unsigned int option_flags,
|
||||
struct acpi_resource_io *io)
|
||||
{
|
||||
struct pnp_port *port;
|
||||
unsigned char flags = 0;
|
||||
|
||||
if (io->address_length == 0)
|
||||
return;
|
||||
port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
|
||||
if (!port)
|
||||
return;
|
||||
port->min = io->minimum;
|
||||
port->max = io->maximum;
|
||||
port->align = io->alignment;
|
||||
port->size = io->address_length;
|
||||
port->flags = ACPI_DECODE_16 == io->io_decode ?
|
||||
PNP_PORT_FLAG_16BITADDR : 0;
|
||||
pnp_register_port_resource(dev, option, port);
|
||||
|
||||
if (io->io_decode == ACPI_DECODE_16)
|
||||
flags = IORESOURCE_IO_16BIT_ADDR;
|
||||
pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum,
|
||||
io->alignment, io->address_length, flags);
|
||||
}
|
||||
|
||||
static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
|
||||
struct pnp_option *option,
|
||||
unsigned int option_flags,
|
||||
struct acpi_resource_fixed_io *io)
|
||||
{
|
||||
struct pnp_port *port;
|
||||
|
||||
if (io->address_length == 0)
|
||||
return;
|
||||
port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
|
||||
if (!port)
|
||||
return;
|
||||
port->min = port->max = io->address;
|
||||
port->size = io->address_length;
|
||||
port->align = 0;
|
||||
port->flags = PNP_PORT_FLAG_FIXED;
|
||||
pnp_register_port_resource(dev, option, port);
|
||||
|
||||
pnp_register_port_resource(dev, option_flags, io->address, io->address,
|
||||
0, io->address_length, IORESOURCE_IO_FIXED);
|
||||
}
|
||||
|
||||
static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
|
||||
struct pnp_option *option,
|
||||
unsigned int option_flags,
|
||||
struct acpi_resource_memory24 *p)
|
||||
{
|
||||
struct pnp_mem *mem;
|
||||
unsigned char flags = 0;
|
||||
|
||||
if (p->address_length == 0)
|
||||
return;
|
||||
mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
|
||||
if (!mem)
|
||||
return;
|
||||
mem->min = p->minimum;
|
||||
mem->max = p->maximum;
|
||||
mem->align = p->alignment;
|
||||
mem->size = p->address_length;
|
||||
|
||||
mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
|
||||
IORESOURCE_MEM_WRITEABLE : 0;
|
||||
|
||||
pnp_register_mem_resource(dev, option, mem);
|
||||
if (p->write_protect == ACPI_READ_WRITE_MEMORY)
|
||||
flags = IORESOURCE_MEM_WRITEABLE;
|
||||
pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
|
||||
p->alignment, p->address_length, flags);
|
||||
}
|
||||
|
||||
static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
|
||||
struct pnp_option *option,
|
||||
unsigned int option_flags,
|
||||
struct acpi_resource_memory32 *p)
|
||||
{
|
||||
struct pnp_mem *mem;
|
||||
unsigned char flags = 0;
|
||||
|
||||
if (p->address_length == 0)
|
||||
return;
|
||||
mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
|
||||
if (!mem)
|
||||
return;
|
||||
mem->min = p->minimum;
|
||||
mem->max = p->maximum;
|
||||
mem->align = p->alignment;
|
||||
mem->size = p->address_length;
|
||||
|
||||
mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
|
||||
IORESOURCE_MEM_WRITEABLE : 0;
|
||||
|
||||
pnp_register_mem_resource(dev, option, mem);
|
||||
if (p->write_protect == ACPI_READ_WRITE_MEMORY)
|
||||
flags = IORESOURCE_MEM_WRITEABLE;
|
||||
pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
|
||||
p->alignment, p->address_length, flags);
|
||||
}
|
||||
|
||||
static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
|
||||
struct pnp_option *option,
|
||||
unsigned int option_flags,
|
||||
struct acpi_resource_fixed_memory32 *p)
|
||||
{
|
||||
struct pnp_mem *mem;
|
||||
unsigned char flags = 0;
|
||||
|
||||
if (p->address_length == 0)
|
||||
return;
|
||||
mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
|
||||
if (!mem)
|
||||
return;
|
||||
mem->min = mem->max = p->address;
|
||||
mem->size = p->address_length;
|
||||
mem->align = 0;
|
||||
|
||||
mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
|
||||
IORESOURCE_MEM_WRITEABLE : 0;
|
||||
|
||||
pnp_register_mem_resource(dev, option, mem);
|
||||
if (p->write_protect == ACPI_READ_WRITE_MEMORY)
|
||||
flags = IORESOURCE_MEM_WRITEABLE;
|
||||
pnp_register_mem_resource(dev, option_flags, p->address, p->address,
|
||||
0, p->address_length, flags);
|
||||
}
|
||||
|
||||
static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
|
||||
struct pnp_option *option,
|
||||
unsigned int option_flags,
|
||||
struct acpi_resource *r)
|
||||
{
|
||||
struct acpi_resource_address64 addr, *p = &addr;
|
||||
acpi_status status;
|
||||
struct pnp_mem *mem;
|
||||
struct pnp_port *port;
|
||||
unsigned char flags = 0;
|
||||
|
||||
status = acpi_resource_to_address64(r, p);
|
||||
if (!ACPI_SUCCESS(status)) {
|
||||
@ -558,49 +620,37 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
|
||||
return;
|
||||
|
||||
if (p->resource_type == ACPI_MEMORY_RANGE) {
|
||||
mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
|
||||
if (!mem)
|
||||
return;
|
||||
mem->min = mem->max = p->minimum;
|
||||
mem->size = p->address_length;
|
||||
mem->align = 0;
|
||||
mem->flags = (p->info.mem.write_protect ==
|
||||
ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE
|
||||
: 0;
|
||||
pnp_register_mem_resource(dev, option, mem);
|
||||
} else if (p->resource_type == ACPI_IO_RANGE) {
|
||||
port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
|
||||
if (!port)
|
||||
return;
|
||||
port->min = port->max = p->minimum;
|
||||
port->size = p->address_length;
|
||||
port->align = 0;
|
||||
port->flags = PNP_PORT_FLAG_FIXED;
|
||||
pnp_register_port_resource(dev, option, port);
|
||||
}
|
||||
if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
|
||||
flags = IORESOURCE_MEM_WRITEABLE;
|
||||
pnp_register_mem_resource(dev, option_flags, p->minimum,
|
||||
p->minimum, 0, p->address_length,
|
||||
flags);
|
||||
} else if (p->resource_type == ACPI_IO_RANGE)
|
||||
pnp_register_port_resource(dev, option_flags, p->minimum,
|
||||
p->minimum, 0, p->address_length,
|
||||
IORESOURCE_IO_FIXED);
|
||||
}
|
||||
|
||||
struct acpipnp_parse_option_s {
|
||||
struct pnp_option *option;
|
||||
struct pnp_option *option_independent;
|
||||
struct pnp_dev *dev;
|
||||
unsigned int option_flags;
|
||||
};
|
||||
|
||||
static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
|
||||
void *data)
|
||||
{
|
||||
int priority = 0;
|
||||
int priority;
|
||||
struct acpipnp_parse_option_s *parse_data = data;
|
||||
struct pnp_dev *dev = parse_data->dev;
|
||||
struct pnp_option *option = parse_data->option;
|
||||
unsigned int option_flags = parse_data->option_flags;
|
||||
|
||||
switch (res->type) {
|
||||
case ACPI_RESOURCE_TYPE_IRQ:
|
||||
pnpacpi_parse_irq_option(dev, option, &res->data.irq);
|
||||
pnpacpi_parse_irq_option(dev, option_flags, &res->data.irq);
|
||||
break;
|
||||
|
||||
case ACPI_RESOURCE_TYPE_DMA:
|
||||
pnpacpi_parse_dma_option(dev, option, &res->data.dma);
|
||||
pnpacpi_parse_dma_option(dev, option_flags, &res->data.dma);
|
||||
break;
|
||||
|
||||
case ACPI_RESOURCE_TYPE_START_DEPENDENT:
|
||||
@ -620,31 +670,19 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
|
||||
priority = PNP_RES_PRIORITY_INVALID;
|
||||
break;
|
||||
}
|
||||
/* TBD: Consider performance/robustness bits */
|
||||
option = pnp_register_dependent_option(dev, priority);
|
||||
if (!option)
|
||||
return AE_ERROR;
|
||||
parse_data->option = option;
|
||||
parse_data->option_flags = pnp_new_dependent_set(dev, priority);
|
||||
break;
|
||||
|
||||
case ACPI_RESOURCE_TYPE_END_DEPENDENT:
|
||||
/*only one EndDependentFn is allowed */
|
||||
if (!parse_data->option_independent) {
|
||||
dev_warn(&dev->dev, "more than one EndDependentFn "
|
||||
"in _PRS\n");
|
||||
return AE_ERROR;
|
||||
}
|
||||
parse_data->option = parse_data->option_independent;
|
||||
parse_data->option_independent = NULL;
|
||||
dev_dbg(&dev->dev, "end dependent options\n");
|
||||
parse_data->option_flags = 0;
|
||||
break;
|
||||
|
||||
case ACPI_RESOURCE_TYPE_IO:
|
||||
pnpacpi_parse_port_option(dev, option, &res->data.io);
|
||||
pnpacpi_parse_port_option(dev, option_flags, &res->data.io);
|
||||
break;
|
||||
|
||||
case ACPI_RESOURCE_TYPE_FIXED_IO:
|
||||
pnpacpi_parse_fixed_port_option(dev, option,
|
||||
pnpacpi_parse_fixed_port_option(dev, option_flags,
|
||||
&res->data.fixed_io);
|
||||
break;
|
||||
|
||||
@ -653,29 +691,31 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
|
||||
break;
|
||||
|
||||
case ACPI_RESOURCE_TYPE_MEMORY24:
|
||||
pnpacpi_parse_mem24_option(dev, option, &res->data.memory24);
|
||||
pnpacpi_parse_mem24_option(dev, option_flags,
|
||||
&res->data.memory24);
|
||||
break;
|
||||
|
||||
case ACPI_RESOURCE_TYPE_MEMORY32:
|
||||
pnpacpi_parse_mem32_option(dev, option, &res->data.memory32);
|
||||
pnpacpi_parse_mem32_option(dev, option_flags,
|
||||
&res->data.memory32);
|
||||
break;
|
||||
|
||||
case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
|
||||
pnpacpi_parse_fixed_mem32_option(dev, option,
|
||||
pnpacpi_parse_fixed_mem32_option(dev, option_flags,
|
||||
&res->data.fixed_memory32);
|
||||
break;
|
||||
|
||||
case ACPI_RESOURCE_TYPE_ADDRESS16:
|
||||
case ACPI_RESOURCE_TYPE_ADDRESS32:
|
||||
case ACPI_RESOURCE_TYPE_ADDRESS64:
|
||||
pnpacpi_parse_address_option(dev, option, res);
|
||||
pnpacpi_parse_address_option(dev, option_flags, res);
|
||||
break;
|
||||
|
||||
case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
|
||||
break;
|
||||
|
||||
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
|
||||
pnpacpi_parse_ext_irq_option(dev, option,
|
||||
pnpacpi_parse_ext_irq_option(dev, option_flags,
|
||||
&res->data.extended_irq);
|
||||
break;
|
||||
|
||||
@ -699,12 +739,9 @@ int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
|
||||
|
||||
dev_dbg(&dev->dev, "parse resource options\n");
|
||||
|
||||
parse_data.option = pnp_register_independent_option(dev);
|
||||
if (!parse_data.option)
|
||||
return -ENOMEM;
|
||||
|
||||
parse_data.option_independent = parse_data.option;
|
||||
parse_data.dev = dev;
|
||||
parse_data.option_flags = 0;
|
||||
|
||||
status = acpi_walk_resources(handle, METHOD_NAME__PRS,
|
||||
pnpacpi_option_resource, &parse_data);
|
||||
|
||||
@ -806,6 +843,13 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev,
|
||||
struct acpi_resource_irq *irq = &resource->data.irq;
|
||||
int triggering, polarity, shareable;
|
||||
|
||||
if (!pnp_resource_enabled(p)) {
|
||||
irq->interrupt_count = 0;
|
||||
dev_dbg(&dev->dev, " encode irq (%s)\n",
|
||||
p ? "disabled" : "missing");
|
||||
return;
|
||||
}
|
||||
|
||||
decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
|
||||
irq->triggering = triggering;
|
||||
irq->polarity = polarity;
|
||||
@ -828,6 +872,13 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
|
||||
struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
|
||||
int triggering, polarity, shareable;
|
||||
|
||||
if (!pnp_resource_enabled(p)) {
|
||||
extended_irq->interrupt_count = 0;
|
||||
dev_dbg(&dev->dev, " encode extended irq (%s)\n",
|
||||
p ? "disabled" : "missing");
|
||||
return;
|
||||
}
|
||||
|
||||
decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
|
||||
extended_irq->producer_consumer = ACPI_CONSUMER;
|
||||
extended_irq->triggering = triggering;
|
||||
@ -848,6 +899,13 @@ static void pnpacpi_encode_dma(struct pnp_dev *dev,
|
||||
{
|
||||
struct acpi_resource_dma *dma = &resource->data.dma;
|
||||
|
||||
if (!pnp_resource_enabled(p)) {
|
||||
dma->channel_count = 0;
|
||||
dev_dbg(&dev->dev, " encode dma (%s)\n",
|
||||
p ? "disabled" : "missing");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
|
||||
switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
|
||||
case IORESOURCE_DMA_TYPEA:
|
||||
@ -889,17 +947,21 @@ static void pnpacpi_encode_io(struct pnp_dev *dev,
|
||||
{
|
||||
struct acpi_resource_io *io = &resource->data.io;
|
||||
|
||||
/* Note: pnp_assign_port will copy pnp_port->flags into p->flags */
|
||||
io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
|
||||
ACPI_DECODE_16 : ACPI_DECODE_10;
|
||||
io->minimum = p->start;
|
||||
io->maximum = p->end;
|
||||
io->alignment = 0; /* Correct? */
|
||||
io->address_length = p->end - p->start + 1;
|
||||
if (pnp_resource_enabled(p)) {
|
||||
/* Note: pnp_assign_port copies pnp_port->flags into p->flags */
|
||||
io->io_decode = (p->flags & IORESOURCE_IO_16BIT_ADDR) ?
|
||||
ACPI_DECODE_16 : ACPI_DECODE_10;
|
||||
io->minimum = p->start;
|
||||
io->maximum = p->end;
|
||||
io->alignment = 0; /* Correct? */
|
||||
io->address_length = p->end - p->start + 1;
|
||||
} else {
|
||||
io->minimum = 0;
|
||||
io->address_length = 0;
|
||||
}
|
||||
|
||||
dev_dbg(&dev->dev, " encode io %#llx-%#llx decode %#x\n",
|
||||
(unsigned long long) p->start, (unsigned long long) p->end,
|
||||
io->io_decode);
|
||||
dev_dbg(&dev->dev, " encode io %#x-%#x decode %#x\n", io->minimum,
|
||||
io->minimum + io->address_length - 1, io->io_decode);
|
||||
}
|
||||
|
||||
static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
|
||||
@ -908,11 +970,16 @@ static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
|
||||
{
|
||||
struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io;
|
||||
|
||||
fixed_io->address = p->start;
|
||||
fixed_io->address_length = p->end - p->start + 1;
|
||||
if (pnp_resource_enabled(p)) {
|
||||
fixed_io->address = p->start;
|
||||
fixed_io->address_length = p->end - p->start + 1;
|
||||
} else {
|
||||
fixed_io->address = 0;
|
||||
fixed_io->address_length = 0;
|
||||
}
|
||||
|
||||
dev_dbg(&dev->dev, " encode fixed_io %#llx-%#llx\n",
|
||||
(unsigned long long) p->start, (unsigned long long) p->end);
|
||||
dev_dbg(&dev->dev, " encode fixed_io %#x-%#x\n", fixed_io->address,
|
||||
fixed_io->address + fixed_io->address_length - 1);
|
||||
}
|
||||
|
||||
static void pnpacpi_encode_mem24(struct pnp_dev *dev,
|
||||
@ -921,17 +988,22 @@ static void pnpacpi_encode_mem24(struct pnp_dev *dev,
|
||||
{
|
||||
struct acpi_resource_memory24 *memory24 = &resource->data.memory24;
|
||||
|
||||
/* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */
|
||||
memory24->write_protect =
|
||||
(p->flags & IORESOURCE_MEM_WRITEABLE) ?
|
||||
ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
|
||||
memory24->minimum = p->start;
|
||||
memory24->maximum = p->end;
|
||||
memory24->alignment = 0;
|
||||
memory24->address_length = p->end - p->start + 1;
|
||||
if (pnp_resource_enabled(p)) {
|
||||
/* Note: pnp_assign_mem copies pnp_mem->flags into p->flags */
|
||||
memory24->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ?
|
||||
ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
|
||||
memory24->minimum = p->start;
|
||||
memory24->maximum = p->end;
|
||||
memory24->alignment = 0;
|
||||
memory24->address_length = p->end - p->start + 1;
|
||||
} else {
|
||||
memory24->minimum = 0;
|
||||
memory24->address_length = 0;
|
||||
}
|
||||
|
||||
dev_dbg(&dev->dev, " encode mem24 %#llx-%#llx write_protect %#x\n",
|
||||
(unsigned long long) p->start, (unsigned long long) p->end,
|
||||
dev_dbg(&dev->dev, " encode mem24 %#x-%#x write_protect %#x\n",
|
||||
memory24->minimum,
|
||||
memory24->minimum + memory24->address_length - 1,
|
||||
memory24->write_protect);
|
||||
}
|
||||
|
||||
@ -941,16 +1013,21 @@ static void pnpacpi_encode_mem32(struct pnp_dev *dev,
|
||||
{
|
||||
struct acpi_resource_memory32 *memory32 = &resource->data.memory32;
|
||||
|
||||
memory32->write_protect =
|
||||
(p->flags & IORESOURCE_MEM_WRITEABLE) ?
|
||||
ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
|
||||
memory32->minimum = p->start;
|
||||
memory32->maximum = p->end;
|
||||
memory32->alignment = 0;
|
||||
memory32->address_length = p->end - p->start + 1;
|
||||
if (pnp_resource_enabled(p)) {
|
||||
memory32->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ?
|
||||
ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
|
||||
memory32->minimum = p->start;
|
||||
memory32->maximum = p->end;
|
||||
memory32->alignment = 0;
|
||||
memory32->address_length = p->end - p->start + 1;
|
||||
} else {
|
||||
memory32->minimum = 0;
|
||||
memory32->alignment = 0;
|
||||
}
|
||||
|
||||
dev_dbg(&dev->dev, " encode mem32 %#llx-%#llx write_protect %#x\n",
|
||||
(unsigned long long) p->start, (unsigned long long) p->end,
|
||||
dev_dbg(&dev->dev, " encode mem32 %#x-%#x write_protect %#x\n",
|
||||
memory32->minimum,
|
||||
memory32->minimum + memory32->address_length - 1,
|
||||
memory32->write_protect);
|
||||
}
|
||||
|
||||
@ -960,15 +1037,20 @@ static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,
|
||||
{
|
||||
struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32;
|
||||
|
||||
fixed_memory32->write_protect =
|
||||
(p->flags & IORESOURCE_MEM_WRITEABLE) ?
|
||||
ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
|
||||
fixed_memory32->address = p->start;
|
||||
fixed_memory32->address_length = p->end - p->start + 1;
|
||||
if (pnp_resource_enabled(p)) {
|
||||
fixed_memory32->write_protect =
|
||||
p->flags & IORESOURCE_MEM_WRITEABLE ?
|
||||
ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
|
||||
fixed_memory32->address = p->start;
|
||||
fixed_memory32->address_length = p->end - p->start + 1;
|
||||
} else {
|
||||
fixed_memory32->address = 0;
|
||||
fixed_memory32->address_length = 0;
|
||||
}
|
||||
|
||||
dev_dbg(&dev->dev, " encode fixed_mem32 %#llx-%#llx "
|
||||
"write_protect %#x\n",
|
||||
(unsigned long long) p->start, (unsigned long long) p->end,
|
||||
dev_dbg(&dev->dev, " encode fixed_mem32 %#x-%#x write_protect %#x\n",
|
||||
fixed_memory32->address,
|
||||
fixed_memory32->address + fixed_memory32->address_length - 1,
|
||||
fixed_memory32->write_protect);
|
||||
}
|
||||
|
||||
|
@ -216,137 +216,116 @@ static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev,
|
||||
|
||||
static __init void pnpbios_parse_mem_option(struct pnp_dev *dev,
|
||||
unsigned char *p, int size,
|
||||
struct pnp_option *option)
|
||||
unsigned int option_flags)
|
||||
{
|
||||
struct pnp_mem *mem;
|
||||
resource_size_t min, max, align, len;
|
||||
unsigned char flags;
|
||||
|
||||
mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
|
||||
if (!mem)
|
||||
return;
|
||||
mem->min = ((p[5] << 8) | p[4]) << 8;
|
||||
mem->max = ((p[7] << 8) | p[6]) << 8;
|
||||
mem->align = (p[9] << 8) | p[8];
|
||||
mem->size = ((p[11] << 8) | p[10]) << 8;
|
||||
mem->flags = p[3];
|
||||
pnp_register_mem_resource(dev, option, mem);
|
||||
min = ((p[5] << 8) | p[4]) << 8;
|
||||
max = ((p[7] << 8) | p[6]) << 8;
|
||||
align = (p[9] << 8) | p[8];
|
||||
len = ((p[11] << 8) | p[10]) << 8;
|
||||
flags = p[3];
|
||||
pnp_register_mem_resource(dev, option_flags, min, max, align, len,
|
||||
flags);
|
||||
}
|
||||
|
||||
static __init void pnpbios_parse_mem32_option(struct pnp_dev *dev,
|
||||
unsigned char *p, int size,
|
||||
struct pnp_option *option)
|
||||
unsigned int option_flags)
|
||||
{
|
||||
struct pnp_mem *mem;
|
||||
resource_size_t min, max, align, len;
|
||||
unsigned char flags;
|
||||
|
||||
mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
|
||||
if (!mem)
|
||||
return;
|
||||
mem->min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
|
||||
mem->max = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
|
||||
mem->align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12];
|
||||
mem->size = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16];
|
||||
mem->flags = p[3];
|
||||
pnp_register_mem_resource(dev, option, mem);
|
||||
min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
|
||||
max = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
|
||||
align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12];
|
||||
len = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16];
|
||||
flags = p[3];
|
||||
pnp_register_mem_resource(dev, option_flags, min, max, align, len,
|
||||
flags);
|
||||
}
|
||||
|
||||
static __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev,
|
||||
unsigned char *p, int size,
|
||||
struct pnp_option *option)
|
||||
unsigned int option_flags)
|
||||
{
|
||||
struct pnp_mem *mem;
|
||||
resource_size_t base, len;
|
||||
unsigned char flags;
|
||||
|
||||
mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
|
||||
if (!mem)
|
||||
return;
|
||||
mem->min = mem->max = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
|
||||
mem->size = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
|
||||
mem->align = 0;
|
||||
mem->flags = p[3];
|
||||
pnp_register_mem_resource(dev, option, mem);
|
||||
base = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
|
||||
len = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
|
||||
flags = p[3];
|
||||
pnp_register_mem_resource(dev, option_flags, base, base, 0, len, flags);
|
||||
}
|
||||
|
||||
static __init void pnpbios_parse_irq_option(struct pnp_dev *dev,
|
||||
unsigned char *p, int size,
|
||||
struct pnp_option *option)
|
||||
unsigned int option_flags)
|
||||
{
|
||||
struct pnp_irq *irq;
|
||||
unsigned long bits;
|
||||
pnp_irq_mask_t map;
|
||||
unsigned char flags = IORESOURCE_IRQ_HIGHEDGE;
|
||||
|
||||
irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
|
||||
if (!irq)
|
||||
return;
|
||||
bits = (p[2] << 8) | p[1];
|
||||
bitmap_copy(irq->map, &bits, 16);
|
||||
|
||||
bitmap_zero(map.bits, PNP_IRQ_NR);
|
||||
bitmap_copy(map.bits, &bits, 16);
|
||||
|
||||
if (size > 2)
|
||||
irq->flags = p[3];
|
||||
else
|
||||
irq->flags = IORESOURCE_IRQ_HIGHEDGE;
|
||||
pnp_register_irq_resource(dev, option, irq);
|
||||
flags = p[3];
|
||||
|
||||
pnp_register_irq_resource(dev, option_flags, &map, flags);
|
||||
}
|
||||
|
||||
static __init void pnpbios_parse_dma_option(struct pnp_dev *dev,
|
||||
unsigned char *p, int size,
|
||||
struct pnp_option *option)
|
||||
unsigned int option_flags)
|
||||
{
|
||||
struct pnp_dma *dma;
|
||||
|
||||
dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
|
||||
if (!dma)
|
||||
return;
|
||||
dma->map = p[1];
|
||||
dma->flags = p[2];
|
||||
pnp_register_dma_resource(dev, option, dma);
|
||||
pnp_register_dma_resource(dev, option_flags, p[1], p[2]);
|
||||
}
|
||||
|
||||
static __init void pnpbios_parse_port_option(struct pnp_dev *dev,
|
||||
unsigned char *p, int size,
|
||||
struct pnp_option *option)
|
||||
unsigned int option_flags)
|
||||
{
|
||||
struct pnp_port *port;
|
||||
resource_size_t min, max, align, len;
|
||||
unsigned char flags;
|
||||
|
||||
port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
|
||||
if (!port)
|
||||
return;
|
||||
port->min = (p[3] << 8) | p[2];
|
||||
port->max = (p[5] << 8) | p[4];
|
||||
port->align = p[6];
|
||||
port->size = p[7];
|
||||
port->flags = p[1] ? PNP_PORT_FLAG_16BITADDR : 0;
|
||||
pnp_register_port_resource(dev, option, port);
|
||||
min = (p[3] << 8) | p[2];
|
||||
max = (p[5] << 8) | p[4];
|
||||
align = p[6];
|
||||
len = p[7];
|
||||
flags = p[1] ? IORESOURCE_IO_16BIT_ADDR : 0;
|
||||
pnp_register_port_resource(dev, option_flags, min, max, align, len,
|
||||
flags);
|
||||
}
|
||||
|
||||
static __init void pnpbios_parse_fixed_port_option(struct pnp_dev *dev,
|
||||
unsigned char *p, int size,
|
||||
struct pnp_option *option)
|
||||
unsigned int option_flags)
|
||||
{
|
||||
struct pnp_port *port;
|
||||
resource_size_t base, len;
|
||||
|
||||
port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
|
||||
if (!port)
|
||||
return;
|
||||
port->min = port->max = (p[2] << 8) | p[1];
|
||||
port->size = p[3];
|
||||
port->align = 0;
|
||||
port->flags = PNP_PORT_FLAG_FIXED;
|
||||
pnp_register_port_resource(dev, option, port);
|
||||
base = (p[2] << 8) | p[1];
|
||||
len = p[3];
|
||||
pnp_register_port_resource(dev, option_flags, base, base, 0, len,
|
||||
IORESOURCE_IO_FIXED);
|
||||
}
|
||||
|
||||
static __init unsigned char *
|
||||
pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
|
||||
struct pnp_dev *dev)
|
||||
struct pnp_dev *dev)
|
||||
{
|
||||
unsigned int len, tag;
|
||||
int priority = 0;
|
||||
struct pnp_option *option, *option_independent;
|
||||
int priority;
|
||||
unsigned int option_flags;
|
||||
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
dev_dbg(&dev->dev, "parse resource options\n");
|
||||
|
||||
option_independent = option = pnp_register_independent_option(dev);
|
||||
if (!option)
|
||||
return NULL;
|
||||
|
||||
option_flags = 0;
|
||||
while ((char *)p < (char *)end) {
|
||||
|
||||
/* determine the type of tag */
|
||||
@ -363,37 +342,38 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
|
||||
case LARGE_TAG_MEM:
|
||||
if (len != 9)
|
||||
goto len_err;
|
||||
pnpbios_parse_mem_option(dev, p, len, option);
|
||||
pnpbios_parse_mem_option(dev, p, len, option_flags);
|
||||
break;
|
||||
|
||||
case LARGE_TAG_MEM32:
|
||||
if (len != 17)
|
||||
goto len_err;
|
||||
pnpbios_parse_mem32_option(dev, p, len, option);
|
||||
pnpbios_parse_mem32_option(dev, p, len, option_flags);
|
||||
break;
|
||||
|
||||
case LARGE_TAG_FIXEDMEM32:
|
||||
if (len != 9)
|
||||
goto len_err;
|
||||
pnpbios_parse_fixed_mem32_option(dev, p, len, option);
|
||||
pnpbios_parse_fixed_mem32_option(dev, p, len,
|
||||
option_flags);
|
||||
break;
|
||||
|
||||
case SMALL_TAG_IRQ:
|
||||
if (len < 2 || len > 3)
|
||||
goto len_err;
|
||||
pnpbios_parse_irq_option(dev, p, len, option);
|
||||
pnpbios_parse_irq_option(dev, p, len, option_flags);
|
||||
break;
|
||||
|
||||
case SMALL_TAG_DMA:
|
||||
if (len != 2)
|
||||
goto len_err;
|
||||
pnpbios_parse_dma_option(dev, p, len, option);
|
||||
pnpbios_parse_dma_option(dev, p, len, option_flags);
|
||||
break;
|
||||
|
||||
case SMALL_TAG_PORT:
|
||||
if (len != 7)
|
||||
goto len_err;
|
||||
pnpbios_parse_port_option(dev, p, len, option);
|
||||
pnpbios_parse_port_option(dev, p, len, option_flags);
|
||||
break;
|
||||
|
||||
case SMALL_TAG_VENDOR:
|
||||
@ -403,28 +383,23 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
|
||||
case SMALL_TAG_FIXEDPORT:
|
||||
if (len != 3)
|
||||
goto len_err;
|
||||
pnpbios_parse_fixed_port_option(dev, p, len, option);
|
||||
pnpbios_parse_fixed_port_option(dev, p, len,
|
||||
option_flags);
|
||||
break;
|
||||
|
||||
case SMALL_TAG_STARTDEP:
|
||||
if (len > 1)
|
||||
goto len_err;
|
||||
priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE;
|
||||
priority = PNP_RES_PRIORITY_ACCEPTABLE;
|
||||
if (len > 0)
|
||||
priority = 0x100 | p[1];
|
||||
option = pnp_register_dependent_option(dev, priority);
|
||||
if (!option)
|
||||
return NULL;
|
||||
priority = p[1];
|
||||
option_flags = pnp_new_dependent_set(dev, priority);
|
||||
break;
|
||||
|
||||
case SMALL_TAG_ENDDEP:
|
||||
if (len != 0)
|
||||
goto len_err;
|
||||
if (option_independent == option)
|
||||
dev_warn(&dev->dev, "missing "
|
||||
"SMALL_TAG_STARTDEP tag\n");
|
||||
option = option_independent;
|
||||
dev_dbg(&dev->dev, "end dependent options\n");
|
||||
option_flags = 0;
|
||||
break;
|
||||
|
||||
case SMALL_TAG_END:
|
||||
@ -526,8 +501,16 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p,
|
||||
static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p,
|
||||
struct resource *res)
|
||||
{
|
||||
unsigned long base = res->start;
|
||||
unsigned long len = res->end - res->start + 1;
|
||||
unsigned long base;
|
||||
unsigned long len;
|
||||
|
||||
if (pnp_resource_enabled(res)) {
|
||||
base = res->start;
|
||||
len = res->end - res->start + 1;
|
||||
} else {
|
||||
base = 0;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
p[4] = (base >> 8) & 0xff;
|
||||
p[5] = ((base >> 8) >> 8) & 0xff;
|
||||
@ -536,15 +519,22 @@ static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p,
|
||||
p[10] = (len >> 8) & 0xff;
|
||||
p[11] = ((len >> 8) >> 8) & 0xff;
|
||||
|
||||
dev_dbg(&dev->dev, " encode mem %#llx-%#llx\n",
|
||||
(unsigned long long) res->start, (unsigned long long) res->end);
|
||||
dev_dbg(&dev->dev, " encode mem %#lx-%#lx\n", base, base + len - 1);
|
||||
}
|
||||
|
||||
static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p,
|
||||
struct resource *res)
|
||||
{
|
||||
unsigned long base = res->start;
|
||||
unsigned long len = res->end - res->start + 1;
|
||||
unsigned long base;
|
||||
unsigned long len;
|
||||
|
||||
if (pnp_resource_enabled(res)) {
|
||||
base = res->start;
|
||||
len = res->end - res->start + 1;
|
||||
} else {
|
||||
base = 0;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
p[4] = base & 0xff;
|
||||
p[5] = (base >> 8) & 0xff;
|
||||
@ -559,15 +549,22 @@ static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p,
|
||||
p[18] = (len >> 16) & 0xff;
|
||||
p[19] = (len >> 24) & 0xff;
|
||||
|
||||
dev_dbg(&dev->dev, " encode mem32 %#llx-%#llx\n",
|
||||
(unsigned long long) res->start, (unsigned long long) res->end);
|
||||
dev_dbg(&dev->dev, " encode mem32 %#lx-%#lx\n", base, base + len - 1);
|
||||
}
|
||||
|
||||
static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p,
|
||||
struct resource *res)
|
||||
{
|
||||
unsigned long base = res->start;
|
||||
unsigned long len = res->end - res->start + 1;
|
||||
unsigned long base;
|
||||
unsigned long len;
|
||||
|
||||
if (pnp_resource_enabled(res)) {
|
||||
base = res->start;
|
||||
len = res->end - res->start + 1;
|
||||
} else {
|
||||
base = 0;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
p[4] = base & 0xff;
|
||||
p[5] = (base >> 8) & 0xff;
|
||||
@ -578,40 +575,54 @@ static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p,
|
||||
p[10] = (len >> 16) & 0xff;
|
||||
p[11] = (len >> 24) & 0xff;
|
||||
|
||||
dev_dbg(&dev->dev, " encode fixed_mem32 %#llx-%#llx\n",
|
||||
(unsigned long long) res->start, (unsigned long long) res->end);
|
||||
dev_dbg(&dev->dev, " encode fixed_mem32 %#lx-%#lx\n", base,
|
||||
base + len - 1);
|
||||
}
|
||||
|
||||
static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p,
|
||||
struct resource *res)
|
||||
{
|
||||
unsigned long map = 0;
|
||||
unsigned long map;
|
||||
|
||||
if (pnp_resource_enabled(res))
|
||||
map = 1 << res->start;
|
||||
else
|
||||
map = 0;
|
||||
|
||||
map = 1 << res->start;
|
||||
p[1] = map & 0xff;
|
||||
p[2] = (map >> 8) & 0xff;
|
||||
|
||||
dev_dbg(&dev->dev, " encode irq %llu\n",
|
||||
(unsigned long long)res->start);
|
||||
dev_dbg(&dev->dev, " encode irq mask %#lx\n", map);
|
||||
}
|
||||
|
||||
static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p,
|
||||
struct resource *res)
|
||||
{
|
||||
unsigned long map = 0;
|
||||
unsigned long map;
|
||||
|
||||
if (pnp_resource_enabled(res))
|
||||
map = 1 << res->start;
|
||||
else
|
||||
map = 0;
|
||||
|
||||
map = 1 << res->start;
|
||||
p[1] = map & 0xff;
|
||||
|
||||
dev_dbg(&dev->dev, " encode dma %llu\n",
|
||||
(unsigned long long)res->start);
|
||||
dev_dbg(&dev->dev, " encode dma mask %#lx\n", map);
|
||||
}
|
||||
|
||||
static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
|
||||
struct resource *res)
|
||||
{
|
||||
unsigned long base = res->start;
|
||||
unsigned long len = res->end - res->start + 1;
|
||||
unsigned long base;
|
||||
unsigned long len;
|
||||
|
||||
if (pnp_resource_enabled(res)) {
|
||||
base = res->start;
|
||||
len = res->end - res->start + 1;
|
||||
} else {
|
||||
base = 0;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
p[2] = base & 0xff;
|
||||
p[3] = (base >> 8) & 0xff;
|
||||
@ -619,8 +630,7 @@ static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
|
||||
p[5] = (base >> 8) & 0xff;
|
||||
p[7] = len & 0xff;
|
||||
|
||||
dev_dbg(&dev->dev, " encode io %#llx-%#llx\n",
|
||||
(unsigned long long) res->start, (unsigned long long) res->end);
|
||||
dev_dbg(&dev->dev, " encode io %#lx-%#lx\n", base, base + len - 1);
|
||||
}
|
||||
|
||||
static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p,
|
||||
@ -629,12 +639,20 @@ static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p,
|
||||
unsigned long base = res->start;
|
||||
unsigned long len = res->end - res->start + 1;
|
||||
|
||||
if (pnp_resource_enabled(res)) {
|
||||
base = res->start;
|
||||
len = res->end - res->start + 1;
|
||||
} else {
|
||||
base = 0;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
p[1] = base & 0xff;
|
||||
p[2] = (base >> 8) & 0xff;
|
||||
p[3] = len & 0xff;
|
||||
|
||||
dev_dbg(&dev->dev, " encode fixed_io %#llx-%#llx\n",
|
||||
(unsigned long long) res->start, (unsigned long long) res->end);
|
||||
dev_dbg(&dev->dev, " encode fixed_io %#lx-%#lx\n", base,
|
||||
base + len - 1);
|
||||
}
|
||||
|
||||
static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev
|
||||
|
@ -5,6 +5,8 @@
|
||||
* when building up the resource structure for the first time.
|
||||
*
|
||||
* Copyright (c) 2000 Peter Denison <peterd@pnd-pc.demon.co.uk>
|
||||
* Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
|
||||
* Bjorn Helgaas <bjorn.helgaas@hp.com>
|
||||
*
|
||||
* Heavily based on PCI quirks handling which is
|
||||
*
|
||||
@ -20,203 +22,207 @@
|
||||
#include <linux/kallsyms.h>
|
||||
#include "base.h"
|
||||
|
||||
static void quirk_awe32_add_ports(struct pnp_dev *dev,
|
||||
struct pnp_option *option,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct pnp_option *new_option;
|
||||
|
||||
new_option = kmalloc(sizeof(struct pnp_option), GFP_KERNEL);
|
||||
if (!new_option) {
|
||||
dev_err(&dev->dev, "couldn't add ioport region to option set "
|
||||
"%d\n", pnp_option_set(option));
|
||||
return;
|
||||
}
|
||||
|
||||
*new_option = *option;
|
||||
new_option->u.port.min += offset;
|
||||
new_option->u.port.max += offset;
|
||||
list_add(&new_option->list, &option->list);
|
||||
|
||||
dev_info(&dev->dev, "added ioport region %#llx-%#llx to set %d\n",
|
||||
(unsigned long long) new_option->u.port.min,
|
||||
(unsigned long long) new_option->u.port.max,
|
||||
pnp_option_set(option));
|
||||
}
|
||||
|
||||
static void quirk_awe32_resources(struct pnp_dev *dev)
|
||||
{
|
||||
struct pnp_port *port, *port2, *port3;
|
||||
struct pnp_option *res = dev->dependent;
|
||||
struct pnp_option *option;
|
||||
unsigned int set = ~0;
|
||||
|
||||
/*
|
||||
* Unfortunately the isapnp_add_port_resource is too tightly bound
|
||||
* into the PnP discovery sequence, and cannot be used. Link in the
|
||||
* two extra ports (at offset 0x400 and 0x800 from the one given) by
|
||||
* hand.
|
||||
* Add two extra ioport regions (at offset 0x400 and 0x800 from the
|
||||
* one given) to every dependent option set.
|
||||
*/
|
||||
for (; res; res = res->next) {
|
||||
port2 = pnp_alloc(sizeof(struct pnp_port));
|
||||
if (!port2)
|
||||
return;
|
||||
port3 = pnp_alloc(sizeof(struct pnp_port));
|
||||
if (!port3) {
|
||||
kfree(port2);
|
||||
return;
|
||||
list_for_each_entry(option, &dev->options, list) {
|
||||
if (pnp_option_is_dependent(option) &&
|
||||
pnp_option_set(option) != set) {
|
||||
set = pnp_option_set(option);
|
||||
quirk_awe32_add_ports(dev, option, 0x800);
|
||||
quirk_awe32_add_ports(dev, option, 0x400);
|
||||
}
|
||||
port = res->port;
|
||||
memcpy(port2, port, sizeof(struct pnp_port));
|
||||
memcpy(port3, port, sizeof(struct pnp_port));
|
||||
port->next = port2;
|
||||
port2->next = port3;
|
||||
port2->min += 0x400;
|
||||
port2->max += 0x400;
|
||||
port3->min += 0x800;
|
||||
port3->max += 0x800;
|
||||
dev_info(&dev->dev,
|
||||
"AWE32 quirk - added ioports 0x%lx and 0x%lx\n",
|
||||
(unsigned long)port2->min,
|
||||
(unsigned long)port3->min);
|
||||
}
|
||||
}
|
||||
|
||||
static void quirk_cmi8330_resources(struct pnp_dev *dev)
|
||||
{
|
||||
struct pnp_option *res = dev->dependent;
|
||||
unsigned long tmp;
|
||||
struct pnp_option *option;
|
||||
struct pnp_irq *irq;
|
||||
struct pnp_dma *dma;
|
||||
|
||||
for (; res; res = res->next) {
|
||||
list_for_each_entry(option, &dev->options, list) {
|
||||
if (!pnp_option_is_dependent(option))
|
||||
continue;
|
||||
|
||||
struct pnp_irq *irq;
|
||||
struct pnp_dma *dma;
|
||||
|
||||
for (irq = res->irq; irq; irq = irq->next) { // Valid irqs are 5, 7, 10
|
||||
tmp = 0x04A0;
|
||||
bitmap_copy(irq->map, &tmp, 16); // 0000 0100 1010 0000
|
||||
}
|
||||
|
||||
for (dma = res->dma; dma; dma = dma->next) // Valid 8bit dma channels are 1,3
|
||||
if (option->type == IORESOURCE_IRQ) {
|
||||
irq = &option->u.irq;
|
||||
bitmap_zero(irq->map.bits, PNP_IRQ_NR);
|
||||
__set_bit(5, irq->map.bits);
|
||||
__set_bit(7, irq->map.bits);
|
||||
__set_bit(10, irq->map.bits);
|
||||
dev_info(&dev->dev, "set possible IRQs in "
|
||||
"option set %d to 5, 7, 10\n",
|
||||
pnp_option_set(option));
|
||||
} else if (option->type == IORESOURCE_DMA) {
|
||||
dma = &option->u.dma;
|
||||
if ((dma->flags & IORESOURCE_DMA_TYPE_MASK) ==
|
||||
IORESOURCE_DMA_8BIT)
|
||||
dma->map = 0x000A;
|
||||
IORESOURCE_DMA_8BIT &&
|
||||
dma->map != 0x0A) {
|
||||
dev_info(&dev->dev, "changing possible "
|
||||
"DMA channel mask in option set %d "
|
||||
"from %#02x to 0x0A (1, 3)\n",
|
||||
pnp_option_set(option), dma->map);
|
||||
dma->map = 0x0A;
|
||||
}
|
||||
}
|
||||
}
|
||||
dev_info(&dev->dev, "CMI8330 quirk - forced possible IRQs to 5, 7, 10 "
|
||||
"and DMA channels to 1, 3\n");
|
||||
}
|
||||
|
||||
static void quirk_sb16audio_resources(struct pnp_dev *dev)
|
||||
{
|
||||
struct pnp_option *option;
|
||||
unsigned int prev_option_flags = ~0, n = 0;
|
||||
struct pnp_port *port;
|
||||
struct pnp_option *res = dev->dependent;
|
||||
int changed = 0;
|
||||
|
||||
/*
|
||||
* The default range on the mpu port for these devices is 0x388-0x388.
|
||||
* The default range on the OPL port for these devices is 0x388-0x388.
|
||||
* Here we increase that range so that two such cards can be
|
||||
* auto-configured.
|
||||
*/
|
||||
list_for_each_entry(option, &dev->options, list) {
|
||||
if (prev_option_flags != option->flags) {
|
||||
prev_option_flags = option->flags;
|
||||
n = 0;
|
||||
}
|
||||
|
||||
for (; res; res = res->next) {
|
||||
port = res->port;
|
||||
if (!port)
|
||||
continue;
|
||||
port = port->next;
|
||||
if (!port)
|
||||
continue;
|
||||
port = port->next;
|
||||
if (!port)
|
||||
continue;
|
||||
if (port->min != port->max)
|
||||
continue;
|
||||
port->max += 0x70;
|
||||
changed = 1;
|
||||
if (pnp_option_is_dependent(option) &&
|
||||
option->type == IORESOURCE_IO) {
|
||||
n++;
|
||||
port = &option->u.port;
|
||||
if (n == 3 && port->min == port->max) {
|
||||
port->max += 0x70;
|
||||
dev_info(&dev->dev, "increased option port "
|
||||
"range from %#llx-%#llx to "
|
||||
"%#llx-%#llx\n",
|
||||
(unsigned long long) port->min,
|
||||
(unsigned long long) port->min,
|
||||
(unsigned long long) port->min,
|
||||
(unsigned long long) port->max);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (changed)
|
||||
dev_info(&dev->dev, "SB audio device quirk - increased port range\n");
|
||||
}
|
||||
|
||||
static struct pnp_option *quirk_isapnp_mpu_options(struct pnp_dev *dev)
|
||||
static struct pnp_option *pnp_clone_dependent_set(struct pnp_dev *dev,
|
||||
unsigned int set)
|
||||
{
|
||||
struct pnp_option *head = NULL;
|
||||
struct pnp_option *prev = NULL;
|
||||
struct pnp_option *res;
|
||||
struct pnp_option *tail = NULL, *first_new_option = NULL;
|
||||
struct pnp_option *option, *new_option;
|
||||
unsigned int flags;
|
||||
|
||||
/*
|
||||
* Build a functional IRQ-less variant of each MPU option.
|
||||
*/
|
||||
|
||||
for (res = dev->dependent; res; res = res->next) {
|
||||
struct pnp_option *curr;
|
||||
struct pnp_port *port;
|
||||
struct pnp_port *copy;
|
||||
|
||||
port = res->port;
|
||||
if (!port || !res->irq)
|
||||
continue;
|
||||
|
||||
copy = pnp_alloc(sizeof *copy);
|
||||
if (!copy)
|
||||
break;
|
||||
|
||||
copy->min = port->min;
|
||||
copy->max = port->max;
|
||||
copy->align = port->align;
|
||||
copy->size = port->size;
|
||||
copy->flags = port->flags;
|
||||
|
||||
curr = pnp_build_option(PNP_RES_PRIORITY_FUNCTIONAL);
|
||||
if (!curr) {
|
||||
kfree(copy);
|
||||
break;
|
||||
}
|
||||
curr->port = copy;
|
||||
|
||||
if (prev)
|
||||
prev->next = curr;
|
||||
else
|
||||
head = curr;
|
||||
prev = curr;
|
||||
list_for_each_entry(option, &dev->options, list) {
|
||||
if (pnp_option_is_dependent(option))
|
||||
tail = option;
|
||||
}
|
||||
if (!tail) {
|
||||
dev_err(&dev->dev, "no dependent option sets\n");
|
||||
return NULL;
|
||||
}
|
||||
if (head)
|
||||
dev_info(&dev->dev, "adding IRQ-less MPU options\n");
|
||||
|
||||
return head;
|
||||
flags = pnp_new_dependent_set(dev, PNP_RES_PRIORITY_FUNCTIONAL);
|
||||
list_for_each_entry(option, &dev->options, list) {
|
||||
if (pnp_option_is_dependent(option) &&
|
||||
pnp_option_set(option) == set) {
|
||||
new_option = kmalloc(sizeof(struct pnp_option),
|
||||
GFP_KERNEL);
|
||||
if (!new_option) {
|
||||
dev_err(&dev->dev, "couldn't clone dependent "
|
||||
"set %d\n", set);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*new_option = *option;
|
||||
new_option->flags = flags;
|
||||
if (!first_new_option)
|
||||
first_new_option = new_option;
|
||||
|
||||
list_add(&new_option->list, &tail->list);
|
||||
tail = new_option;
|
||||
}
|
||||
}
|
||||
|
||||
return first_new_option;
|
||||
}
|
||||
|
||||
|
||||
static void quirk_add_irq_optional_dependent_sets(struct pnp_dev *dev)
|
||||
{
|
||||
struct pnp_option *new_option;
|
||||
unsigned int num_sets, i, set;
|
||||
struct pnp_irq *irq;
|
||||
|
||||
num_sets = dev->num_dependent_sets;
|
||||
for (i = 0; i < num_sets; i++) {
|
||||
new_option = pnp_clone_dependent_set(dev, i);
|
||||
if (!new_option)
|
||||
return;
|
||||
|
||||
set = pnp_option_set(new_option);
|
||||
while (new_option && pnp_option_set(new_option) == set) {
|
||||
if (new_option->type == IORESOURCE_IRQ) {
|
||||
irq = &new_option->u.irq;
|
||||
irq->flags |= IORESOURCE_IRQ_OPTIONAL;
|
||||
}
|
||||
dbg_pnp_show_option(dev, new_option);
|
||||
new_option = list_entry(new_option->list.next,
|
||||
struct pnp_option, list);
|
||||
}
|
||||
|
||||
dev_info(&dev->dev, "added dependent option set %d (same as "
|
||||
"set %d except IRQ optional)\n", set, i);
|
||||
}
|
||||
}
|
||||
|
||||
static void quirk_ad1815_mpu_resources(struct pnp_dev *dev)
|
||||
{
|
||||
struct pnp_option *res;
|
||||
struct pnp_irq *irq;
|
||||
struct pnp_option *option;
|
||||
struct pnp_irq *irq = NULL;
|
||||
unsigned int independent_irqs = 0;
|
||||
|
||||
/*
|
||||
* Distribute the independent IRQ over the dependent options
|
||||
*/
|
||||
|
||||
res = dev->independent;
|
||||
if (!res)
|
||||
return;
|
||||
|
||||
irq = res->irq;
|
||||
if (!irq || irq->next)
|
||||
return;
|
||||
|
||||
res = dev->dependent;
|
||||
if (!res)
|
||||
return;
|
||||
|
||||
while (1) {
|
||||
struct pnp_irq *copy;
|
||||
|
||||
copy = pnp_alloc(sizeof *copy);
|
||||
if (!copy)
|
||||
break;
|
||||
|
||||
memcpy(copy->map, irq->map, sizeof copy->map);
|
||||
copy->flags = irq->flags;
|
||||
|
||||
copy->next = res->irq; /* Yes, this is NULL */
|
||||
res->irq = copy;
|
||||
|
||||
if (!res->next)
|
||||
break;
|
||||
res = res->next;
|
||||
list_for_each_entry(option, &dev->options, list) {
|
||||
if (option->type == IORESOURCE_IRQ &&
|
||||
!pnp_option_is_dependent(option)) {
|
||||
independent_irqs++;
|
||||
irq = &option->u.irq;
|
||||
}
|
||||
}
|
||||
kfree(irq);
|
||||
|
||||
res->next = quirk_isapnp_mpu_options(dev);
|
||||
|
||||
res = dev->independent;
|
||||
res->irq = NULL;
|
||||
}
|
||||
|
||||
static void quirk_isapnp_mpu_resources(struct pnp_dev *dev)
|
||||
{
|
||||
struct pnp_option *res;
|
||||
|
||||
res = dev->dependent;
|
||||
if (!res)
|
||||
if (independent_irqs != 1)
|
||||
return;
|
||||
|
||||
while (res->next)
|
||||
res = res->next;
|
||||
|
||||
res->next = quirk_isapnp_mpu_options(dev);
|
||||
irq->flags |= IORESOURCE_IRQ_OPTIONAL;
|
||||
dev_info(&dev->dev, "made independent IRQ optional\n");
|
||||
}
|
||||
|
||||
#include <linux/pci.h>
|
||||
@ -248,8 +254,7 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
|
||||
for (j = 0;
|
||||
(res = pnp_get_resource(dev, IORESOURCE_MEM, j));
|
||||
j++) {
|
||||
if (res->flags & IORESOURCE_UNSET ||
|
||||
(res->start == 0 && res->end == 0))
|
||||
if (res->start == 0 && res->end == 0)
|
||||
continue;
|
||||
|
||||
pnp_start = res->start;
|
||||
@ -312,10 +317,10 @@ static struct pnp_fixup pnp_fixups[] = {
|
||||
{"CTL0043", quirk_sb16audio_resources},
|
||||
{"CTL0044", quirk_sb16audio_resources},
|
||||
{"CTL0045", quirk_sb16audio_resources},
|
||||
/* Add IRQ-less MPU options */
|
||||
/* Add IRQ-optional MPU options */
|
||||
{"ADS7151", quirk_ad1815_mpu_resources},
|
||||
{"ADS7181", quirk_isapnp_mpu_resources},
|
||||
{"AZT0002", quirk_isapnp_mpu_resources},
|
||||
{"ADS7181", quirk_add_irq_optional_dependent_sets},
|
||||
{"AZT0002", quirk_add_irq_optional_dependent_sets},
|
||||
/* PnP resources that might overlap PCI BARs */
|
||||
{"PNP0c01", quirk_system_pci_resources},
|
||||
{"PNP0c02", quirk_system_pci_resources},
|
||||
|
@ -3,6 +3,8 @@
|
||||
*
|
||||
* based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
|
||||
* Copyright 2003 Adam Belay <ambx1@neo.rr.com>
|
||||
* Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
|
||||
* Bjorn Helgaas <bjorn.helgaas@hp.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -28,201 +30,121 @@ static int pnp_reserve_mem[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some
|
||||
* option registration
|
||||
*/
|
||||
|
||||
struct pnp_option *pnp_build_option(int priority)
|
||||
struct pnp_option *pnp_build_option(struct pnp_dev *dev, unsigned long type,
|
||||
unsigned int option_flags)
|
||||
{
|
||||
struct pnp_option *option = pnp_alloc(sizeof(struct pnp_option));
|
||||
struct pnp_option *option;
|
||||
|
||||
option = kzalloc(sizeof(struct pnp_option), GFP_KERNEL);
|
||||
if (!option)
|
||||
return NULL;
|
||||
|
||||
option->priority = priority & 0xff;
|
||||
/* make sure the priority is valid */
|
||||
if (option->priority > PNP_RES_PRIORITY_FUNCTIONAL)
|
||||
option->priority = PNP_RES_PRIORITY_INVALID;
|
||||
option->flags = option_flags;
|
||||
option->type = type;
|
||||
|
||||
list_add_tail(&option->list, &dev->options);
|
||||
return option;
|
||||
}
|
||||
|
||||
struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev)
|
||||
int pnp_register_irq_resource(struct pnp_dev *dev, unsigned int option_flags,
|
||||
pnp_irq_mask_t *map, unsigned char flags)
|
||||
{
|
||||
struct pnp_option *option;
|
||||
struct pnp_irq *irq;
|
||||
|
||||
option = pnp_build_option(PNP_RES_PRIORITY_PREFERRED);
|
||||
option = pnp_build_option(dev, IORESOURCE_IRQ, option_flags);
|
||||
if (!option)
|
||||
return -ENOMEM;
|
||||
|
||||
/* this should never happen but if it does we'll try to continue */
|
||||
if (dev->independent)
|
||||
dev_err(&dev->dev, "independent resource already registered\n");
|
||||
dev->independent = option;
|
||||
|
||||
dev_dbg(&dev->dev, "new independent option\n");
|
||||
return option;
|
||||
}
|
||||
|
||||
struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
|
||||
int priority)
|
||||
{
|
||||
struct pnp_option *option;
|
||||
|
||||
option = pnp_build_option(priority);
|
||||
|
||||
if (dev->dependent) {
|
||||
struct pnp_option *parent = dev->dependent;
|
||||
while (parent->next)
|
||||
parent = parent->next;
|
||||
parent->next = option;
|
||||
} else
|
||||
dev->dependent = option;
|
||||
|
||||
dev_dbg(&dev->dev, "new dependent option (priority %#x)\n", priority);
|
||||
return option;
|
||||
}
|
||||
|
||||
int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option,
|
||||
struct pnp_irq *data)
|
||||
{
|
||||
struct pnp_irq *ptr;
|
||||
#ifdef DEBUG
|
||||
char buf[PNP_IRQ_NR]; /* hex-encoded, so this is overkill but safe */
|
||||
#endif
|
||||
|
||||
ptr = option->irq;
|
||||
while (ptr && ptr->next)
|
||||
ptr = ptr->next;
|
||||
if (ptr)
|
||||
ptr->next = data;
|
||||
else
|
||||
option->irq = data;
|
||||
irq = &option->u.irq;
|
||||
irq->map = *map;
|
||||
irq->flags = flags;
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
if (test_bit(i, data->map))
|
||||
if (test_bit(i, irq->map.bits))
|
||||
pcibios_penalize_isa_irq(i, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
bitmap_scnprintf(buf, sizeof(buf), data->map, PNP_IRQ_NR);
|
||||
dev_dbg(&dev->dev, " irq bitmask %s flags %#x\n", buf,
|
||||
data->flags);
|
||||
#endif
|
||||
dbg_pnp_show_option(dev, option);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option,
|
||||
struct pnp_dma *data)
|
||||
int pnp_register_dma_resource(struct pnp_dev *dev, unsigned int option_flags,
|
||||
unsigned char map, unsigned char flags)
|
||||
{
|
||||
struct pnp_dma *ptr;
|
||||
struct pnp_option *option;
|
||||
struct pnp_dma *dma;
|
||||
|
||||
ptr = option->dma;
|
||||
while (ptr && ptr->next)
|
||||
ptr = ptr->next;
|
||||
if (ptr)
|
||||
ptr->next = data;
|
||||
else
|
||||
option->dma = data;
|
||||
option = pnp_build_option(dev, IORESOURCE_DMA, option_flags);
|
||||
if (!option)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_dbg(&dev->dev, " dma bitmask %#x flags %#x\n", data->map,
|
||||
data->flags);
|
||||
dma = &option->u.dma;
|
||||
dma->map = map;
|
||||
dma->flags = flags;
|
||||
|
||||
dbg_pnp_show_option(dev, option);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option,
|
||||
struct pnp_port *data)
|
||||
int pnp_register_port_resource(struct pnp_dev *dev, unsigned int option_flags,
|
||||
resource_size_t min, resource_size_t max,
|
||||
resource_size_t align, resource_size_t size,
|
||||
unsigned char flags)
|
||||
{
|
||||
struct pnp_port *ptr;
|
||||
struct pnp_option *option;
|
||||
struct pnp_port *port;
|
||||
|
||||
ptr = option->port;
|
||||
while (ptr && ptr->next)
|
||||
ptr = ptr->next;
|
||||
if (ptr)
|
||||
ptr->next = data;
|
||||
else
|
||||
option->port = data;
|
||||
option = pnp_build_option(dev, IORESOURCE_IO, option_flags);
|
||||
if (!option)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_dbg(&dev->dev, " io "
|
||||
"min %#x max %#x align %d size %d flags %#x\n",
|
||||
data->min, data->max, data->align, data->size, data->flags);
|
||||
port = &option->u.port;
|
||||
port->min = min;
|
||||
port->max = max;
|
||||
port->align = align;
|
||||
port->size = size;
|
||||
port->flags = flags;
|
||||
|
||||
dbg_pnp_show_option(dev, option);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option,
|
||||
struct pnp_mem *data)
|
||||
int pnp_register_mem_resource(struct pnp_dev *dev, unsigned int option_flags,
|
||||
resource_size_t min, resource_size_t max,
|
||||
resource_size_t align, resource_size_t size,
|
||||
unsigned char flags)
|
||||
{
|
||||
struct pnp_mem *ptr;
|
||||
struct pnp_option *option;
|
||||
struct pnp_mem *mem;
|
||||
|
||||
ptr = option->mem;
|
||||
while (ptr && ptr->next)
|
||||
ptr = ptr->next;
|
||||
if (ptr)
|
||||
ptr->next = data;
|
||||
else
|
||||
option->mem = data;
|
||||
option = pnp_build_option(dev, IORESOURCE_MEM, option_flags);
|
||||
if (!option)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_dbg(&dev->dev, " mem "
|
||||
"min %#x max %#x align %d size %d flags %#x\n",
|
||||
data->min, data->max, data->align, data->size, data->flags);
|
||||
mem = &option->u.mem;
|
||||
mem->min = min;
|
||||
mem->max = max;
|
||||
mem->align = align;
|
||||
mem->size = size;
|
||||
mem->flags = flags;
|
||||
|
||||
dbg_pnp_show_option(dev, option);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pnp_free_port(struct pnp_port *port)
|
||||
void pnp_free_options(struct pnp_dev *dev)
|
||||
{
|
||||
struct pnp_port *next;
|
||||
struct pnp_option *option, *tmp;
|
||||
|
||||
while (port) {
|
||||
next = port->next;
|
||||
kfree(port);
|
||||
port = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void pnp_free_irq(struct pnp_irq *irq)
|
||||
{
|
||||
struct pnp_irq *next;
|
||||
|
||||
while (irq) {
|
||||
next = irq->next;
|
||||
kfree(irq);
|
||||
irq = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void pnp_free_dma(struct pnp_dma *dma)
|
||||
{
|
||||
struct pnp_dma *next;
|
||||
|
||||
while (dma) {
|
||||
next = dma->next;
|
||||
kfree(dma);
|
||||
dma = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void pnp_free_mem(struct pnp_mem *mem)
|
||||
{
|
||||
struct pnp_mem *next;
|
||||
|
||||
while (mem) {
|
||||
next = mem->next;
|
||||
kfree(mem);
|
||||
mem = next;
|
||||
}
|
||||
}
|
||||
|
||||
void pnp_free_option(struct pnp_option *option)
|
||||
{
|
||||
struct pnp_option *next;
|
||||
|
||||
while (option) {
|
||||
next = option->next;
|
||||
pnp_free_port(option->port);
|
||||
pnp_free_irq(option->irq);
|
||||
pnp_free_dma(option->dma);
|
||||
pnp_free_mem(option->mem);
|
||||
list_for_each_entry_safe(option, tmp, &dev->options, list) {
|
||||
list_del(&option->list);
|
||||
kfree(option);
|
||||
option = next;
|
||||
}
|
||||
}
|
||||
|
||||
@ -237,7 +159,7 @@ void pnp_free_option(struct pnp_option *option)
|
||||
!((*(enda) < *(startb)) || (*(endb) < *(starta)))
|
||||
|
||||
#define cannot_compare(flags) \
|
||||
((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED))
|
||||
((flags) & IORESOURCE_DISABLED)
|
||||
|
||||
int pnp_check_port(struct pnp_dev *dev, struct resource *res)
|
||||
{
|
||||
@ -364,6 +286,61 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
|
||||
unsigned int irq)
|
||||
{
|
||||
u32 class;
|
||||
u8 progif;
|
||||
|
||||
if (pci->irq == irq) {
|
||||
dev_dbg(&pnp->dev, "device %s using irq %d\n",
|
||||
pci_name(pci), irq);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* See pci_setup_device() and ata_pci_sff_activate_host() for
|
||||
* similar IDE legacy detection.
|
||||
*/
|
||||
pci_read_config_dword(pci, PCI_CLASS_REVISION, &class);
|
||||
class >>= 8; /* discard revision ID */
|
||||
progif = class & 0xff;
|
||||
class >>= 8;
|
||||
|
||||
if (class == PCI_CLASS_STORAGE_IDE) {
|
||||
/*
|
||||
* Unless both channels are native-PCI mode only,
|
||||
* treat the compatibility IRQs as busy.
|
||||
*/
|
||||
if ((progif & 0x5) != 0x5)
|
||||
if (pci_get_legacy_ide_irq(pci, 0) == irq ||
|
||||
pci_get_legacy_ide_irq(pci, 1) == irq) {
|
||||
dev_dbg(&pnp->dev, "legacy IDE device %s "
|
||||
"using irq %d\n", pci_name(pci), irq);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int pci_uses_irq(struct pnp_dev *pnp, unsigned int irq)
|
||||
{
|
||||
#ifdef CONFIG_PCI
|
||||
struct pci_dev *pci = NULL;
|
||||
|
||||
for_each_pci_dev(pci) {
|
||||
if (pci_dev_uses_irq(pnp, pci, irq)) {
|
||||
pci_dev_put(pci);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
|
||||
{
|
||||
int i;
|
||||
@ -395,18 +372,9 @@ int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
/* check if the resource is being used by a pci device */
|
||||
{
|
||||
struct pci_dev *pci = NULL;
|
||||
for_each_pci_dev(pci) {
|
||||
if (pci->irq == *irq) {
|
||||
pci_dev_put(pci);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (pci_uses_irq(dev, *irq))
|
||||
return 0;
|
||||
|
||||
/* check if the resource is already in use, skip if the
|
||||
* device is active because it itself may be in use */
|
||||
@ -499,81 +467,37 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
|
||||
#endif
|
||||
}
|
||||
|
||||
struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev,
|
||||
unsigned int type, unsigned int num)
|
||||
int pnp_resource_type(struct resource *res)
|
||||
{
|
||||
struct pnp_resource_table *res = dev->res;
|
||||
|
||||
switch (type) {
|
||||
case IORESOURCE_IO:
|
||||
if (num >= PNP_MAX_PORT)
|
||||
return NULL;
|
||||
return &res->port[num];
|
||||
case IORESOURCE_MEM:
|
||||
if (num >= PNP_MAX_MEM)
|
||||
return NULL;
|
||||
return &res->mem[num];
|
||||
case IORESOURCE_IRQ:
|
||||
if (num >= PNP_MAX_IRQ)
|
||||
return NULL;
|
||||
return &res->irq[num];
|
||||
case IORESOURCE_DMA:
|
||||
if (num >= PNP_MAX_DMA)
|
||||
return NULL;
|
||||
return &res->dma[num];
|
||||
}
|
||||
return NULL;
|
||||
return res->flags & (IORESOURCE_IO | IORESOURCE_MEM |
|
||||
IORESOURCE_IRQ | IORESOURCE_DMA);
|
||||
}
|
||||
|
||||
struct resource *pnp_get_resource(struct pnp_dev *dev,
|
||||
unsigned int type, unsigned int num)
|
||||
{
|
||||
struct pnp_resource *pnp_res;
|
||||
struct resource *res;
|
||||
|
||||
pnp_res = pnp_get_pnp_resource(dev, type, num);
|
||||
if (pnp_res)
|
||||
return &pnp_res->res;
|
||||
|
||||
list_for_each_entry(pnp_res, &dev->resources, list) {
|
||||
res = &pnp_res->res;
|
||||
if (pnp_resource_type(res) == type && num-- == 0)
|
||||
return res;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(pnp_get_resource);
|
||||
|
||||
static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev, int type)
|
||||
static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev)
|
||||
{
|
||||
struct pnp_resource *pnp_res;
|
||||
int i;
|
||||
|
||||
switch (type) {
|
||||
case IORESOURCE_IO:
|
||||
for (i = 0; i < PNP_MAX_PORT; i++) {
|
||||
pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, i);
|
||||
if (pnp_res && !pnp_resource_valid(&pnp_res->res))
|
||||
return pnp_res;
|
||||
}
|
||||
break;
|
||||
case IORESOURCE_MEM:
|
||||
for (i = 0; i < PNP_MAX_MEM; i++) {
|
||||
pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, i);
|
||||
if (pnp_res && !pnp_resource_valid(&pnp_res->res))
|
||||
return pnp_res;
|
||||
}
|
||||
break;
|
||||
case IORESOURCE_IRQ:
|
||||
for (i = 0; i < PNP_MAX_IRQ; i++) {
|
||||
pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, i);
|
||||
if (pnp_res && !pnp_resource_valid(&pnp_res->res))
|
||||
return pnp_res;
|
||||
}
|
||||
break;
|
||||
case IORESOURCE_DMA:
|
||||
for (i = 0; i < PNP_MAX_DMA; i++) {
|
||||
pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, i);
|
||||
if (pnp_res && !pnp_resource_valid(&pnp_res->res))
|
||||
return pnp_res;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
pnp_res = kzalloc(sizeof(struct pnp_resource), GFP_KERNEL);
|
||||
if (!pnp_res)
|
||||
return NULL;
|
||||
|
||||
list_add_tail(&pnp_res->list, &dev->resources);
|
||||
return pnp_res;
|
||||
}
|
||||
|
||||
struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
|
||||
@ -581,15 +505,10 @@ struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
|
||||
{
|
||||
struct pnp_resource *pnp_res;
|
||||
struct resource *res;
|
||||
static unsigned char warned;
|
||||
|
||||
pnp_res = pnp_new_resource(dev, IORESOURCE_IRQ);
|
||||
pnp_res = pnp_new_resource(dev);
|
||||
if (!pnp_res) {
|
||||
if (!warned) {
|
||||
dev_err(&dev->dev, "can't add resource for IRQ %d\n",
|
||||
irq);
|
||||
warned = 1;
|
||||
}
|
||||
dev_err(&dev->dev, "can't add resource for IRQ %d\n", irq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -607,15 +526,10 @@ struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
|
||||
{
|
||||
struct pnp_resource *pnp_res;
|
||||
struct resource *res;
|
||||
static unsigned char warned;
|
||||
|
||||
pnp_res = pnp_new_resource(dev, IORESOURCE_DMA);
|
||||
pnp_res = pnp_new_resource(dev);
|
||||
if (!pnp_res) {
|
||||
if (!warned) {
|
||||
dev_err(&dev->dev, "can't add resource for DMA %d\n",
|
||||
dma);
|
||||
warned = 1;
|
||||
}
|
||||
dev_err(&dev->dev, "can't add resource for DMA %d\n", dma);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -634,16 +548,12 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
|
||||
{
|
||||
struct pnp_resource *pnp_res;
|
||||
struct resource *res;
|
||||
static unsigned char warned;
|
||||
|
||||
pnp_res = pnp_new_resource(dev, IORESOURCE_IO);
|
||||
pnp_res = pnp_new_resource(dev);
|
||||
if (!pnp_res) {
|
||||
if (!warned) {
|
||||
dev_err(&dev->dev, "can't add resource for IO "
|
||||
"%#llx-%#llx\n",(unsigned long long) start,
|
||||
(unsigned long long) end);
|
||||
warned = 1;
|
||||
}
|
||||
dev_err(&dev->dev, "can't add resource for IO %#llx-%#llx\n",
|
||||
(unsigned long long) start,
|
||||
(unsigned long long) end);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -663,16 +573,12 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
|
||||
{
|
||||
struct pnp_resource *pnp_res;
|
||||
struct resource *res;
|
||||
static unsigned char warned;
|
||||
|
||||
pnp_res = pnp_new_resource(dev, IORESOURCE_MEM);
|
||||
pnp_res = pnp_new_resource(dev);
|
||||
if (!pnp_res) {
|
||||
if (!warned) {
|
||||
dev_err(&dev->dev, "can't add resource for MEM "
|
||||
"%#llx-%#llx\n",(unsigned long long) start,
|
||||
(unsigned long long) end);
|
||||
warned = 1;
|
||||
}
|
||||
dev_err(&dev->dev, "can't add resource for MEM %#llx-%#llx\n",
|
||||
(unsigned long long) start,
|
||||
(unsigned long long) end);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -686,6 +592,52 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
|
||||
return pnp_res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine whether the specified resource is a possible configuration
|
||||
* for this device.
|
||||
*/
|
||||
int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start,
|
||||
resource_size_t size)
|
||||
{
|
||||
struct pnp_option *option;
|
||||
struct pnp_port *port;
|
||||
struct pnp_mem *mem;
|
||||
struct pnp_irq *irq;
|
||||
struct pnp_dma *dma;
|
||||
|
||||
list_for_each_entry(option, &dev->options, list) {
|
||||
if (option->type != type)
|
||||
continue;
|
||||
|
||||
switch (option->type) {
|
||||
case IORESOURCE_IO:
|
||||
port = &option->u.port;
|
||||
if (port->min == start && port->size == size)
|
||||
return 1;
|
||||
break;
|
||||
case IORESOURCE_MEM:
|
||||
mem = &option->u.mem;
|
||||
if (mem->min == start && mem->size == size)
|
||||
return 1;
|
||||
break;
|
||||
case IORESOURCE_IRQ:
|
||||
irq = &option->u.irq;
|
||||
if (start < PNP_IRQ_NR &&
|
||||
test_bit(start, irq->map.bits))
|
||||
return 1;
|
||||
break;
|
||||
case IORESOURCE_DMA:
|
||||
dma = &option->u.dma;
|
||||
if (dma->map & (1 << start))
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(pnp_possible_config);
|
||||
|
||||
/* format is: pnp_reserve_irq=irq1[,irq2] .... */
|
||||
static int __init pnp_setup_reserve_irq(char *str)
|
||||
{
|
||||
|
@ -2,6 +2,8 @@
|
||||
* support.c - standard functions for the use of pnp protocol drivers
|
||||
*
|
||||
* Copyright 2003 Adam Belay <ambx1@neo.rr.com>
|
||||
* Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
|
||||
* Bjorn Helgaas <bjorn.helgaas@hp.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -16,6 +18,10 @@
|
||||
*/
|
||||
int pnp_is_active(struct pnp_dev *dev)
|
||||
{
|
||||
/*
|
||||
* I don't think this is very reliable because pnp_disable_dev()
|
||||
* only clears out auto-assigned resources.
|
||||
*/
|
||||
if (!pnp_port_start(dev, 0) && pnp_port_len(dev, 0) <= 1 &&
|
||||
!pnp_mem_start(dev, 0) && pnp_mem_len(dev, 0) <= 1 &&
|
||||
pnp_irq(dev, 0) == -1 && pnp_dma(dev, 0) == -1)
|
||||
@ -52,39 +58,154 @@ void pnp_eisa_id_to_string(u32 id, char *str)
|
||||
str[7] = '\0';
|
||||
}
|
||||
|
||||
char *pnp_resource_type_name(struct resource *res)
|
||||
{
|
||||
switch (pnp_resource_type(res)) {
|
||||
case IORESOURCE_IO:
|
||||
return "io";
|
||||
case IORESOURCE_MEM:
|
||||
return "mem";
|
||||
case IORESOURCE_IRQ:
|
||||
return "irq";
|
||||
case IORESOURCE_DMA:
|
||||
return "dma";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
char buf[128];
|
||||
int len = 0;
|
||||
struct pnp_resource *pnp_res;
|
||||
struct resource *res;
|
||||
int i;
|
||||
|
||||
dev_dbg(&dev->dev, "current resources: %s\n", desc);
|
||||
if (list_empty(&dev->resources)) {
|
||||
dev_dbg(&dev->dev, "%s: no current resources\n", desc);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < PNP_MAX_IRQ; i++) {
|
||||
res = pnp_get_resource(dev, IORESOURCE_IRQ, i);
|
||||
if (res && !(res->flags & IORESOURCE_UNSET))
|
||||
dev_dbg(&dev->dev, " irq %lld flags %#lx\n",
|
||||
(unsigned long long) res->start, res->flags);
|
||||
}
|
||||
for (i = 0; i < PNP_MAX_DMA; i++) {
|
||||
res = pnp_get_resource(dev, IORESOURCE_DMA, i);
|
||||
if (res && !(res->flags & IORESOURCE_UNSET))
|
||||
dev_dbg(&dev->dev, " dma %lld flags %#lx\n",
|
||||
(unsigned long long) res->start, res->flags);
|
||||
}
|
||||
for (i = 0; i < PNP_MAX_PORT; i++) {
|
||||
res = pnp_get_resource(dev, IORESOURCE_IO, i);
|
||||
if (res && !(res->flags & IORESOURCE_UNSET))
|
||||
dev_dbg(&dev->dev, " io %#llx-%#llx flags %#lx\n",
|
||||
(unsigned long long) res->start,
|
||||
(unsigned long long) res->end, res->flags);
|
||||
}
|
||||
for (i = 0; i < PNP_MAX_MEM; i++) {
|
||||
res = pnp_get_resource(dev, IORESOURCE_MEM, i);
|
||||
if (res && !(res->flags & IORESOURCE_UNSET))
|
||||
dev_dbg(&dev->dev, " mem %#llx-%#llx flags %#lx\n",
|
||||
(unsigned long long) res->start,
|
||||
(unsigned long long) res->end, res->flags);
|
||||
dev_dbg(&dev->dev, "%s: current resources:\n", desc);
|
||||
list_for_each_entry(pnp_res, &dev->resources, list) {
|
||||
res = &pnp_res->res;
|
||||
|
||||
len += snprintf(buf + len, sizeof(buf) - len, " %-3s ",
|
||||
pnp_resource_type_name(res));
|
||||
|
||||
if (res->flags & IORESOURCE_DISABLED) {
|
||||
dev_dbg(&dev->dev, "%sdisabled\n", buf);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (pnp_resource_type(res)) {
|
||||
case IORESOURCE_IO:
|
||||
case IORESOURCE_MEM:
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"%#llx-%#llx flags %#lx",
|
||||
(unsigned long long) res->start,
|
||||
(unsigned long long) res->end,
|
||||
res->flags);
|
||||
break;
|
||||
case IORESOURCE_IRQ:
|
||||
case IORESOURCE_DMA:
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"%lld flags %#lx",
|
||||
(unsigned long long) res->start,
|
||||
res->flags);
|
||||
break;
|
||||
}
|
||||
dev_dbg(&dev->dev, "%s\n", buf);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
char *pnp_option_priority_name(struct pnp_option *option)
|
||||
{
|
||||
switch (pnp_option_priority(option)) {
|
||||
case PNP_RES_PRIORITY_PREFERRED:
|
||||
return "preferred";
|
||||
case PNP_RES_PRIORITY_ACCEPTABLE:
|
||||
return "acceptable";
|
||||
case PNP_RES_PRIORITY_FUNCTIONAL:
|
||||
return "functional";
|
||||
}
|
||||
return "invalid";
|
||||
}
|
||||
|
||||
void dbg_pnp_show_option(struct pnp_dev *dev, struct pnp_option *option)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
char buf[128];
|
||||
int len = 0, i;
|
||||
struct pnp_port *port;
|
||||
struct pnp_mem *mem;
|
||||
struct pnp_irq *irq;
|
||||
struct pnp_dma *dma;
|
||||
|
||||
if (pnp_option_is_dependent(option))
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
" dependent set %d (%s) ",
|
||||
pnp_option_set(option),
|
||||
pnp_option_priority_name(option));
|
||||
else
|
||||
len += snprintf(buf + len, sizeof(buf) - len, " independent ");
|
||||
|
||||
switch (option->type) {
|
||||
case IORESOURCE_IO:
|
||||
port = &option->u.port;
|
||||
len += snprintf(buf + len, sizeof(buf) - len, "io min %#llx "
|
||||
"max %#llx align %lld size %lld flags %#x",
|
||||
(unsigned long long) port->min,
|
||||
(unsigned long long) port->max,
|
||||
(unsigned long long) port->align,
|
||||
(unsigned long long) port->size, port->flags);
|
||||
break;
|
||||
case IORESOURCE_MEM:
|
||||
mem = &option->u.mem;
|
||||
len += snprintf(buf + len, sizeof(buf) - len, "mem min %#llx "
|
||||
"max %#llx align %lld size %lld flags %#x",
|
||||
(unsigned long long) mem->min,
|
||||
(unsigned long long) mem->max,
|
||||
(unsigned long long) mem->align,
|
||||
(unsigned long long) mem->size, mem->flags);
|
||||
break;
|
||||
case IORESOURCE_IRQ:
|
||||
irq = &option->u.irq;
|
||||
len += snprintf(buf + len, sizeof(buf) - len, "irq");
|
||||
if (bitmap_empty(irq->map.bits, PNP_IRQ_NR))
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
" <none>");
|
||||
else {
|
||||
for (i = 0; i < PNP_IRQ_NR; i++)
|
||||
if (test_bit(i, irq->map.bits))
|
||||
len += snprintf(buf + len,
|
||||
sizeof(buf) - len,
|
||||
" %d", i);
|
||||
}
|
||||
len += snprintf(buf + len, sizeof(buf) - len, " flags %#x",
|
||||
irq->flags);
|
||||
if (irq->flags & IORESOURCE_IRQ_OPTIONAL)
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
" (optional)");
|
||||
break;
|
||||
case IORESOURCE_DMA:
|
||||
dma = &option->u.dma;
|
||||
len += snprintf(buf + len, sizeof(buf) - len, "dma");
|
||||
if (!dma->map)
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
" <none>");
|
||||
else {
|
||||
for (i = 0; i < 8; i++)
|
||||
if (dma->map & (1 << i))
|
||||
len += snprintf(buf + len,
|
||||
sizeof(buf) - len,
|
||||
" %d", i);
|
||||
}
|
||||
len += snprintf(buf + len, sizeof(buf) - len, " (bitmask %#x) "
|
||||
"flags %#x", dma->map, dma->flags);
|
||||
break;
|
||||
}
|
||||
dev_dbg(&dev->dev, "%s\n", buf);
|
||||
#endif
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ static void reserve_resources_of_dev(struct pnp_dev *dev)
|
||||
int i;
|
||||
|
||||
for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
|
||||
if (res->flags & IORESOURCE_UNSET)
|
||||
if (res->flags & IORESOURCE_DISABLED)
|
||||
continue;
|
||||
if (res->start == 0)
|
||||
continue; /* disabled */
|
||||
@ -81,7 +81,7 @@ static void reserve_resources_of_dev(struct pnp_dev *dev)
|
||||
}
|
||||
|
||||
for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
|
||||
if (res->flags & (IORESOURCE_UNSET | IORESOURCE_DISABLED))
|
||||
if (res->flags & IORESOURCE_DISABLED)
|
||||
continue;
|
||||
|
||||
reserve_range(dev, res->start, res->end, 0);
|
||||
|
@ -383,21 +383,14 @@ static int __devinit check_name(char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit check_resources(struct pnp_option *option)
|
||||
static int __devinit check_resources(struct pnp_dev *dev)
|
||||
{
|
||||
struct pnp_option *tmp;
|
||||
if (!option)
|
||||
return 0;
|
||||
resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8};
|
||||
int i;
|
||||
|
||||
for (tmp = option; tmp; tmp = tmp->next) {
|
||||
struct pnp_port *port;
|
||||
for (port = tmp->port; port; port = port->next)
|
||||
if ((port->size == 8) &&
|
||||
((port->min == 0x2f8) ||
|
||||
(port->min == 0x3f8) ||
|
||||
(port->min == 0x2e8) ||
|
||||
(port->min == 0x3e8)))
|
||||
return 1;
|
||||
for (i = 0; i < ARRAY_SIZE(base); i++) {
|
||||
if (pnp_possible_config(dev, IORESOURCE_IO, base[i], 8))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -420,10 +413,7 @@ static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags)
|
||||
(dev->card && check_name(dev->card->name))))
|
||||
return -ENODEV;
|
||||
|
||||
if (check_resources(dev->independent))
|
||||
return 0;
|
||||
|
||||
if (check_resources(dev->dependent))
|
||||
if (check_resources(dev))
|
||||
return 0;
|
||||
|
||||
return -ENODEV;
|
||||
|
@ -63,7 +63,7 @@
|
||||
|
||||
/* Current ACPICA subsystem version in YYYYMMDD format */
|
||||
|
||||
#define ACPI_CA_VERSION 0x20080321
|
||||
#define ACPI_CA_VERSION 0x20080609
|
||||
|
||||
/*
|
||||
* OS name, used for the _OS object. The _OS object is essentially obsolete,
|
||||
|
@ -162,6 +162,7 @@ extern struct acpi_dmtable_info acpi_dm_table_info_dmar_hdr[];
|
||||
extern struct acpi_dmtable_info acpi_dm_table_info_dmar_scope[];
|
||||
extern struct acpi_dmtable_info acpi_dm_table_info_dmar0[];
|
||||
extern struct acpi_dmtable_info acpi_dm_table_info_dmar1[];
|
||||
extern struct acpi_dmtable_info acpi_dm_table_info_dmar2[];
|
||||
extern struct acpi_dmtable_info acpi_dm_table_info_ecdt[];
|
||||
extern struct acpi_dmtable_info acpi_dm_table_info_einj[];
|
||||
extern struct acpi_dmtable_info acpi_dm_table_info_einj0[];
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user