Browse Source

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
  ...
Linus Torvalds 17 years ago
parent
commit
4314652bb4
100 changed files with 3997 additions and 2168 deletions
  1. 87 40
      Documentation/ABI/testing/sysfs-firmware-acpi
  2. 4 1
      Documentation/kernel-parameters.txt
  3. 0 2
      Documentation/laptops/acer-wmi.txt
  4. 18 7
      MAINTAINERS
  5. 4 0
      arch/ia64/kernel/process.c
  6. 6 0
      arch/x86/kernel/acpi/processor.c
  7. 27 1
      arch/x86/kernel/process.c
  8. 1 2
      arch/x86/mm/srat_32.c
  9. 1 1
      drivers/acpi/Makefile
  10. 3 0
      drivers/acpi/bay.c
  11. 1 1
      drivers/acpi/bus.c
  12. 1 1
      drivers/acpi/dispatcher/dsinit.c
  13. 0 1
      drivers/acpi/dispatcher/dsmethod.c
  14. 3 19
      drivers/acpi/dispatcher/dsopcode.c
  15. 0 8
      drivers/acpi/dispatcher/dswexec.c
  16. 7 13
      drivers/acpi/dispatcher/dswstate.c
  17. 3 0
      drivers/acpi/dock.c
  18. 3 3
      drivers/acpi/events/evevent.c
  19. 18 18
      drivers/acpi/events/evgpe.c
  20. 10 8
      drivers/acpi/events/evgpeblk.c
  21. 2 2
      drivers/acpi/events/evmisc.c
  22. 2 3
      drivers/acpi/events/evregion.c
  23. 1 1
      drivers/acpi/events/evrgnini.c
  24. 15 3
      drivers/acpi/events/evxfevnt.c
  25. 9 8
      drivers/acpi/executer/exconfig.c
  26. 6 6
      drivers/acpi/executer/exconvrt.c
  27. 0 2
      drivers/acpi/executer/excreate.c
  28. 26 41
      drivers/acpi/executer/exdump.c
  29. 5 4
      drivers/acpi/executer/exfldio.c
  30. 4 4
      drivers/acpi/executer/exmisc.c
  31. 4 4
      drivers/acpi/executer/exprep.c
  32. 1 1
      drivers/acpi/executer/exregion.c
  33. 4 0
      drivers/acpi/executer/exresop.c
  34. 0 6
      drivers/acpi/executer/exstore.c
  35. 7 1
      drivers/acpi/fan.c
  36. 3 0
      drivers/acpi/glue.c
  37. 49 3
      drivers/acpi/hardware/hwgpe.c
  38. 3 3
      drivers/acpi/namespace/nsdump.c
  39. 35 0
      drivers/acpi/namespace/nseval.c
  40. 0 1
      drivers/acpi/namespace/nsinit.c
  41. 1 2
      drivers/acpi/namespace/nsload.c
  42. 7 8
      drivers/acpi/namespace/nsparse.c
  43. 25 25
      drivers/acpi/namespace/nsutils.c
  44. 1 2
      drivers/acpi/namespace/nsxfeval.c
  45. 2 2
      drivers/acpi/numa.c
  46. 2 2
      drivers/acpi/parser/psargs.c
  47. 2 2
      drivers/acpi/parser/psxface.c
  48. 17 21
      drivers/acpi/pci_irq.c
  49. 60 15
      drivers/acpi/processor_core.c
  50. 30 4
      drivers/acpi/processor_idle.c
  51. 9 9
      drivers/acpi/processor_perflib.c
  52. 27 11
      drivers/acpi/processor_throttling.c
  53. 50 0
      drivers/acpi/reboot.c
  54. 2 2
      drivers/acpi/resources/rscalc.c
  55. 29 12
      drivers/acpi/resources/rscreate.c
  56. 1 1
      drivers/acpi/resources/rsmisc.c
  57. 6 7
      drivers/acpi/resources/rsutils.c
  58. 37 25
      drivers/acpi/scan.c
  59. 4 35
      drivers/acpi/sleep/main.c
  60. 156 13
      drivers/acpi/system.c
  61. 14 9
      drivers/acpi/tables/tbfadt.c
  62. 2 3
      drivers/acpi/tables/tbfind.c
  63. 14 16
      drivers/acpi/tables/tbinstal.c
  64. 7 8
      drivers/acpi/tables/tbutils.c
  65. 13 15
      drivers/acpi/tables/tbxface.c
  66. 2 2
      drivers/acpi/tables/tbxfroot.c
  67. 3 2
      drivers/acpi/utilities/utalloc.c
  68. 2 2
      drivers/acpi/utilities/utcopy.c
  69. 33 21
      drivers/acpi/utilities/utdebug.c
  70. 1 1
      drivers/acpi/utilities/utdelete.c
  71. 2 3
      drivers/acpi/utilities/uteval.c
  72. 18 21
      drivers/acpi/utilities/utmisc.c
  73. 2 2
      drivers/acpi/utilities/utmutex.c
  74. 5 4
      drivers/acpi/utilities/utobject.c
  75. 73 50
      drivers/acpi/video.c
  76. 207 139
      drivers/char/apm-emulation.c
  77. 30 1
      drivers/misc/Kconfig
  78. 3 2
      drivers/misc/Makefile
  79. 135 10
      drivers/misc/acer-wmi.c
  80. 404 0
      drivers/misc/compal-laptop.c
  81. 2 2
      drivers/misc/eeepc-laptop.c
  82. 774 51
      drivers/misc/fujitsu-laptop.c
  83. 2 4
      drivers/pci/pci-acpi.c
  84. 2 2
      drivers/pci/pci.c
  85. 1 2
      drivers/pci/pci.h
  86. 119 29
      drivers/pnp/base.h
  87. 19 10
      drivers/pnp/core.c
  88. 89 118
      drivers/pnp/interface.c
  89. 97 156
      drivers/pnp/isapnp/core.c
  90. 131 283
      drivers/pnp/manager.c
  91. 1 3
      drivers/pnp/pnpacpi/core.c
  92. 287 205
      drivers/pnp/pnpacpi/rsparser.c
  93. 146 128
      drivers/pnp/pnpbios/rsparser.c
  94. 156 151
      drivers/pnp/quirks.c
  95. 203 251
      drivers/pnp/resource.c
  96. 146 25
      drivers/pnp/support.c
  97. 2 2
      drivers/pnp/system.c
  98. 7 17
      drivers/serial/8250_pnp.c
  99. 1 1
      include/acpi/acconfig.h
  100. 1 0
      include/acpi/acdisasm.h

+ 87 - 40
Documentation/ABI/testing/sysfs-firmware-acpi

@@ -29,46 +29,46 @@ Description:
 
 
 		$ cd /sys/firmware/acpi/interrupts
 		$ cd /sys/firmware/acpi/interrupts
 		$ grep . *
 		$ 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
 		sci - The total number of times the ACPI SCI
 		has claimed an interrupt.
 		has claimed an interrupt.
@@ -89,6 +89,13 @@ Description:
 
 
 		error - an interrupt that can't be accounted for above.
 		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.
 		Root has permission to clear any of these counters.  Eg.
 		# echo 0 > gpe11
 		# echo 0 > gpe11
 
 
@@ -97,3 +104,43 @@ Description:
 
 
 		None of these counters has an effect on the function
 		None of these counters has an effect on the function
 		of the system, they are simply statistics.
 		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
+

+ 4 - 1
Documentation/kernel-parameters.txt

@@ -818,7 +818,7 @@ and is between 256 and 4096 characters. It is defined in the file
 			See Documentation/ide/ide.txt.
 			See Documentation/ide/ide.txt.
 
 
 	idle=		[X86]
 	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
 			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
 			of waking up a idle CPU, but will use a lot of power and make the system
 			run hot. Not recommended.
 			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
 			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
 			loop use the MONITOR/MWAIT idle loop anyways. Performance should be the same
 			as idle=poll.
 			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
 	ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem
 			Claim all unknown PCI IDE storage controllers.
 			Claim all unknown PCI IDE storage controllers.

+ 0 - 2
Documentation/laptops/acer-wmi.txt

@@ -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
 The mail LED is autodetected, so if you don't have one, the LED device won't
 be registered.
 be registered.
 
 
-If you have a mail LED that is not green, please report this to me.
-
 Backlight
 Backlight
 *********
 *********
 
 

+ 18 - 7
MAINTAINERS

@@ -216,8 +216,8 @@ W:	http://code.google.com/p/aceracpi
 S:	Maintained
 S:	Maintained
 
 
 ACPI
 ACPI
-P:	Len Brown
-M:	len.brown@intel.com
+P:	Andi Kleen
+M:	ak@linux.intel.com
 M:	lenb@kernel.org
 M:	lenb@kernel.org
 L:	linux-acpi@vger.kernel.org
 L:	linux-acpi@vger.kernel.org
 W:	http://www.lesswatts.org/projects/acpi/
 W:	http://www.lesswatts.org/projects/acpi/
@@ -239,8 +239,8 @@ W:	http://www.lesswatts.org/projects/acpi/
 S:	Supported
 S:	Supported
 
 
 ACPI FAN DRIVER
 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
 L:	linux-acpi@vger.kernel.org
 W:	http://www.lesswatts.org/projects/acpi/
 W:	http://www.lesswatts.org/projects/acpi/
 S:	Supported
 S:	Supported
@@ -252,14 +252,14 @@ L:	pcihpd-discuss@lists.sourceforge.net
 S:	Supported
 S:	Supported
 
 
 ACPI THERMAL DRIVER
 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
 L:	linux-acpi@vger.kernel.org
 W:	http://www.lesswatts.org/projects/acpi/
 W:	http://www.lesswatts.org/projects/acpi/
 S:	Supported
 S:	Supported
 
 
 ACPI VIDEO DRIVER
 ACPI VIDEO DRIVER
-P:	Rui Zhang
+P:	Zhang Rui
 M:	rui.zhang@intel.com
 M:	rui.zhang@intel.com
 L:	linux-acpi@vger.kernel.org
 L:	linux-acpi@vger.kernel.org
 W:	http://www.lesswatts.org/projects/acpi/
 W:	http://www.lesswatts.org/projects/acpi/
@@ -1160,6 +1160,11 @@ M:	scott@spiteful.org
 L:	pcihpd-discuss@lists.sourceforge.net
 L:	pcihpd-discuss@lists.sourceforge.net
 S:	Supported
 S:	Supported
 
 
+COMPAL LAPTOP SUPPORT
+P:	Cezary Jackiewicz
+M:	cezary.jackiewicz@gmail.com
+S:	Maintained
+
 COMPUTONE INTELLIPORT MULTIPORT CARD
 COMPUTONE INTELLIPORT MULTIPORT CARD
 P:	Michael H. Warfield
 P:	Michael H. Warfield
 M:	mhw@wittsend.com
 M:	mhw@wittsend.com
@@ -1787,6 +1792,12 @@ P:	David Howells
 M:	dhowells@redhat.com
 M:	dhowells@redhat.com
 S:	Maintained
 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
 FUSE: FILESYSTEM IN USERSPACE
 P:	Miklos Szeredi
 P:	Miklos Szeredi
 M:	miklos@szeredi.hu
 M:	miklos@szeredi.hu

+ 4 - 0
arch/ia64/kernel/process.c

@@ -55,6 +55,10 @@ void (*ia64_mark_idle)(int);
 
 
 unsigned long boot_option_idle_override = 0;
 unsigned long boot_option_idle_override = 0;
 EXPORT_SYMBOL(boot_option_idle_override);
 EXPORT_SYMBOL(boot_option_idle_override);
+unsigned long idle_halt;
+EXPORT_SYMBOL(idle_halt);
+unsigned long idle_nomwait;
+EXPORT_SYMBOL(idle_nomwait);
 
 
 void
 void
 ia64_do_show_stack (struct unw_frame_info *info, void *arg)
 ia64_do_show_stack (struct unw_frame_info *info, void *arg)

+ 6 - 0
arch/x86/kernel/acpi/processor.c

@@ -56,6 +56,12 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c)
 	if (cpu_has(c, X86_FEATURE_ACPI))
 	if (cpu_has(c, X86_FEATURE_ACPI))
 		buf[2] |= ACPI_PDC_T_FFH;
 		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->type = ACPI_TYPE_BUFFER;
 	obj->buffer.length = 12;
 	obj->buffer.length = 12;
 	obj->buffer.pointer = (u8 *) buf;
 	obj->buffer.pointer = (u8 *) buf;

+ 27 - 1
arch/x86/kernel/process.c

@@ -7,6 +7,12 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/pm.h>
 #include <linux/pm.h>
 #include <linux/clockchips.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;
 struct kmem_cache *task_xstate_cachep;
 
 
@@ -325,7 +331,27 @@ static int __init idle_setup(char *str)
 		pm_idle = poll_idle;
 		pm_idle = poll_idle;
 	} else if (!strcmp(str, "mwait"))
 	} else if (!strcmp(str, "mwait"))
 		force_mwait = 1;
 		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;
 		return -1;
 
 
 	boot_option_idle_override = 1;
 	boot_option_idle_override = 1;

+ 1 - 2
arch/x86/mm/srat_32.c

@@ -156,10 +156,9 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *memory_affinity)
 
 
 	num_memory_chunks++;
 	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",
 			  " in proximity domain %02x %s\n",
 		start_pfn, end_pfn,
 		start_pfn, end_pfn,
-		memory_affinity->memory_type,
 		pxm,
 		pxm,
 		((memory_affinity->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) ?
 		((memory_affinity->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) ?
 		 "enabled and removable" : "enabled" ) );
 		 "enabled and removable" : "enabled" ) );

+ 1 - 1
drivers/acpi/Makefile

@@ -21,7 +21,7 @@ obj-$(CONFIG_X86)		+= blacklist.o
 #
 #
 # ACPI Core Subsystem (Interpreter)
 # ACPI Core Subsystem (Interpreter)
 #
 #
-obj-y				+= osl.o utils.o \
+obj-y				+= osl.o utils.o reboot.o\
 				   dispatcher/ events/ executer/ hardware/ \
 				   dispatcher/ events/ executer/ hardware/ \
 				   namespace/ parser/ resources/ tables/ \
 				   namespace/ parser/ resources/ tables/ \
 				   utilities/
 				   utilities/

+ 3 - 0
drivers/acpi/bay.c

@@ -377,6 +377,9 @@ static int __init bay_init(void)
 
 
 	INIT_LIST_HEAD(&drive_bays);
 	INIT_LIST_HEAD(&drive_bays);
 
 
+	if (acpi_disabled)
+		return -ENODEV;
+
 	if (acpi_disabled)
 	if (acpi_disabled)
 		return -ENODEV;
 		return -ENODEV;
 
 

+ 1 - 1
drivers/acpi/bus.c

@@ -612,7 +612,7 @@ static int __init acpi_bus_init_irq(void)
 	return 0;
 	return 0;
 }
 }
 
 
-acpi_native_uint acpi_gbl_permanent_mmap;
+u8 acpi_gbl_permanent_mmap;
 
 
 
 
 void __init acpi_early_init(void)
 void __init acpi_early_init(void)

+ 1 - 1
drivers/acpi/dispatcher/dsinit.c

@@ -151,7 +151,7 @@ acpi_ds_init_one_object(acpi_handle obj_handle,
  ******************************************************************************/
  ******************************************************************************/
 
 
 acpi_status
 acpi_status
-acpi_ds_initialize_objects(acpi_native_uint table_index,
+acpi_ds_initialize_objects(u32 table_index,
 			   struct acpi_namespace_node * start_node)
 			   struct acpi_namespace_node * start_node)
 {
 {
 	acpi_status status;
 	acpi_status status;

+ 0 - 1
drivers/acpi/dispatcher/dsmethod.c

@@ -377,7 +377,6 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
 	}
 	}
 
 
 	info->parameters = &this_walk_state->operands[0];
 	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,
 	status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node,
 				       obj_desc->method.aml_start,
 				       obj_desc->method.aml_start,

+ 3 - 19
drivers/acpi/dispatcher/dsopcode.c

@@ -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,
 	status = acpi_ex_resolve_operands(op->common.aml_opcode,
 					  ACPI_WALK_OPERANDS, walk_state);
 					  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)) {
 	if (ACPI_FAILURE(status)) {
 		ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)",
 		ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)",
 			    acpi_ps_get_opcode_name(op->common.aml_opcode),
 			    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);
 		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);
 	obj_desc = acpi_ns_get_attached_object(node);
 	if (!obj_desc) {
 	if (!obj_desc) {
 		return_ACPI_STATUS(AE_NOT_EXIST);
 		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;
 	union acpi_operand_object **operand;
 	struct acpi_namespace_node *node;
 	struct acpi_namespace_node *node;
 	union acpi_parse_object *next_op;
 	union acpi_parse_object *next_op;
-	acpi_native_uint table_index;
+	u32 table_index;
 	struct acpi_table_header *table;
 	struct acpi_table_header *table;
 
 
 	ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op);
 	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);
 		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];
 	operand = &walk_state->operands[0];
 
 
 	/* Find the ACPI table */
 	/* Find the ACPI table */
@@ -1091,10 +1077,8 @@ acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state,
 		return_ACPI_STATUS(status);
 		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
 	 * Get the bank_value operand and save it
 	 * (at Top of stack)
 	 * (at Top of stack)

+ 0 - 8
drivers/acpi/dispatcher/dswexec.c

@@ -408,14 +408,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
 							    [walk_state->
 							    [walk_state->
 							     num_operands - 1]),
 							     num_operands - 1]),
 							  walk_state);
 							  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)) {
 		if (ACPI_SUCCESS(status)) {

+ 7 - 13
drivers/acpi/dispatcher/dswstate.c

@@ -70,7 +70,7 @@ acpi_status
 acpi_ds_result_pop(union acpi_operand_object **object,
 acpi_ds_result_pop(union acpi_operand_object **object,
 		   struct acpi_walk_state *walk_state)
 		   struct acpi_walk_state *walk_state)
 {
 {
-	acpi_native_uint index;
+	u32 index;
 	union acpi_generic_state *state;
 	union acpi_generic_state *state;
 	acpi_status status;
 	acpi_status status;
 
 
@@ -122,7 +122,7 @@ acpi_ds_result_pop(union acpi_operand_object **object,
 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 			  "Obj=%p [%s] Index=%X State=%p Num=%X\n", *object,
 			  "Obj=%p [%s] Index=%X State=%p Num=%X\n", *object,
 			  acpi_ut_get_object_type_name(*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);
 	return (AE_OK);
 }
 }
@@ -146,7 +146,7 @@ acpi_ds_result_push(union acpi_operand_object * object,
 {
 {
 	union acpi_generic_state *state;
 	union acpi_generic_state *state;
 	acpi_status status;
 	acpi_status status;
-	acpi_native_uint index;
+	u32 index;
 
 
 	ACPI_FUNCTION_NAME(ds_result_push);
 	ACPI_FUNCTION_NAME(ds_result_push);
 
 
@@ -400,7 +400,7 @@ void
 acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
 acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
 				 struct acpi_walk_state *walk_state)
 				 struct acpi_walk_state *walk_state)
 {
 {
-	acpi_native_int i;
+	s32 i;
 	union acpi_operand_object *obj_desc;
 	union acpi_operand_object *obj_desc;
 
 
 	ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete);
 	ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete);
@@ -409,7 +409,7 @@ acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
 		return;
 		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) {
 		if (walk_state->num_operands == 0) {
 			return;
 			return;
 		}
 		}
@@ -615,14 +615,8 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
 	walk_state->pass_number = pass_number;
 	walk_state->pass_number = pass_number;
 
 
 	if (info) {
 	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);
 	status = acpi_ps_init_scope(&walk_state->parser_state, op);

+ 3 - 0
drivers/acpi/dock.c

@@ -917,6 +917,9 @@ static int __init dock_init(void)
 
 
 	dock_station = NULL;
 	dock_station = NULL;
 
 
+	if (acpi_disabled)
+		return 0;
+
 	if (acpi_disabled)
 	if (acpi_disabled)
 		return 0;
 		return 0;
 
 

+ 3 - 3
drivers/acpi/events/evevent.c

@@ -188,7 +188,7 @@ acpi_status acpi_ev_install_xrupt_handlers(void)
 
 
 static acpi_status acpi_ev_fixed_event_initialize(void)
 static acpi_status acpi_ev_fixed_event_initialize(void)
 {
 {
-	acpi_native_uint i;
+	u32 i;
 	acpi_status status;
 	acpi_status status;
 
 
 	/*
 	/*
@@ -231,7 +231,7 @@ u32 acpi_ev_fixed_event_detect(void)
 	u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
 	u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
 	u32 fixed_status;
 	u32 fixed_status;
 	u32 fixed_enable;
 	u32 fixed_enable;
-	acpi_native_uint i;
+	u32 i;
 
 
 	ACPI_FUNCTION_NAME(ev_fixed_event_detect);
 	ACPI_FUNCTION_NAME(ev_fixed_event_detect);
 
 
@@ -260,7 +260,7 @@ u32 acpi_ev_fixed_event_detect(void)
 
 
 			/* Found an active (signalled) event */
 			/* Found an active (signalled) event */
 			acpi_os_fixed_event_count(i);
 			acpi_os_fixed_event_count(i);
-			int_status |= acpi_ev_fixed_event_dispatch((u32) i);
+			int_status |= acpi_ev_fixed_event_dispatch(i);
 		}
 		}
 	}
 	}
 
 

+ 18 - 18
drivers/acpi/events/evgpe.c

@@ -256,7 +256,7 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
 		return_ACPI_STATUS(status);
 		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) {
 	switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
 	case ACPI_GPE_TYPE_WAKE:
 	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 */
 		/* Disable the requested runtime GPE */
 
 
 		ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
 		ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
-
-		/* fallthrough */
+		break;
 
 
 	default:
 	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);
 	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;
 	union acpi_operand_object *obj_desc;
 	struct acpi_gpe_block_info *gpe_block;
 	struct acpi_gpe_block_info *gpe_block;
-	acpi_native_uint i;
+	u32 i;
 
 
 	ACPI_FUNCTION_ENTRY();
 	ACPI_FUNCTION_ENTRY();
 
 
@@ -379,8 +389,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
 	u32 status_reg;
 	u32 status_reg;
 	u32 enable_reg;
 	u32 enable_reg;
 	acpi_cpu_flags flags;
 	acpi_cpu_flags flags;
-	acpi_native_uint i;
-	acpi_native_uint j;
+	u32 i;
+	u32 j;
 
 
 	ACPI_FUNCTION_NAME(ev_gpe_detect);
 	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 |=
 					int_status |=
 					    acpi_ev_gpe_dispatch(&gpe_block->
 					    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 =
 			info->prefix_node =
 			    local_gpe_event_info.dispatch.method_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;
 			info->flags = ACPI_IGNORE_RETURN_VALUE;
 
 
 			status = acpi_ns_evaluate(info);
 			status = acpi_ns_evaluate(info);

+ 10 - 8
drivers/acpi/events/evgpeblk.c

@@ -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_block_info *gpe_block)
 {
 {
 	struct acpi_gpe_event_info *gpe_event_info;
 	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);
 	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++) {
 		for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
 			gpe_event_info =
 			gpe_event_info =
 			    &gpe_block->
 			    &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) ==
 			if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
 			    ACPI_GPE_DISPATCH_HANDLER) {
 			    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 *gpe_event_info = NULL;
 	struct acpi_gpe_event_info *this_event;
 	struct acpi_gpe_event_info *this_event;
 	struct acpi_gpe_register_info *this_register;
 	struct acpi_gpe_register_info *this_register;
-	acpi_native_uint i;
-	acpi_native_uint j;
+	u32 i;
+	u32 j;
 	acpi_status status;
 	acpi_status status;
 
 
 	ACPI_FUNCTION_TRACE(ev_create_gpe_info_blocks);
 	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;
 	struct acpi_gpe_walk_info gpe_info;
 	u32 wake_gpe_count;
 	u32 wake_gpe_count;
 	u32 gpe_enabled_count;
 	u32 gpe_enabled_count;
-	acpi_native_uint i;
-	acpi_native_uint j;
+	u32 i;
+	u32 j;
 
 
 	ACPI_FUNCTION_TRACE(ev_initialize_gpe_block);
 	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_event_info =
 			    &gpe_block->
 			    &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) ==
 			if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
 			     ACPI_GPE_DISPATCH_METHOD)
 			     ACPI_GPE_DISPATCH_METHOD)

+ 2 - 2
drivers/acpi/events/evmisc.c

@@ -575,7 +575,7 @@ acpi_status acpi_ev_release_global_lock(void)
 
 
 void acpi_ev_terminate(void)
 void acpi_ev_terminate(void)
 {
 {
-	acpi_native_uint i;
+	u32 i;
 	acpi_status status;
 	acpi_status status;
 
 
 	ACPI_FUNCTION_TRACE(ev_terminate);
 	ACPI_FUNCTION_TRACE(ev_terminate);
@@ -589,7 +589,7 @@ void acpi_ev_terminate(void)
 		/* Disable all fixed events */
 		/* Disable all fixed events */
 
 
 		for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
 		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)) {
 			if (ACPI_FAILURE(status)) {
 				ACPI_ERROR((AE_INFO,
 				ACPI_ERROR((AE_INFO,
 					    "Could not disable fixed event %d",
 					    "Could not disable fixed event %d",

+ 2 - 3
drivers/acpi/events/evregion.c

@@ -81,7 +81,7 @@ acpi_ev_install_handler(acpi_handle obj_handle,
 acpi_status acpi_ev_install_region_handlers(void)
 acpi_status acpi_ev_install_region_handlers(void)
 {
 {
 	acpi_status status;
 	acpi_status status;
-	acpi_native_uint i;
+	u32 i;
 
 
 	ACPI_FUNCTION_TRACE(ev_install_region_handlers);
 	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 acpi_ev_initialize_op_regions(void)
 {
 {
 	acpi_status status;
 	acpi_status status;
-	acpi_native_uint i;
+	u32 i;
 
 
 	ACPI_FUNCTION_TRACE(ev_initialize_op_regions);
 	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->prefix_node = region_obj2->extra.method_REG;
 	info->pathname = NULL;
 	info->pathname = NULL;
 	info->parameters = args;
 	info->parameters = args;
-	info->parameter_type = ACPI_PARAM_ARGS;
 	info->flags = ACPI_IGNORE_RETURN_VALUE;
 	info->flags = ACPI_IGNORE_RETURN_VALUE;
 
 
 	/*
 	/*

+ 1 - 1
drivers/acpi/events/evrgnini.c

@@ -380,7 +380,7 @@ static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
 	acpi_status status;
 	acpi_status status;
 	struct acpica_device_id hid;
 	struct acpica_device_id hid;
 	struct acpi_compatible_id_list *cid;
 	struct acpi_compatible_id_list *cid;
-	acpi_native_uint i;
+	u32 i;
 
 
 	/*
 	/*
 	 * Get the _HID and check for a PCI Root Bridge
 	 * Get the _HID and check for a PCI Root Bridge

+ 15 - 3
drivers/acpi/events/evxfevnt.c

@@ -472,7 +472,6 @@ acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
 }
 }
 
 
 ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
 ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
-#ifdef ACPI_FUTURE_USAGE
 /*******************************************************************************
 /*******************************************************************************
  *
  *
  * FUNCTION:    acpi_get_event_status
  * 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 acpi_get_event_status(u32 event, acpi_event_status * event_status)
 {
 {
 	acpi_status status = AE_OK;
 	acpi_status status = AE_OK;
+	u32 value;
 
 
 	ACPI_FUNCTION_TRACE(acpi_get_event_status);
 	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 =
 	status =
 	    acpi_get_register(acpi_gbl_fixed_event_info[event].
 	    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);
 	return_ACPI_STATUS(status);
 }
 }
@@ -566,7 +579,6 @@ acpi_get_gpe_status(acpi_handle gpe_device,
 }
 }
 
 
 ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
 ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
-#endif				/*  ACPI_FUTURE_USAGE  */
 /*******************************************************************************
 /*******************************************************************************
  *
  *
  * FUNCTION:    acpi_install_gpe_block
  * FUNCTION:    acpi_install_gpe_block

+ 9 - 8
drivers/acpi/executer/exconfig.c

@@ -53,7 +53,7 @@ ACPI_MODULE_NAME("exconfig")
 
 
 /* Local prototypes */
 /* Local prototypes */
 static acpi_status
 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,
 		  struct acpi_namespace_node *parent_node,
 		  union acpi_operand_object **ddb_handle);
 		  union acpi_operand_object **ddb_handle);
 
 
@@ -73,7 +73,7 @@ acpi_ex_add_table(acpi_native_uint table_index,
  ******************************************************************************/
  ******************************************************************************/
 
 
 static acpi_status
 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,
 		  struct acpi_namespace_node *parent_node,
 		  union acpi_operand_object **ddb_handle)
 		  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 */
 	/* 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 */
 	/* Add the table to the namespace */
 
 
@@ -128,12 +129,12 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
 {
 {
 	acpi_status status;
 	acpi_status status;
 	union acpi_operand_object **operand = &walk_state->operands[0];
 	union acpi_operand_object **operand = &walk_state->operands[0];
-	acpi_native_uint table_index;
 	struct acpi_namespace_node *parent_node;
 	struct acpi_namespace_node *parent_node;
 	struct acpi_namespace_node *start_node;
 	struct acpi_namespace_node *start_node;
 	struct acpi_namespace_node *parameter_node = NULL;
 	struct acpi_namespace_node *parameter_node = NULL;
 	union acpi_operand_object *ddb_handle;
 	union acpi_operand_object *ddb_handle;
 	struct acpi_table_header *table;
 	struct acpi_table_header *table;
+	u32 table_index;
 
 
 	ACPI_FUNCTION_TRACE(ex_load_table_op);
 	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;
 	union acpi_operand_object *ddb_handle;
 	struct acpi_table_desc table_desc;
 	struct acpi_table_desc table_desc;
-	acpi_native_uint table_index;
+	u32 table_index;
 	acpi_status status;
 	acpi_status status;
 	u32 length;
 	u32 length;
 
 
@@ -437,7 +438,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
 {
 {
 	acpi_status status = AE_OK;
 	acpi_status status = AE_OK;
 	union acpi_operand_object *table_desc = ddb_handle;
 	union acpi_operand_object *table_desc = ddb_handle;
-	acpi_native_uint table_index;
+	u32 table_index;
 	struct acpi_table_header *table;
 	struct acpi_table_header *table;
 
 
 	ACPI_FUNCTION_TRACE(ex_unload_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);
 		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 */
 	/* Invoke table handler if present */
 
 

+ 6 - 6
drivers/acpi/executer/exconvrt.c

@@ -288,11 +288,11 @@ acpi_ex_convert_to_ascii(acpi_integer integer,
 			 u16 base, u8 * string, u8 data_width)
 			 u16 base, u8 * string, u8 data_width)
 {
 {
 	acpi_integer digit;
 	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;
 	u32 remainder;
 	u8 supress_zeros;
 	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: 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--) {
 		for (i = 0, j = (hex_length - 1); i < hex_length; i++, j--) {
 
 
 			/* Get one hex digit, most significant digits first */
 			/* Get one hex digit, most significant digits first */

+ 0 - 2
drivers/acpi/executer/excreate.c

@@ -45,8 +45,6 @@
 #include <acpi/acinterp.h>
 #include <acpi/acinterp.h>
 #include <acpi/amlcode.h>
 #include <acpi/amlcode.h>
 #include <acpi/acnamesp.h>
 #include <acpi/acnamesp.h>
-#include <acpi/acevents.h>
-#include <acpi/actables.h>
 
 
 #define _COMPONENT          ACPI_EXECUTER
 #define _COMPONENT          ACPI_EXECUTER
 ACPI_MODULE_NAME("excreate")
 ACPI_MODULE_NAME("excreate")

+ 26 - 41
drivers/acpi/executer/exdump.c

@@ -580,25 +580,22 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
 
 
 	case ACPI_TYPE_BUFFER:
 	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.length,
 			       obj_desc->buffer.pointer);
 			       obj_desc->buffer.pointer);
 
 
-		length = obj_desc->buffer.length;
-		if (length > 64) {
-			length = 64;
-		}
-
 		/* Debug only -- dump the buffer contents */
 		/* Debug only -- dump the buffer contents */
 
 
 		if (obj_desc->buffer.pointer) {
 		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;
 		break;
 
 
@@ -756,54 +753,42 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
  *
  *
  * FUNCTION:    acpi_ex_dump_operands
  * 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
 void
 acpi_ex_dump_operands(union acpi_operand_object **operands,
 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);
 	ACPI_FUNCTION_NAME(ex_dump_operands);
 
 
-	if (!ident) {
-		ident = "?";
-	}
-
-	if (!note) {
-		note = "?";
+	if (!opcode_name) {
+		opcode_name = "UNKNOWN";
 	}
 	}
 
 
 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 	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,
 	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;
 	return;
 }
 }
 
 

+ 5 - 4
drivers/acpi/executer/exfldio.c

@@ -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
 			 * 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
 			 * 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,
 			if (ACPI_ROUND_UP(rgn_desc->region.length,
 					  obj_desc->common_field.
 					  obj_desc->common_field.
 					  access_byte_width) >=
 					  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);
 				return_ACPI_STATUS(AE_OK);
 			}
 			}
 		}
 		}

+ 4 - 4
drivers/acpi/executer/exmisc.c

@@ -329,8 +329,8 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
 
 
 		/* Result of two Strings is a String */
 		/* 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 +
 							    length +
 							    local_operand1->
 							    local_operand1->
 							    string.length));
 							    string.length));
@@ -352,8 +352,8 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
 
 
 		/* Result of two Buffers is a Buffer */
 		/* 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 +
 							    length +
 							    local_operand1->
 							    local_operand1->
 							    buffer.length));
 							    buffer.length));

+ 4 - 4
drivers/acpi/executer/exprep.c

@@ -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 = obj_desc->common.next_object;
 		second_desc->extra.aml_start =
 		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 =
 		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;
 		break;
 
 

+ 1 - 1
drivers/acpi/executer/exregion.c

@@ -156,7 +156,7 @@ acpi_ex_system_memory_space_handler(u32 function,
 		/* Create a new mapping starting at the address given */
 		/* Create a new mapping starting at the address given */
 
 
 		mem_info->mapped_logical_address =
 		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) {
 		if (!mem_info->mapped_logical_address) {
 			ACPI_ERROR((AE_INFO,
 			ACPI_ERROR((AE_INFO,
 				    "Could not map memory at %8.8X%8.8X, size %X",
 				    "Could not map memory at %8.8X%8.8X, size %X",

+ 4 - 0
drivers/acpi/executer/exresop.c

@@ -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);
 	return_ACPI_STATUS(status);
 }
 }

+ 0 - 6
drivers/acpi/executer/exstore.c

@@ -343,12 +343,6 @@ acpi_ex_store(union acpi_operand_object *source_desc,
 			    acpi_ut_get_object_type_name(dest_desc),
 			    acpi_ut_get_object_type_name(dest_desc),
 			    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);
 		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 	}
 	}
 
 

+ 7 - 1
drivers/acpi/fan.c

@@ -148,7 +148,7 @@ acpi_fan_write_state(struct file *file, const char __user * buffer,
 	int result = 0;
 	int result = 0;
 	struct seq_file *m = file->private_data;
 	struct seq_file *m = file->private_data;
 	struct acpi_device *device = m->private;
 	struct acpi_device *device = m->private;
-	char state_string[12] = { '\0' };
+	char state_string[3] = { '\0' };
 
 
 	if (count > sizeof(state_string) - 1)
 	if (count > sizeof(state_string) - 1)
 		return -EINVAL;
 		return -EINVAL;
@@ -157,6 +157,12 @@ acpi_fan_write_state(struct file *file, const char __user * buffer,
 		return -EFAULT;
 		return -EFAULT;
 
 
 	state_string[count] = '\0';
 	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,
 	result = acpi_bus_set_power(device->handle,
 				    simple_strtoul(state_string, NULL, 0));
 				    simple_strtoul(state_string, NULL, 0));

+ 3 - 0
drivers/acpi/glue.c

@@ -333,6 +333,9 @@ static int __init acpi_rtc_init(void)
 {
 {
 	struct device *dev = get_rtc_dev();
 	struct device *dev = get_rtc_dev();
 
 
+	if (acpi_disabled)
+		return 0;
+
 	if (acpi_disabled)
 	if (acpi_disabled)
 		return 0;
 		return 0;
 
 

+ 49 - 3
drivers/acpi/hardware/hwgpe.c

@@ -53,6 +53,54 @@ static acpi_status
 acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 				struct acpi_gpe_block_info *gpe_block);
 				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
  * 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_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;
 	struct acpi_gpe_register_info *gpe_register_info;
 	acpi_status status;
 	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_status
 acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
 acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
 		       acpi_event_status * event_status)
 		       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:
       unlock_and_exit:
 	return (status);
 	return (status);
 }
 }
-#endif				/*  ACPI_FUTURE_USAGE  */
 
 
 /******************************************************************************
 /******************************************************************************
  *
  *

+ 3 - 3
drivers/acpi/namespace/nsdump.c

@@ -73,7 +73,7 @@ acpi_ns_dump_one_device(acpi_handle obj_handle,
 
 
 void acpi_ns_print_pathname(u32 num_segments, char *pathname)
 void acpi_ns_print_pathname(u32 num_segments, char *pathname)
 {
 {
-	acpi_native_uint i;
+	u32 i;
 
 
 	ACPI_FUNCTION_NAME(ns_print_pathname);
 	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) {
 			if (obj_type > ACPI_TYPE_LOCAL_MAX) {
 				acpi_os_printf
 				acpi_os_printf
-				    ("(Ptr to ACPI Object type %X [UNKNOWN])\n",
+				    ("(Pointer to ACPI Object type %.2X [UNKNOWN])\n",
 				     obj_type);
 				     obj_type);
 				bytes_to_dump = 32;
 				bytes_to_dump = 32;
 			} else {
 			} else {
 				acpi_os_printf
 				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));
 				     obj_type, acpi_ut_get_type_name(obj_type));
 				bytes_to_dump =
 				bytes_to_dump =
 				    sizeof(union acpi_operand_object);
 				    sizeof(union acpi_operand_object);

+ 35 - 0
drivers/acpi/namespace/nseval.c

@@ -138,6 +138,41 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
 			return_ACPI_STATUS(AE_NULL_OBJECT);
 			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_DUMP_PATHNAME(info->resolved_node, "Execute Method:",
 				   ACPI_LV_INFO, _COMPONENT);
 				   ACPI_LV_INFO, _COMPONENT);
 
 

+ 0 - 1
drivers/acpi/namespace/nsinit.c

@@ -542,7 +542,6 @@ acpi_ns_init_one_device(acpi_handle obj_handle,
 	info->prefix_node = device_node;
 	info->prefix_node = device_node;
 	info->pathname = METHOD_NAME__INI;
 	info->pathname = METHOD_NAME__INI;
 	info->parameters = NULL;
 	info->parameters = NULL;
-	info->parameter_type = ACPI_PARAM_ARGS;
 	info->flags = ACPI_IGNORE_RETURN_VALUE;
 	info->flags = ACPI_IGNORE_RETURN_VALUE;
 
 
 	/*
 	/*

+ 1 - 2
drivers/acpi/namespace/nsload.c

@@ -71,8 +71,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle);
  ******************************************************************************/
  ******************************************************************************/
 
 
 acpi_status
 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;
 	acpi_status status;
 
 

+ 7 - 8
drivers/acpi/namespace/nsparse.c

@@ -63,13 +63,13 @@ ACPI_MODULE_NAME("nsparse")
  *
  *
  ******************************************************************************/
  ******************************************************************************/
 acpi_status
 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;
 	union acpi_parse_object *parse_root;
 	acpi_status status;
 	acpi_status status;
-	acpi_native_uint aml_length;
+       u32 aml_length;
 	u8 *aml_start;
 	u8 *aml_start;
 	struct acpi_walk_state *walk_state;
 	struct acpi_walk_state *walk_state;
 	struct acpi_table_header *table;
 	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_start = (u8 *) table + sizeof(struct acpi_table_header);
 		aml_length = table->length - 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,
 		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)) {
 	if (ACPI_FAILURE(status)) {
@@ -158,8 +158,7 @@ acpi_ns_one_complete_parse(acpi_native_uint pass_number,
  ******************************************************************************/
  ******************************************************************************/
 
 
 acpi_status
 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;
 	acpi_status status;
 
 

+ 25 - 25
drivers/acpi/namespace/nsutils.c

@@ -73,9 +73,9 @@ acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
  ******************************************************************************/
  ******************************************************************************/
 
 
 void
 void
-acpi_ns_report_error(char *module_name,
+acpi_ns_report_error(const char *module_name,
 		     u32 line_number,
 		     u32 line_number,
-		     char *internal_name, acpi_status lookup_status)
+		     const char *internal_name, acpi_status lookup_status)
 {
 {
 	acpi_status status;
 	acpi_status status;
 	u32 bad_name;
 	u32 bad_name;
@@ -130,11 +130,11 @@ acpi_ns_report_error(char *module_name,
  ******************************************************************************/
  ******************************************************************************/
 
 
 void
 void
-acpi_ns_report_method_error(char *module_name,
+acpi_ns_report_method_error(const char *module_name,
 			    u32 line_number,
 			    u32 line_number,
-			    char *message,
+			    const char *message,
 			    struct acpi_namespace_node *prefix_node,
 			    struct acpi_namespace_node *prefix_node,
-			    char *path, acpi_status method_status)
+			    const char *path, acpi_status method_status)
 {
 {
 	acpi_status status;
 	acpi_status status;
 	struct acpi_namespace_node *node = prefix_node;
 	struct acpi_namespace_node *node = prefix_node;
@@ -167,7 +167,8 @@ acpi_ns_report_method_error(char *module_name,
  ******************************************************************************/
  ******************************************************************************/
 
 
 void
 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;
 	struct acpi_buffer buffer;
 	acpi_status status;
 	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)
 void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info)
 {
 {
-	char *next_external_char;
+	const char *next_external_char;
 	u32 i;
 	u32 i;
 
 
 	ACPI_FUNCTION_ENTRY();
 	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;
 	u32 num_segments = info->num_segments;
 	char *internal_name = info->internal_name;
 	char *internal_name = info->internal_name;
-	char *external_name = info->next_external_char;
+	const char *external_name = info->next_external_char;
 	char *result = NULL;
 	char *result = NULL;
-	acpi_native_uint i;
+	u32 i;
 
 
 	ACPI_FUNCTION_TRACE(ns_build_internal_name);
 	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];
 			result = &internal_name[i];
 		} else if (num_segments == 2) {
 		} else if (num_segments == 2) {
 			internal_name[i] = AML_DUAL_NAME_PREFIX;
 			internal_name[i] = AML_DUAL_NAME_PREFIX;
-			result = &internal_name[(acpi_native_uint) (i + 1)];
+			result = &internal_name[(acpi_size) i + 1];
 		} else {
 		} else {
 			internal_name[i] = AML_MULTI_NAME_PREFIX_OP;
 			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;
 	char *internal_name;
 	struct acpi_namestring_info info;
 	struct acpi_namestring_info info;
@@ -528,15 +529,15 @@ acpi_status acpi_ns_internalize_name(char *external_name, char **converted_name)
 
 
 acpi_status
 acpi_status
 acpi_ns_externalize_name(u32 internal_name_length,
 acpi_ns_externalize_name(u32 internal_name_length,
-			 char *internal_name,
+			 const char *internal_name,
 			 u32 * converted_name_length, char **converted_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);
 	ACPI_FUNCTION_TRACE(ns_externalize_name);
 
 
@@ -582,9 +583,8 @@ acpi_ns_externalize_name(u32 internal_name_length,
 			/* <count> 4-byte names */
 			/* <count> 4-byte names */
 
 
 			names_index = prefix_length + 2;
 			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;
 			break;
 
 
 		case AML_DUAL_NAME_PREFIX:
 		case AML_DUAL_NAME_PREFIX:
@@ -823,7 +823,7 @@ u32 acpi_ns_opens_scope(acpi_object_type type)
 
 
 acpi_status
 acpi_status
 acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
 acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
-		 char *pathname,
+		 const char *pathname,
 		 u32 flags, struct acpi_namespace_node **return_node)
 		 u32 flags, struct acpi_namespace_node **return_node)
 {
 {
 	union acpi_generic_state scope_info;
 	union acpi_generic_state scope_info;

+ 1 - 2
drivers/acpi/namespace/nsxfeval.c

@@ -182,7 +182,6 @@ acpi_evaluate_object(acpi_handle handle,
 	}
 	}
 
 
 	info->pathname = pathname;
 	info->pathname = pathname;
-	info->parameter_type = ACPI_PARAM_ARGS;
 
 
 	/* Convert and validate the device handle */
 	/* Convert and validate the device handle */
 
 
@@ -442,7 +441,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
 	u32 flags;
 	u32 flags;
 	struct acpica_device_id hid;
 	struct acpica_device_id hid;
 	struct acpi_compatible_id_list *cid;
 	struct acpi_compatible_id_list *cid;
-	acpi_native_uint i;
+	u32 i;
 	int found;
 	int found;
 
 
 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);

+ 2 - 2
drivers/acpi/numa.c

@@ -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 *p =
 			    (struct acpi_srat_mem_affinity *)header;
 			    (struct acpi_srat_mem_affinity *)header;
 			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 			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->base_address,
 					  (unsigned long)p->length,
 					  (unsigned long)p->length,
-					  p->memory_type, p->proximity_domain,
+					  p->proximity_domain,
 					  (p->flags & ACPI_SRAT_MEM_ENABLED)?
 					  (p->flags & ACPI_SRAT_MEM_ENABLED)?
 					  "enabled" : "disabled",
 					  "enabled" : "disabled",
 					  (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)?
 					  (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)?

+ 2 - 2
drivers/acpi/parser/psargs.c

@@ -76,7 +76,7 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state)
 {
 {
 	u8 *aml = parser_state->aml;
 	u8 *aml = parser_state->aml;
 	u32 package_length = 0;
 	u32 package_length = 0;
-	acpi_native_uint byte_count;
+	u32 byte_count;
 	u8 byte_zero_mask = 0x3F;	/* Default [0:5] */
 	u8 byte_zero_mask = 0x3F;	/* Default [0:5] */
 
 
 	ACPI_FUNCTION_TRACE(ps_get_next_package_length);
 	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
 	 * used to encode the package length, either 0,1,2, or 3
 	 */
 	 */
 	byte_count = (aml[0] >> 6);
 	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 */
 	/* Get bytes 3, 2, 1 as needed */
 
 

+ 2 - 2
drivers/acpi/parser/psxface.c

@@ -333,9 +333,9 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
 static void
 static void
 acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action)
 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 */
 		/* Update reference count for each parameter */
 
 

+ 17 - 21
drivers/acpi/pci_irq.c

@@ -162,7 +162,7 @@ do_prt_fixups(struct acpi_prt_entry *entry, struct acpi_pci_routing_table *prt)
 		    !strcmp(prt->source, quirk->source) &&
 		    !strcmp(prt->source, quirk->source) &&
 		    strlen(prt->source) >= strlen(quirk->actual_source)) {
 		    strlen(prt->source) >= strlen(quirk->actual_source)) {
 			printk(KERN_WARNING PREFIX "firmware reports "
 			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",
 				"changing to %s\n",
 				entry->id.segment, entry->id.bus,
 				entry->id.segment, entry->id.bus,
 				entry->id.device, 'A' + entry->pin,
 				entry->id.device, 'A' + entry->pin,
@@ -429,7 +429,7 @@ acpi_pci_irq_derive(struct pci_dev *dev,
 {
 {
 	struct pci_dev *bridge = dev;
 	struct pci_dev *bridge = dev;
 	int irq = -1;
 	int irq = -1;
-	u8 bridge_pin = 0;
+	u8 bridge_pin = 0, orig_pin = pin;
 
 
 
 
 	if (!dev)
 	if (!dev)
@@ -463,8 +463,8 @@ acpi_pci_irq_derive(struct pci_dev *dev,
 	}
 	}
 
 
 	if (irq < 0) {
 	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;
 		return -1;
 	}
 	}
 
 
@@ -487,6 +487,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 	int triggering = ACPI_LEVEL_SENSITIVE;
 	int triggering = ACPI_LEVEL_SENSITIVE;
 	int polarity = ACPI_ACTIVE_LOW;
 	int polarity = ACPI_ACTIVE_LOW;
 	char *link = NULL;
 	char *link = NULL;
+	char link_desc[16];
 	int rc;
 	int rc;
 
 
 
 
@@ -503,7 +504,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 	pin--;
 	pin--;
 
 
 	if (!dev->bus) {
 	if (!dev->bus) {
-		printk(KERN_ERR PREFIX "Invalid (NULL) 'bus' field\n");
+		dev_err(&dev->dev, "invalid (NULL) 'bus' field\n");
 		return -ENODEV;
 		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.
 	 * driver reported one, then use it. Exit in any case.
 	 */
 	 */
 	if (irq < 0) {
 	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 */
 		/* Interrupt Line values above 0xF are forbidden */
 		if (dev->irq > 0 && (dev->irq <= 0xF)) {
 		if (dev->irq > 0 && (dev->irq <= 0xF)) {
 			printk(" - using IRQ %d\n", dev->irq);
 			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);
 	rc = acpi_register_gsi(irq, triggering, polarity);
 	if (rc < 0) {
 	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;
 		return rc;
 	}
 	}
 	dev->irq = rc;
 	dev->irq = rc;
 
 
-	printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ",
-	       pci_name(dev), 'A' + pin);
-
 	if (link)
 	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;
 	return 0;
 }
 }
@@ -616,10 +616,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
 	 * (e.g. PCI_UNDEFINED_IRQ).
 	 * (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);
 	acpi_unregister_gsi(gsi);
-
-	return;
 }
 }

+ 60 - 15
drivers/acpi/processor_core.c

@@ -118,8 +118,31 @@ static const struct file_operations acpi_processor_info_fops = {
 	.release = single_release,
 	.release = single_release,
 };
 };
 
 
-struct acpi_processor *processors[NR_CPUS];
+DEFINE_PER_CPU(struct acpi_processor *, processors);
 struct acpi_processor_errata errata __read_mostly;
 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
                                 Errata Handling
@@ -265,7 +288,20 @@ static int acpi_processor_set_pdc(struct acpi_processor *pr)
 
 
 	if (!pdc_in)
 	if (!pdc_in)
 		return status;
 		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);
 	status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL);
 
 
 	if (ACPI_FAILURE(status))
 	if (ACPI_FAILURE(status))
@@ -614,14 +650,14 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid)
 	return 0;
 	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)
 static int __cpuinit acpi_processor_start(struct acpi_device *device)
 {
 {
 	int result = 0;
 	int result = 0;
 	acpi_status status = AE_OK;
 	acpi_status status = AE_OK;
 	struct acpi_processor *pr;
 	struct acpi_processor *pr;
-
+	struct sys_device *sysdev;
 
 
 	pr = acpi_driver_data(device);
 	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.
 	 * ACPI id of processors can be reported wrongly by the BIOS.
 	 * Don't trust it blindly
 	 * 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 "
 		printk(KERN_WARNING "BIOS reported wrong ACPI id "
 			"for the processor\n");
 			"for the processor\n");
 		return -ENODEV;
 		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);
 	result = acpi_processor_add_fs(device);
 	if (result)
 	if (result)
 		goto end;
 		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,
 	status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
 					     acpi_processor_notify, pr);
 					     acpi_processor_notify, pr);
 
 
@@ -749,7 +789,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
 		unsigned long action, void *hcpu)
 		unsigned long action, void *hcpu)
 {
 {
 	unsigned int cpu = (unsigned long)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) {
 	if (action == CPU_ONLINE && pr) {
 		acpi_processor_ppc_has_changed(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,
 	status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
 					    acpi_processor_notify);
 					    acpi_processor_notify);
 
 
+	sysfs_remove_link(&device->dev.kobj, "sysdev");
+
 	acpi_processor_remove_fs(device);
 	acpi_processor_remove_fs(device);
 
 
 	if (pr->cdev) {
 	if (pr->cdev) {
@@ -819,8 +861,8 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
 		pr->cdev = NULL;
 		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);
 	kfree(pr);
 
 
 	return 0;
 	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)
 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);
 	arch_unregister_cpu(pr->id);
 	acpi_unmap_lsapic(pr->id);
 	acpi_unmap_lsapic(pr->id);
 	return (0);
 	return (0);
@@ -1068,8 +1110,6 @@ static int __init acpi_processor_init(void)
 {
 {
 	int result = 0;
 	int result = 0;
 
 
-
-	memset(&processors, 0, sizeof(processors));
 	memset(&errata, 0, sizeof(errata));
 	memset(&errata, 0, sizeof(errata));
 
 
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
@@ -1083,6 +1123,11 @@ static int __init acpi_processor_init(void)
 		return -ENOMEM;
 		return -ENOMEM;
 	acpi_processor_dir->owner = THIS_MODULE;
 	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);
 	result = cpuidle_register_driver(&acpi_idle_driver);
 	if (result < 0)
 	if (result < 0)
 		goto out_proc;
 		goto out_proc;

+ 30 - 4
drivers/acpi/processor_idle.c

@@ -41,6 +41,7 @@
 #include <linux/pm_qos_params.h>
 #include <linux/pm_qos_params.h>
 #include <linux/clockchips.h>
 #include <linux/clockchips.h>
 #include <linux/cpuidle.h>
 #include <linux/cpuidle.h>
+#include <linux/cpuidle.h>
 
 
 /*
 /*
  * Include the apic definitions for x86 to have the APIC timer related defines
  * Include the apic definitions for x86 to have the APIC timer related defines
@@ -57,6 +58,7 @@
 
 
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/processor.h>
 #include <acpi/processor.h>
+#include <asm/processor.h>
 
 
 #define ACPI_PROCESSOR_COMPONENT        0x01000000
 #define ACPI_PROCESSOR_COMPONENT        0x01000000
 #define ACPI_PROCESSOR_CLASS            "processor"
 #define ACPI_PROCESSOR_CLASS            "processor"
@@ -401,7 +403,7 @@ static void acpi_processor_idle(void)
 	 */
 	 */
 	local_irq_disable();
 	local_irq_disable();
 
 
-	pr = processors[smp_processor_id()];
+	pr = __get_cpu_var(processors);
 	if (!pr) {
 	if (!pr) {
 		local_irq_enable();
 		local_irq_enable();
 		return;
 		return;
@@ -955,6 +957,21 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
 			} else {
 			} else {
 				continue;
 				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 {
 		} else {
 			snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI IOPORT 0x%x",
 			snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI IOPORT 0x%x",
 				 cx.address);
 				 cx.address);
@@ -1431,7 +1448,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
 	struct acpi_processor *pr;
 	struct acpi_processor *pr;
 	struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
 	struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
 
 
-	pr = processors[smp_processor_id()];
+	pr = __get_cpu_var(processors);
 
 
 	if (unlikely(!pr))
 	if (unlikely(!pr))
 		return 0;
 		return 0;
@@ -1471,7 +1488,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
 	u32 t1, t2;
 	u32 t1, t2;
 	int sleep_ticks = 0;
 	int sleep_ticks = 0;
 
 
-	pr = processors[smp_processor_id()];
+	pr = __get_cpu_var(processors);
 
 
 	if (unlikely(!pr))
 	if (unlikely(!pr))
 		return 0;
 		return 0;
@@ -1549,7 +1566,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
 	u32 t1, t2;
 	u32 t1, t2;
 	int sleep_ticks = 0;
 	int sleep_ticks = 0;
 
 
-	pr = processors[smp_processor_id()];
+	pr = __get_cpu_var(processors);
 
 
 	if (unlikely(!pr))
 	if (unlikely(!pr))
 		return 0;
 		return 0;
@@ -1780,6 +1797,15 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
 		return 0;
 		return 0;
 
 
 	if (!first_run) {
 	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);
 		dmi_check_system(processor_power_dmi_table);
 		max_cstate = acpi_processor_cstate_check(max_cstate);
 		max_cstate = acpi_processor_cstate_check(max_cstate);
 		if (max_cstate < ACPI_C_STATES_MAX)
 		if (max_cstate < ACPI_C_STATES_MAX)

+ 9 - 9
drivers/acpi/processor_perflib.c

@@ -89,7 +89,7 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb,
 	if (event != CPUFREQ_INCOMPATIBLE)
 	if (event != CPUFREQ_INCOMPATIBLE)
 		goto out;
 		goto out;
 
 
-	pr = processors[policy->cpu];
+	pr = per_cpu(processors, policy->cpu);
 	if (!pr || !pr->performance)
 	if (!pr || !pr->performance)
 		goto out;
 		goto out;
 
 
@@ -572,7 +572,7 @@ int acpi_processor_preregister_performance(
 
 
 	/* Call _PSD for all CPUs */
 	/* Call _PSD for all CPUs */
 	for_each_possible_cpu(i) {
 	for_each_possible_cpu(i) {
-		pr = processors[i];
+		pr = per_cpu(processors, i);
 		if (!pr) {
 		if (!pr) {
 			/* Look only at processors in ACPI namespace */
 			/* Look only at processors in ACPI namespace */
 			continue;
 			continue;
@@ -603,7 +603,7 @@ int acpi_processor_preregister_performance(
 	 * domain info.
 	 * domain info.
 	 */
 	 */
 	for_each_possible_cpu(i) {
 	for_each_possible_cpu(i) {
-		pr = processors[i];
+		pr = per_cpu(processors, i);
 		if (!pr)
 		if (!pr)
 			continue;
 			continue;
 
 
@@ -624,7 +624,7 @@ int acpi_processor_preregister_performance(
 
 
 	cpus_clear(covered_cpus);
 	cpus_clear(covered_cpus);
 	for_each_possible_cpu(i) {
 	for_each_possible_cpu(i) {
-		pr = processors[i];
+		pr = per_cpu(processors, i);
 		if (!pr)
 		if (!pr)
 			continue;
 			continue;
 
 
@@ -651,7 +651,7 @@ int acpi_processor_preregister_performance(
 			if (i == j)
 			if (i == j)
 				continue;
 				continue;
 
 
-			match_pr = processors[j];
+			match_pr = per_cpu(processors, j);
 			if (!match_pr)
 			if (!match_pr)
 				continue;
 				continue;
 
 
@@ -680,7 +680,7 @@ int acpi_processor_preregister_performance(
 			if (i == j)
 			if (i == j)
 				continue;
 				continue;
 
 
-			match_pr = processors[j];
+			match_pr = per_cpu(processors, j);
 			if (!match_pr)
 			if (!match_pr)
 				continue;
 				continue;
 
 
@@ -697,7 +697,7 @@ int acpi_processor_preregister_performance(
 
 
 err_ret:
 err_ret:
 	for_each_possible_cpu(i) {
 	for_each_possible_cpu(i) {
-		pr = processors[i];
+		pr = per_cpu(processors, i);
 		if (!pr || !pr->performance)
 		if (!pr || !pr->performance)
 			continue;
 			continue;
 
 
@@ -728,7 +728,7 @@ acpi_processor_register_performance(struct acpi_processor_performance
 
 
 	mutex_lock(&performance_mutex);
 	mutex_lock(&performance_mutex);
 
 
-	pr = processors[cpu];
+	pr = per_cpu(processors, cpu);
 	if (!pr) {
 	if (!pr) {
 		mutex_unlock(&performance_mutex);
 		mutex_unlock(&performance_mutex);
 		return -ENODEV;
 		return -ENODEV;
@@ -766,7 +766,7 @@ acpi_processor_unregister_performance(struct acpi_processor_performance
 
 
 	mutex_lock(&performance_mutex);
 	mutex_lock(&performance_mutex);
 
 
-	pr = processors[cpu];
+	pr = per_cpu(processors, cpu);
 	if (!pr) {
 	if (!pr) {
 		mutex_unlock(&performance_mutex);
 		mutex_unlock(&performance_mutex);
 		return;
 		return;

+ 27 - 11
drivers/acpi/processor_throttling.c

@@ -71,7 +71,7 @@ static int acpi_processor_update_tsd_coord(void)
 	 * coordination between all CPUs.
 	 * coordination between all CPUs.
 	 */
 	 */
 	for_each_possible_cpu(i) {
 	for_each_possible_cpu(i) {
-		pr = processors[i];
+		pr = per_cpu(processors, i);
 		if (!pr)
 		if (!pr)
 			continue;
 			continue;
 
 
@@ -93,7 +93,7 @@ static int acpi_processor_update_tsd_coord(void)
 
 
 	cpus_clear(covered_cpus);
 	cpus_clear(covered_cpus);
 	for_each_possible_cpu(i) {
 	for_each_possible_cpu(i) {
-		pr = processors[i];
+		pr = per_cpu(processors, i);
 		if (!pr)
 		if (!pr)
 			continue;
 			continue;
 
 
@@ -119,7 +119,7 @@ static int acpi_processor_update_tsd_coord(void)
 			if (i == j)
 			if (i == j)
 				continue;
 				continue;
 
 
-			match_pr = processors[j];
+			match_pr = per_cpu(processors, j);
 			if (!match_pr)
 			if (!match_pr)
 				continue;
 				continue;
 
 
@@ -152,7 +152,7 @@ static int acpi_processor_update_tsd_coord(void)
 			if (i == j)
 			if (i == j)
 				continue;
 				continue;
 
 
-			match_pr = processors[j];
+			match_pr = per_cpu(processors, j);
 			if (!match_pr)
 			if (!match_pr)
 				continue;
 				continue;
 
 
@@ -172,7 +172,7 @@ static int acpi_processor_update_tsd_coord(void)
 
 
 err_ret:
 err_ret:
 	for_each_possible_cpu(i) {
 	for_each_possible_cpu(i) {
-		pr = processors[i];
+		pr = per_cpu(processors, i);
 		if (!pr)
 		if (!pr)
 			continue;
 			continue;
 
 
@@ -214,7 +214,7 @@ static int acpi_processor_throttling_notifier(unsigned long event, void *data)
 	struct acpi_processor_throttling *p_throttling;
 	struct acpi_processor_throttling *p_throttling;
 
 
 	cpu = p_tstate->cpu;
 	cpu = p_tstate->cpu;
-	pr = processors[cpu];
+	pr = per_cpu(processors, cpu);
 	if (!pr) {
 	if (!pr) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid pr pointer\n"));
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid pr pointer\n"));
 		return 0;
 		return 0;
@@ -1035,7 +1035,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
 		 * cpus.
 		 * cpus.
 		 */
 		 */
 		for_each_cpu_mask(i, online_throttling_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
 			 * If the pointer is invalid, we will report the
 			 * error message and continue.
 			 * error message and continue.
@@ -1232,7 +1232,10 @@ static ssize_t acpi_processor_write_throttling(struct file *file,
 	int result = 0;
 	int result = 0;
 	struct seq_file *m = file->private_data;
 	struct seq_file *m = file->private_data;
 	struct acpi_processor *pr = m->private;
 	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))
 	if (!pr || (count > sizeof(state_string) - 1))
 		return -EINVAL;
 		return -EINVAL;
@@ -1241,10 +1244,23 @@ static ssize_t acpi_processor_write_throttling(struct file *file,
 		return -EFAULT;
 		return -EFAULT;
 
 
 	state_string[count] = '\0';
 	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)
 	if (result)
 		return result;
 		return result;
 
 

+ 50 - 0
drivers/acpi/reboot.c

@@ -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);
+}

+ 2 - 2
drivers/acpi/resources/rscalc.c

@@ -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)
 static u8 acpi_rs_count_set_bits(u16 bit_field)
 {
 {
-	acpi_native_uint bits_set;
+	u8 bits_set;
 
 
 	ACPI_FUNCTION_ENTRY();
 	ACPI_FUNCTION_ENTRY();
 
 
@@ -84,7 +84,7 @@ static u8 acpi_rs_count_set_bits(u16 bit_field)
 		bit_field &= (u16) (bit_field - 1);
 		bit_field &= (u16) (bit_field - 1);
 	}
 	}
 
 
-	return ((u8) bits_set);
+	return bits_set;
 }
 }
 
 
 /*******************************************************************************
 /*******************************************************************************

+ 29 - 12
drivers/acpi/resources/rscreate.c

@@ -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;
 	top_object_list = package_object->package.elements;
 	number_of_elements = package_object->package.count;
 	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 */
 		/* 1) First subobject: Dereference the PRT.Address */
 
 
 		obj_desc = sub_object_list[0];
 		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,
 			ACPI_ERROR((AE_INFO,
 				    "(PRT[%X].Address) Need Integer, found %s",
 				    "(PRT[%X].Address) Need Integer, found %s",
 				    index,
 				    index,
@@ -250,12 +248,12 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
 			return_ACPI_STATUS(AE_BAD_DATA);
 			return_ACPI_STATUS(AE_BAD_DATA);
 		}
 		}
 
 
+		user_prt->address = obj_desc->integer.value;
+
 		/* 2) Second subobject: Dereference the PRT.Pin */
 		/* 2) Second subobject: Dereference the PRT.Pin */
 
 
 		obj_desc = sub_object_list[1];
 		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,
 			ACPI_ERROR((AE_INFO,
 				    "(PRT[%X].Pin) Need Integer, found %s",
 				    "(PRT[%X].Pin) Need Integer, found %s",
 				    index,
 				    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
 		 * 3) Third subobject: Dereference the PRT.source_name
 		 * The name may be unresolved (slack mode), so allow a null object
 		 * 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 */
 		/* 4) Fourth subobject: Dereference the PRT.source_index */
 
 
 		obj_desc = sub_object_list[source_index_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,
 			ACPI_ERROR((AE_INFO,
 				    "(PRT[%X].SourceIndex) Need Integer, found %s",
 				    "(PRT[%X].SourceIndex) Need Integer, found %s",
 				    index,
 				    index,
@@ -374,6 +389,8 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
 			return_ACPI_STATUS(AE_BAD_DATA);
 			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 */
 		/* Point to the next union acpi_operand_object in the top level package */
 
 
 		top_object_list++;
 		top_object_list++;

+ 1 - 1
drivers/acpi/resources/rsmisc.c

@@ -82,7 +82,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
 
 
 	ACPI_FUNCTION_TRACE(rs_convert_aml_to_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 */
 		/* Each internal resource struct is expected to be 32-bit aligned */
 
 

+ 6 - 7
drivers/acpi/resources/rsutils.c

@@ -62,7 +62,7 @@ ACPI_MODULE_NAME("rsutils")
  ******************************************************************************/
  ******************************************************************************/
 u8 acpi_rs_decode_bitmask(u16 mask, u8 * list)
 u8 acpi_rs_decode_bitmask(u16 mask, u8 * list)
 {
 {
-	acpi_native_uint i;
+	u8 i;
 	u8 bit_count;
 	u8 bit_count;
 
 
 	ACPI_FUNCTION_ENTRY();
 	ACPI_FUNCTION_ENTRY();
@@ -71,7 +71,7 @@ u8 acpi_rs_decode_bitmask(u16 mask, u8 * list)
 
 
 	for (i = 0, bit_count = 0; mask; i++) {
 	for (i = 0, bit_count = 0; mask; i++) {
 		if (mask & 0x0001) {
 		if (mask & 0x0001) {
-			list[bit_count] = (u8) i;
+			list[bit_count] = i;
 			bit_count++;
 			bit_count++;
 		}
 		}
 
 
@@ -96,8 +96,8 @@ u8 acpi_rs_decode_bitmask(u16 mask, u8 * list)
 
 
 u16 acpi_rs_encode_bitmask(u8 * list, u8 count)
 u16 acpi_rs_encode_bitmask(u8 * list, u8 count)
 {
 {
-	acpi_native_uint i;
-	acpi_native_uint mask;
+	u32 i;
+	u16 mask;
 
 
 	ACPI_FUNCTION_ENTRY();
 	ACPI_FUNCTION_ENTRY();
 
 
@@ -107,7 +107,7 @@ u16 acpi_rs_encode_bitmask(u8 * list, u8 count)
 		mask |= (0x1 << list[i]);
 		mask |= (0x1 << list[i]);
 	}
 	}
 
 
-	return ((u16) mask);
+	return mask;
 }
 }
 
 
 /*******************************************************************************
 /*******************************************************************************
@@ -130,7 +130,7 @@ u16 acpi_rs_encode_bitmask(u8 * list, u8 count)
 void
 void
 acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)
 acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)
 {
 {
-	acpi_native_uint i;
+	u32 i;
 
 
 	ACPI_FUNCTION_ENTRY();
 	ACPI_FUNCTION_ENTRY();
 
 
@@ -679,7 +679,6 @@ acpi_rs_set_srs_method_data(struct acpi_namespace_node *node,
 	info->prefix_node = node;
 	info->prefix_node = node;
 	info->pathname = METHOD_NAME__SRS;
 	info->pathname = METHOD_NAME__SRS;
 	info->parameters = args;
 	info->parameters = args;
-	info->parameter_type = ACPI_PARAM_ARGS;
 	info->flags = ACPI_IGNORE_RETURN_VALUE;
 	info->flags = ACPI_IGNORE_RETURN_VALUE;
 
 
 	/*
 	/*

+ 37 - 25
drivers/acpi/scan.c

@@ -6,6 +6,8 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
+#include <linux/signal.h>
+#include <linux/kthread.h>
 
 
 #include <acpi/acpi_drivers.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/acinterp.h>	/* for acpi_ex_eisa_id_to_string() */
 #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 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;
 	struct acpi_object_list arg_list;
 	union acpi_object arg;
 	union acpi_object arg;
 	acpi_status status = AE_OK;
 	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.count = 1;
 		arg_list.pointer = &arg;
 		arg_list.pointer = &arg;
 		arg.type = ACPI_TYPE_INTEGER;
 		arg.type = ACPI_TYPE_INTEGER;
@@ -118,26 +140,22 @@ static int acpi_eject_operation(acpi_handle handle, int lockable)
 	/*
 	/*
 	 * TBD: _EJD support.
 	 * TBD: _EJD support.
 	 */
 	 */
-
 	status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
 	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
 static ssize_t
 acpi_eject_store(struct device *d, struct device_attribute *attr,
 acpi_eject_store(struct device *d, struct device_attribute *attr,
 		const char *buf, size_t count)
 		const char *buf, size_t count)
 {
 {
-	int result;
 	int ret = count;
 	int ret = count;
-	int islockable;
 	acpi_status status;
 	acpi_status status;
-	acpi_handle handle;
 	acpi_object_type type = 0;
 	acpi_object_type type = 0;
 	struct acpi_device *acpi_device = to_acpi_device(d);
 	struct acpi_device *acpi_device = to_acpi_device(d);
+	struct task_struct *task;
 
 
 	if ((!count) || (buf[0] != '1')) {
 	if ((!count) || (buf[0] != '1')) {
 		return -EINVAL;
 		return -EINVAL;
@@ -154,18 +172,12 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
 		goto err;
 		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;
 	return ret;
 }
 }
 
 

+ 4 - 35
drivers/acpi/sleep/main.c

@@ -61,8 +61,6 @@ static u32 acpi_suspend_states[] = {
 	[PM_SUSPEND_MAX] = ACPI_STATE_S5
 	[PM_SUSPEND_MAX] = ACPI_STATE_S5
 };
 };
 
 
-static int init_8259A_after_S1;
-
 /**
 /**
  *	acpi_suspend_begin - Set the target system sleep state to the state
  *	acpi_suspend_begin - Set the target system sleep state to the state
  *		associated with given @pm_state, if supported.
  *		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_set_firmware_waking_vector((acpi_physical_address) 0);
 
 
 	acpi_target_sleep_state = ACPI_STATE_S0;
 	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,
 	.finish = acpi_suspend_finish,
 	.end = acpi_suspend_end,
 	.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 */
 #endif /* CONFIG_SUSPEND */
 
 
 #ifdef CONFIG_HIBERNATION
 #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
  *	acpi_pm_device_sleep_state - return preferred power state of ACPI device
  *		in the system sleep state given by %acpi_target_sleep_state
  *		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
  *	@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
  *	Return value: preferred power state of the device on success, -ENODEV on
  *		failure (ie. if there's no 'struct acpi_device' for @dev)
  *		failure (ie. if there's no 'struct acpi_device' for @dev)
@@ -387,7 +358,7 @@ int acpi_suspend(u32 acpi_state)
  *	via @wake.
  *	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);
 	acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
 	struct acpi_device *adev;
 	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.
 	 * can wake the system.  _S0W may be valid, too.
 	 */
 	 */
 	if (acpi_target_sleep_state == ACPI_STATE_S0 ||
 	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)) {
 	     adev->wakeup.sleep_state <= acpi_target_sleep_state)) {
 		acpi_status status;
 		acpi_status status;
 
 
@@ -472,8 +443,6 @@ int __init acpi_sleep_init(void)
 	u8 type_a, type_b;
 	u8 type_a, type_b;
 #ifdef CONFIG_SUSPEND
 #ifdef CONFIG_SUSPEND
 	int i = 0;
 	int i = 0;
-
-	dmi_check_system(acpisleep_dmi_table);
 #endif
 #endif
 
 
 	if (acpi_disabled)
 	if (acpi_disabled)

+ 156 - 13
drivers/acpi/system.c

@@ -167,7 +167,13 @@ static int acpi_system_sysfs_init(void)
 #define COUNT_ERROR 2	/* other */
 #define COUNT_ERROR 2	/* other */
 #define NUM_COUNTERS_EXTRA 3
 #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_gpes;
 static u32 num_counters;
 static u32 num_counters;
 static struct attribute **all_attrs;
 static struct attribute **all_attrs;
@@ -202,9 +208,44 @@ static int count_num_gpes(void)
 	return count;
 	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)
 static void delete_gpe_attr_array(void)
 {
 {
-	u32 *tmp = all_counters;
+	struct event_counter *tmp = all_counters;
 
 
 	all_counters = NULL;
 	all_counters = NULL;
 	kfree(tmp);
 	kfree(tmp);
@@ -230,9 +271,10 @@ void acpi_os_gpe_count(u32 gpe_number)
 		return;
 		return;
 
 
 	if (gpe_number < num_gpes)
 	if (gpe_number < num_gpes)
-		all_counters[gpe_number]++;
+		all_counters[gpe_number].count++;
 	else
 	else
-		all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR]++;
+		all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR].
+					count++;
 
 
 	return;
 	return;
 }
 }
@@ -243,44 +285,144 @@ void acpi_os_fixed_event_count(u32 event_number)
 		return;
 		return;
 
 
 	if (event_number < ACPI_NUM_FIXED_EVENTS)
 	if (event_number < ACPI_NUM_FIXED_EVENTS)
-		all_counters[num_gpes + event_number]++;
+		all_counters[num_gpes + event_number].count++;
 	else
 	else
-		all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR]++;
+		all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR].
+				count++;
 
 
 	return;
 	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,
 static ssize_t counter_show(struct kobject *kobj,
 	struct kobj_attribute *attr, char *buf)
 	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;
 		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;
 		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.
  * counter_set() sets the specified counter.
  * setting the total "sci" file to any value clears all counters.
  * 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,
 static ssize_t counter_set(struct kobject *kobj,
 	struct kobj_attribute *attr, const char *buf, size_t size)
 	struct kobj_attribute *attr, const char *buf, size_t size)
 {
 {
 	int index = attr - counter_attrs;
 	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) {
 	if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) {
 		int i;
 		int i;
 		for (i = 0; i < num_counters; ++i)
 		for (i = 0; i < num_counters; ++i)
-			all_counters[i] = 0;
+			all_counters[i].count = 0;
 		acpi_gpe_count = 0;
 		acpi_gpe_count = 0;
 		acpi_irq_handled = 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
 	} 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)
 void acpi_irq_stats_init(void)
@@ -298,7 +440,8 @@ void acpi_irq_stats_init(void)
 	if (all_attrs == NULL)
 	if (all_attrs == NULL)
 		return;
 		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)
 	if (all_counters == NULL)
 		goto fail;
 		goto fail;
 
 

+ 14 - 9
drivers/acpi/tables/tbfadt.c

@@ -124,7 +124,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
 
 
 static void inline
 static void inline
 acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
 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 */
 	/* All other fields are byte-wide */
 
 
 	generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO;
 	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->bit_offset = 0;
 	generic_address->access_width = 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;
 	u32 length;
 	struct acpi_table_header *table;
 	struct acpi_table_header *table;
@@ -280,7 +280,7 @@ static void acpi_tb_convert_fadt(void)
 {
 {
 	u8 pm1_register_length;
 	u8 pm1_register_length;
 	struct acpi_generic_address *target;
 	struct acpi_generic_address *target;
-	acpi_native_uint i;
+	u32 i;
 
 
 	/* Update the local FADT table header length */
 	/* 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
 	 * The PM event blocks are split into two register blocks, first is the
 	 * PM Status Register block, followed immediately by the PM Enable Register
 	 * 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 */
 	/* 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 */
 	/* The PM1B register block is optional, ignore if not present */
 
 
 	if (acpi_gbl_FADT.xpm1b_event_block.address) {
 	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,
 		acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
 					     pm1_register_length,
 					     pm1_register_length,
 					     (acpi_gbl_FADT.xpm1b_event_block.
 					     (acpi_gbl_FADT.xpm1b_event_block.
 					      address + pm1_register_length));
 					      address + pm1_register_length));
 		/* Don't forget to copy space_id of the GAS */
 		/* Don't forget to copy space_id of the GAS */
 		acpi_gbl_xpm1b_enable.space_id =
 		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;
 	u32 *address32;
 	struct acpi_generic_address *address64;
 	struct acpi_generic_address *address64;
 	u8 length;
 	u8 length;
-	acpi_native_uint i;
+	u32 i;
 
 
 	/* Examine all of the 64-bit extended address fields (X fields) */
 	/* Examine all of the 64-bit extended address fields (X fields) */
 
 

+ 2 - 3
drivers/acpi/tables/tbfind.c

@@ -65,10 +65,9 @@ ACPI_MODULE_NAME("tbfind")
  ******************************************************************************/
  ******************************************************************************/
 acpi_status
 acpi_status
 acpi_tb_find_table(char *signature,
 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;
 	acpi_status status;
 	struct acpi_table_header header;
 	struct acpi_table_header header;
 
 

+ 14 - 16
drivers/acpi/tables/tbinstal.c

@@ -107,11 +107,10 @@ acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc)
  ******************************************************************************/
  ******************************************************************************/
 
 
 acpi_status
 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_status status = AE_OK;
 
 
 	ACPI_FUNCTION_TRACE(tb_add_table);
 	ACPI_FUNCTION_TRACE(tb_add_table);
@@ -207,8 +206,8 @@ acpi_status acpi_tb_resize_root_table_list(void)
 
 
 	/* Increase the Table Array size */
 	/* 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));
 				      * sizeof(struct acpi_table_desc));
 	if (!tables) {
 	if (!tables) {
 		ACPI_ERROR((AE_INFO,
 		ACPI_ERROR((AE_INFO,
@@ -220,7 +219,7 @@ acpi_status acpi_tb_resize_root_table_list(void)
 
 
 	if (acpi_gbl_root_table_list.tables) {
 	if (acpi_gbl_root_table_list.tables) {
 		ACPI_MEMCPY(tables, 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));
 			    sizeof(struct acpi_table_desc));
 
 
 		if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
 		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_status
 acpi_tb_store_table(acpi_physical_address address,
 acpi_tb_store_table(acpi_physical_address address,
 		    struct acpi_table_header *table,
 		    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;
 	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)
 void acpi_tb_terminate(void)
 {
 {
-	acpi_native_uint i;
+	u32 i;
 
 
 	ACPI_FUNCTION_TRACE(tb_terminate);
 	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;
 	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;
 	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;
 	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;
 	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;
 	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);
 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);

+ 7 - 8
drivers/acpi/tables/tbutils.c

@@ -49,8 +49,8 @@ ACPI_MODULE_NAME("tbutils")
 
 
 /* Local prototypes */
 /* Local prototypes */
 static acpi_physical_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);
+
 /*******************************************************************************
 /*******************************************************************************
  *
  *
  * FUNCTION:    acpi_tb_check_xsdt
  * 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 sum = 0;
 	u8 *end = buffer + length;
 	u8 *end = buffer + length;
@@ -268,7 +268,7 @@ u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length)
 
 
 void
 void
 acpi_tb_install_table(acpi_physical_address address,
 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;
 	struct acpi_table_header *table;
 
 
@@ -336,8 +336,7 @@ acpi_tb_install_table(acpi_physical_address address,
  ******************************************************************************/
  ******************************************************************************/
 
 
 static acpi_physical_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;
 	u64 address64;
 
 
@@ -395,8 +394,8 @@ acpi_status __init
 acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
 acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
 {
 {
 	struct acpi_table_rsdp *rsdp;
 	struct acpi_table_rsdp *rsdp;
-	acpi_native_uint table_entry_size;
-	acpi_native_uint i;
+	u32 table_entry_size;
+	u32 i;
 	u32 table_count;
 	u32 table_count;
 	struct acpi_table_header *table;
 	struct acpi_table_header *table;
 	acpi_physical_address address;
 	acpi_physical_address address;

+ 13 - 15
drivers/acpi/tables/tbxface.c

@@ -125,7 +125,7 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array,
 		/* Root Table Array has been statically allocated by the host */
 		/* Root Table Array has been statically allocated by the host */
 
 
 		ACPI_MEMSET(initial_table_array, 0,
 		ACPI_MEMSET(initial_table_array, 0,
-			    initial_table_count *
+			    (acpi_size) initial_table_count *
 			    sizeof(struct acpi_table_desc));
 			    sizeof(struct acpi_table_desc));
 
 
 		acpi_gbl_root_table_list.tables = initial_table_array;
 		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);
 		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 */
 	/* 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 acpi_load_table(struct acpi_table_header *table_ptr)
 {
 {
 	acpi_status status;
 	acpi_status status;
-	acpi_native_uint table_index;
+	u32 table_index;
 	struct acpi_table_desc table_desc;
 	struct acpi_table_desc table_desc;
 
 
 	if (!table_ptr)
 	if (!table_ptr)
@@ -264,11 +264,10 @@ ACPI_EXPORT_SYMBOL(acpi_load_table)
  *****************************************************************************/
  *****************************************************************************/
 acpi_status
 acpi_status
 acpi_get_table_header(char *signature,
 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;
 	struct acpi_table_header *header;
 
 
 	/* Parameter validation */
 	/* Parameter validation */
@@ -378,10 +377,10 @@ ACPI_EXPORT_SYMBOL(acpi_unload_table_id)
  *****************************************************************************/
  *****************************************************************************/
 acpi_status
 acpi_status
 acpi_get_table(char *signature,
 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;
 	acpi_status status;
 
 
 	/* Parameter validation */
 	/* Parameter validation */
@@ -435,8 +434,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_table)
  *
  *
  ******************************************************************************/
  ******************************************************************************/
 acpi_status
 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;
 	acpi_status status;
 
 
@@ -493,7 +491,7 @@ static acpi_status acpi_tb_load_namespace(void)
 {
 {
 	acpi_status status;
 	acpi_status status;
 	struct acpi_table_header *table;
 	struct acpi_table_header *table;
-	acpi_native_uint i;
+	u32 i;
 
 
 	ACPI_FUNCTION_TRACE(tb_load_namespace);
 	ACPI_FUNCTION_TRACE(tb_load_namespace);
 
 

+ 2 - 2
drivers/acpi/tables/tbxfroot.c

@@ -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 *table_ptr;
 	u8 *mem_rover;
 	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
 		 * 1b) Search EBDA paragraphs (EBDA is required to be a
 		 *     minimum of 1_k length)
 		 *     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,
 					       physical_address,
 					       ACPI_EBDA_WINDOW_SIZE);
 					       ACPI_EBDA_WINDOW_SIZE);
 		if (!table_ptr) {
 		if (!table_ptr) {

+ 3 - 2
drivers/acpi/utilities/utalloc.c

@@ -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;
 	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,
 void *acpi_ut_allocate_zeroed(acpi_size size,
-			      u32 component, char *module, u32 line)
+			      u32 component, const char *module, u32 line)
 {
 {
 	void *allocation;
 	void *allocation;
 
 

+ 2 - 2
drivers/acpi/utilities/utcopy.c

@@ -572,7 +572,7 @@ acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
 	acpi_status status = AE_OK;
 	acpi_status status = AE_OK;
 	union acpi_operand_object *package_object;
 	union acpi_operand_object *package_object;
 	union acpi_operand_object **package_elements;
 	union acpi_operand_object **package_elements;
-	acpi_native_uint i;
+	u32 i;
 
 
 	ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage);
 	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 */
 			/* Truncate package and delete it */
 
 
-			package_object->package.count = (u32) i;
+			package_object->package.count = i;
 			package_elements[i] = NULL;
 			package_elements[i] = NULL;
 			acpi_ut_remove_reference(package_object);
 			acpi_ut_remove_reference(package_object);
 			return_ACPI_STATUS(status);
 			return_ACPI_STATUS(status);

+ 33 - 21
drivers/acpi/utilities/utdebug.c

@@ -157,7 +157,8 @@ void ACPI_INTERNAL_VAR_XFACE
 acpi_ut_debug_print(u32 requested_debug_level,
 acpi_ut_debug_print(u32 requested_debug_level,
 		    u32 line_number,
 		    u32 line_number,
 		    const char *function_name,
 		    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;
 	acpi_thread_id thread_id;
 	va_list args;
 	va_list args;
@@ -228,7 +229,8 @@ void ACPI_INTERNAL_VAR_XFACE
 acpi_ut_debug_print_raw(u32 requested_debug_level,
 acpi_ut_debug_print_raw(u32 requested_debug_level,
 			u32 line_number,
 			u32 line_number,
 			const char *function_name,
 			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;
 	va_list args;
 
 
@@ -261,7 +263,8 @@ ACPI_EXPORT_SYMBOL(acpi_ut_debug_print_raw)
  ******************************************************************************/
  ******************************************************************************/
 void
 void
 acpi_ut_trace(u32 line_number,
 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++;
 	acpi_gbl_nesting_level++;
@@ -293,7 +296,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_trace)
 void
 void
 acpi_ut_trace_ptr(u32 line_number,
 acpi_ut_trace_ptr(u32 line_number,
 		  const char *function_name,
 		  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_gbl_nesting_level++;
 	acpi_ut_track_stack_ptr();
 	acpi_ut_track_stack_ptr();
@@ -324,7 +327,7 @@ acpi_ut_trace_ptr(u32 line_number,
 void
 void
 acpi_ut_trace_str(u32 line_number,
 acpi_ut_trace_str(u32 line_number,
 		  const char *function_name,
 		  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++;
 	acpi_gbl_nesting_level++;
@@ -356,7 +359,7 @@ acpi_ut_trace_str(u32 line_number,
 void
 void
 acpi_ut_trace_u32(u32 line_number,
 acpi_ut_trace_u32(u32 line_number,
 		  const char *function_name,
 		  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++;
 	acpi_gbl_nesting_level++;
@@ -386,7 +389,8 @@ acpi_ut_trace_u32(u32 line_number,
 
 
 void
 void
 acpi_ut_exit(u32 line_number,
 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,
 	acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
@@ -417,7 +421,8 @@ ACPI_EXPORT_SYMBOL(acpi_ut_exit)
 void
 void
 acpi_ut_status_exit(u32 line_number,
 acpi_ut_status_exit(u32 line_number,
 		    const char *function_name,
 		    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)) {
 	if (ACPI_SUCCESS(status)) {
@@ -458,7 +463,8 @@ ACPI_EXPORT_SYMBOL(acpi_ut_status_exit)
 void
 void
 acpi_ut_value_exit(u32 line_number,
 acpi_ut_value_exit(u32 line_number,
 		   const char *function_name,
 		   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,
 	acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
@@ -490,7 +496,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_value_exit)
 void
 void
 acpi_ut_ptr_exit(u32 line_number,
 acpi_ut_ptr_exit(u32 line_number,
 		 const char *function_name,
 		 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,
 	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)
 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;
 	u32 temp32;
 	u8 buf_char;
 	u8 buf_char;
 
 
@@ -539,7 +545,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
 
 
 		/* Print current offset */
 		/* Print current offset */
 
 
-		acpi_os_printf("%6.4X: ", (u32) i);
+		acpi_os_printf("%6.4X: ", i);
 
 
 		/* Print 16 hex chars */
 		/* Print 16 hex chars */
 
 
@@ -549,7 +555,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
 				/* Dump fill spaces */
 				/* Dump fill spaces */
 
 
 				acpi_os_printf("%*s", ((display * 2) + 1), " ");
 				acpi_os_printf("%*s", ((display * 2) + 1), " ");
-				j += (acpi_native_uint) display;
+				j += display;
 				continue;
 				continue;
 			}
 			}
 
 
@@ -557,32 +563,38 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
 			case DB_BYTE_DISPLAY:
 			case DB_BYTE_DISPLAY:
 			default:	/* Default is BYTE display */
 			default:	/* Default is BYTE display */
 
 
-				acpi_os_printf("%02X ", buffer[i + j]);
+				acpi_os_printf("%02X ",
+					       buffer[(acpi_size) i + j]);
 				break;
 				break;
 
 
 			case DB_WORD_DISPLAY:
 			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);
 				acpi_os_printf("%04X ", temp32);
 				break;
 				break;
 
 
 			case DB_DWORD_DISPLAY:
 			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);
 				acpi_os_printf("%08X ", temp32);
 				break;
 				break;
 
 
 			case DB_QWORD_DISPLAY:
 			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_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);
 				acpi_os_printf("%08X ", temp32);
 				break;
 				break;
 			}
 			}
 
 
-			j += (acpi_native_uint) display;
+			j += display;
 		}
 		}
 
 
 		/*
 		/*
@@ -596,7 +608,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
 				return;
 				return;
 			}
 			}
 
 
-			buf_char = buffer[i + j];
+			buf_char = buffer[(acpi_size) i + j];
 			if (ACPI_IS_PRINT(buf_char)) {
 			if (ACPI_IS_PRINT(buf_char)) {
 				acpi_os_printf("%c", buf_char);
 				acpi_os_printf("%c", buf_char);
 			} else {
 			} else {

+ 1 - 1
drivers/acpi/utilities/utdelete.c

@@ -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_generic_state *state_list = NULL;
 	union acpi_operand_object *next_object = NULL;
 	union acpi_operand_object *next_object = NULL;
 	union acpi_generic_state *state;
 	union acpi_generic_state *state;
-	acpi_native_uint i;
+	u32 i;
 
 
 	ACPI_FUNCTION_TRACE_PTR(ut_update_object_reference, object);
 	ACPI_FUNCTION_TRACE_PTR(ut_update_object_reference, object);
 
 

+ 2 - 3
drivers/acpi/utilities/uteval.c

@@ -97,7 +97,7 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
 	acpi_status status;
 	acpi_status status;
 	union acpi_operand_object *string_desc;
 	union acpi_operand_object *string_desc;
 	union acpi_operand_object *return_desc;
 	union acpi_operand_object *return_desc;
-	acpi_native_uint i;
+	u32 i;
 
 
 	ACPI_FUNCTION_TRACE(ut_osi_implementation);
 	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->prefix_node = prefix_node;
 	info->pathname = path;
 	info->pathname = path;
-	info->parameter_type = ACPI_PARAM_ARGS;
 
 
 	/* Evaluate the object/method */
 	/* Evaluate the object/method */
 
 
@@ -514,7 +513,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node * device_node,
 	u32 count;
 	u32 count;
 	u32 size;
 	u32 size;
 	struct acpi_compatible_id_list *cid_list;
 	struct acpi_compatible_id_list *cid_list;
-	acpi_native_uint i;
+	u32 i;
 
 
 	ACPI_FUNCTION_TRACE(ut_execute_CID);
 	ACPI_FUNCTION_TRACE(ut_execute_CID);
 
 

+ 18 - 21
drivers/acpi/utilities/utmisc.c

@@ -64,7 +64,7 @@ ACPI_MODULE_NAME("utmisc")
  ******************************************************************************/
  ******************************************************************************/
 const char *acpi_ut_validate_exception(acpi_status status)
 const char *acpi_ut_validate_exception(acpi_status status)
 {
 {
-	acpi_status sub_status;
+	u32 sub_status;
 	const char *exception = NULL;
 	const char *exception = NULL;
 
 
 	ACPI_FUNCTION_ENTRY();
 	ACPI_FUNCTION_ENTRY();
@@ -85,32 +85,28 @@ const char *acpi_ut_validate_exception(acpi_status status)
 	case AE_CODE_PROGRAMMER:
 	case AE_CODE_PROGRAMMER:
 
 
 		if (sub_status <= AE_CODE_PGM_MAX) {
 		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;
 		break;
 
 
 	case AE_CODE_ACPI_TABLES:
 	case AE_CODE_ACPI_TABLES:
 
 
 		if (sub_status <= AE_CODE_TBL_MAX) {
 		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;
 		break;
 
 
 	case AE_CODE_AML:
 	case AE_CODE_AML:
 
 
 		if (sub_status <= AE_CODE_AML_MAX) {
 		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;
 		break;
 
 
 	case AE_CODE_CONTROL:
 	case AE_CODE_CONTROL:
 
 
 		if (sub_status <= AE_CODE_CTRL_MAX) {
 		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;
 		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_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_status status;
 
 
 	ACPI_FUNCTION_TRACE(ut_allocate_owner_id);
 	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_owner_id owner_id = *owner_id_ptr;
 	acpi_status status;
 	acpi_status status;
-	acpi_native_uint index;
+	u32 index;
 	u32 bit;
 	u32 bit;
 
 
 	ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id);
 	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') ||
 	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)
 u8 acpi_ut_valid_acpi_name(u32 name)
 {
 {
-	acpi_native_uint i;
+	u32 i;
 
 
 	ACPI_FUNCTION_ENTRY();
 	ACPI_FUNCTION_ENTRY();
 
 
@@ -657,7 +653,7 @@ u8 acpi_ut_valid_acpi_name(u32 name)
 
 
 acpi_name acpi_ut_repair_name(char *name)
 acpi_name acpi_ut_repair_name(char *name)
 {
 {
-	acpi_native_uint i;
+       u32 i;
 	char new_name[ACPI_NAME_SIZE];
 	char new_name[ACPI_NAME_SIZE];
 
 
 	for (i = 0; i < ACPI_NAME_SIZE; i++) {
 	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
 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;
 	va_list args;
 
 
@@ -1037,8 +1033,8 @@ acpi_ut_error(char *module_name, u32 line_number, char *format, ...)
 }
 }
 
 
 void ACPI_INTERNAL_VAR_XFACE
 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;
 	va_list args;
 
 
@@ -1054,7 +1050,8 @@ acpi_ut_exception(char *module_name,
 EXPORT_SYMBOL(acpi_ut_exception);
 EXPORT_SYMBOL(acpi_ut_exception);
 
 
 void ACPI_INTERNAL_VAR_XFACE
 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;
 	va_list args;
 
 
@@ -1067,7 +1064,7 @@ acpi_ut_warning(char *module_name, u32 line_number, char *format, ...)
 }
 }
 
 
 void ACPI_INTERNAL_VAR_XFACE
 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;
 	va_list args;
 
 

+ 2 - 2
drivers/acpi/utilities/utmutex.c

@@ -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 mutex ordering rule.  This indicates a coding error somewhere in
 		 * the ACPI subsystem code.
 		 * 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 (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
 				if (i == mutex_id) {
 				if (i == mutex_id) {
 					ACPI_ERROR((AE_INFO,
 					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
 		 * ordering rule.  This indicates a coding error somewhere in
 		 * the ACPI subsystem code.
 		 * 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 (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
 				if (i == mutex_id) {
 				if (i == mutex_id) {
 					continue;
 					continue;

+ 5 - 4
drivers/acpi/utilities/utobject.c

@@ -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 line_number,
 							      u32 component_id,
 							      u32 component_id,
 							      acpi_object_type
 							      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
 	 * Create the element array. Count+1 allows the array to be null
 	 * terminated.
 	 * 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) {
 	if (!package_elements) {
 		acpi_ut_remove_reference(package_desc);
 		acpi_ut_remove_reference(package_desc);
 		return_PTR(NULL);
 		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)
 				       u32 line_number, u32 component_id)
 {
 {
 	union acpi_operand_object *object;
 	union acpi_operand_object *object;

+ 73 - 50
drivers/acpi/video.c

@@ -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, ..)
  *  	device	: video output device (LCD, CRT, ..)
  *
  *
  *  Return Value:
  *  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
  *  	None
  *
  *
  *  Find out all required AML methods defined under the output
  *  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)
 static void acpi_video_device_find_cap(struct acpi_video_device *device)
 {
 {
 	acpi_handle h_dummy1;
 	acpi_handle h_dummy1;
-	int i;
 	u32 max_level = 0;
 	u32 max_level = 0;
-	union acpi_object *obj = NULL;
-	struct acpi_video_device_brightness *br = NULL;
 
 
 
 
 	memset(&device->cap, 0, sizeof(device->cap));
 	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;
 		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){
 	if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){
 		int result;
 		int result;
@@ -1695,6 +1716,8 @@ static void
 acpi_video_switch_brightness(struct acpi_video_device *device, int event)
 acpi_video_switch_brightness(struct acpi_video_device *device, int event)
 {
 {
 	unsigned long level_current, level_next;
 	unsigned long level_current, level_next;
+	if (!device->brightness)
+		return;
 	acpi_video_device_lcd_get_level_current(device, &level_current);
 	acpi_video_device_lcd_get_level_current(device, &level_current);
 	level_next = acpi_video_get_next_level(device, level_current, event);
 	level_next = acpi_video_get_next_level(device, level_current, event);
 	acpi_video_device_lcd_set_level(device, level_next);
 	acpi_video_device_lcd_set_level(device, level_next);

+ 207 - 139
drivers/char/apm-emulation.c

@@ -58,6 +58,55 @@ struct apm_queue {
 	apm_event_t		events[APM_MAX_EVENTS];
 	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
  * The per-file APM data
  */
  */
@@ -69,13 +118,7 @@ struct apm_user {
 	unsigned int		reader: 1;
 	unsigned int		reader: 1;
 
 
 	int			suspend_result;
 	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;
 	struct apm_queue	queue;
 };
 };
@@ -83,7 +126,8 @@ struct apm_user {
 /*
 /*
  * Local variables
  * 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 int apm_disabled;
 static struct task_struct *kapmd_tsk;
 static struct task_struct *kapmd_tsk;
 
 
@@ -166,78 +210,6 @@ static void queue_event(apm_event_t event)
 	wake_up_interruptible(&apm_waitqueue);
 	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)
 static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
 {
 {
 	struct apm_user *as = fp->private_data;
 	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;
 		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,
 			 * If we read a suspend command from /dev/apm_bios,
 			 * then the corresponding APM_IOC_SUSPEND ioctl is
 			 * then the corresponding APM_IOC_SUSPEND ioctl is
 			 * interpreted as an acknowledge.
 			 * interpreted as an acknowledge.
 			 */
 			 */
 			as->suspend_state = SUSPEND_ACKED;
 			as->suspend_state = SUSPEND_ACKED;
-			suspends_pending--;
-			pending = suspends_pending == 0;
+			atomic_dec(&suspend_acks_pending);
 			mutex_unlock(&state_lock);
 			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
 			 * 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
 			 * try_to_freeze() in freezer_count() will not trigger
 			 */
 			 */
 			freezer_count();
 			freezer_count();
-		} else {
+			break;
+		case SUSPEND_ACKTO:
+			as->suspend_result = -ETIMEDOUT;
+			mutex_unlock(&state_lock);
+			break;
+		default:
 			as->suspend_state = SUSPEND_WAIT;
 			as->suspend_state = SUSPEND_WAIT;
 			mutex_unlock(&state_lock);
 			mutex_unlock(&state_lock);
 
 
 			/*
 			/*
 			 * Otherwise it is a request to suspend the system.
 			 * 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.
-			 */
-			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.
+			 * Just invoke pm_suspend(), we'll handle it from
+			 * there via the notifier.
 			 */
 			 */
-			wait_event_freezable(apm_suspend_waitqueue,
-					 as->suspend_state == SUSPEND_DONE);
+			as->suspend_result = pm_suspend(PM_SUSPEND_MEM);
 		}
 		}
 
 
 		mutex_lock(&state_lock);
 		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)
 static int apm_release(struct inode * inode, struct file * filp)
 {
 {
 	struct apm_user *as = filp->private_data;
 	struct apm_user *as = filp->private_data;
-	int pending = 0;
 
 
 	filp->private_data = NULL;
 	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
 	 * 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);
 	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);
 	mutex_unlock(&state_lock);
-	if (pending)
-		apm_suspend();
+
+	wake_up(&apm_suspend_waitqueue);
 
 
 	kfree(as);
 	kfree(as);
 	return 0;
 	return 0;
@@ -545,7 +496,6 @@ static int kapmd(void *arg)
 {
 {
 	do {
 	do {
 		apm_event_t event;
 		apm_event_t event;
-		int ret;
 
 
 		wait_event_interruptible(kapmd_wait,
 		wait_event_interruptible(kapmd_wait,
 				!queue_empty(&kapmd_queue) || kthread_should_stop());
 				!queue_empty(&kapmd_queue) || kthread_should_stop());
@@ -570,20 +520,13 @@ static int kapmd(void *arg)
 
 
 		case APM_USER_SUSPEND:
 		case APM_USER_SUSPEND:
 		case APM_SYS_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;
 			break;
 
 
 		case APM_CRITICAL_SUSPEND:
 		case APM_CRITICAL_SUSPEND:
-			apm_suspend();
+			atomic_inc(&userspace_notification_inhibit);
+			pm_suspend(PM_SUSPEND_MEM);
+			atomic_dec(&userspace_notification_inhibit);
 			break;
 			break;
 		}
 		}
 	} while (1);
 	} while (1);
@@ -591,6 +534,120 @@ static int kapmd(void *arg)
 	return 0;
 	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)
 static int __init apm_init(void)
 {
 {
 	int ret;
 	int ret;
@@ -604,7 +661,7 @@ static int __init apm_init(void)
 	if (IS_ERR(kapmd_tsk)) {
 	if (IS_ERR(kapmd_tsk)) {
 		ret = PTR_ERR(kapmd_tsk);
 		ret = PTR_ERR(kapmd_tsk);
 		kapmd_tsk = NULL;
 		kapmd_tsk = NULL;
-		return ret;
+		goto out;
 	}
 	}
 	wake_up_process(kapmd_tsk);
 	wake_up_process(kapmd_tsk);
 
 
@@ -613,16 +670,27 @@ static int __init apm_init(void)
 #endif
 #endif
 
 
 	ret = misc_register(&apm_device);
 	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;
 	return ret;
 }
 }
 
 
 static void __exit apm_exit(void)
 static void __exit apm_exit(void)
 {
 {
+	unregister_pm_notifier(&apm_notif_block);
 	misc_deregister(&apm_device);
 	misc_deregister(&apm_device);
 	remove_proc_entry("apm", NULL);
 	remove_proc_entry("apm", NULL);
 
 

+ 30 - 1
drivers/misc/Kconfig

@@ -179,17 +179,29 @@ config FUJITSU_LAPTOP
         tristate "Fujitsu Laptop Extras"
         tristate "Fujitsu Laptop Extras"
         depends on X86
         depends on X86
         depends on ACPI
         depends on ACPI
+	depends on INPUT
         depends on BACKLIGHT_CLASS_DEVICE
         depends on BACKLIGHT_CLASS_DEVICE
         ---help---
         ---help---
 	  This is a driver for laptops built by Fujitsu:
 	  This is a driver for laptops built by Fujitsu:
 
 
 	    * P2xxx/P5xxx/S6xxx/S7xxx series Lifebooks
 	    * P2xxx/P5xxx/S6xxx/S7xxx series Lifebooks
 	    * Possibly other Fujitsu laptop models
 	    * 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.
 	  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
 config TC1100_WMI
 	tristate "HP Compaq TC1100 Tablet WMI Extras (EXPERIMENTAL)"
 	tristate "HP Compaq TC1100 Tablet WMI Extras (EXPERIMENTAL)"
 	depends on X86 && !X86_64
 	depends on X86 && !X86_64
@@ -219,6 +231,23 @@ config MSI_LAPTOP
 
 
 	  If you have an MSI S270 laptop, say Y or M here.
 	  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
 config SONY_LAPTOP
 	tristate "Sony Laptop Extras"
 	tristate "Sony Laptop Extras"
 	depends on X86 && ACPI
 	depends on X86 && ACPI

+ 3 - 2
drivers/misc/Makefile

@@ -5,10 +5,11 @@ obj- := misc.o	# Dummy rule to force built-in.o to be made
 
 
 obj-$(CONFIG_IBM_ASM)		+= ibmasm/
 obj-$(CONFIG_IBM_ASM)		+= ibmasm/
 obj-$(CONFIG_HDPU_FEATURES)	+= hdpuftrs/
 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_ASUS_LAPTOP)	+= asus-laptop.o
 obj-$(CONFIG_EEEPC_LAPTOP)	+= eeepc-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_PWM)		+= atmel_pwm.o
 obj-$(CONFIG_ATMEL_SSC)		+= atmel-ssc.o
 obj-$(CONFIG_ATMEL_SSC)		+= atmel-ssc.o
 obj-$(CONFIG_ATMEL_TCLIB)	+= atmel_tclib.o
 obj-$(CONFIG_ATMEL_TCLIB)	+= atmel_tclib.o

+ 135 - 10
drivers/misc/acer-wmi.c

@@ -22,18 +22,18 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  */
 
 
-#define ACER_WMI_VERSION	"0.1"
-
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/dmi.h>
 #include <linux/dmi.h>
+#include <linux/fb.h>
 #include <linux/backlight.h>
 #include <linux/backlight.h>
 #include <linux/leds.h>
 #include <linux/leds.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
 #include <linux/i8042.h>
 #include <linux/i8042.h>
+#include <linux/debugfs.h>
 
 
 #include <acpi/acpi_drivers.h>
 #include <acpi/acpi_drivers.h>
 
 
@@ -87,6 +87,7 @@ struct acer_quirks {
  * Acer ACPI method GUIDs
  * Acer ACPI method GUIDs
  */
  */
 #define AMW0_GUID1		"67C3371D-95A3-4C37-BB61-DD47B491DAAB"
 #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_GUID1		"6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3"
 #define WMID_GUID2		"95764E09-FB56-4e83-B31A-37761F60994A"
 #define WMID_GUID2		"95764E09-FB56-4e83-B31A-37761F60994A"
 
 
@@ -150,6 +151,12 @@ struct acer_data {
 	int brightness;
 	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 */
 /* Each low-level interface must define at least some of the following */
 struct wmi_interface {
 struct wmi_interface {
 	/* The WMI device type */
 	/* The WMI device type */
@@ -160,6 +167,9 @@ struct wmi_interface {
 
 
 	/* Private data for the current interface */
 	/* Private data for the current interface */
 	struct acer_data data;
 	struct acer_data data;
+
+	/* debugfs entries associated with this interface */
+	struct acer_debug debug;
 };
 };
 
 
 /* The static interface pointer, points to the currently detected interface */
 /* The static interface pointer, points to the currently detected interface */
@@ -174,7 +184,7 @@ static struct wmi_interface *interface;
 struct quirk_entry {
 struct quirk_entry {
 	u8 wireless;
 	u8 wireless;
 	u8 mailled;
 	u8 mailled;
-	u8 brightness;
+	s8 brightness;
 	u8 bluetooth;
 	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_unknown = {
 };
 };
 
 
+static struct quirk_entry quirk_acer_aspire_1520 = {
+	.brightness = -1,
+};
+
 static struct quirk_entry quirk_acer_travelmate_2490 = {
 static struct quirk_entry quirk_acer_travelmate_2490 = {
 	.mailled = 1,
 	.mailled = 1,
 };
 };
@@ -207,7 +221,29 @@ static struct quirk_entry quirk_medion_md_98300 = {
 	.wireless = 1,
 	.wireless = 1,
 };
 };
 
 
+static struct quirk_entry quirk_fujitsu_amilo_li_1718 = {
+	.wireless = 2,
+};
+
 static struct dmi_system_id acer_quirks[] = {
 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,
 		.callback = dmi_matched,
 		.ident = "Acer Aspire 3100",
 		.ident = "Acer Aspire 3100",
@@ -298,6 +334,15 @@ static struct dmi_system_id acer_quirks[] = {
 		},
 		},
 		.driver_data = &quirk_acer_travelmate_2490,
 		.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,
 		.callback = dmi_matched,
 		.ident = "Medion MD 98300",
 		.ident = "Medion MD 98300",
@@ -393,6 +438,12 @@ struct wmi_interface *iface)
 				return AE_ERROR;
 				return AE_ERROR;
 			*value = result & 0x1;
 			*value = result & 0x1;
 			return AE_OK;
 			return AE_OK;
+		case 2:
+			err = ec_read(0x71, &result);
+			if (err)
+				return AE_ERROR;
+			*value = result & 0x1;
+			return AE_OK;
 		default:
 		default:
 			err = ec_read(0xA, &result);
 			err = ec_read(0xA, &result);
 			if (err)
 			if (err)
@@ -506,6 +557,15 @@ static acpi_status AMW0_set_capabilities(void)
 	struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
 	struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
 	union acpi_object *obj;
 	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.eax = ACER_AMW0_WRITE;
 	args.ecx = args.edx = 0;
 	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
 	 * appear to use the same EC register for brightness, even if they
 	 * differ for wireless, etc
 	 * differ for wireless, etc
 	 */
 	 */
-	interface->capability |= ACER_CAP_BRIGHTNESS;
+	if (quirks->brightness >= 0)
+		interface->capability |= ACER_CAP_BRIGHTNESS;
 
 
 	return AE_OK;
 	return AE_OK;
 }
 }
@@ -807,7 +868,15 @@ static int read_brightness(struct backlight_device *bd)
 
 
 static int update_bl_status(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;
 	return 0;
 }
 }
 
 
@@ -829,8 +898,9 @@ static int __devinit acer_backlight_init(struct device *dev)
 
 
 	acer_backlight_device = bd;
 	acer_backlight_device = bd;
 
 
+	bd->props.power = FB_BLANK_UNBLANK;
+	bd->props.brightness = max_brightness;
 	bd->props.max_brightness = max_brightness;
 	bd->props.max_brightness = max_brightness;
-	bd->props.brightness = read_brightness(NULL);
 	backlight_update_status(bd);
 	backlight_update_status(bd);
 	return 0;
 	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,
 static DEVICE_ATTR(interface, S_IWUGO | S_IRUGO | S_IWUSR,
 	show_interface, NULL);
 	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
  * Platform device
  */
  */
@@ -1052,12 +1144,40 @@ error_sysfs:
 	return retval;
 	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)
 static int __init acer_wmi_init(void)
 {
 {
 	int err;
 	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.
 	 * 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))
 	if (wmi_has_guid(AMW0_GUID1))
 		AMW0_find_mailled();
 		AMW0_find_mailled();
 
 
-	find_quirks();
-
 	if (!interface) {
 	if (!interface) {
 		printk(ACER_ERR "No or unsupported WMI interface, unable to "
 		printk(ACER_ERR "No or unsupported WMI interface, unable to "
 				"load\n");
 				"load\n");
@@ -1111,6 +1229,13 @@ static int __init acer_wmi_init(void)
 	if (err)
 	if (err)
 		return 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 */
 	/* Override any initial settings with values from the commandline */
 	acer_commandline_init();
 	acer_commandline_init();
 
 

+ 404 - 0
drivers/misc/compal-laptop.c

@@ -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:*");

+ 2 - 2
drivers/misc/eeepc-laptop.c

@@ -87,7 +87,7 @@ enum {
 	CM_ASL_LID
 	CM_ASL_LID
 };
 };
 
 
-const char *cm_getv[] = {
+static const char *cm_getv[] = {
 	"WLDG", NULL, NULL, NULL,
 	"WLDG", NULL, NULL, NULL,
 	"CAMG", NULL, NULL, NULL,
 	"CAMG", NULL, NULL, NULL,
 	NULL, "PBLG", NULL, NULL,
 	NULL, "PBLG", NULL, NULL,
@@ -96,7 +96,7 @@ const char *cm_getv[] = {
 	"CRDG", "LIDG"
 	"CRDG", "LIDG"
 };
 };
 
 
-const char *cm_setv[] = {
+static const char *cm_setv[] = {
 	"WLDS", NULL, NULL, NULL,
 	"WLDS", NULL, NULL, NULL,
 	"CAMS", NULL, NULL, NULL,
 	"CAMS", NULL, NULL, NULL,
 	"SDSP", "PBLS", "HDPS", NULL,
 	"SDSP", "PBLS", "HDPS", NULL,

+ 774 - 51
drivers/misc/fujitsu-laptop.c

@@ -1,12 +1,14 @@
 /*-*-linux-c-*-*/
 /*-*-linux-c-*-*/
 
 
 /*
 /*
-  Copyright (C) 2007 Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
+  Copyright (C) 2007,2008 Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
+  Copyright (C) 2008 Peter Gruber <nokos@gmx.net>
   Based on earlier work:
   Based on earlier work:
     Copyright (C) 2003 Shane Spencer <shane@bogomip.com>
     Copyright (C) 2003 Shane Spencer <shane@bogomip.com>
     Adrian Yee <brewt-fujitsu@brewt.org>
     Adrian Yee <brewt-fujitsu@brewt.org>
 
 
-  Templated from msi-laptop.c which is copyright by its respective authors.
+  Templated from msi-laptop.c and thinkpad_acpi.c which is copyright
+  by its respective authors.
 
 
   This program is free software; you can redistribute it and/or modify
   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
   it under the terms of the GNU General Public License as published by
@@ -39,8 +41,17 @@
  * registers itself in the Linux backlight control subsystem and is
  * registers itself in the Linux backlight control subsystem and is
  * available to userspace under /sys/class/backlight/fujitsu-laptop/.
  * available to userspace under /sys/class/backlight/fujitsu-laptop/.
  *
  *
- * This driver has been tested on a Fujitsu Lifebook S7020.  It should
- * work on most P-series and S-series Lifebooks, but YMMV.
+ * Hotkeys present on certain Fujitsu laptops (eg: the S6xxx series) are
+ * also supported by this driver.
+ *
+ * This driver has been tested on a Fujitsu Lifebook S6410 and S7020.  It
+ * should work on most P-series and S-series Lifebooks, but YMMV.
+ *
+ * The module parameter use_alt_lcd_levels switches between different ACPI
+ * brightness controls which are used by different Fujitsu laptops.  In most
+ * cases the correct method is automatically detected. "use_alt_lcd_levels=1"
+ * is applicable for a Fujitsu Lifebook S6410 if autodetection fails.
+ *
  */
  */
 
 
 #include <linux/module.h>
 #include <linux/module.h>
@@ -49,30 +60,105 @@
 #include <linux/acpi.h>
 #include <linux/acpi.h>
 #include <linux/dmi.h>
 #include <linux/dmi.h>
 #include <linux/backlight.h>
 #include <linux/backlight.h>
+#include <linux/input.h>
+#include <linux/kfifo.h>
+#include <linux/video_output.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 
 
-#define FUJITSU_DRIVER_VERSION "0.3"
+#define FUJITSU_DRIVER_VERSION "0.4.2"
 
 
 #define FUJITSU_LCD_N_LEVELS 8
 #define FUJITSU_LCD_N_LEVELS 8
 
 
 #define ACPI_FUJITSU_CLASS              "fujitsu"
 #define ACPI_FUJITSU_CLASS              "fujitsu"
 #define ACPI_FUJITSU_HID                "FUJ02B1"
 #define ACPI_FUJITSU_HID                "FUJ02B1"
-#define ACPI_FUJITSU_DRIVER_NAME        "Fujitsu laptop FUJ02B1 ACPI extras driver"
+#define ACPI_FUJITSU_DRIVER_NAME	"Fujitsu laptop FUJ02B1 ACPI brightness driver"
 #define ACPI_FUJITSU_DEVICE_NAME        "Fujitsu FUJ02B1"
 #define ACPI_FUJITSU_DEVICE_NAME        "Fujitsu FUJ02B1"
-
+#define ACPI_FUJITSU_HOTKEY_HID 	"FUJ02E3"
+#define ACPI_FUJITSU_HOTKEY_DRIVER_NAME "Fujitsu laptop FUJ02E3 ACPI hotkeys driver"
+#define ACPI_FUJITSU_HOTKEY_DEVICE_NAME "Fujitsu FUJ02E3"
+
+#define ACPI_FUJITSU_NOTIFY_CODE1     0x80
+
+#define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS     0x86
+#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS     0x87
+
+/* Hotkey details */
+#define LOCK_KEY	0x410	/* codes for the keys in the GIRB register */
+#define DISPLAY_KEY	0x411	/* keys are mapped to KEY_SCREENLOCK (the key with the key symbol) */
+#define ENERGY_KEY	0x412	/* KEY_MEDIA (the key with the laptop symbol, KEY_EMAIL (E key)) */
+#define REST_KEY	0x413	/* KEY_SUSPEND (R key) */
+
+#define MAX_HOTKEY_RINGBUFFER_SIZE 100
+#define RINGBUFFERSIZE 40
+
+/* Debugging */
+#define FUJLAPTOP_LOG	   ACPI_FUJITSU_HID ": "
+#define FUJLAPTOP_ERR	   KERN_ERR FUJLAPTOP_LOG
+#define FUJLAPTOP_NOTICE   KERN_NOTICE FUJLAPTOP_LOG
+#define FUJLAPTOP_INFO	   KERN_INFO FUJLAPTOP_LOG
+#define FUJLAPTOP_DEBUG    KERN_DEBUG FUJLAPTOP_LOG
+
+#define FUJLAPTOP_DBG_ALL	  0xffff
+#define FUJLAPTOP_DBG_ERROR	  0x0001
+#define FUJLAPTOP_DBG_WARN	  0x0002
+#define FUJLAPTOP_DBG_INFO	  0x0004
+#define FUJLAPTOP_DBG_TRACE	  0x0008
+
+#define dbg_printk(a_dbg_level, format, arg...) \
+	do { if (dbg_level & a_dbg_level) \
+		printk(FUJLAPTOP_DEBUG "%s: " format, __func__ , ## arg); \
+	} while (0)
+#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
+#define vdbg_printk(a_dbg_level, format, arg...) \
+	dbg_printk(a_dbg_level, format, ## arg)
+#else
+#define vdbg_printk(a_dbg_level, format, arg...)
+#endif
+
+/* Device controlling the backlight and associated keys */
 struct fujitsu_t {
 struct fujitsu_t {
 	acpi_handle acpi_handle;
 	acpi_handle acpi_handle;
+	struct acpi_device *dev;
+	struct input_dev *input;
+	char phys[32];
 	struct backlight_device *bl_device;
 	struct backlight_device *bl_device;
 	struct platform_device *pf_device;
 	struct platform_device *pf_device;
 
 
-	unsigned long fuj02b1_state;
+	unsigned int max_brightness;
 	unsigned int brightness_changed;
 	unsigned int brightness_changed;
 	unsigned int brightness_level;
 	unsigned int brightness_level;
 };
 };
 
 
 static struct fujitsu_t *fujitsu;
 static struct fujitsu_t *fujitsu;
+static int use_alt_lcd_levels = -1;
+static int disable_brightness_keys = -1;
+static int disable_brightness_adjust = -1;
+
+/* Device used to access other hotkeys on the laptop */
+struct fujitsu_hotkey_t {
+	acpi_handle acpi_handle;
+	struct acpi_device *dev;
+	struct input_dev *input;
+	char phys[32];
+	struct platform_device *pf_device;
+	struct kfifo *fifo;
+	spinlock_t fifo_lock;
+
+	unsigned int irb;	/* info about the pressed buttons */
+};
 
 
-/* Hardware access */
+static struct fujitsu_hotkey_t *fujitsu_hotkey;
+
+static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
+				       void *data);
+
+#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
+static u32 dbg_level = 0x03;
+#endif
+
+static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data);
+
+/* Hardware access for LCD brightness control */
 
 
 static int set_lcd_level(int level)
 static int set_lcd_level(int level)
 {
 {
@@ -81,7 +167,10 @@ static int set_lcd_level(int level)
 	struct acpi_object_list arg_list = { 1, &arg0 };
 	struct acpi_object_list arg_list = { 1, &arg0 };
 	acpi_handle handle = NULL;
 	acpi_handle handle = NULL;
 
 
-	if (level < 0 || level >= FUJITSU_LCD_N_LEVELS)
+	vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBLL [%d]\n",
+		    level);
+
+	if (level < 0 || level >= fujitsu->max_brightness)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if (!fujitsu)
 	if (!fujitsu)
@@ -89,7 +178,38 @@ static int set_lcd_level(int level)
 
 
 	status = acpi_get_handle(fujitsu->acpi_handle, "SBLL", &handle);
 	status = acpi_get_handle(fujitsu->acpi_handle, "SBLL", &handle);
 	if (ACPI_FAILURE(status)) {
 	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SBLL not present\n"));
+		vdbg_printk(FUJLAPTOP_DBG_ERROR, "SBLL not present\n");
+		return -ENODEV;
+	}
+
+	arg0.integer.value = level;
+
+	status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	return 0;
+}
+
+static int set_lcd_level_alt(int level)
+{
+	acpi_status status = AE_OK;
+	union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+	struct acpi_object_list arg_list = { 1, &arg0 };
+	acpi_handle handle = NULL;
+
+	vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBL2 [%d]\n",
+		    level);
+
+	if (level < 0 || level >= fujitsu->max_brightness)
+		return -EINVAL;
+
+	if (!fujitsu)
+		return -EINVAL;
+
+	status = acpi_get_handle(fujitsu->acpi_handle, "SBL2", &handle);
+	if (ACPI_FAILURE(status)) {
+		vdbg_printk(FUJLAPTOP_DBG_ERROR, "SBL2 not present\n");
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
@@ -107,13 +227,52 @@ static int get_lcd_level(void)
 	unsigned long state = 0;
 	unsigned long state = 0;
 	acpi_status status = AE_OK;
 	acpi_status status = AE_OK;
 
 
-	// Get the Brightness
+	vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLL\n");
+
 	status =
 	status =
 	    acpi_evaluate_integer(fujitsu->acpi_handle, "GBLL", NULL, &state);
 	    acpi_evaluate_integer(fujitsu->acpi_handle, "GBLL", NULL, &state);
 	if (status < 0)
 	if (status < 0)
 		return status;
 		return status;
 
 
-	fujitsu->fuj02b1_state = state;
+	fujitsu->brightness_level = state & 0x0fffffff;
+
+	if (state & 0x80000000)
+		fujitsu->brightness_changed = 1;
+	else
+		fujitsu->brightness_changed = 0;
+
+	return fujitsu->brightness_level;
+}
+
+static int get_max_brightness(void)
+{
+	unsigned long state = 0;
+	acpi_status status = AE_OK;
+
+	vdbg_printk(FUJLAPTOP_DBG_TRACE, "get max lcd level via RBLL\n");
+
+	status =
+	    acpi_evaluate_integer(fujitsu->acpi_handle, "RBLL", NULL, &state);
+	if (status < 0)
+		return status;
+
+	fujitsu->max_brightness = state;
+
+	return fujitsu->max_brightness;
+}
+
+static int get_lcd_level_alt(void)
+{
+	unsigned long state = 0;
+	acpi_status status = AE_OK;
+
+	vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLS\n");
+
+	status =
+	    acpi_evaluate_integer(fujitsu->acpi_handle, "GBLS", NULL, &state);
+	if (status < 0)
+		return status;
+
 	fujitsu->brightness_level = state & 0x0fffffff;
 	fujitsu->brightness_level = state & 0x0fffffff;
 
 
 	if (state & 0x80000000)
 	if (state & 0x80000000)
@@ -128,12 +287,18 @@ static int get_lcd_level(void)
 
 
 static int bl_get_brightness(struct backlight_device *b)
 static int bl_get_brightness(struct backlight_device *b)
 {
 {
-	return get_lcd_level();
+	if (use_alt_lcd_levels)
+		return get_lcd_level_alt();
+	else
+		return get_lcd_level();
 }
 }
 
 
 static int bl_update_status(struct backlight_device *b)
 static int bl_update_status(struct backlight_device *b)
 {
 {
-	return set_lcd_level(b->props.brightness);
+	if (use_alt_lcd_levels)
+		return set_lcd_level_alt(b->props.brightness);
+	else
+		return set_lcd_level(b->props.brightness);
 }
 }
 
 
 static struct backlight_ops fujitsubl_ops = {
 static struct backlight_ops fujitsubl_ops = {
@@ -141,7 +306,35 @@ static struct backlight_ops fujitsubl_ops = {
 	.update_status = bl_update_status,
 	.update_status = bl_update_status,
 };
 };
 
 
-/* Platform device */
+/* Platform LCD brightness device */
+
+static ssize_t
+show_max_brightness(struct device *dev,
+		    struct device_attribute *attr, char *buf)
+{
+
+	int ret;
+
+	ret = get_max_brightness();
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%i\n", ret);
+}
+
+static ssize_t
+show_brightness_changed(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+
+	int ret;
+
+	ret = fujitsu->brightness_changed;
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%i\n", ret);
+}
 
 
 static ssize_t show_lcd_level(struct device *dev,
 static ssize_t show_lcd_level(struct device *dev,
 			      struct device_attribute *attr, char *buf)
 			      struct device_attribute *attr, char *buf)
@@ -149,7 +342,10 @@ static ssize_t show_lcd_level(struct device *dev,
 
 
 	int ret;
 	int ret;
 
 
-	ret = get_lcd_level();
+	if (use_alt_lcd_levels)
+		ret = get_lcd_level_alt();
+	else
+		ret = get_lcd_level();
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
@@ -164,19 +360,61 @@ static ssize_t store_lcd_level(struct device *dev,
 	int level, ret;
 	int level, ret;
 
 
 	if (sscanf(buf, "%i", &level) != 1
 	if (sscanf(buf, "%i", &level) != 1
-	    || (level < 0 || level >= FUJITSU_LCD_N_LEVELS))
+	    || (level < 0 || level >= fujitsu->max_brightness))
 		return -EINVAL;
 		return -EINVAL;
 
 
-	ret = set_lcd_level(level);
+	if (use_alt_lcd_levels)
+		ret = set_lcd_level_alt(level);
+	else
+		ret = set_lcd_level(level);
+	if (ret < 0)
+		return ret;
+
+	if (use_alt_lcd_levels)
+		ret = get_lcd_level_alt();
+	else
+		ret = get_lcd_level();
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
 	return count;
 	return count;
 }
 }
 
 
+/* Hardware access for hotkey device */
+
+static int get_irb(void)
+{
+	unsigned long state = 0;
+	acpi_status status = AE_OK;
+
+	vdbg_printk(FUJLAPTOP_DBG_TRACE, "Get irb\n");
+
+	status =
+	    acpi_evaluate_integer(fujitsu_hotkey->acpi_handle, "GIRB", NULL,
+				  &state);
+	if (status < 0)
+		return status;
+
+	fujitsu_hotkey->irb = state;
+
+	return fujitsu_hotkey->irb;
+}
+
+static ssize_t
+ignore_store(struct device *dev,
+	     struct device_attribute *attr, const char *buf, size_t count)
+{
+	return count;
+}
+
+static DEVICE_ATTR(max_brightness, 0444, show_max_brightness, ignore_store);
+static DEVICE_ATTR(brightness_changed, 0444, show_brightness_changed,
+		   ignore_store);
 static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level);
 static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level);
 
 
 static struct attribute *fujitsupf_attributes[] = {
 static struct attribute *fujitsupf_attributes[] = {
+	&dev_attr_brightness_changed.attr,
+	&dev_attr_max_brightness.attr,
 	&dev_attr_lcd_level.attr,
 	&dev_attr_lcd_level.attr,
 	NULL
 	NULL
 };
 };
@@ -192,14 +430,52 @@ static struct platform_driver fujitsupf_driver = {
 		   }
 		   }
 };
 };
 
 
-/* ACPI device */
+static int dmi_check_cb_s6410(const struct dmi_system_id *id)
+{
+	acpi_handle handle;
+	int have_blnf;
+	printk(KERN_INFO "fujitsu-laptop: Identified laptop model '%s'.\n",
+	       id->ident);
+	have_blnf = ACPI_SUCCESS
+	    (acpi_get_handle(NULL, "\\_SB.PCI0.GFX0.LCD.BLNF", &handle));
+	if (use_alt_lcd_levels == -1) {
+		vdbg_printk(FUJLAPTOP_DBG_TRACE, "auto-detecting usealt\n");
+		use_alt_lcd_levels = 1;
+	}
+	if (disable_brightness_keys == -1) {
+		vdbg_printk(FUJLAPTOP_DBG_TRACE,
+			    "auto-detecting disable_keys\n");
+		disable_brightness_keys = have_blnf ? 1 : 0;
+	}
+	if (disable_brightness_adjust == -1) {
+		vdbg_printk(FUJLAPTOP_DBG_TRACE,
+			    "auto-detecting disable_adjust\n");
+		disable_brightness_adjust = have_blnf ? 0 : 1;
+	}
+	return 0;
+}
+
+static struct dmi_system_id __initdata fujitsu_dmi_table[] = {
+	{
+	 .ident = "Fujitsu Siemens",
+	 .matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"),
+		     },
+	 .callback = dmi_check_cb_s6410},
+	{}
+};
+
+/* ACPI device for LCD brightness control */
 
 
 static int acpi_fujitsu_add(struct acpi_device *device)
 static int acpi_fujitsu_add(struct acpi_device *device)
 {
 {
+	acpi_status status;
+	acpi_handle handle;
 	int result = 0;
 	int result = 0;
 	int state = 0;
 	int state = 0;
-
-	ACPI_FUNCTION_TRACE("acpi_fujitsu_add");
+	struct input_dev *input;
+	int error;
 
 
 	if (!device)
 	if (!device)
 		return -EINVAL;
 		return -EINVAL;
@@ -209,10 +485,42 @@ static int acpi_fujitsu_add(struct acpi_device *device)
 	sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
 	sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
 	acpi_driver_data(device) = fujitsu;
 	acpi_driver_data(device) = fujitsu;
 
 
+	status = acpi_install_notify_handler(device->handle,
+					     ACPI_DEVICE_NOTIFY,
+					     acpi_fujitsu_notify, fujitsu);
+
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR "Error installing notify handler\n");
+		error = -ENODEV;
+		goto err_stop;
+	}
+
+	fujitsu->input = input = input_allocate_device();
+	if (!input) {
+		error = -ENOMEM;
+		goto err_uninstall_notify;
+	}
+
+	snprintf(fujitsu->phys, sizeof(fujitsu->phys),
+		 "%s/video/input0", acpi_device_hid(device));
+
+	input->name = acpi_device_name(device);
+	input->phys = fujitsu->phys;
+	input->id.bustype = BUS_HOST;
+	input->id.product = 0x06;
+	input->dev.parent = &device->dev;
+	input->evbit[0] = BIT(EV_KEY);
+	set_bit(KEY_BRIGHTNESSUP, input->keybit);
+	set_bit(KEY_BRIGHTNESSDOWN, input->keybit);
+	set_bit(KEY_UNKNOWN, input->keybit);
+
+	error = input_register_device(input);
+	if (error)
+		goto err_free_input_dev;
+
 	result = acpi_bus_get_power(fujitsu->acpi_handle, &state);
 	result = acpi_bus_get_power(fujitsu->acpi_handle, &state);
 	if (result) {
 	if (result) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Error reading power state\n"));
+		printk(KERN_ERR "Error reading power state\n");
 		goto end;
 		goto end;
 	}
 	}
 
 
@@ -220,22 +528,373 @@ static int acpi_fujitsu_add(struct acpi_device *device)
 	       acpi_device_name(device), acpi_device_bid(device),
 	       acpi_device_name(device), acpi_device_bid(device),
 	       !device->power.state ? "on" : "off");
 	       !device->power.state ? "on" : "off");
 
 
-      end:
+	fujitsu->dev = device;
+
+	if (ACPI_SUCCESS
+	    (acpi_get_handle(device->handle, METHOD_NAME__INI, &handle))) {
+		vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n");
+		if (ACPI_FAILURE
+		    (acpi_evaluate_object
+		     (device->handle, METHOD_NAME__INI, NULL, NULL)))
+			printk(KERN_ERR "_INI Method failed\n");
+	}
+
+	/* do config (detect defaults) */
+	dmi_check_system(fujitsu_dmi_table);
+	use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0;
+	disable_brightness_keys = disable_brightness_keys == 1 ? 1 : 0;
+	disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0;
+	vdbg_printk(FUJLAPTOP_DBG_INFO,
+		    "config: [alt interface: %d], [key disable: %d], [adjust disable: %d]\n",
+		    use_alt_lcd_levels, disable_brightness_keys,
+		    disable_brightness_adjust);
+
+	if (get_max_brightness() <= 0)
+		fujitsu->max_brightness = FUJITSU_LCD_N_LEVELS;
+	if (use_alt_lcd_levels)
+		get_lcd_level_alt();
+	else
+		get_lcd_level();
+
+	return result;
+
+end:
+err_free_input_dev:
+	input_free_device(input);
+err_uninstall_notify:
+	acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
+				   acpi_fujitsu_notify);
+err_stop:
 
 
 	return result;
 	return result;
 }
 }
 
 
 static int acpi_fujitsu_remove(struct acpi_device *device, int type)
 static int acpi_fujitsu_remove(struct acpi_device *device, int type)
 {
 {
-	ACPI_FUNCTION_TRACE("acpi_fujitsu_remove");
+	acpi_status status;
+	struct fujitsu_t *fujitsu = NULL;
 
 
 	if (!device || !acpi_driver_data(device))
 	if (!device || !acpi_driver_data(device))
 		return -EINVAL;
 		return -EINVAL;
+
+	fujitsu = acpi_driver_data(device);
+
+	status = acpi_remove_notify_handler(fujitsu->acpi_handle,
+					    ACPI_DEVICE_NOTIFY,
+					    acpi_fujitsu_notify);
+
+	if (!device || !acpi_driver_data(device))
+		return -EINVAL;
+
 	fujitsu->acpi_handle = NULL;
 	fujitsu->acpi_handle = NULL;
 
 
 	return 0;
 	return 0;
 }
 }
 
 
+/* Brightness notify */
+
+static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
+{
+	struct input_dev *input;
+	int keycode;
+	int oldb, newb;
+
+	input = fujitsu->input;
+
+	switch (event) {
+	case ACPI_FUJITSU_NOTIFY_CODE1:
+		keycode = 0;
+		oldb = fujitsu->brightness_level;
+		get_lcd_level();  /* the alt version always yields changed */
+		newb = fujitsu->brightness_level;
+
+		vdbg_printk(FUJLAPTOP_DBG_TRACE,
+			    "brightness button event [%i -> %i (%i)]\n",
+			    oldb, newb, fujitsu->brightness_changed);
+
+		if (oldb == newb && fujitsu->brightness_changed) {
+			keycode = 0;
+			if (disable_brightness_keys != 1) {
+				if (oldb == 0) {
+					acpi_bus_generate_proc_event(fujitsu->
+						dev,
+						ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS,
+						0);
+					keycode = KEY_BRIGHTNESSDOWN;
+				} else if (oldb ==
+					   (fujitsu->max_brightness) - 1) {
+					acpi_bus_generate_proc_event(fujitsu->
+						dev,
+						ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS,
+						0);
+					keycode = KEY_BRIGHTNESSUP;
+				}
+			}
+		} else if (oldb < newb) {
+			if (disable_brightness_adjust != 1) {
+				if (use_alt_lcd_levels)
+					set_lcd_level_alt(newb);
+				else
+					set_lcd_level(newb);
+			}
+			if (disable_brightness_keys != 1) {
+				acpi_bus_generate_proc_event(fujitsu->dev,
+					ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS,
+					0);
+				keycode = KEY_BRIGHTNESSUP;
+			}
+		} else if (oldb > newb) {
+			if (disable_brightness_adjust != 1) {
+				if (use_alt_lcd_levels)
+					set_lcd_level_alt(newb);
+				else
+					set_lcd_level(newb);
+			}
+			if (disable_brightness_keys != 1) {
+				acpi_bus_generate_proc_event(fujitsu->dev,
+					ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS,
+					0);
+				keycode = KEY_BRIGHTNESSDOWN;
+			}
+		} else {
+			keycode = KEY_UNKNOWN;
+		}
+		break;
+	default:
+		keycode = KEY_UNKNOWN;
+		vdbg_printk(FUJLAPTOP_DBG_WARN,
+			    "unsupported event [0x%x]\n", event);
+		break;
+	}
+
+	if (keycode != 0) {
+		input_report_key(input, keycode, 1);
+		input_sync(input);
+		input_report_key(input, keycode, 0);
+		input_sync(input);
+	}
+
+	return;
+}
+
+/* ACPI device for hotkey handling */
+
+static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
+{
+	acpi_status status;
+	acpi_handle handle;
+	int result = 0;
+	int state = 0;
+	struct input_dev *input;
+	int error;
+	int i;
+
+	if (!device)
+		return -EINVAL;
+
+	fujitsu_hotkey->acpi_handle = device->handle;
+	sprintf(acpi_device_name(device), "%s",
+		ACPI_FUJITSU_HOTKEY_DEVICE_NAME);
+	sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
+	acpi_driver_data(device) = fujitsu_hotkey;
+
+	status = acpi_install_notify_handler(device->handle,
+					     ACPI_DEVICE_NOTIFY,
+					     acpi_fujitsu_hotkey_notify,
+					     fujitsu_hotkey);
+
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR "Error installing notify handler\n");
+		error = -ENODEV;
+		goto err_stop;
+	}
+
+	/* kfifo */
+	spin_lock_init(&fujitsu_hotkey->fifo_lock);
+	fujitsu_hotkey->fifo =
+	    kfifo_alloc(RINGBUFFERSIZE * sizeof(int), GFP_KERNEL,
+			&fujitsu_hotkey->fifo_lock);
+	if (IS_ERR(fujitsu_hotkey->fifo)) {
+		printk(KERN_ERR "kfifo_alloc failed\n");
+		error = PTR_ERR(fujitsu_hotkey->fifo);
+		goto err_stop;
+	}
+
+	fujitsu_hotkey->input = input = input_allocate_device();
+	if (!input) {
+		error = -ENOMEM;
+		goto err_uninstall_notify;
+	}
+
+	snprintf(fujitsu_hotkey->phys, sizeof(fujitsu_hotkey->phys),
+		 "%s/video/input0", acpi_device_hid(device));
+
+	input->name = acpi_device_name(device);
+	input->phys = fujitsu_hotkey->phys;
+	input->id.bustype = BUS_HOST;
+	input->id.product = 0x06;
+	input->dev.parent = &device->dev;
+	input->evbit[0] = BIT(EV_KEY);
+	set_bit(KEY_SCREENLOCK, input->keybit);
+	set_bit(KEY_MEDIA, input->keybit);
+	set_bit(KEY_EMAIL, input->keybit);
+	set_bit(KEY_SUSPEND, input->keybit);
+	set_bit(KEY_UNKNOWN, input->keybit);
+
+	error = input_register_device(input);
+	if (error)
+		goto err_free_input_dev;
+
+	result = acpi_bus_get_power(fujitsu_hotkey->acpi_handle, &state);
+	if (result) {
+		printk(KERN_ERR "Error reading power state\n");
+		goto end;
+	}
+
+	printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
+	       acpi_device_name(device), acpi_device_bid(device),
+	       !device->power.state ? "on" : "off");
+
+	fujitsu_hotkey->dev = device;
+
+	if (ACPI_SUCCESS
+	    (acpi_get_handle(device->handle, METHOD_NAME__INI, &handle))) {
+		vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n");
+		if (ACPI_FAILURE
+		    (acpi_evaluate_object
+		     (device->handle, METHOD_NAME__INI, NULL, NULL)))
+			printk(KERN_ERR "_INI Method failed\n");
+	}
+
+	i = 0;			/* Discard hotkey ringbuffer */
+	while (get_irb() != 0 && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) ;
+	vdbg_printk(FUJLAPTOP_DBG_INFO, "Discarded %i ringbuffer entries\n", i);
+
+	return result;
+
+end:
+err_free_input_dev:
+	input_free_device(input);
+err_uninstall_notify:
+	acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
+				   acpi_fujitsu_hotkey_notify);
+	kfifo_free(fujitsu_hotkey->fifo);
+err_stop:
+
+	return result;
+}
+
+static int acpi_fujitsu_hotkey_remove(struct acpi_device *device, int type)
+{
+	acpi_status status;
+	struct fujitsu_hotkey_t *fujitsu_hotkey = NULL;
+
+	if (!device || !acpi_driver_data(device))
+		return -EINVAL;
+
+	fujitsu_hotkey = acpi_driver_data(device);
+
+	status = acpi_remove_notify_handler(fujitsu_hotkey->acpi_handle,
+					    ACPI_DEVICE_NOTIFY,
+					    acpi_fujitsu_hotkey_notify);
+
+	fujitsu_hotkey->acpi_handle = NULL;
+
+	kfifo_free(fujitsu_hotkey->fifo);
+
+	return 0;
+}
+
+static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
+				       void *data)
+{
+	struct input_dev *input;
+	int keycode, keycode_r;
+	unsigned int irb = 1;
+	int i, status;
+
+	input = fujitsu_hotkey->input;
+
+	vdbg_printk(FUJLAPTOP_DBG_TRACE, "Hotkey event\n");
+
+	switch (event) {
+	case ACPI_FUJITSU_NOTIFY_CODE1:
+		i = 0;
+		while ((irb = get_irb()) != 0
+		       && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) {
+			vdbg_printk(FUJLAPTOP_DBG_TRACE, "GIRB result [%x]\n",
+				    irb);
+
+			switch (irb & 0x4ff) {
+			case LOCK_KEY:
+				keycode = KEY_SCREENLOCK;
+				break;
+			case DISPLAY_KEY:
+				keycode = KEY_MEDIA;
+				break;
+			case ENERGY_KEY:
+				keycode = KEY_EMAIL;
+				break;
+			case REST_KEY:
+				keycode = KEY_SUSPEND;
+				break;
+			case 0:
+				keycode = 0;
+				break;
+			default:
+				vdbg_printk(FUJLAPTOP_DBG_WARN,
+					"Unknown GIRB result [%x]\n", irb);
+				keycode = -1;
+				break;
+			}
+			if (keycode > 0) {
+				vdbg_printk(FUJLAPTOP_DBG_TRACE,
+					"Push keycode into ringbuffer [%d]\n",
+					keycode);
+				status = kfifo_put(fujitsu_hotkey->fifo,
+						(unsigned char *)&keycode,
+						sizeof(keycode));
+				if (status != sizeof(keycode)) {
+					vdbg_printk(FUJLAPTOP_DBG_WARN,
+						"Could not push keycode [0x%x]\n",
+						keycode);
+				} else {
+					input_report_key(input, keycode, 1);
+					input_sync(input);
+				}
+			} else if (keycode == 0) {
+				while ((status =
+					kfifo_get
+					(fujitsu_hotkey->fifo, (unsigned char *)
+					 &keycode_r,
+					 sizeof
+					 (keycode_r))) == sizeof(keycode_r)) {
+					input_report_key(input, keycode_r, 0);
+					input_sync(input);
+					vdbg_printk(FUJLAPTOP_DBG_TRACE,
+						    "Pop keycode from ringbuffer [%d]\n",
+						    keycode_r);
+				}
+			}
+		}
+
+		break;
+	default:
+		keycode = KEY_UNKNOWN;
+		vdbg_printk(FUJLAPTOP_DBG_WARN,
+			    "Unsupported event [0x%x]\n", event);
+		input_report_key(input, keycode, 1);
+		input_sync(input);
+		input_report_key(input, keycode, 0);
+		input_sync(input);
+		break;
+	}
+
+	return;
+}
+
+/* Initialization */
+
 static const struct acpi_device_id fujitsu_device_ids[] = {
 static const struct acpi_device_id fujitsu_device_ids[] = {
 	{ACPI_FUJITSU_HID, 0},
 	{ACPI_FUJITSU_HID, 0},
 	{"", 0},
 	{"", 0},
@@ -251,11 +910,24 @@ static struct acpi_driver acpi_fujitsu_driver = {
 		},
 		},
 };
 };
 
 
-/* Initialization */
+static const struct acpi_device_id fujitsu_hotkey_device_ids[] = {
+	{ACPI_FUJITSU_HOTKEY_HID, 0},
+	{"", 0},
+};
+
+static struct acpi_driver acpi_fujitsu_hotkey_driver = {
+	.name = ACPI_FUJITSU_HOTKEY_DRIVER_NAME,
+	.class = ACPI_FUJITSU_CLASS,
+	.ids = fujitsu_hotkey_device_ids,
+	.ops = {
+		.add = acpi_fujitsu_hotkey_add,
+		.remove = acpi_fujitsu_hotkey_remove,
+		},
+};
 
 
 static int __init fujitsu_init(void)
 static int __init fujitsu_init(void)
 {
 {
-	int ret, result;
+	int ret, result, max_brightness;
 
 
 	if (acpi_disabled)
 	if (acpi_disabled)
 		return -ENODEV;
 		return -ENODEV;
@@ -271,19 +943,6 @@ static int __init fujitsu_init(void)
 		goto fail_acpi;
 		goto fail_acpi;
 	}
 	}
 
 
-	/* Register backlight stuff */
-
-	fujitsu->bl_device =
-	    backlight_device_register("fujitsu-laptop", NULL, NULL,
-				      &fujitsubl_ops);
-	if (IS_ERR(fujitsu->bl_device))
-		return PTR_ERR(fujitsu->bl_device);
-
-	fujitsu->bl_device->props.max_brightness = FUJITSU_LCD_N_LEVELS - 1;
-	ret = platform_driver_register(&fujitsupf_driver);
-	if (ret)
-		goto fail_backlight;
-
 	/* Register platform stuff */
 	/* Register platform stuff */
 
 
 	fujitsu->pf_device = platform_device_alloc("fujitsu-laptop", -1);
 	fujitsu->pf_device = platform_device_alloc("fujitsu-laptop", -1);
@@ -302,28 +961,68 @@ static int __init fujitsu_init(void)
 	if (ret)
 	if (ret)
 		goto fail_platform_device2;
 		goto fail_platform_device2;
 
 
+	/* Register backlight stuff */
+
+	fujitsu->bl_device =
+	    backlight_device_register("fujitsu-laptop", NULL, NULL,
+				      &fujitsubl_ops);
+	if (IS_ERR(fujitsu->bl_device))
+		return PTR_ERR(fujitsu->bl_device);
+
+	max_brightness = fujitsu->max_brightness;
+
+	fujitsu->bl_device->props.max_brightness = max_brightness - 1;
+	fujitsu->bl_device->props.brightness = fujitsu->brightness_level;
+
+	ret = platform_driver_register(&fujitsupf_driver);
+	if (ret)
+		goto fail_backlight;
+
+	/* Register hotkey driver */
+
+	fujitsu_hotkey = kmalloc(sizeof(struct fujitsu_hotkey_t), GFP_KERNEL);
+	if (!fujitsu_hotkey) {
+		ret = -ENOMEM;
+		goto fail_hotkey;
+	}
+	memset(fujitsu_hotkey, 0, sizeof(struct fujitsu_hotkey_t));
+
+	result = acpi_bus_register_driver(&acpi_fujitsu_hotkey_driver);
+	if (result < 0) {
+		ret = -ENODEV;
+		goto fail_hotkey1;
+	}
+
 	printk(KERN_INFO "fujitsu-laptop: driver " FUJITSU_DRIVER_VERSION
 	printk(KERN_INFO "fujitsu-laptop: driver " FUJITSU_DRIVER_VERSION
 	       " successfully loaded.\n");
 	       " successfully loaded.\n");
 
 
 	return 0;
 	return 0;
 
 
-      fail_platform_device2:
+fail_hotkey1:
 
 
-	platform_device_del(fujitsu->pf_device);
-
-      fail_platform_device1:
-
-	platform_device_put(fujitsu->pf_device);
+	kfree(fujitsu_hotkey);
 
 
-      fail_platform_driver:
+fail_hotkey:
 
 
 	platform_driver_unregister(&fujitsupf_driver);
 	platform_driver_unregister(&fujitsupf_driver);
 
 
-      fail_backlight:
+fail_backlight:
 
 
 	backlight_device_unregister(fujitsu->bl_device);
 	backlight_device_unregister(fujitsu->bl_device);
 
 
-      fail_acpi:
+fail_platform_device2:
+
+	platform_device_del(fujitsu->pf_device);
+
+fail_platform_device1:
+
+	platform_device_put(fujitsu->pf_device);
+
+fail_platform_driver:
+
+	acpi_bus_unregister_driver(&acpi_fujitsu_driver);
+
+fail_acpi:
 
 
 	kfree(fujitsu);
 	kfree(fujitsu);
 
 
@@ -342,19 +1041,43 @@ static void __exit fujitsu_cleanup(void)
 
 
 	kfree(fujitsu);
 	kfree(fujitsu);
 
 
+	acpi_bus_unregister_driver(&acpi_fujitsu_hotkey_driver);
+
+	kfree(fujitsu_hotkey);
+
 	printk(KERN_INFO "fujitsu-laptop: driver unloaded.\n");
 	printk(KERN_INFO "fujitsu-laptop: driver unloaded.\n");
 }
 }
 
 
 module_init(fujitsu_init);
 module_init(fujitsu_init);
 module_exit(fujitsu_cleanup);
 module_exit(fujitsu_cleanup);
 
 
-MODULE_AUTHOR("Jonathan Woithe");
+module_param(use_alt_lcd_levels, uint, 0644);
+MODULE_PARM_DESC(use_alt_lcd_levels,
+		 "Use alternative interface for lcd_levels (needed for Lifebook s6410).");
+module_param(disable_brightness_keys, uint, 0644);
+MODULE_PARM_DESC(disable_brightness_keys,
+		 "Disable brightness keys (eg. if they are already handled by the generic ACPI_VIDEO device).");
+module_param(disable_brightness_adjust, uint, 0644);
+MODULE_PARM_DESC(disable_brightness_adjust, "Disable brightness adjustment .");
+#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
+module_param_named(debug, dbg_level, uint, 0644);
+MODULE_PARM_DESC(debug, "Sets debug level bit-mask");
+#endif
+
+MODULE_AUTHOR("Jonathan Woithe, Peter Gruber");
 MODULE_DESCRIPTION("Fujitsu laptop extras support");
 MODULE_DESCRIPTION("Fujitsu laptop extras support");
 MODULE_VERSION(FUJITSU_DRIVER_VERSION);
 MODULE_VERSION(FUJITSU_DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 
 
+MODULE_ALIAS
+    ("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*");
+MODULE_ALIAS
+    ("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*");
+
 static struct pnp_device_id pnp_ids[] = {
 static struct pnp_device_id pnp_ids[] = {
 	{ .id = "FUJ02bf" },
 	{ .id = "FUJ02bf" },
+	{ .id = "FUJ02B1" },
+	{ .id = "FUJ02E3" },
 	{ .id = "" }
 	{ .id = "" }
 };
 };
 MODULE_DEVICE_TABLE(pnp, pnp_ids);
 MODULE_DEVICE_TABLE(pnp, pnp_ids);

+ 2 - 4
drivers/pci/pci-acpi.c

@@ -293,13 +293,11 @@ EXPORT_SYMBOL(pci_osc_control_set);
  * 	choose highest power _SxD or any lower power
  * 	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;
 	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)
 	if (acpi_state < 0)
 		return PCI_POWER_ERROR;
 		return PCI_POWER_ERROR;
 
 

+ 2 - 2
drivers/pci/pci.c

@@ -508,7 +508,7 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
 	return 0;
 	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
  * 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;
 		return PCI_D0;
 
 
 	if (platform_pci_choose_state) {
 	if (platform_pci_choose_state) {
-		ret = platform_pci_choose_state(dev, state);
+		ret = platform_pci_choose_state(dev);
 		if (ret != PCI_POWER_ERROR)
 		if (ret != PCI_POWER_ERROR)
 			return ret;
 			return ret;
 	}
 	}

+ 1 - 2
drivers/pci/pci.h

@@ -6,8 +6,7 @@ extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
 extern void pci_cleanup_rom(struct pci_dev *dev);
 extern void pci_cleanup_rom(struct pci_dev *dev);
 
 
 /* Firmware callbacks */
 /* 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,
 extern int (*platform_pci_set_power_state)(struct pci_dev *dev,
 						pci_power_t state);
 						pci_power_t state);
 
 

+ 119 - 29
drivers/pnp/base.h

@@ -1,3 +1,8 @@
+/*
+ * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
+ *	Bjorn Helgaas <bjorn.helgaas@hp.com>
+ */
+
 extern spinlock_t pnp_lock;
 extern spinlock_t pnp_lock;
 void *pnp_alloc(long size);
 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);
 int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev);
 void pnp_remove_card_device(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_init_resources(struct pnp_dev *dev);
 
 
 void pnp_fixup_device(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);
 int __pnp_add_device(struct pnp_dev *dev);
 void __pnp_remove_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_irq(struct pnp_dev *dev, struct resource *res);
 int pnp_check_dma(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 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 pnp_resource {
+	struct list_head list;
 	struct resource res;
 	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,
 struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
 					  int flags);
 					  int flags);

+ 19 - 10
drivers/pnp/core.c

@@ -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)
 static void pnp_release_device(struct device *dmdev)
 {
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
 
 
-	pnp_free_option(dev->independent);
-	pnp_free_option(dev->dependent);
 	pnp_free_ids(dev);
 	pnp_free_ids(dev);
-	kfree(dev->res);
+	pnp_free_resources(dev);
+	pnp_free_options(dev);
 	kfree(dev);
 	kfree(dev);
 }
 }
 
 
@@ -119,12 +133,8 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid
 	if (!dev)
 	if (!dev)
 		return NULL;
 		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->protocol = protocol;
 	dev->number = id;
 	dev->number = id;
 	dev->dma_mask = DMA_24BIT_MASK;
 	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);
 	dev_id = pnp_add_id(dev, pnpid);
 	if (!dev_id) {
 	if (!dev_id) {
-		kfree(dev->res);
 		kfree(dev);
 		kfree(dev);
 		return NULL;
 		return NULL;
 	}
 	}

+ 89 - 118
drivers/pnp/interface.c

@@ -3,6 +3,8 @@
  *
  *
  * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela <perex@perex.cz>
  * 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 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>
 #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,
 static void pnp_print_port(pnp_info_buffer_t * buffer, char *space,
 			   struct pnp_port *port)
 			   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,
 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);
 	pnp_printf(buffer, "%sirq ", space);
 	for (i = 0; i < PNP_IRQ_NR; i++)
 	for (i = 0; i < PNP_IRQ_NR; i++)
-		if (test_bit(i, irq->map)) {
+		if (test_bit(i, irq->map.bits)) {
 			if (!first) {
 			if (!first) {
 				pnp_printf(buffer, ",");
 				pnp_printf(buffer, ",");
 			} else {
 			} else {
@@ -78,7 +82,7 @@ static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space,
 			else
 			else
 				pnp_printf(buffer, "%i", i);
 				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>");
 		pnp_printf(buffer, "<none>");
 	if (irq->flags & IORESOURCE_IRQ_HIGHEDGE)
 	if (irq->flags & IORESOURCE_IRQ_HIGHEDGE)
 		pnp_printf(buffer, " High-Edge");
 		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");
 		pnp_printf(buffer, " High-Level");
 	if (irq->flags & IORESOURCE_IRQ_LOWLEVEL)
 	if (irq->flags & IORESOURCE_IRQ_LOWLEVEL)
 		pnp_printf(buffer, " Low-Level");
 		pnp_printf(buffer, " Low-Level");
+	if (irq->flags & IORESOURCE_IRQ_OPTIONAL)
+		pnp_printf(buffer, " (optional)");
 	pnp_printf(buffer, "\n");
 	pnp_printf(buffer, "\n");
 }
 }
 
 
@@ -148,8 +154,11 @@ static void pnp_print_mem(pnp_info_buffer_t * buffer, char *space,
 {
 {
 	char *s;
 	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)
 	if (mem->flags & IORESOURCE_MEM_WRITEABLE)
 		pnp_printf(buffer, ", writeable");
 		pnp_printf(buffer, ", writeable");
 	if (mem->flags & IORESOURCE_MEM_CACHEABLE)
 	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,
 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,
 static ssize_t pnp_show_options(struct device *dmdev,
 				struct device_attribute *attr, char *buf)
 				struct device_attribute *attr, char *buf)
 {
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
 	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)
 	if (!buffer)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	buffer->len = PAGE_SIZE;
 	buffer->len = PAGE_SIZE;
 	buffer->buffer = buf;
 	buffer->buffer = buf;
 	buffer->curr = buffer->buffer;
 	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);
 	ret = (buffer->curr - buf);
 	kfree(buffer);
 	kfree(buffer);
 	return ret;
 	return ret;
@@ -248,79 +250,59 @@ static ssize_t pnp_show_current_resources(struct device *dmdev,
 					  char *buf)
 					  char *buf)
 {
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
-	struct resource *res;
-	int i, ret;
 	pnp_info_buffer_t *buffer;
 	pnp_info_buffer_t *buffer;
+	struct pnp_resource *pnp_res;
+	struct resource *res;
+	int ret;
 
 
 	if (!dev)
 	if (!dev)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	buffer = (pnp_info_buffer_t *) pnp_alloc(sizeof(pnp_info_buffer_t));
+	buffer = pnp_alloc(sizeof(pnp_info_buffer_t));
 	if (!buffer)
 	if (!buffer)
 		return -ENOMEM;
 		return -ENOMEM;
+
 	buffer->len = PAGE_SIZE;
 	buffer->len = PAGE_SIZE;
 	buffer->buffer = buf;
 	buffer->buffer = buf;
 	buffer->curr = buffer->buffer;
 	buffer->curr = buffer->buffer;
 
 
-	pnp_printf(buffer, "state = ");
-	if (dev->active)
-		pnp_printf(buffer, "active\n");
-	else
-		pnp_printf(buffer, "disabled\n");
-
-	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);
+	pnp_printf(buffer, "state = %s\n", dev->active ? "active" : "disabled");
+
+	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;
 		}
 		}
-	}
-	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);
+
+		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);
 	ret = (buffer->curr - buf);
 	kfree(buffer);
 	kfree(buffer);
 	return ret;
 	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_dev *dev = to_pnp_dev(dmdev);
-	struct pnp_resource *pnp_res;
 	char *buf = (void *)ubuf;
 	char *buf = (void *)ubuf;
 	int retval = 0;
 	int retval = 0;
 	resource_size_t start, end;
 	resource_size_t start, end;
@@ -368,7 +350,6 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
 		goto done;
 		goto done;
 	}
 	}
 	if (!strnicmp(buf, "set", 3)) {
 	if (!strnicmp(buf, "set", 3)) {
-		int nport = 0, nmem = 0, nirq = 0, ndma = 0;
 		if (dev->active)
 		if (dev->active)
 			goto done;
 			goto done;
 		buf += 3;
 		buf += 3;
@@ -391,10 +372,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
 					end = simple_strtoul(buf, &buf, 0);
 					end = simple_strtoul(buf, &buf, 0);
 				} else
 				} else
 					end = start;
 					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;
 				continue;
 			}
 			}
 			if (!strnicmp(buf, "mem", 3)) {
 			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);
 					end = simple_strtoul(buf, &buf, 0);
 				} else
 				} else
 					end = start;
 					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;
 				continue;
 			}
 			}
 			if (!strnicmp(buf, "irq", 3)) {
 			if (!strnicmp(buf, "irq", 3)) {
@@ -422,9 +397,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
 				while (isspace(*buf))
 				while (isspace(*buf))
 					++buf;
 					++buf;
 				start = simple_strtoul(buf, &buf, 0);
 				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;
 				continue;
 			}
 			}
 			if (!strnicmp(buf, "dma", 3)) {
 			if (!strnicmp(buf, "dma", 3)) {
@@ -432,9 +405,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
 				while (isspace(*buf))
 				while (isspace(*buf))
 					++buf;
 					++buf;
 				start = simple_strtoul(buf, &buf, 0);
 				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;
 				continue;
 			}
 			}
 			break;
 			break;

+ 97 - 156
drivers/pnp/isapnp/core.c

@@ -429,154 +429,135 @@ static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card,
  *  Add IRQ resource to resources list.
  *  Add IRQ resource to resources list.
  */
  */
 static void __init isapnp_parse_irq_resource(struct pnp_dev *dev,
 static void __init isapnp_parse_irq_resource(struct pnp_dev *dev,
-					     struct pnp_option *option,
+					     unsigned int option_flags,
 					     int size)
 					     int size)
 {
 {
 	unsigned char tmp[3];
 	unsigned char tmp[3];
-	struct pnp_irq *irq;
 	unsigned long bits;
 	unsigned long bits;
+	pnp_irq_mask_t map;
+	unsigned char flags = IORESOURCE_IRQ_HIGHEDGE;
 
 
 	isapnp_peek(tmp, size);
 	isapnp_peek(tmp, size);
-	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
-	if (!irq)
-		return;
 	bits = (tmp[1] << 8) | tmp[0];
 	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)
 	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.
  *  Add DMA resource to resources list.
  */
  */
 static void __init isapnp_parse_dma_resource(struct pnp_dev *dev,
 static void __init isapnp_parse_dma_resource(struct pnp_dev *dev,
-					     struct pnp_option *option,
+					     unsigned int option_flags,
 					     int size)
 					     int size)
 {
 {
 	unsigned char tmp[2];
 	unsigned char tmp[2];
-	struct pnp_dma *dma;
 
 
 	isapnp_peek(tmp, size);
 	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.
  *  Add port resource to resources list.
  */
  */
 static void __init isapnp_parse_port_resource(struct pnp_dev *dev,
 static void __init isapnp_parse_port_resource(struct pnp_dev *dev,
-					      struct pnp_option *option,
+					      unsigned int option_flags,
 					      int size)
 					      int size)
 {
 {
 	unsigned char tmp[7];
 	unsigned char tmp[7];
-	struct pnp_port *port;
+	resource_size_t min, max, align, len;
+	unsigned char flags;
 
 
 	isapnp_peek(tmp, size);
 	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.
  *  Add fixed port resource to resources list.
  */
  */
 static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev,
 static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev,
-						    struct pnp_option *option,
+						    unsigned int option_flags,
 						    int size)
 						    int size)
 {
 {
 	unsigned char tmp[3];
 	unsigned char tmp[3];
-	struct pnp_port *port;
+	resource_size_t base, len;
 
 
 	isapnp_peek(tmp, size);
 	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.
  *  Add memory resource to resources list.
  */
  */
 static void __init isapnp_parse_mem_resource(struct pnp_dev *dev,
 static void __init isapnp_parse_mem_resource(struct pnp_dev *dev,
-					     struct pnp_option *option,
+					     unsigned int option_flags,
 					     int size)
 					     int size)
 {
 {
 	unsigned char tmp[9];
 	unsigned char tmp[9];
-	struct pnp_mem *mem;
+	resource_size_t min, max, align, len;
+	unsigned char flags;
 
 
 	isapnp_peek(tmp, size);
 	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.
  *  Add 32-bit memory resource to resources list.
  */
  */
 static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev,
 static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev,
-					       struct pnp_option *option,
+					       unsigned int option_flags,
 					       int size)
 					       int size)
 {
 {
 	unsigned char tmp[17];
 	unsigned char tmp[17];
-	struct pnp_mem *mem;
+	resource_size_t min, max, align, len;
+	unsigned char flags;
 
 
 	isapnp_peek(tmp, size);
 	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.
  *  Add 32-bit fixed memory resource to resources list.
  */
  */
 static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev,
 static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev,
-						     struct pnp_option *option,
+						     unsigned int option_flags,
 						     int size)
 						     int size)
 {
 {
 	unsigned char tmp[9];
 	unsigned char tmp[9];
-	struct pnp_mem *mem;
+	resource_size_t base, len;
+	unsigned char flags;
 
 
 	isapnp_peek(tmp, size);
 	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,
 static int __init isapnp_create_device(struct pnp_card *card,
 				       unsigned short size)
 				       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];
 	unsigned char type, tmp[17];
-	struct pnp_option *option;
+	unsigned int option_flags;
 	struct pnp_dev *dev;
 	struct pnp_dev *dev;
 	u32 eisa_id;
 	u32 eisa_id;
 	char id[8];
 	char id[8];
 
 
 	if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
 	if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
 		return 1;
 		return 1;
-	option = pnp_register_independent_option(dev);
-	if (!option) {
-		kfree(dev);
-		return 1;
-	}
+	option_flags = 0;
 	pnp_add_card_device(card, dev);
 	pnp_add_card_device(card, dev);
 
 
 	while (1) {
 	while (1) {
@@ -634,16 +611,11 @@ static int __init isapnp_create_device(struct pnp_card *card,
 					return 1;
 					return 1;
 				size = 0;
 				size = 0;
 				skip = 0;
 				skip = 0;
-				option = pnp_register_independent_option(dev);
-				if (!option) {
-					kfree(dev);
-					return 1;
-				}
+				option_flags = 0;
 				pnp_add_card_device(card, dev);
 				pnp_add_card_device(card, dev);
 			} else {
 			} else {
 				skip = 1;
 				skip = 1;
 			}
 			}
-			priority = 0;
 			compat = 0;
 			compat = 0;
 			break;
 			break;
 		case _STAG_COMPATDEVID:
 		case _STAG_COMPATDEVID:
@@ -660,44 +632,42 @@ static int __init isapnp_create_device(struct pnp_card *card,
 		case _STAG_IRQ:
 		case _STAG_IRQ:
 			if (size < 2 || size > 3)
 			if (size < 2 || size > 3)
 				goto __skip;
 				goto __skip;
-			isapnp_parse_irq_resource(dev, option, size);
+			isapnp_parse_irq_resource(dev, option_flags, size);
 			size = 0;
 			size = 0;
 			break;
 			break;
 		case _STAG_DMA:
 		case _STAG_DMA:
 			if (size != 2)
 			if (size != 2)
 				goto __skip;
 				goto __skip;
-			isapnp_parse_dma_resource(dev, option, size);
+			isapnp_parse_dma_resource(dev, option_flags, size);
 			size = 0;
 			size = 0;
 			break;
 			break;
 		case _STAG_STARTDEP:
 		case _STAG_STARTDEP:
 			if (size > 1)
 			if (size > 1)
 				goto __skip;
 				goto __skip;
-			priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE;
+			priority = PNP_RES_PRIORITY_ACCEPTABLE;
 			if (size > 0) {
 			if (size > 0) {
 				isapnp_peek(tmp, size);
 				isapnp_peek(tmp, size);
-				priority = 0x100 | tmp[0];
+				priority = tmp[0];
 				size = 0;
 				size = 0;
 			}
 			}
-			option = pnp_register_dependent_option(dev, priority);
-			if (!option)
-				return 1;
+			option_flags = pnp_new_dependent_set(dev, priority);
 			break;
 			break;
 		case _STAG_ENDDEP:
 		case _STAG_ENDDEP:
 			if (size != 0)
 			if (size != 0)
 				goto __skip;
 				goto __skip;
-			priority = 0;
-			dev_dbg(&dev->dev, "end dependent options\n");
+			option_flags = 0;
 			break;
 			break;
 		case _STAG_IOPORT:
 		case _STAG_IOPORT:
 			if (size != 7)
 			if (size != 7)
 				goto __skip;
 				goto __skip;
-			isapnp_parse_port_resource(dev, option, size);
+			isapnp_parse_port_resource(dev, option_flags, size);
 			size = 0;
 			size = 0;
 			break;
 			break;
 		case _STAG_FIXEDIO:
 		case _STAG_FIXEDIO:
 			if (size != 3)
 			if (size != 3)
 				goto __skip;
 				goto __skip;
-			isapnp_parse_fixed_port_resource(dev, option, size);
+			isapnp_parse_fixed_port_resource(dev, option_flags,
+							 size);
 			size = 0;
 			size = 0;
 			break;
 			break;
 		case _STAG_VENDOR:
 		case _STAG_VENDOR:
@@ -705,7 +675,7 @@ static int __init isapnp_create_device(struct pnp_card *card,
 		case _LTAG_MEMRANGE:
 		case _LTAG_MEMRANGE:
 			if (size != 9)
 			if (size != 9)
 				goto __skip;
 				goto __skip;
-			isapnp_parse_mem_resource(dev, option, size);
+			isapnp_parse_mem_resource(dev, option_flags, size);
 			size = 0;
 			size = 0;
 			break;
 			break;
 		case _LTAG_ANSISTR:
 		case _LTAG_ANSISTR:
@@ -720,13 +690,14 @@ static int __init isapnp_create_device(struct pnp_card *card,
 		case _LTAG_MEM32RANGE:
 		case _LTAG_MEM32RANGE:
 			if (size != 17)
 			if (size != 17)
 				goto __skip;
 				goto __skip;
-			isapnp_parse_mem32_resource(dev, option, size);
+			isapnp_parse_mem32_resource(dev, option_flags, size);
 			size = 0;
 			size = 0;
 			break;
 			break;
 		case _LTAG_FIXEDMEM32RANGE:
 		case _LTAG_FIXEDMEM32RANGE:
 			if (size != 9)
 			if (size != 9)
 				goto __skip;
 				goto __skip;
-			isapnp_parse_fixed_mem32_resource(dev, option, size);
+			isapnp_parse_fixed_mem32_resource(dev, option_flags,
+							  size);
 			size = 0;
 			size = 0;
 			break;
 			break;
 		case _STAG_END:
 		case _STAG_END:
@@ -928,7 +899,6 @@ EXPORT_SYMBOL(isapnp_write_byte);
 
 
 static int isapnp_get_resources(struct pnp_dev *dev)
 static int isapnp_get_resources(struct pnp_dev *dev)
 {
 {
-	struct pnp_resource *pnp_res;
 	int i, ret;
 	int i, ret;
 
 
 	dev_dbg(&dev->dev, "get resources\n");
 	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++) {
 	for (i = 0; i < ISAPNP_MAX_PORT; i++) {
 		ret = isapnp_read_word(ISAPNP_CFG_PORT + (i << 1));
 		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++) {
 	for (i = 0; i < ISAPNP_MAX_MEM; i++) {
 		ret = isapnp_read_word(ISAPNP_CFG_MEM + (i << 3)) << 8;
 		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++) {
 	for (i = 0; i < ISAPNP_MAX_IRQ; i++) {
 		ret = isapnp_read_word(ISAPNP_CFG_IRQ + (i << 1)) >> 8;
 		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++) {
 	for (i = 0; i < ISAPNP_MAX_DMA; i++) {
 		ret = isapnp_read_byte(ISAPNP_CFG_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:
 __end:
@@ -978,62 +936,45 @@ __end:
 
 
 static int isapnp_set_resources(struct pnp_dev *dev)
 static int isapnp_set_resources(struct pnp_dev *dev)
 {
 {
-	struct pnp_resource *pnp_res;
 	struct resource *res;
 	struct resource *res;
-	int tmp, index;
+	int tmp;
 
 
 	dev_dbg(&dev->dev, "set resources\n");
 	dev_dbg(&dev->dev, "set resources\n");
 	isapnp_cfg_begin(dev->card->number, dev->number);
 	isapnp_cfg_begin(dev->card->number, dev->number);
 	dev->active = 1;
 	dev->active = 1;
 	for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) {
 	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",
 			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);
 					  res->start);
 		}
 		}
 	}
 	}
 	for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) {
 	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;
 			int irq = res->start;
 			if (irq == 2)
 			if (irq == 2)
 				irq = 9;
 				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++) {
 	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",
 			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++) {
 	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",
 			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);
 					  (res->start >> 8) & 0xffff);
 		}
 		}
 	}
 	}

+ 131 - 283
drivers/pnp/manager.c

@@ -3,6 +3,8 @@
  *
  *
  * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
  * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
  * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
  * 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>
 #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)
 static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
 {
 {
-	struct pnp_resource *pnp_res;
-	struct resource *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;
+	struct resource *res, local_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 "
 		dev_dbg(&dev->dev, "  io %d already set to %#llx-%#llx "
 			"flags %#lx\n", idx, (unsigned long long) res->start,
 			"flags %#lx\n", idx, (unsigned long long) res->start,
 			(unsigned long long) res->end, res->flags);
 			(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) {
 	if (!rule->size) {
 		res->flags |= IORESOURCE_DISABLED;
 		res->flags |= IORESOURCE_DISABLED;
 		dev_dbg(&dev->dev, "  io %d disabled\n", idx);
 		dev_dbg(&dev->dev, "  io %d disabled\n", idx);
-		return 1;	/* skip disabled resource requests */
+		goto __add;
 	}
 	}
 
 
 	res->start = rule->min;
 	res->start = rule->min;
 	res->end = res->start + rule->size - 1;
 	res->end = res->start + rule->size - 1;
 
 
-	/* run through until pnp_check_port is happy */
 	while (!pnp_check_port(dev, res)) {
 	while (!pnp_check_port(dev, res)) {
 		res->start += rule->align;
 		res->start += rule->align;
 		res->end = res->start + rule->size - 1;
 		res->end = res->start + rule->size - 1;
 		if (res->start > rule->max || !rule->align) {
 		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)
 static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
 {
 {
-	struct pnp_resource *pnp_res;
-	struct resource *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;
-	}
+	struct resource *res, local_res;
 
 
-	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 "
 		dev_dbg(&dev->dev, "  mem %d already set to %#llx-%#llx "
 			"flags %#lx\n", idx, (unsigned long long) res->start,
 			"flags %#lx\n", idx, (unsigned long long) res->start,
 			(unsigned long long) res->end, res->flags);
 			(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))
 	if (!(rule->flags & IORESOURCE_MEM_WRITEABLE))
 		res->flags |= IORESOURCE_READONLY;
 		res->flags |= IORESOURCE_READONLY;
 	if (rule->flags & IORESOURCE_MEM_CACHEABLE)
 	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) {
 	if (!rule->size) {
 		res->flags |= IORESOURCE_DISABLED;
 		res->flags |= IORESOURCE_DISABLED;
 		dev_dbg(&dev->dev, "  mem %d disabled\n", idx);
 		dev_dbg(&dev->dev, "  mem %d disabled\n", idx);
-		return 1;	/* skip disabled resource requests */
+		goto __add;
 	}
 	}
 
 
 	res->start = rule->min;
 	res->start = rule->min;
 	res->end = res->start + rule->size - 1;
 	res->end = res->start + rule->size - 1;
 
 
-	/* run through until pnp_check_mem is happy */
 	while (!pnp_check_mem(dev, res)) {
 	while (!pnp_check_mem(dev, res)) {
 		res->start += rule->align;
 		res->start += rule->align;
 		res->end = res->start + rule->size - 1;
 		res->end = res->start + rule->size - 1;
 		if (res->start > rule->max || !rule->align) {
 		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)
 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;
 	int i;
 
 
 	/* IRQ priority: this table is good for i386 */
 	/* 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
 		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",
 		dev_dbg(&dev->dev, "  irq %d already set to %d flags %#lx\n",
 			idx, (int) res->start, res->flags);
 			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;
 		res->flags |= IORESOURCE_DISABLED;
 		dev_dbg(&dev->dev, "  irq %d disabled\n", idx);
 		dev_dbg(&dev->dev, "  irq %d disabled\n", idx);
-		return 1;	/* skip disabled resource requests */
+		goto __add;
 	}
 	}
 
 
 	/* TBD: need check for >16 IRQ */
 	/* 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) {
 	if (res->start < PNP_IRQ_NR) {
 		res->end = res->start;
 		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++) {
 	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];
 			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);
 	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;
 	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;
 	int i;
 
 
 	/* DMA priority: this table is good for i386 */
 	/* 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
 		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",
 		dev_dbg(&dev->dev, "  dma %d already set to %d flags %#lx\n",
 			idx, (int) res->start, res->flags);
 			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++) {
 	for (i = 0; i < 8; i++) {
 		if (rule->map & (1 << xtab[i])) {
 		if (rule->map & (1 << xtab[i])) {
 			res->start = res->end = 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
 #ifdef MAX_DMA_CHANNELS
 	res->start = res->end = MAX_DMA_CHANNELS;
 	res->start = res->end = MAX_DMA_CHANNELS;
 #endif
 #endif
-	res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
+	res->flags |= IORESOURCE_DISABLED;
 	dev_dbg(&dev->dev, "  disable dma %d\n", idx);
 	dev_dbg(&dev->dev, "  disable dma %d\n", idx);
-}
-
-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;
-	}
+__add:
+	pnp_add_dma_resource(dev, res->start, res->flags);
+	return 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)
 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)
 static void pnp_clean_resource_table(struct pnp_dev *dev)
 {
 {
-	struct resource *res;
-	int idx;
-
-	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);
-		}
+	struct pnp_resource *pnp_res, *tmp;
+
+	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
  * pnp_assign_resources - assigns resources to the device based on the specified dependent number
  * @dev: pointer to the desired device
  * @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 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);
 	mutex_lock(&pnp_res_mutex);
 	pnp_clean_resource_table(dev);
 	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;
-		}
-	}
 
 
-	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;
+	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;
 		}
 		}
-		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;
+		if (ret < 0)
+			break;
+	}
 
 
-fail:
-	pnp_clean_resource_table(dev);
 	mutex_unlock(&pnp_res_mutex);
 	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 @@ fail:
  */
  */
 int pnp_auto_config_dev(struct pnp_dev *dev)
 int pnp_auto_config_dev(struct pnp_dev *dev)
 {
 {
-	struct pnp_option *dep;
-	int i = 1;
+	int i, ret;
 
 
 	if (!pnp_can_configure(dev)) {
 	if (!pnp_can_configure(dev)) {
 		dev_dbg(&dev->dev, "configuration not supported\n");
 		dev_dbg(&dev->dev, "configuration not supported\n");
 		return -ENODEV;
 		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;
 			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");
 	dev_err(&dev->dev, "unable to assign resources\n");
-	return -EBUSY;
+	return ret;
 }
 }
 
 
 /**
 /**

+ 1 - 3
drivers/pnp/pnpacpi/core.c

@@ -117,9 +117,7 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
 {
 {
 	int power_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)
 	if (power_state < 0)
 		power_state = (state.event == PM_EVENT_ON) ?
 		power_state = (state.event == PM_EVENT_ON) ?
 				ACPI_STATE_D0 : ACPI_STATE_D3;
 				ACPI_STATE_D0 : ACPI_STATE_D3;

+ 287 - 205
drivers/pnp/pnpacpi/rsparser.c

@@ -3,6 +3,8 @@
  *
  *
  * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr>
  * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr>
  * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com>
  * 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
  * 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
  * 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 irq, flags;
 	int p, t;
 	int p, t;
 
 
-	if (!valid_IRQ(gsi))
+	if (!valid_IRQ(gsi)) {
+		pnp_add_irq_resource(dev, gsi, IORESOURCE_DISABLED);
 		return;
 		return;
+	}
 
 
 	/*
 	/*
 	 * in IO-APIC mode, use overrided attribute. Two reasons:
 	 * 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;
 	u64 end = start + len - 1;
 
 
 	if (io_decode == ACPI_DECODE_16)
 	if (io_decode == ACPI_DECODE_16)
-		flags |= PNP_PORT_FLAG_16BITADDR;
+		flags |= IORESOURCE_IO_16BIT_ADDR;
 	if (len == 0 || end >= 0x10003)
 	if (len == 0 || end >= 0x10003)
 		flags |= IORESOURCE_DISABLED;
 		flags |= IORESOURCE_DISABLED;
 
 
 	pnp_add_io_resource(dev, start, end, flags);
 	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,
 static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
 						u64 start, u64 len,
 						u64 start, u64 len,
 						int write_protect)
 						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_dma *dma;
 	struct acpi_resource_io *io;
 	struct acpi_resource_io *io;
 	struct acpi_resource_fixed_io *fixed_io;
 	struct acpi_resource_fixed_io *fixed_io;
+	struct acpi_resource_vendor_typed *vendor_typed;
 	struct acpi_resource_memory24 *memory24;
 	struct acpi_resource_memory24 *memory24;
 	struct acpi_resource_memory32 *memory32;
 	struct acpi_resource_memory32 *memory32;
 	struct acpi_resource_fixed_memory32 *fixed_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.
 		 * _CRS, but some firmware violates this, so parse them all.
 		 */
 		 */
 		irq = &res->data.irq;
 		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;
 		break;
 
 
 	case ACPI_RESOURCE_TYPE_DMA:
 	case ACPI_RESOURCE_TYPE_DMA:
 		dma = &res->data.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,
 			flags = dma_flags(dma->type, dma->bus_master,
 					  dma->transfer);
 					  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;
 		break;
 
 
 	case ACPI_RESOURCE_TYPE_IO:
 	case ACPI_RESOURCE_TYPE_IO:
@@ -289,6 +364,8 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
 		break;
 		break;
 
 
 	case ACPI_RESOURCE_TYPE_VENDOR:
 	case ACPI_RESOURCE_TYPE_VENDOR:
+		vendor_typed = &res->data.vendor_typed;
+		pnpacpi_parse_allocated_vendor(dev, vendor_typed);
 		break;
 		break;
 
 
 	case ACPI_RESOURCE_TYPE_END_TAG:
 	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)
 		if (extended_irq->producer_consumer == ACPI_PRODUCER)
 			return AE_OK;
 			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;
 		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,
 static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
-					    struct pnp_option *option,
+					    unsigned int option_flags,
 					    struct acpi_resource_dma *p)
 					    struct acpi_resource_dma *p)
 {
 {
 	int i;
 	int i;
-	struct pnp_dma *dma;
+	unsigned char map = 0, flags;
 
 
 	if (p->channel_count == 0)
 	if (p->channel_count == 0)
 		return;
 		return;
-	dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
-	if (!dma)
-		return;
 
 
 	for (i = 0; i < p->channel_count; i++)
 	for (i = 0; i < p->channel_count; i++)
-		dma->map |= 1 << p->channels[i];
-
-	dma->flags = dma_flags(p->type, p->bus_master, p->transfer);
+		map |= 1 << p->channels[i];
 
 
-	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,
 static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
-					    struct pnp_option *option,
+					    unsigned int option_flags,
 					    struct acpi_resource_irq *p)
 					    struct acpi_resource_irq *p)
 {
 {
 	int i;
 	int i;
-	struct pnp_irq *irq;
+	pnp_irq_mask_t map;
+	unsigned char flags;
 
 
 	if (p->interrupt_count == 0)
 	if (p->interrupt_count == 0)
 		return;
 		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++)
 	for (i = 0; i < p->interrupt_count; i++)
 		if (p->interrupts[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,
 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)
 					struct acpi_resource_extended_irq *p)
 {
 {
 	int i;
 	int i;
-	struct pnp_irq *irq;
+	pnp_irq_mask_t map;
+	unsigned char flags;
 
 
 	if (p->interrupt_count == 0)
 	if (p->interrupt_count == 0)
 		return;
 		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,
 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 acpi_resource_io *io)
 {
 {
-	struct pnp_port *port;
+	unsigned char flags = 0;
 
 
 	if (io->address_length == 0)
 	if (io->address_length == 0)
 		return;
 		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,
 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 acpi_resource_fixed_io *io)
 {
 {
-	struct pnp_port *port;
-
 	if (io->address_length == 0)
 	if (io->address_length == 0)
 		return;
 		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,
 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 acpi_resource_memory24 *p)
 {
 {
-	struct pnp_mem *mem;
+	unsigned char flags = 0;
 
 
 	if (p->address_length == 0)
 	if (p->address_length == 0)
 		return;
 		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,
 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 acpi_resource_memory32 *p)
 {
 {
-	struct pnp_mem *mem;
+	unsigned char flags = 0;
 
 
 	if (p->address_length == 0)
 	if (p->address_length == 0)
 		return;
 		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,
 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 acpi_resource_fixed_memory32 *p)
 {
 {
-	struct pnp_mem *mem;
+	unsigned char flags = 0;
 
 
 	if (p->address_length == 0)
 	if (p->address_length == 0)
 		return;
 		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,
 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 *r)
 {
 {
 	struct acpi_resource_address64 addr, *p = &addr;
 	struct acpi_resource_address64 addr, *p = &addr;
 	acpi_status status;
 	acpi_status status;
-	struct pnp_mem *mem;
-	struct pnp_port *port;
+	unsigned char flags = 0;
 
 
 	status = acpi_resource_to_address64(r, p);
 	status = acpi_resource_to_address64(r, p);
 	if (!ACPI_SUCCESS(status)) {
 	if (!ACPI_SUCCESS(status)) {
@@ -558,49 +620,37 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
 		return;
 		return;
 
 
 	if (p->resource_type == ACPI_MEMORY_RANGE) {
 	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 acpipnp_parse_option_s {
-	struct pnp_option *option;
-	struct pnp_option *option_independent;
 	struct pnp_dev *dev;
 	struct pnp_dev *dev;
+	unsigned int option_flags;
 };
 };
 
 
 static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
 static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
 						  void *data)
 						  void *data)
 {
 {
-	int priority = 0;
+	int priority;
 	struct acpipnp_parse_option_s *parse_data = data;
 	struct acpipnp_parse_option_s *parse_data = data;
 	struct pnp_dev *dev = parse_data->dev;
 	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) {
 	switch (res->type) {
 	case ACPI_RESOURCE_TYPE_IRQ:
 	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;
 		break;
 
 
 	case ACPI_RESOURCE_TYPE_DMA:
 	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;
 		break;
 
 
 	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
 	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;
 			priority = PNP_RES_PRIORITY_INVALID;
 			break;
 			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;
 		break;
 
 
 	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
 	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;
 		break;
 
 
 	case ACPI_RESOURCE_TYPE_IO:
 	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;
 		break;
 
 
 	case ACPI_RESOURCE_TYPE_FIXED_IO:
 	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);
 					        &res->data.fixed_io);
 		break;
 		break;
 
 
@@ -653,29 +691,31 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
 		break;
 		break;
 
 
 	case ACPI_RESOURCE_TYPE_MEMORY24:
 	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;
 		break;
 
 
 	case ACPI_RESOURCE_TYPE_MEMORY32:
 	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;
 		break;
 
 
 	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
 	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);
 						 &res->data.fixed_memory32);
 		break;
 		break;
 
 
 	case ACPI_RESOURCE_TYPE_ADDRESS16:
 	case ACPI_RESOURCE_TYPE_ADDRESS16:
 	case ACPI_RESOURCE_TYPE_ADDRESS32:
 	case ACPI_RESOURCE_TYPE_ADDRESS32:
 	case ACPI_RESOURCE_TYPE_ADDRESS64:
 	case ACPI_RESOURCE_TYPE_ADDRESS64:
-		pnpacpi_parse_address_option(dev, option, res);
+		pnpacpi_parse_address_option(dev, option_flags, res);
 		break;
 		break;
 
 
 	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
 	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
 		break;
 		break;
 
 
 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 	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);
 					     &res->data.extended_irq);
 		break;
 		break;
 
 
@@ -699,12 +739,9 @@ int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
 
 
 	dev_dbg(&dev->dev, "parse resource options\n");
 	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.dev = dev;
+	parse_data.option_flags = 0;
+
 	status = acpi_walk_resources(handle, METHOD_NAME__PRS,
 	status = acpi_walk_resources(handle, METHOD_NAME__PRS,
 				     pnpacpi_option_resource, &parse_data);
 				     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;
 	struct acpi_resource_irq *irq = &resource->data.irq;
 	int triggering, polarity, shareable;
 	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);
 	decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
 	irq->triggering = triggering;
 	irq->triggering = triggering;
 	irq->polarity = polarity;
 	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;
 	struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
 	int triggering, polarity, shareable;
 	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);
 	decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
 	extended_irq->producer_consumer = ACPI_CONSUMER;
 	extended_irq->producer_consumer = ACPI_CONSUMER;
 	extended_irq->triggering = triggering;
 	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;
 	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 */
 	/* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
 	switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
 	switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
 	case IORESOURCE_DMA_TYPEA:
 	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;
 	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;
-
-	dev_dbg(&dev->dev, "  encode io %#llx-%#llx decode %#x\n",
-		(unsigned long long) p->start, (unsigned long long) p->end,
-		io->io_decode);
+	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 %#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,
 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;
 	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,
 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;
 	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;
-
-	dev_dbg(&dev->dev, "  encode mem24 %#llx-%#llx write_protect %#x\n",
-		(unsigned long long) p->start, (unsigned long long) p->end,
+	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 %#x-%#x write_protect %#x\n",
+		memory24->minimum,
+		memory24->minimum + memory24->address_length - 1,
 		memory24->write_protect);
 		memory24->write_protect);
 }
 }
 
 
@@ -941,16 +1013,21 @@ static void pnpacpi_encode_mem32(struct pnp_dev *dev,
 {
 {
 	struct acpi_resource_memory32 *memory32 = &resource->data.memory32;
 	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);
 		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;
 	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);
 		fixed_memory32->write_protect);
 }
 }
 
 

+ 146 - 128
drivers/pnp/pnpbios/rsparser.c

@@ -216,137 +216,116 @@ len_err:
 
 
 static __init void pnpbios_parse_mem_option(struct pnp_dev *dev,
 static __init void pnpbios_parse_mem_option(struct pnp_dev *dev,
 					    unsigned char *p, int size,
 					    unsigned char *p, int size,
-					    struct pnp_option *option)
+					    unsigned int option_flags)
 {
 {
-	struct pnp_mem *mem;
-
-	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);
+	resource_size_t min, max, align, len;
+	unsigned char flags;
+
+	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,
 static __init void pnpbios_parse_mem32_option(struct pnp_dev *dev,
 					      unsigned char *p, int size,
 					      unsigned char *p, int size,
-					      struct pnp_option *option)
+					      unsigned int option_flags)
 {
 {
-	struct pnp_mem *mem;
-
-	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);
+	resource_size_t min, max, align, len;
+	unsigned char flags;
+
+	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,
 static __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev,
 						    unsigned char *p, int size,
 						    unsigned char *p, int size,
-						    struct pnp_option *option)
+						    unsigned int option_flags)
 {
 {
-	struct pnp_mem *mem;
-
-	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);
+	resource_size_t base, len;
+	unsigned char flags;
+
+	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,
 static __init void pnpbios_parse_irq_option(struct pnp_dev *dev,
 					    unsigned char *p, int size,
 					    unsigned char *p, int size,
-					    struct pnp_option *option)
+					    unsigned int option_flags)
 {
 {
-	struct pnp_irq *irq;
 	unsigned long bits;
 	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];
 	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)
 	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,
 static __init void pnpbios_parse_dma_option(struct pnp_dev *dev,
 					    unsigned char *p, int size,
 					    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,
 static __init void pnpbios_parse_port_option(struct pnp_dev *dev,
 					     unsigned char *p, int size,
 					     unsigned char *p, int size,
-					     struct pnp_option *option)
+					     unsigned int option_flags)
 {
 {
-	struct pnp_port *port;
-
-	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);
+	resource_size_t min, max, align, len;
+	unsigned char flags;
+
+	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,
 static __init void pnpbios_parse_fixed_port_option(struct pnp_dev *dev,
 						   unsigned char *p, int size,
 						   unsigned char *p, int size,
-						   struct pnp_option *option)
+						   unsigned int option_flags)
 {
 {
-	struct pnp_port *port;
-
-	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);
+	resource_size_t base, len;
+
+	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 *
 static __init unsigned char *
 pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
 pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
-					struct pnp_dev *dev)
+				   struct pnp_dev *dev)
 {
 {
 	unsigned int len, tag;
 	unsigned int len, tag;
-	int priority = 0;
-	struct pnp_option *option, *option_independent;
+	int priority;
+	unsigned int option_flags;
 
 
 	if (!p)
 	if (!p)
 		return NULL;
 		return NULL;
 
 
 	dev_dbg(&dev->dev, "parse resource options\n");
 	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) {
 	while ((char *)p < (char *)end) {
 
 
 		/* determine the type of tag */
 		/* determine the type of tag */
@@ -363,37 +342,38 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
 		case LARGE_TAG_MEM:
 		case LARGE_TAG_MEM:
 			if (len != 9)
 			if (len != 9)
 				goto len_err;
 				goto len_err;
-			pnpbios_parse_mem_option(dev, p, len, option);
+			pnpbios_parse_mem_option(dev, p, len, option_flags);
 			break;
 			break;
 
 
 		case LARGE_TAG_MEM32:
 		case LARGE_TAG_MEM32:
 			if (len != 17)
 			if (len != 17)
 				goto len_err;
 				goto len_err;
-			pnpbios_parse_mem32_option(dev, p, len, option);
+			pnpbios_parse_mem32_option(dev, p, len, option_flags);
 			break;
 			break;
 
 
 		case LARGE_TAG_FIXEDMEM32:
 		case LARGE_TAG_FIXEDMEM32:
 			if (len != 9)
 			if (len != 9)
 				goto len_err;
 				goto len_err;
-			pnpbios_parse_fixed_mem32_option(dev, p, len, option);
+			pnpbios_parse_fixed_mem32_option(dev, p, len,
+							 option_flags);
 			break;
 			break;
 
 
 		case SMALL_TAG_IRQ:
 		case SMALL_TAG_IRQ:
 			if (len < 2 || len > 3)
 			if (len < 2 || len > 3)
 				goto len_err;
 				goto len_err;
-			pnpbios_parse_irq_option(dev, p, len, option);
+			pnpbios_parse_irq_option(dev, p, len, option_flags);
 			break;
 			break;
 
 
 		case SMALL_TAG_DMA:
 		case SMALL_TAG_DMA:
 			if (len != 2)
 			if (len != 2)
 				goto len_err;
 				goto len_err;
-			pnpbios_parse_dma_option(dev, p, len, option);
+			pnpbios_parse_dma_option(dev, p, len, option_flags);
 			break;
 			break;
 
 
 		case SMALL_TAG_PORT:
 		case SMALL_TAG_PORT:
 			if (len != 7)
 			if (len != 7)
 				goto len_err;
 				goto len_err;
-			pnpbios_parse_port_option(dev, p, len, option);
+			pnpbios_parse_port_option(dev, p, len, option_flags);
 			break;
 			break;
 
 
 		case SMALL_TAG_VENDOR:
 		case SMALL_TAG_VENDOR:
@@ -403,28 +383,23 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
 		case SMALL_TAG_FIXEDPORT:
 		case SMALL_TAG_FIXEDPORT:
 			if (len != 3)
 			if (len != 3)
 				goto len_err;
 				goto len_err;
-			pnpbios_parse_fixed_port_option(dev, p, len, option);
+			pnpbios_parse_fixed_port_option(dev, p, len,
+							option_flags);
 			break;
 			break;
 
 
 		case SMALL_TAG_STARTDEP:
 		case SMALL_TAG_STARTDEP:
 			if (len > 1)
 			if (len > 1)
 				goto len_err;
 				goto len_err;
-			priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE;
+			priority = PNP_RES_PRIORITY_ACCEPTABLE;
 			if (len > 0)
 			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;
 			break;
 
 
 		case SMALL_TAG_ENDDEP:
 		case SMALL_TAG_ENDDEP:
 			if (len != 0)
 			if (len != 0)
 				goto len_err;
 				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;
 			break;
 
 
 		case SMALL_TAG_END:
 		case SMALL_TAG_END:
@@ -526,8 +501,16 @@ len_err:
 static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p,
 static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p,
 			       struct resource *res)
 			       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[4] = (base >> 8) & 0xff;
 	p[5] = ((base >> 8) >> 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[10] = (len >> 8) & 0xff;
 	p[11] = ((len >> 8) >> 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,
 static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p,
 				 struct resource *res)
 				 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[4] = base & 0xff;
 	p[5] = (base >> 8) & 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[18] = (len >> 16) & 0xff;
 	p[19] = (len >> 24) & 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,
 static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p,
 				       struct resource *res)
 				       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[4] = base & 0xff;
 	p[5] = (base >> 8) & 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[10] = (len >> 16) & 0xff;
 	p[11] = (len >> 24) & 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,
 static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p,
 			       struct resource *res)
 			       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[1] = map & 0xff;
 	p[2] = (map >> 8) & 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,
 static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p,
 			       struct resource *res)
 			       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[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,
 static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
 				struct resource *res)
 				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[2] = base & 0xff;
 	p[3] = (base >> 8) & 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[5] = (base >> 8) & 0xff;
 	p[7] = len & 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,
 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 base = res->start;
 	unsigned long len = res->end - res->start + 1;
 	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[1] = base & 0xff;
 	p[2] = (base >> 8) & 0xff;
 	p[2] = (base >> 8) & 0xff;
 	p[3] = len & 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
 static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev

+ 156 - 151
drivers/pnp/quirks.c

@@ -5,6 +5,8 @@
  *  when building up the resource structure for the first time.
  *  when building up the resource structure for the first time.
  *
  *
  *  Copyright (c) 2000 Peter Denison <peterd@pnd-pc.demon.co.uk>
  *  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
  *  Heavily based on PCI quirks handling which is
  *
  *
@@ -20,203 +22,207 @@
 #include <linux/kallsyms.h>
 #include <linux/kallsyms.h>
 #include "base.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)
 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)
 static void quirk_cmi8330_resources(struct pnp_dev *dev)
 {
 {
-	struct pnp_option *res = dev->dependent;
-	unsigned long tmp;
-
-	for (; res; res = res->next) {
-
-		struct pnp_irq *irq;
-		struct pnp_dma *dma;
+	struct pnp_option *option;
+	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
-		}
+	list_for_each_entry(option, &dev->options, list) {
+		if (!pnp_option_is_dependent(option))
+			continue;
 
 
-		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) ==
 			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)
 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_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
 	 * Here we increase that range so that two such cards can be
 	 * auto-configured.
 	 * 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;
-
-	/*
-	 * 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;
+	struct pnp_option *tail = NULL, *first_new_option = NULL;
+	struct pnp_option *option, *new_option;
+	unsigned int flags;
 
 
-		port = res->port;
-		if (!port || !res->irq)
-			continue;
+	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;
+	}
 
 
-		copy = pnp_alloc(sizeof *copy);
-		if (!copy)
-			break;
+	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;
+			}
 
 
-		copy->min = port->min;
-		copy->max = port->max;
-		copy->align = port->align;
-		copy->size = port->size;
-		copy->flags = port->flags;
+			*new_option = *option;
+			new_option->flags = flags;
+			if (!first_new_option)
+				first_new_option = new_option;
 
 
-		curr = pnp_build_option(PNP_RES_PRIORITY_FUNCTIONAL);
-		if (!curr) {
-			kfree(copy);
-			break;
+			list_add(&new_option->list, &tail->list);
+			tail = new_option;
 		}
 		}
-		curr->port = copy;
-
-		if (prev)
-			prev->next = curr;
-		else
-			head = curr;
-		prev = curr;
 	}
 	}
-	if (head)
-		dev_info(&dev->dev, "adding IRQ-less MPU options\n");
 
 
-	return head;
+	return first_new_option;
 }
 }
 
 
-static void quirk_ad1815_mpu_resources(struct pnp_dev *dev)
+
+static void quirk_add_irq_optional_dependent_sets(struct pnp_dev *dev)
 {
 {
-	struct pnp_option *res;
+	struct pnp_option *new_option;
+	unsigned int num_sets, i, set;
 	struct pnp_irq *irq;
 	struct pnp_irq *irq;
 
 
-	/*
-	 * 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;
+	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;
 
 
-		copy->next = res->irq; /* Yes, this is NULL */
-		res->irq = copy;
+		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);
+		}
 
 
-		if (!res->next)
-			break;
-		res = res->next;
+		dev_info(&dev->dev, "added dependent option set %d (same as "
+			 "set %d except IRQ optional)\n", set, i);
 	}
 	}
-	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)
+static void quirk_ad1815_mpu_resources(struct pnp_dev *dev)
 {
 {
-	struct pnp_option *res;
+	struct pnp_option *option;
+	struct pnp_irq *irq = NULL;
+	unsigned int independent_irqs = 0;
+
+	list_for_each_entry(option, &dev->options, list) {
+		if (option->type == IORESOURCE_IRQ &&
+		    !pnp_option_is_dependent(option)) {
+			independent_irqs++;
+			irq = &option->u.irq;
+		}
+	}
 
 
-	res = dev->dependent;
-	if (!res)
+	if (independent_irqs != 1)
 		return;
 		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>
 #include <linux/pci.h>
@@ -248,8 +254,7 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
 			for (j = 0;
 			for (j = 0;
 			     (res = pnp_get_resource(dev, IORESOURCE_MEM, j));
 			     (res = pnp_get_resource(dev, IORESOURCE_MEM, j));
 			     j++) {
 			     j++) {
-				if (res->flags & IORESOURCE_UNSET ||
-				    (res->start == 0 && res->end == 0))
+				if (res->start == 0 && res->end == 0)
 					continue;
 					continue;
 
 
 				pnp_start = res->start;
 				pnp_start = res->start;
@@ -312,10 +317,10 @@ static struct pnp_fixup pnp_fixups[] = {
 	{"CTL0043", quirk_sb16audio_resources},
 	{"CTL0043", quirk_sb16audio_resources},
 	{"CTL0044", quirk_sb16audio_resources},
 	{"CTL0044", quirk_sb16audio_resources},
 	{"CTL0045", quirk_sb16audio_resources},
 	{"CTL0045", quirk_sb16audio_resources},
-	/* Add IRQ-less MPU options */
+	/* Add IRQ-optional MPU options */
 	{"ADS7151", quirk_ad1815_mpu_resources},
 	{"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 */
 	/* PnP resources that might overlap PCI BARs */
 	{"PNP0c01", quirk_system_pci_resources},
 	{"PNP0c01", quirk_system_pci_resources},
 	{"PNP0c02", quirk_system_pci_resources},
 	{"PNP0c02", quirk_system_pci_resources},

+ 203 - 251
drivers/pnp/resource.c

@@ -3,6 +3,8 @@
  *
  *
  * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
  * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
  * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
  * 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>
 #include <linux/module.h>
@@ -28,201 +30,121 @@ static int pnp_reserve_mem[16] = {[0 ... 15] = -1 };	/* reserve (don't use) some
  * option registration
  * 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)
 	if (!option)
 		return NULL;
 		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;
-
-	return option;
-}
-
-struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev)
-{
-	struct pnp_option *option;
-
-	option = pnp_build_option(PNP_RES_PRIORITY_PREFERRED);
-
-	/* 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;
+	option->flags = option_flags;
+	option->type = type;
 
 
-	dev_dbg(&dev->dev, "new independent option\n");
+	list_add_tail(&option->list, &dev->options);
 	return option;
 	return option;
 }
 }
 
 
-struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
-						 int priority)
+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_option *option;
+	struct pnp_irq *irq;
 
 
-	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
+	option = pnp_build_option(dev, IORESOURCE_IRQ, option_flags);
+	if (!option)
+		return -ENOMEM;
 
 
-	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
 #ifdef CONFIG_PCI
 	{
 	{
 		int i;
 		int i;
 
 
 		for (i = 0; i < 16; 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);
 				pcibios_penalize_isa_irq(i, 0);
 	}
 	}
 #endif
 #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;
 	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;
-
-	ptr = option->dma;
-	while (ptr && ptr->next)
-		ptr = ptr->next;
-	if (ptr)
-		ptr->next = data;
-	else
-		option->dma = data;
-
-	dev_dbg(&dev->dev, "  dma bitmask %#x flags %#x\n", data->map,
-		data->flags);
-	return 0;
-}
+	struct pnp_option *option;
+	struct pnp_dma *dma;
 
 
-int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option,
-			       struct pnp_port *data)
-{
-	struct pnp_port *ptr;
-
-	ptr = option->port;
-	while (ptr && ptr->next)
-		ptr = ptr->next;
-	if (ptr)
-		ptr->next = data;
-	else
-		option->port = data;
-
-	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);
-	return 0;
-}
+	option = pnp_build_option(dev, IORESOURCE_DMA, option_flags);
+	if (!option)
+		return -ENOMEM;
 
 
-int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option,
-			      struct pnp_mem *data)
-{
-	struct pnp_mem *ptr;
-
-	ptr = option->mem;
-	while (ptr && ptr->next)
-		ptr = ptr->next;
-	if (ptr)
-		ptr->next = data;
-	else
-		option->mem = data;
-
-	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);
+	dma = &option->u.dma;
+	dma->map = map;
+	dma->flags = flags;
+
+	dbg_pnp_show_option(dev, option);
 	return 0;
 	return 0;
 }
 }
 
 
-static void pnp_free_port(struct pnp_port *port)
+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 *next;
+	struct pnp_option *option;
+	struct pnp_port *port;
 
 
-	while (port) {
-		next = port->next;
-		kfree(port);
-		port = next;
-	}
-}
+	option = pnp_build_option(dev, IORESOURCE_IO, option_flags);
+	if (!option)
+		return -ENOMEM;
 
 
-static void pnp_free_irq(struct pnp_irq *irq)
-{
-	struct pnp_irq *next;
+	port = &option->u.port;
+	port->min = min;
+	port->max = max;
+	port->align = align;
+	port->size = size;
+	port->flags = flags;
 
 
-	while (irq) {
-		next = irq->next;
-		kfree(irq);
-		irq = next;
-	}
+	dbg_pnp_show_option(dev, option);
+	return 0;
 }
 }
 
 
-static void pnp_free_dma(struct pnp_dma *dma)
+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_dma *next;
+	struct pnp_option *option;
+	struct pnp_mem *mem;
 
 
-	while (dma) {
-		next = dma->next;
-		kfree(dma);
-		dma = next;
-	}
-}
+	option = pnp_build_option(dev, IORESOURCE_MEM, option_flags);
+	if (!option)
+		return -ENOMEM;
 
 
-static void pnp_free_mem(struct pnp_mem *mem)
-{
-	struct pnp_mem *next;
+	mem = &option->u.mem;
+	mem->min = min;
+	mem->max = max;
+	mem->align = align;
+	mem->size = size;
+	mem->flags = flags;
 
 
-	while (mem) {
-		next = mem->next;
-		kfree(mem);
-		mem = next;
-	}
+	dbg_pnp_show_option(dev, option);
+	return 0;
 }
 }
 
 
-void pnp_free_option(struct pnp_option *option)
+void pnp_free_options(struct pnp_dev *dev)
 {
 {
-	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);
+	struct pnp_option *option, *tmp;
+
+	list_for_each_entry_safe(option, tmp, &dev->options, list) {
+		list_del(&option->list);
 		kfree(option);
 		kfree(option);
-		option = next;
 	}
 	}
 }
 }
 
 
@@ -237,7 +159,7 @@ void pnp_free_option(struct pnp_option *option)
 	!((*(enda) < *(startb)) || (*(endb) < *(starta)))
 	!((*(enda) < *(startb)) || (*(endb) < *(starta)))
 
 
 #define cannot_compare(flags) \
 #define cannot_compare(flags) \
-((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED))
+((flags) & IORESOURCE_DISABLED)
 
 
 int pnp_check_port(struct pnp_dev *dev, struct resource *res)
 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;
 	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 pnp_check_irq(struct pnp_dev *dev, struct resource *res)
 {
 {
 	int i;
 	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 */
 	/* 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
 	/* check if the resource is already in use, skip if the
 	 * device is active because it itself may be in use */
 	 * 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
 #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,
 struct resource *pnp_get_resource(struct pnp_dev *dev,
 				  unsigned int type, unsigned int num)
 				  unsigned int type, unsigned int num)
 {
 {
 	struct pnp_resource *pnp_res;
 	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;
 	return NULL;
 }
 }
 EXPORT_SYMBOL(pnp_get_resource);
 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;
 	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,
 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 pnp_resource *pnp_res;
 	struct resource *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 (!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;
 		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 pnp_resource *pnp_res;
 	struct resource *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 (!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;
 		return NULL;
 	}
 	}
 
 
@@ -634,16 +548,12 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
 {
 {
 	struct pnp_resource *pnp_res;
 	struct pnp_resource *pnp_res;
 	struct resource *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 (!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;
 		return NULL;
 	}
 	}
 
 
@@ -663,16 +573,12 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
 {
 {
 	struct pnp_resource *pnp_res;
 	struct pnp_resource *pnp_res;
 	struct resource *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 (!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;
 		return NULL;
 	}
 	}
 
 
@@ -686,6 +592,52 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
 	return pnp_res;
 	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] .... */
 /* format is: pnp_reserve_irq=irq1[,irq2] .... */
 static int __init pnp_setup_reserve_irq(char *str)
 static int __init pnp_setup_reserve_irq(char *str)
 {
 {

+ 146 - 25
drivers/pnp/support.c

@@ -2,6 +2,8 @@
  * support.c - standard functions for the use of pnp protocol drivers
  * support.c - standard functions for the use of pnp protocol drivers
  *
  *
  * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
  * 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>
 #include <linux/module.h>
@@ -16,6 +18,10 @@
  */
  */
 int pnp_is_active(struct pnp_dev *dev)
 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 &&
 	if (!pnp_port_start(dev, 0) && pnp_port_len(dev, 0) <= 1 &&
 	    !pnp_mem_start(dev, 0) && pnp_mem_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)
 	    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';
 	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)
 void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
 {
 {
 #ifdef DEBUG
 #ifdef DEBUG
+	char buf[128];
+	int len = 0;
+	struct pnp_resource *pnp_res;
 	struct resource *res;
 	struct resource *res;
-	int i;
 
 
-	dev_dbg(&dev->dev, "current resources: %s\n", desc);
-
-	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);
+	if (list_empty(&dev->resources)) {
+		dev_dbg(&dev->dev, "%s: no current resources\n", desc);
+		return;
 	}
 	}
-	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);
+
+	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);
 	}
 	}
-	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);
+#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";
 	}
 	}
-	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);
+	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
 #endif
 }
 }

+ 2 - 2
drivers/pnp/system.c

@@ -60,7 +60,7 @@ static void reserve_resources_of_dev(struct pnp_dev *dev)
 	int i;
 	int i;
 
 
 	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
 	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
-		if (res->flags & IORESOURCE_UNSET)
+		if (res->flags & IORESOURCE_DISABLED)
 			continue;
 			continue;
 		if (res->start == 0)
 		if (res->start == 0)
 			continue;	/* disabled */
 			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++) {
 	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;
 			continue;
 
 
 		reserve_range(dev, res->start, res->end, 0);
 		reserve_range(dev, res->start, res->end, 0);

+ 7 - 17
drivers/serial/8250_pnp.c

@@ -383,21 +383,14 @@ static int __devinit check_name(char *name)
 	return 0;
 	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;
 	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))))
 		(dev->card && check_name(dev->card->name))))
 			return -ENODEV;
 			return -ENODEV;
 
 
-	if (check_resources(dev->independent))
-		return 0;
-
-	if (check_resources(dev->dependent))
+	if (check_resources(dev))
 		return 0;
 		return 0;
 
 
 	return -ENODEV;
 	return -ENODEV;

+ 1 - 1
include/acpi/acconfig.h

@@ -63,7 +63,7 @@
 
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 /* 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,
  * OS name, used for the _OS object.  The _OS object is essentially obsolete,

+ 1 - 0
include/acpi/acdisasm.h

@@ -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_dmar_scope[];
 extern struct acpi_dmtable_info acpi_dm_table_info_dmar0[];
 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_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_ecdt[];
 extern struct acpi_dmtable_info acpi_dm_table_info_einj[];
 extern struct acpi_dmtable_info acpi_dm_table_info_einj[];
 extern struct acpi_dmtable_info acpi_dm_table_info_einj0[];
 extern struct acpi_dmtable_info acpi_dm_table_info_einj0[];

Some files were not shown because too many files changed in this diff