From b0bf32f647a190bb4707e8da4a3af858141ad48f Mon Sep 17 00:00:00 2001 From: Dimitri Gorokhovik Date: Wed, 16 Jul 2008 20:33:34 +0200 Subject: [PATCH] --- yaml --- r: 102066 b: refs/heads/master c: 84e0f3f6c1e26588fdcb9f1b0f99d0275229bc99 h: refs/heads/master v: v3 --- [refs] | 2 +- .../ABI/testing/sysfs-firmware-acpi | 127 +-- trunk/Documentation/i2c/chips/max6875 | 2 +- trunk/Documentation/i2c/chips/pca9539 | 10 +- trunk/Documentation/i2c/chips/pcf8574 | 12 +- trunk/Documentation/i2c/chips/pcf8575 | 9 +- trunk/Documentation/kernel-parameters.txt | 5 +- trunk/Documentation/laptops/acer-wmi.txt | 2 + trunk/MAINTAINERS | 25 +- trunk/Makefile | 4 +- trunk/arch/ia64/kernel/process.c | 4 - trunk/arch/powerpc/platforms/82xx/ep8248e.c | 4 - trunk/arch/x86/kernel/acpi/processor.c | 6 - trunk/arch/x86/kernel/process.c | 28 +- trunk/arch/x86/mm/srat_32.c | 3 +- trunk/drivers/acpi/Makefile | 2 +- trunk/drivers/acpi/bay.c | 3 - trunk/drivers/acpi/bus.c | 2 +- trunk/drivers/acpi/dispatcher/dsinit.c | 2 +- trunk/drivers/acpi/dispatcher/dsmethod.c | 1 + trunk/drivers/acpi/dispatcher/dsopcode.c | 22 +- trunk/drivers/acpi/dispatcher/dswexec.c | 8 + trunk/drivers/acpi/dispatcher/dswstate.c | 20 +- trunk/drivers/acpi/dock.c | 3 - trunk/drivers/acpi/events/evevent.c | 6 +- trunk/drivers/acpi/events/evgpe.c | 36 +- trunk/drivers/acpi/events/evgpeblk.c | 18 +- trunk/drivers/acpi/events/evmisc.c | 4 +- trunk/drivers/acpi/events/evregion.c | 5 +- trunk/drivers/acpi/events/evrgnini.c | 2 +- trunk/drivers/acpi/events/evxfevnt.c | 18 +- trunk/drivers/acpi/executer/exconfig.c | 17 +- trunk/drivers/acpi/executer/exconvrt.c | 12 +- trunk/drivers/acpi/executer/excreate.c | 2 + trunk/drivers/acpi/executer/exdump.c | 67 +- trunk/drivers/acpi/executer/exfldio.c | 9 +- trunk/drivers/acpi/executer/exmisc.c | 8 +- trunk/drivers/acpi/executer/exprep.c | 8 +- trunk/drivers/acpi/executer/exregion.c | 2 +- trunk/drivers/acpi/executer/exresop.c | 4 - trunk/drivers/acpi/executer/exstore.c | 6 + trunk/drivers/acpi/fan.c | 8 +- trunk/drivers/acpi/glue.c | 3 - trunk/drivers/acpi/hardware/hwgpe.c | 52 +- trunk/drivers/acpi/namespace/nsdump.c | 6 +- trunk/drivers/acpi/namespace/nseval.c | 35 - trunk/drivers/acpi/namespace/nsinit.c | 1 + trunk/drivers/acpi/namespace/nsload.c | 3 +- trunk/drivers/acpi/namespace/nsparse.c | 15 +- trunk/drivers/acpi/namespace/nsutils.c | 50 +- trunk/drivers/acpi/namespace/nsxfeval.c | 3 +- trunk/drivers/acpi/numa.c | 4 +- trunk/drivers/acpi/parser/psargs.c | 4 +- trunk/drivers/acpi/parser/psxface.c | 4 +- trunk/drivers/acpi/pci_irq.c | 38 +- trunk/drivers/acpi/processor_core.c | 75 +- trunk/drivers/acpi/processor_idle.c | 34 +- trunk/drivers/acpi/processor_perflib.c | 18 +- trunk/drivers/acpi/processor_throttling.c | 38 +- trunk/drivers/acpi/reboot.c | 50 - trunk/drivers/acpi/resources/rscalc.c | 4 +- trunk/drivers/acpi/resources/rscreate.c | 41 +- trunk/drivers/acpi/resources/rsmisc.c | 2 +- trunk/drivers/acpi/resources/rsutils.c | 13 +- trunk/drivers/acpi/scan.c | 62 +- trunk/drivers/acpi/sleep/main.c | 39 +- trunk/drivers/acpi/system.c | 169 +--- trunk/drivers/acpi/tables/tbfadt.c | 23 +- trunk/drivers/acpi/tables/tbfind.c | 5 +- trunk/drivers/acpi/tables/tbinstal.c | 30 +- trunk/drivers/acpi/tables/tbutils.c | 15 +- trunk/drivers/acpi/tables/tbxface.c | 28 +- trunk/drivers/acpi/tables/tbxfroot.c | 4 +- trunk/drivers/acpi/utilities/utalloc.c | 5 +- trunk/drivers/acpi/utilities/utcopy.c | 4 +- trunk/drivers/acpi/utilities/utdebug.c | 54 +- trunk/drivers/acpi/utilities/utdelete.c | 2 +- trunk/drivers/acpi/utilities/uteval.c | 5 +- trunk/drivers/acpi/utilities/utmisc.c | 39 +- trunk/drivers/acpi/utilities/utmutex.c | 4 +- trunk/drivers/acpi/utilities/utobject.c | 9 +- trunk/drivers/acpi/video.c | 123 +-- trunk/drivers/char/apm-emulation.c | 346 +++---- trunk/drivers/hwmon/ad7418.c | 109 ++- trunk/drivers/hwmon/adm1021.c | 105 ++- trunk/drivers/hwmon/adm1025.c | 101 +- trunk/drivers/hwmon/adm1026.c | 109 ++- trunk/drivers/hwmon/adm1029.c | 97 +- trunk/drivers/hwmon/adm1031.c | 96 +- trunk/drivers/hwmon/adm9240.c | 93 +- trunk/drivers/hwmon/ads7828.c | 89 +- trunk/drivers/hwmon/adt7470.c | 100 +- trunk/drivers/hwmon/adt7473.c | 102 +- trunk/drivers/hwmon/asb100.c | 207 ++-- trunk/drivers/hwmon/atxp1.c | 109 +-- trunk/drivers/hwmon/ds1621.c | 99 +- trunk/drivers/hwmon/f75375s.c | 89 +- trunk/drivers/hwmon/fscher.c | 93 +- trunk/drivers/hwmon/fschmd.c | 112 ++- trunk/drivers/hwmon/fscpos.c | 94 +- trunk/drivers/hwmon/gl518sm.c | 99 +- trunk/drivers/hwmon/gl520sm.c | 91 +- trunk/drivers/hwmon/lm63.c | 99 +- trunk/drivers/hwmon/lm77.c | 102 +- trunk/drivers/hwmon/lm80.c | 94 +- trunk/drivers/hwmon/lm83.c | 104 ++- trunk/drivers/hwmon/lm87.c | 99 +- trunk/drivers/hwmon/lm90.c | 119 ++- trunk/drivers/hwmon/lm92.c | 98 +- trunk/drivers/hwmon/lm93.c | 126 +-- trunk/drivers/hwmon/max1619.c | 101 +- trunk/drivers/hwmon/max6650.c | 102 +- trunk/drivers/hwmon/smsc47m192.c | 102 +- trunk/drivers/hwmon/thmc50.c | 107 +-- trunk/drivers/hwmon/w83791d.c | 205 ++-- trunk/drivers/hwmon/w83792d.c | 214 +++-- trunk/drivers/hwmon/w83793.c | 227 +++-- trunk/drivers/hwmon/w83l785ts.c | 117 ++- trunk/drivers/hwmon/w83l786ng.c | 98 +- trunk/drivers/i2c/busses/i2c-amd756-s4882.c | 27 +- trunk/drivers/i2c/busses/i2c-nforce2-s4985.c | 31 +- trunk/drivers/i2c/chips/eeprom.c | 92 +- trunk/drivers/i2c/chips/max6875.c | 120 ++- trunk/drivers/i2c/chips/pca9539.c | 109 ++- trunk/drivers/i2c/chips/pcf8574.c | 108 ++- trunk/drivers/i2c/chips/pcf8575.c | 96 +- trunk/drivers/i2c/chips/pcf8591.c | 94 +- trunk/drivers/i2c/i2c-core.c | 4 - trunk/drivers/ide/pci/it821x.c | 6 + trunk/drivers/misc/Kconfig | 31 +- trunk/drivers/misc/Makefile | 5 +- trunk/drivers/misc/acer-wmi.c | 145 +-- trunk/drivers/misc/compal-laptop.c | 404 -------- trunk/drivers/misc/eeepc-laptop.c | 4 +- trunk/drivers/misc/fujitsu-laptop.c | 825 +--------------- trunk/drivers/pci/pci-acpi.c | 6 +- trunk/drivers/pci/pci.c | 4 +- trunk/drivers/pci/pci.h | 3 +- trunk/drivers/pnp/base.h | 148 +-- trunk/drivers/pnp/core.c | 29 +- trunk/drivers/pnp/interface.c | 207 ++-- trunk/drivers/pnp/isapnp/core.c | 253 +++-- trunk/drivers/pnp/manager.c | 414 +++++--- trunk/drivers/pnp/pnpacpi/core.c | 4 +- trunk/drivers/pnp/pnpacpi/rsparser.c | 492 ++++------ trunk/drivers/pnp/pnpbios/rsparser.c | 274 +++--- trunk/drivers/pnp/quirks.c | 307 +++--- trunk/drivers/pnp/resource.c | 454 +++++---- trunk/drivers/pnp/support.c | 171 +--- trunk/drivers/pnp/system.c | 4 +- trunk/drivers/serial/8250_pnp.c | 24 +- trunk/drivers/w1/masters/ds2482.c | 104 ++- trunk/firmware/.gitignore | 6 - trunk/firmware/Makefile | 2 +- trunk/fs/Kconfig | 136 +-- trunk/fs/compat_ioctl.c | 6 - trunk/fs/lockd/clntproc.c | 8 +- trunk/fs/lockd/svc4proc.c | 2 - trunk/fs/lockd/svclock.c | 7 +- trunk/fs/lockd/svcproc.c | 2 - trunk/fs/nfs/callback.c | 34 +- trunk/fs/nfs/client.c | 13 +- trunk/fs/nfs/dir.c | 88 +- trunk/fs/nfs/direct.c | 4 +- trunk/fs/nfs/file.c | 155 +-- trunk/fs/nfs/inode.c | 79 +- trunk/fs/nfs/internal.h | 1 - trunk/fs/nfs/iostat.h | 119 ++- trunk/fs/nfs/nfs3acl.c | 9 +- trunk/fs/nfs/nfs3proc.c | 275 +++--- trunk/fs/nfs/nfs4proc.c | 265 +++--- trunk/fs/nfs/nfs4state.c | 2 + trunk/fs/nfs/nfsroot.c | 10 +- trunk/fs/nfs/proc.c | 28 +- trunk/fs/nfs/super.c | 882 ++++++------------ trunk/fs/nfs/write.c | 322 +++---- trunk/fs/nfsd/nfs4callback.c | 2 +- trunk/include/acpi/acconfig.h | 2 +- trunk/include/acpi/acdisasm.h | 1 - trunk/include/acpi/acdispat.h | 2 +- trunk/include/acpi/acexcep.h | 10 +- trunk/include/acpi/acglobal.h | 2 +- trunk/include/acpi/achware.h | 4 +- trunk/include/acpi/acinterp.h | 5 +- trunk/include/acpi/aclocal.h | 6 +- trunk/include/acpi/acmacros.h | 38 +- trunk/include/acpi/acnamesp.h | 30 +- trunk/include/acpi/acpi_bus.h | 4 +- trunk/include/acpi/acpiosxf.h | 2 +- trunk/include/acpi/acpixf.h | 12 +- trunk/include/acpi/acstruct.h | 10 +- trunk/include/acpi/actables.h | 27 +- trunk/include/acpi/actbl1.h | 23 +- trunk/include/acpi/actypes.h | 16 +- trunk/include/acpi/acutils.h | 70 +- trunk/include/acpi/processor.h | 2 +- trunk/include/acpi/reboot.h | 14 +- trunk/include/asm-ia64/processor.h | 2 - trunk/include/asm-x86/processor.h | 2 - trunk/include/linux/blkdev.h | 3 - trunk/include/linux/freezer.h | 10 - trunk/include/linux/inet.h | 7 - trunk/include/linux/ioport.h | 5 - trunk/include/linux/nfs_fs.h | 10 - trunk/include/linux/nfs_iostat.h | 119 --- trunk/include/linux/nfs_page.h | 9 +- trunk/include/linux/nfs_xdr.h | 3 +- trunk/include/linux/pnp.h | 146 ++- trunk/include/linux/sched.h | 1 - trunk/include/linux/sunrpc/clnt.h | 7 +- trunk/include/linux/sunrpc/sched.h | 1 + trunk/kernel/cpu.c | 1 - trunk/kernel/kthread.c | 2 +- trunk/kernel/power/process.c | 97 +- trunk/kernel/power/user.c | 71 +- trunk/net/sunrpc/auth_gss/auth_gss.c | 27 +- trunk/net/sunrpc/auth_gss/gss_krb5_mech.c | 4 +- trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c | 4 +- trunk/net/sunrpc/auth_gss/gss_spkm3_token.c | 2 +- trunk/net/sunrpc/auth_unix.c | 2 +- trunk/net/sunrpc/clnt.c | 161 ++-- trunk/net/sunrpc/rpcb_clnt.c | 356 ++----- trunk/net/sunrpc/sched.c | 23 +- trunk/net/sunrpc/xprt.c | 9 +- trunk/net/sunrpc/xprtsock.c | 2 + 225 files changed, 6501 insertions(+), 8426 deletions(-) delete mode 100644 trunk/drivers/acpi/reboot.c delete mode 100644 trunk/drivers/misc/compal-laptop.c delete mode 100644 trunk/firmware/.gitignore delete mode 100644 trunk/include/linux/nfs_iostat.h diff --git a/[refs] b/[refs] index aa507c2e7156..76857878ad85 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 4314652bb41df08ad65bd25176ba1dfd24b14a51 +refs/heads/master: 84e0f3f6c1e26588fdcb9f1b0f99d0275229bc99 diff --git a/trunk/Documentation/ABI/testing/sysfs-firmware-acpi b/trunk/Documentation/ABI/testing/sysfs-firmware-acpi index f27be7d1a49f..9470ed9afcc0 100644 --- a/trunk/Documentation/ABI/testing/sysfs-firmware-acpi +++ b/trunk/Documentation/ABI/testing/sysfs-firmware-acpi @@ -29,46 +29,46 @@ Description: $ cd /sys/firmware/acpi/interrupts $ grep . * - 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 + 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 sci - The total number of times the ACPI SCI has claimed an interrupt. @@ -89,13 +89,6 @@ Description: error - an interrupt that can't be accounted for above. - invalid: it's either a wakeup GPE or a GPE/Fixed Event that - doesn't have an event handler. - - disable: the GPE/Fixed Event is valid but disabled. - - enable: the GPE/Fixed Event is valid and enabled. - Root has permission to clear any of these counters. Eg. # echo 0 > gpe11 @@ -104,43 +97,3 @@ Description: None of these counters has an effect on the function of the system, they are simply statistics. - - Besides this, user can also write specific strings to these files - to enable/disable/clear ACPI interrupts in user space, which can be - used to debug some ACPI interrupt storm issues. - - Note that only writting to VALID GPE/Fixed Event is allowed, - i.e. user can only change the status of runtime GPE and - Fixed Event with event handler installed. - - Let's take power button fixed event for example, please kill acpid - and other user space applications so that the machine won't shutdown - when pressing the power button. - # cat ff_pwr_btn - 0 - # press the power button for 3 times; - # cat ff_pwr_btn - 3 - # echo disable > ff_pwr_btn - # cat ff_pwr_btn - disable - # press the power button for 3 times; - # cat ff_pwr_btn - disable - # echo enable > ff_pwr_btn - # cat ff_pwr_btn - 4 - /* - * this is because the status bit is set even if the enable bit is cleared, - * and it triggers an ACPI fixed event when the enable bit is set again - */ - # press the power button for 3 times; - # cat ff_pwr_btn - 7 - # echo disable > ff_pwr_btn - # press the power button for 3 times; - # echo clear > ff_pwr_btn /* clear the status bit */ - # echo disable > ff_pwr_btn - # cat ff_pwr_btn - 7 - diff --git a/trunk/Documentation/i2c/chips/max6875 b/trunk/Documentation/i2c/chips/max6875 index 10ca43cd1a72..a0cd8af2f408 100644 --- a/trunk/Documentation/i2c/chips/max6875 +++ b/trunk/Documentation/i2c/chips/max6875 @@ -49,7 +49,7 @@ $ modprobe max6875 force=0,0x50 The MAX6874/MAX6875 ignores address bit 0, so this driver attaches to multiple addresses. For example, for address 0x50, it also reserves 0x51. -The even-address instance is called 'max6875', the odd one is 'dummy'. +The even-address instance is called 'max6875', the odd one is 'max6875 subclient'. Programming the chip using i2c-dev diff --git a/trunk/Documentation/i2c/chips/pca9539 b/trunk/Documentation/i2c/chips/pca9539 index 6aff890088b1..1d81c530c4a5 100644 --- a/trunk/Documentation/i2c/chips/pca9539 +++ b/trunk/Documentation/i2c/chips/pca9539 @@ -7,7 +7,7 @@ drivers/gpio/pca9539.c instead. Supported chips: * Philips PCA9539 Prefix: 'pca9539' - Addresses scanned: none + Addresses scanned: 0x74 - 0x77 Datasheet: http://www.semiconductors.philips.com/acrobat/datasheets/PCA9539_2.pdf @@ -23,14 +23,6 @@ The input sense can also be inverted. The 16 lines are split between two bytes. -Detection ---------- - -The PCA9539 is difficult to detect and not commonly found in PC machines, -so you have to pass the I2C bus and address of the installed PCA9539 -devices explicitly to the driver at load time via the force=... parameter. - - Sysfs entries ------------- diff --git a/trunk/Documentation/i2c/chips/pcf8574 b/trunk/Documentation/i2c/chips/pcf8574 index 235815c075ff..5c1ad1376b62 100644 --- a/trunk/Documentation/i2c/chips/pcf8574 +++ b/trunk/Documentation/i2c/chips/pcf8574 @@ -4,13 +4,13 @@ Kernel driver pcf8574 Supported chips: * Philips PCF8574 Prefix: 'pcf8574' - Addresses scanned: none + Addresses scanned: I2C 0x20 - 0x27 Datasheet: Publicly available at the Philips Semiconductors website http://www.semiconductors.philips.com/pip/PCF8574P.html * Philips PCF8574A Prefix: 'pcf8574a' - Addresses scanned: none + Addresses scanned: I2C 0x38 - 0x3f Datasheet: Publicly available at the Philips Semiconductors website http://www.semiconductors.philips.com/pip/PCF8574P.html @@ -38,10 +38,12 @@ For more informations see the datasheet. Accessing PCF8574(A) via /sys interface ------------------------------------- +! Be careful ! The PCF8574(A) is plainly impossible to detect ! Stupid chip. -So, you have to pass the I2C bus and address of the installed PCF857A -and PCF8574A devices explicitly to the driver at load time via the -force=... parameter. +So every chip with address in the interval [20..27] and [38..3f] are +detected as PCF8574(A). If you have other chips in this address +range, the workaround is to load this module after the one +for your others chips. On detection (i.e. insmod, modprobe et al.), directories are being created for each detected PCF8574(A): diff --git a/trunk/Documentation/i2c/chips/pcf8575 b/trunk/Documentation/i2c/chips/pcf8575 index 40b268eb276f..25f5698a61cf 100644 --- a/trunk/Documentation/i2c/chips/pcf8575 +++ b/trunk/Documentation/i2c/chips/pcf8575 @@ -40,9 +40,12 @@ Detection --------- There is no method known to detect whether a chip on a given I2C address is -a PCF8575 or whether it is any other I2C device, so you have to pass the I2C -bus and address of the installed PCF8575 devices explicitly to the driver at -load time via the force=... parameter. +a PCF8575 or whether it is any other I2C device. So there are two alternatives +to let the driver find the installed PCF8575 devices: +- Load this driver after any other I2C driver for I2C devices with addresses + in the range 0x20 .. 0x27. +- Pass the I2C bus and address of the installed PCF8575 devices explicitly to + the driver at load time via the probe=... or force=... parameters. /sys interface -------------- diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index 5e497d16fb51..312fe77764a4 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/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. idle= [X86] - Format: idle=poll or idle=mwait, idle=halt, idle=nomwait + Format: idle=poll or idle=mwait Poll forces a polling idle loop that can slightly improves the performance of waking up a idle CPU, but will use a lot of power and make the system run hot. Not recommended. @@ -826,9 +826,6 @@ and is between 256 and 4096 characters. It is defined in the file to not use it because it doesn't save as much power as a normal idle loop use the MONITOR/MWAIT idle loop anyways. Performance should be the same as idle=poll. - idle=halt. Halt is forced to be used for CPU idle. - In such case C2/C3 won't be used again. - idle=nomwait. Disable mwait for CPU C-states ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem Claim all unknown PCI IDE storage controllers. diff --git a/trunk/Documentation/laptops/acer-wmi.txt b/trunk/Documentation/laptops/acer-wmi.txt index 69b5dd4e5a59..79b7dbd22141 100644 --- a/trunk/Documentation/laptops/acer-wmi.txt +++ b/trunk/Documentation/laptops/acer-wmi.txt @@ -174,6 +174,8 @@ The LED is exposed through the LED subsystem, and can be found in: The mail LED is autodetected, so if you don't have one, the LED device won't be registered. +If you have a mail LED that is not green, please report this to me. + Backlight ********* diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 633bda666e45..ee1c56a20750 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -216,8 +216,8 @@ W: http://code.google.com/p/aceracpi S: Maintained ACPI -P: Andi Kleen -M: ak@linux.intel.com +P: Len Brown +M: len.brown@intel.com M: lenb@kernel.org L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ @@ -239,8 +239,8 @@ W: http://www.lesswatts.org/projects/acpi/ S: Supported ACPI FAN DRIVER -P: Zhang Rui -M: rui.zhang@intel.com +P: Len Brown +M: len.brown@intel.com L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ S: Supported @@ -252,14 +252,14 @@ L: pcihpd-discuss@lists.sourceforge.net S: Supported ACPI THERMAL DRIVER -P: Zhang Rui -M: rui.zhang@intel.com +P: Len Brown +M: len.brown@intel.com L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ S: Supported ACPI VIDEO DRIVER -P: Zhang Rui +P: Rui Zhang M: rui.zhang@intel.com L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ @@ -1160,11 +1160,6 @@ M: scott@spiteful.org L: pcihpd-discuss@lists.sourceforge.net S: Supported -COMPAL LAPTOP SUPPORT -P: Cezary Jackiewicz -M: cezary.jackiewicz@gmail.com -S: Maintained - COMPUTONE INTELLIPORT MULTIPORT CARD P: Michael H. Warfield M: mhw@wittsend.com @@ -1792,12 +1787,6 @@ P: David Howells M: dhowells@redhat.com S: Maintained -FUJITSU LAPTOP EXTRAS -P: Jonathan Woithe -M: jwoithe@physics.adelaide.edu.au -L: linux-acpi@vger.kernel.org -S: Maintained - FUSE: FILESYSTEM IN USERSPACE P: Miklos Szeredi M: miklos@szeredi.hu diff --git a/trunk/Makefile b/trunk/Makefile index 1564577bdc53..8a2a275be304 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -508,8 +508,6 @@ else KBUILD_CFLAGS += -O2 endif -include $(srctree)/arch/$(SRCARCH)/Makefile - ifneq (CONFIG_FRAME_WARN,0) KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN}) endif @@ -518,6 +516,8 @@ endif # Arch Makefiles may override this setting KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector) +include $(srctree)/arch/$(SRCARCH)/Makefile + ifdef CONFIG_FRAME_POINTER KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls else diff --git a/trunk/arch/ia64/kernel/process.c b/trunk/arch/ia64/kernel/process.c index 3ab8373103ec..fabaf08d9a69 100644 --- a/trunk/arch/ia64/kernel/process.c +++ b/trunk/arch/ia64/kernel/process.c @@ -55,10 +55,6 @@ void (*ia64_mark_idle)(int); unsigned long boot_option_idle_override = 0; EXPORT_SYMBOL(boot_option_idle_override); -unsigned long idle_halt; -EXPORT_SYMBOL(idle_halt); -unsigned long idle_nomwait; -EXPORT_SYMBOL(idle_nomwait); void ia64_do_show_stack (struct unw_frame_info *info, void *arg) diff --git a/trunk/arch/powerpc/platforms/82xx/ep8248e.c b/trunk/arch/powerpc/platforms/82xx/ep8248e.c index 373e993a5ed5..d5770fdf7f09 100644 --- a/trunk/arch/powerpc/platforms/82xx/ep8248e.c +++ b/trunk/arch/powerpc/platforms/82xx/ep8248e.c @@ -59,7 +59,6 @@ static void __init ep8248e_pic_init(void) of_node_put(np); } -#ifdef CONFIG_FS_ENET_MDIO_FCC static void ep8248e_set_mdc(struct mdiobb_ctrl *ctrl, int level) { if (level) @@ -165,7 +164,6 @@ static struct of_platform_driver ep8248e_mdio_driver = { .probe = ep8248e_mdio_probe, .remove = ep8248e_mdio_remove, }; -#endif struct cpm_pin { int port, pin, flags; @@ -298,9 +296,7 @@ static __initdata struct of_device_id of_bus_ids[] = { static int __init declare_of_platform_devices(void) { of_platform_bus_probe(NULL, of_bus_ids, NULL); -#ifdef CONFIG_FS_ENET_MDIO_FCC of_register_platform_driver(&ep8248e_mdio_driver); -#endif return 0; } diff --git a/trunk/arch/x86/kernel/acpi/processor.c b/trunk/arch/x86/kernel/acpi/processor.c index 7c074eec39fb..de2d2e4ebad9 100644 --- a/trunk/arch/x86/kernel/acpi/processor.c +++ b/trunk/arch/x86/kernel/acpi/processor.c @@ -56,12 +56,6 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) if (cpu_has(c, X86_FEATURE_ACPI)) buf[2] |= ACPI_PDC_T_FFH; - /* - * If mwait/monitor is unsupported, C2/C3_FFH will be disabled - */ - if (!cpu_has(c, X86_FEATURE_MWAIT)) - buf[2] &= ~(ACPI_PDC_C_C2C3_FFH); - obj->type = ACPI_TYPE_BUFFER; obj->buffer.length = 12; obj->buffer.pointer = (u8 *) buf; diff --git a/trunk/arch/x86/kernel/process.c b/trunk/arch/x86/kernel/process.c index 4d629c62f4f8..7dceea947232 100644 --- a/trunk/arch/x86/kernel/process.c +++ b/trunk/arch/x86/kernel/process.c @@ -7,12 +7,6 @@ #include #include #include -#include - -unsigned long idle_halt; -EXPORT_SYMBOL(idle_halt); -unsigned long idle_nomwait; -EXPORT_SYMBOL(idle_nomwait); struct kmem_cache *task_xstate_cachep; @@ -331,27 +325,7 @@ static int __init idle_setup(char *str) pm_idle = poll_idle; } else if (!strcmp(str, "mwait")) force_mwait = 1; - 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 + else return -1; boot_option_idle_override = 1; diff --git a/trunk/arch/x86/mm/srat_32.c b/trunk/arch/x86/mm/srat_32.c index 1eb2973a301c..f41d67f8f831 100644 --- a/trunk/arch/x86/mm/srat_32.c +++ b/trunk/arch/x86/mm/srat_32.c @@ -156,9 +156,10 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *memory_affinity) num_memory_chunks++; - printk(KERN_DEBUG "Memory range %08lx to %08lx" + printk(KERN_DEBUG "Memory range %08lx to %08lx (type %x)" " in proximity domain %02x %s\n", start_pfn, end_pfn, + memory_affinity->memory_type, pxm, ((memory_affinity->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) ? "enabled and removable" : "enabled" ) ); diff --git a/trunk/drivers/acpi/Makefile b/trunk/drivers/acpi/Makefile index 4efbe598c817..40b0fcae4c78 100644 --- a/trunk/drivers/acpi/Makefile +++ b/trunk/drivers/acpi/Makefile @@ -21,7 +21,7 @@ obj-$(CONFIG_X86) += blacklist.o # # ACPI Core Subsystem (Interpreter) # -obj-y += osl.o utils.o reboot.o\ +obj-y += osl.o utils.o \ dispatcher/ events/ executer/ hardware/ \ namespace/ parser/ resources/ tables/ \ utilities/ diff --git a/trunk/drivers/acpi/bay.c b/trunk/drivers/acpi/bay.c index e6caf5d42e0e..61b6c5beb2d3 100644 --- a/trunk/drivers/acpi/bay.c +++ b/trunk/drivers/acpi/bay.c @@ -377,9 +377,6 @@ static int __init bay_init(void) INIT_LIST_HEAD(&drive_bays); - if (acpi_disabled) - return -ENODEV; - if (acpi_disabled) return -ENODEV; diff --git a/trunk/drivers/acpi/bus.c b/trunk/drivers/acpi/bus.c index afb34387d5f2..a6dbcf4d9ef5 100644 --- a/trunk/drivers/acpi/bus.c +++ b/trunk/drivers/acpi/bus.c @@ -612,7 +612,7 @@ static int __init acpi_bus_init_irq(void) return 0; } -u8 acpi_gbl_permanent_mmap; +acpi_native_uint acpi_gbl_permanent_mmap; void __init acpi_early_init(void) diff --git a/trunk/drivers/acpi/dispatcher/dsinit.c b/trunk/drivers/acpi/dispatcher/dsinit.c index 949f7c75029e..610b1ee102b0 100644 --- a/trunk/drivers/acpi/dispatcher/dsinit.c +++ b/trunk/drivers/acpi/dispatcher/dsinit.c @@ -151,7 +151,7 @@ acpi_ds_init_one_object(acpi_handle obj_handle, ******************************************************************************/ acpi_status -acpi_ds_initialize_objects(u32 table_index, +acpi_ds_initialize_objects(acpi_native_uint table_index, struct acpi_namespace_node * start_node) { acpi_status status; diff --git a/trunk/drivers/acpi/dispatcher/dsmethod.c b/trunk/drivers/acpi/dispatcher/dsmethod.c index 4613b9ca5792..2509809a36cf 100644 --- a/trunk/drivers/acpi/dispatcher/dsmethod.c +++ b/trunk/drivers/acpi/dispatcher/dsmethod.c @@ -377,6 +377,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, } info->parameters = &this_walk_state->operands[0]; + info->parameter_type = ACPI_PARAM_ARGS; status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node, obj_desc->method.aml_start, diff --git a/trunk/drivers/acpi/dispatcher/dsopcode.c b/trunk/drivers/acpi/dispatcher/dsopcode.c index 6a81c4400edf..a818e0ddb996 100644 --- a/trunk/drivers/acpi/dispatcher/dsopcode.c +++ b/trunk/drivers/acpi/dispatcher/dsopcode.c @@ -691,6 +691,12 @@ acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state, status = acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS, walk_state); + + ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, + acpi_ps_get_opcode_name(op->common.aml_opcode), + walk_state->num_operands, + "after AcpiExResolveOperands"); + if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)", acpi_ps_get_opcode_name(op->common.aml_opcode), @@ -779,6 +785,10 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); } + ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, + acpi_ps_get_opcode_name(op->common.aml_opcode), + 1, "after AcpiExResolveOperands"); + obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { return_ACPI_STATUS(AE_NOT_EXIST); @@ -838,7 +848,7 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, union acpi_operand_object **operand; struct acpi_namespace_node *node; union acpi_parse_object *next_op; - u32 table_index; + acpi_native_uint table_index; struct acpi_table_header *table; ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op); @@ -872,6 +882,10 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); } + ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, + acpi_ps_get_opcode_name(op->common.aml_opcode), + 1, "after AcpiExResolveOperands"); + operand = &walk_state->operands[0]; /* Find the ACPI table */ @@ -1077,8 +1091,10 @@ acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); } - ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, - acpi_ps_get_opcode_name(op->common.aml_opcode), 1); + ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, + acpi_ps_get_opcode_name(op->common.aml_opcode), + 1, "after AcpiExResolveOperands"); + /* * Get the bank_value operand and save it * (at Top of stack) diff --git a/trunk/drivers/acpi/dispatcher/dswexec.c b/trunk/drivers/acpi/dispatcher/dswexec.c index b5072fa9c920..b246b9657ead 100644 --- a/trunk/drivers/acpi/dispatcher/dswexec.c +++ b/trunk/drivers/acpi/dispatcher/dswexec.c @@ -408,6 +408,14 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) [walk_state-> num_operands - 1]), walk_state); + if (ACPI_SUCCESS(status)) { + ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, + ACPI_IMODE_EXECUTE, + acpi_ps_get_opcode_name + (walk_state->opcode), + walk_state->num_operands, + "after ExResolveOperands"); + } } if (ACPI_SUCCESS(status)) { diff --git a/trunk/drivers/acpi/dispatcher/dswstate.c b/trunk/drivers/acpi/dispatcher/dswstate.c index b00d4af791aa..1386ced332ec 100644 --- a/trunk/drivers/acpi/dispatcher/dswstate.c +++ b/trunk/drivers/acpi/dispatcher/dswstate.c @@ -70,7 +70,7 @@ acpi_status acpi_ds_result_pop(union acpi_operand_object **object, struct acpi_walk_state *walk_state) { - u32 index; + acpi_native_uint index; union acpi_generic_state *state; acpi_status status; @@ -122,7 +122,7 @@ acpi_ds_result_pop(union acpi_operand_object **object, ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] Index=%X State=%p Num=%X\n", *object, acpi_ut_get_object_type_name(*object), - index, walk_state, walk_state->result_count)); + (u32) index, walk_state, walk_state->result_count)); return (AE_OK); } @@ -146,7 +146,7 @@ acpi_ds_result_push(union acpi_operand_object * object, { union acpi_generic_state *state; acpi_status status; - u32 index; + acpi_native_uint index; ACPI_FUNCTION_NAME(ds_result_push); @@ -400,7 +400,7 @@ void acpi_ds_obj_stack_pop_and_delete(u32 pop_count, struct acpi_walk_state *walk_state) { - s32 i; + acpi_native_int i; union acpi_operand_object *obj_desc; ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete); @@ -409,7 +409,7 @@ acpi_ds_obj_stack_pop_and_delete(u32 pop_count, return; } - for (i = (s32) pop_count - 1; i >= 0; i--) { + for (i = (acpi_native_int) (pop_count - 1); i >= 0; i--) { if (walk_state->num_operands == 0) { return; } @@ -615,8 +615,14 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state, walk_state->pass_number = pass_number; if (info) { - walk_state->params = info->parameters; - walk_state->caller_return_desc = &info->return_object; + 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; + } } status = acpi_ps_init_scope(&walk_state->parser_state, op); diff --git a/trunk/drivers/acpi/dock.c b/trunk/drivers/acpi/dock.c index 1e872e79db33..bb7c51f712bd 100644 --- a/trunk/drivers/acpi/dock.c +++ b/trunk/drivers/acpi/dock.c @@ -917,9 +917,6 @@ static int __init dock_init(void) dock_station = NULL; - if (acpi_disabled) - return 0; - if (acpi_disabled) return 0; diff --git a/trunk/drivers/acpi/events/evevent.c b/trunk/drivers/acpi/events/evevent.c index c56c5c6ea77b..5d30e5be1b1c 100644 --- a/trunk/drivers/acpi/events/evevent.c +++ b/trunk/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) { - u32 i; + acpi_native_uint i; acpi_status status; /* @@ -231,7 +231,7 @@ u32 acpi_ev_fixed_event_detect(void) u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; u32 fixed_status; u32 fixed_enable; - u32 i; + acpi_native_uint i; ACPI_FUNCTION_NAME(ev_fixed_event_detect); @@ -260,7 +260,7 @@ u32 acpi_ev_fixed_event_detect(void) /* Found an active (signalled) event */ acpi_os_fixed_event_count(i); - int_status |= acpi_ev_fixed_event_dispatch(i); + int_status |= acpi_ev_fixed_event_dispatch((u32) i); } } diff --git a/trunk/drivers/acpi/events/evgpe.c b/trunk/drivers/acpi/events/evgpe.c index c5e53aae86f7..5354be44f876 100644 --- a/trunk/drivers/acpi/events/evgpe.c +++ b/trunk/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); } - /* Clear the appropriate enabled flags for this GPE */ + /* Mark wake-disabled or HW disable, or both */ switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) { case ACPI_GPE_TYPE_WAKE: @@ -273,23 +273,13 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) /* Disable the requested runtime GPE */ ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED); - break; + + /* fallthrough */ default: - break; + acpi_hw_write_gpe_enable_reg(gpe_event_info); } - /* - * 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); } @@ -315,7 +305,7 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, { union acpi_operand_object *obj_desc; struct acpi_gpe_block_info *gpe_block; - u32 i; + acpi_native_uint i; ACPI_FUNCTION_ENTRY(); @@ -389,8 +379,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) u32 status_reg; u32 enable_reg; acpi_cpu_flags flags; - u32 i; - u32 j; + acpi_native_uint i; + acpi_native_uint j; ACPI_FUNCTION_NAME(ev_gpe_detect); @@ -472,7 +462,13 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) */ int_status |= acpi_ev_gpe_dispatch(&gpe_block-> - event_info[((acpi_size) i * ACPI_GPE_REGISTER_WIDTH) + j], j + gpe_register_info->base_gpe_number); + event_info[(i * + ACPI_GPE_REGISTER_WIDTH) + + + j], + (u32) j + + gpe_register_info-> + base_gpe_number); } } } @@ -559,6 +555,10 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) */ info->prefix_node = local_gpe_event_info.dispatch.method_node; + info->parameters = + ACPI_CAST_PTR(union acpi_operand_object *, + gpe_event_info); + info->parameter_type = ACPI_PARAM_GPE; info->flags = ACPI_IGNORE_RETURN_VALUE; status = acpi_ns_evaluate(info); diff --git a/trunk/drivers/acpi/events/evgpeblk.c b/trunk/drivers/acpi/events/evgpeblk.c index 73c058e2f5c2..e6c4d4c49e79 100644 --- a/trunk/drivers/acpi/events/evgpeblk.c +++ b/trunk/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_event_info *gpe_event_info; - u32 i; - u32 j; + acpi_native_uint i; + acpi_native_uint j; ACPI_FUNCTION_TRACE(ev_delete_gpe_handlers); @@ -203,8 +203,7 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { gpe_event_info = &gpe_block-> - event_info[((acpi_size) i * - ACPI_GPE_REGISTER_WIDTH) + j]; + event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j]; if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) { @@ -745,8 +744,8 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) struct acpi_gpe_event_info *gpe_event_info = NULL; struct acpi_gpe_event_info *this_event; struct acpi_gpe_register_info *this_register; - u32 i; - u32 j; + acpi_native_uint i; + acpi_native_uint j; acpi_status status; ACPI_FUNCTION_TRACE(ev_create_gpe_info_blocks); @@ -984,8 +983,8 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, struct acpi_gpe_walk_info gpe_info; u32 wake_gpe_count; u32 gpe_enabled_count; - u32 i; - u32 j; + acpi_native_uint i; + acpi_native_uint j; ACPI_FUNCTION_TRACE(ev_initialize_gpe_block); @@ -1034,8 +1033,7 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, gpe_event_info = &gpe_block-> - event_info[((acpi_size) i * - ACPI_GPE_REGISTER_WIDTH) + j]; + event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j]; if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) diff --git a/trunk/drivers/acpi/events/evmisc.c b/trunk/drivers/acpi/events/evmisc.c index 1d5670be729a..2113e58e2221 100644 --- a/trunk/drivers/acpi/events/evmisc.c +++ b/trunk/drivers/acpi/events/evmisc.c @@ -575,7 +575,7 @@ acpi_status acpi_ev_release_global_lock(void) void acpi_ev_terminate(void) { - u32 i; + acpi_native_uint i; acpi_status status; ACPI_FUNCTION_TRACE(ev_terminate); @@ -589,7 +589,7 @@ void acpi_ev_terminate(void) /* Disable all fixed events */ for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { - status = acpi_disable_event(i, 0); + status = acpi_disable_event((u32) i, 0); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "Could not disable fixed event %d", diff --git a/trunk/drivers/acpi/events/evregion.c b/trunk/drivers/acpi/events/evregion.c index 236fbd1ca438..1628f5934752 100644 --- a/trunk/drivers/acpi/events/evregion.c +++ b/trunk/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 status; - u32 i; + acpi_native_uint i; ACPI_FUNCTION_TRACE(ev_install_region_handlers); @@ -151,7 +151,7 @@ acpi_status acpi_ev_install_region_handlers(void) acpi_status acpi_ev_initialize_op_regions(void) { acpi_status status; - u32 i; + acpi_native_uint i; ACPI_FUNCTION_TRACE(ev_initialize_op_regions); @@ -219,6 +219,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) info->prefix_node = region_obj2->extra.method_REG; info->pathname = NULL; info->parameters = args; + info->parameter_type = ACPI_PARAM_ARGS; info->flags = ACPI_IGNORE_RETURN_VALUE; /* diff --git a/trunk/drivers/acpi/events/evrgnini.c b/trunk/drivers/acpi/events/evrgnini.c index 6b94b38df07d..2e3d2c5e4f4d 100644 --- a/trunk/drivers/acpi/events/evrgnini.c +++ b/trunk/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; struct acpica_device_id hid; struct acpi_compatible_id_list *cid; - u32 i; + acpi_native_uint i; /* * Get the _HID and check for a PCI Root Bridge diff --git a/trunk/drivers/acpi/events/evxfevnt.c b/trunk/drivers/acpi/events/evxfevnt.c index 73bfd6bf962f..99a7502e6a87 100644 --- a/trunk/drivers/acpi/events/evxfevnt.c +++ b/trunk/drivers/acpi/events/evxfevnt.c @@ -472,6 +472,7 @@ acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) } ACPI_EXPORT_SYMBOL(acpi_clear_gpe) +#ifdef ACPI_FUTURE_USAGE /******************************************************************************* * * FUNCTION: acpi_get_event_status @@ -488,7 +489,6 @@ ACPI_EXPORT_SYMBOL(acpi_clear_gpe) acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) { acpi_status status = AE_OK; - u32 value; ACPI_FUNCTION_TRACE(acpi_get_event_status); @@ -506,20 +506,7 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) status = acpi_get_register(acpi_gbl_fixed_event_info[event]. - 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; + status_register_id, event_status); return_ACPI_STATUS(status); } @@ -579,6 +566,7 @@ acpi_get_gpe_status(acpi_handle gpe_device, } ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) +#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* * * FUNCTION: acpi_install_gpe_block diff --git a/trunk/drivers/acpi/executer/exconfig.c b/trunk/drivers/acpi/executer/exconfig.c index 2a32c843cb4a..39d742190584 100644 --- a/trunk/drivers/acpi/executer/exconfig.c +++ b/trunk/drivers/acpi/executer/exconfig.c @@ -53,7 +53,7 @@ ACPI_MODULE_NAME("exconfig") /* Local prototypes */ static acpi_status -acpi_ex_add_table(u32 table_index, +acpi_ex_add_table(acpi_native_uint table_index, struct acpi_namespace_node *parent_node, union acpi_operand_object **ddb_handle); @@ -73,7 +73,7 @@ acpi_ex_add_table(u32 table_index, ******************************************************************************/ static acpi_status -acpi_ex_add_table(u32 table_index, +acpi_ex_add_table(acpi_native_uint table_index, struct acpi_namespace_node *parent_node, union acpi_operand_object **ddb_handle) { @@ -96,8 +96,7 @@ acpi_ex_add_table(u32 table_index, /* Install the new table into the local data structures */ - obj_desc->reference.object = ACPI_CAST_PTR(void, - (unsigned long)table_index); + obj_desc->reference.object = ACPI_CAST_PTR(void, table_index); /* Add the table to the namespace */ @@ -129,12 +128,12 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, { acpi_status status; union acpi_operand_object **operand = &walk_state->operands[0]; + acpi_native_uint table_index; struct acpi_namespace_node *parent_node; struct acpi_namespace_node *start_node; struct acpi_namespace_node *parameter_node = NULL; union acpi_operand_object *ddb_handle; struct acpi_table_header *table; - u32 table_index; ACPI_FUNCTION_TRACE(ex_load_table_op); @@ -281,7 +280,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, { union acpi_operand_object *ddb_handle; struct acpi_table_desc table_desc; - u32 table_index; + acpi_native_uint table_index; acpi_status status; u32 length; @@ -438,7 +437,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) { acpi_status status = AE_OK; union acpi_operand_object *table_desc = ddb_handle; - u32 table_index; + acpi_native_uint table_index; struct acpi_table_header *table; ACPI_FUNCTION_TRACE(ex_unload_table); @@ -455,9 +454,9 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Get the table index from the ddb_handle (acpi_size for 64-bit case) */ + /* Get the table index from the ddb_handle */ - table_index = (u32) (acpi_size) table_desc->reference.object; + table_index = (acpi_native_uint) table_desc->reference.object; /* Invoke table handler if present */ diff --git a/trunk/drivers/acpi/executer/exconvrt.c b/trunk/drivers/acpi/executer/exconvrt.c index 261d97516d9b..fd954b4ed83d 100644 --- a/trunk/drivers/acpi/executer/exconvrt.c +++ b/trunk/drivers/acpi/executer/exconvrt.c @@ -288,11 +288,11 @@ acpi_ex_convert_to_ascii(acpi_integer integer, u16 base, u8 * string, u8 data_width) { acpi_integer digit; - u32 i; - u32 j; - u32 k = 0; - u32 hex_length; - u32 decimal_length; + acpi_native_uint i; + acpi_native_uint j; + acpi_native_uint k = 0; + acpi_native_uint hex_length; + acpi_native_uint decimal_length; u32 remainder; u8 supress_zeros; @@ -348,7 +348,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer, /* hex_length: 2 ascii hex chars per data byte */ - hex_length = ACPI_MUL_2(data_width); + hex_length = (acpi_native_uint) ACPI_MUL_2(data_width); for (i = 0, j = (hex_length - 1); i < hex_length; i++, j--) { /* Get one hex digit, most significant digits first */ diff --git a/trunk/drivers/acpi/executer/excreate.c b/trunk/drivers/acpi/executer/excreate.c index ad09696d5069..60e62c4f0577 100644 --- a/trunk/drivers/acpi/executer/excreate.c +++ b/trunk/drivers/acpi/executer/excreate.c @@ -45,6 +45,8 @@ #include #include #include +#include +#include #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("excreate") diff --git a/trunk/drivers/acpi/executer/exdump.c b/trunk/drivers/acpi/executer/exdump.c index 2be2e2bf95bf..74f1b22601b3 100644 --- a/trunk/drivers/acpi/executer/exdump.c +++ b/trunk/drivers/acpi/executer/exdump.c @@ -580,22 +580,25 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) case ACPI_TYPE_BUFFER: - acpi_os_printf("Buffer length %.2X @ %p\n", + acpi_os_printf("Buffer len %X @ %p\n", obj_desc->buffer.length, obj_desc->buffer.pointer); + length = obj_desc->buffer.length; + if (length > 64) { + length = 64; + } + /* Debug only -- dump the buffer contents */ if (obj_desc->buffer.pointer) { - length = obj_desc->buffer.length; - if (length > 128) { - length = 128; - } + acpi_os_printf("Buffer Contents: "); - acpi_os_printf - ("Buffer Contents: (displaying length 0x%.2X)\n", - length); - ACPI_DUMP_BUFFER(obj_desc->buffer.pointer, length); + for (index = 0; index < length; index++) { + acpi_os_printf(" %02x", + obj_desc->buffer.pointer[index]); + } + acpi_os_printf("\n"); } break; @@ -753,42 +756,54 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) * * FUNCTION: acpi_ex_dump_operands * - * PARAMETERS: Operands - A list of Operand objects - * opcode_name - AML opcode name - * num_operands - Operand count for this opcode + * 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 * - * DESCRIPTION: Dump the operands associated with the opcode + * DESCRIPTION: Dump the object stack * ******************************************************************************/ void acpi_ex_dump_operands(union acpi_operand_object **operands, - const char *opcode_name, u32 num_operands) + acpi_interpreter_mode interpreter_mode, + char *ident, + u32 num_levels, + char *note, char *module_name, u32 line_number) { + acpi_native_uint i; + ACPI_FUNCTION_NAME(ex_dump_operands); - if (!opcode_name) { - opcode_name = "UNKNOWN"; + if (!ident) { + ident = "?"; + } + + if (!note) { + note = "?"; } ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "**** Start operand dump for opcode [%s], %d operands\n", - opcode_name, num_operands)); + "************* Operand Stack Contents (Opcode [%s], %d Operands)\n", + ident, num_levels)); - if (num_operands == 0) { - num_operands = 1; + if (num_levels == 0) { + num_levels = 1; } - /* Dump the individual operands */ + /* Dump the operand stack starting at the top */ - while (num_operands) { - acpi_ex_dump_operand(*operands, 0); - operands++; - num_operands--; + for (i = 0; num_levels > 0; i--, num_levels--) { + acpi_ex_dump_operand(operands[i], 0); } ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "**** End operand dump for [%s]\n", opcode_name)); + "************* Operand Stack dump from %s(%d), %s\n", + module_name, line_number, note)); return; } diff --git a/trunk/drivers/acpi/executer/exfldio.c b/trunk/drivers/acpi/executer/exfldio.c index 9ff9d1f4615d..e336b5dc7a50 100644 --- a/trunk/drivers/acpi/executer/exfldio.c +++ b/trunk/drivers/acpi/executer/exfldio.c @@ -153,15 +153,14 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, /* * Slack mode only: We will go ahead and allow access to this * field if it is within the region length rounded up to the next - * access width boundary. acpi_size cast for 64-bit compile. + * access width boundary. */ if (ACPI_ROUND_UP(rgn_desc->region.length, obj_desc->common_field. access_byte_width) >= - ((acpi_size) obj_desc->common_field. - base_byte_offset + - obj_desc->common_field.access_byte_width + - field_datum_byte_offset)) { + (obj_desc->common_field.base_byte_offset + + (acpi_native_uint) obj_desc->common_field. + access_byte_width + field_datum_byte_offset)) { return_ACPI_STATUS(AE_OK); } } diff --git a/trunk/drivers/acpi/executer/exmisc.c b/trunk/drivers/acpi/executer/exmisc.c index 731414a581a6..cc956a5b5267 100644 --- a/trunk/drivers/acpi/executer/exmisc.c +++ b/trunk/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 */ - return_desc = acpi_ut_create_string_object(((acpi_size) - operand0->string. + return_desc = acpi_ut_create_string_object((acpi_size) + (operand0->string. length + local_operand1-> string.length)); @@ -352,8 +352,8 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, /* Result of two Buffers is a Buffer */ - return_desc = acpi_ut_create_buffer_object(((acpi_size) - operand0->buffer. + return_desc = acpi_ut_create_buffer_object((acpi_size) + (operand0->buffer. length + local_operand1-> buffer.length)); diff --git a/trunk/drivers/acpi/executer/exprep.c b/trunk/drivers/acpi/executer/exprep.c index 5d438c32989d..3a2f8cd4c62a 100644 --- a/trunk/drivers/acpi/executer/exprep.c +++ b/trunk/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->extra.aml_start = - ACPI_CAST_PTR(union acpi_parse_object, - info->data_register_node)->named.data; + ((union acpi_parse_object *)(info->data_register_node))-> + named.data; second_desc->extra.aml_length = - ACPI_CAST_PTR(union acpi_parse_object, - info->data_register_node)->named.length; + ((union acpi_parse_object *)(info->data_register_node))-> + named.length; break; diff --git a/trunk/drivers/acpi/executer/exregion.c b/trunk/drivers/acpi/executer/exregion.c index 7a41c409ae4d..7cd8bb54fa01 100644 --- a/trunk/drivers/acpi/executer/exregion.c +++ b/trunk/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 */ mem_info->mapped_logical_address = - acpi_os_map_memory((acpi_physical_address) address, window_size); + acpi_os_map_memory((acpi_native_uint) address, window_size); if (!mem_info->mapped_logical_address) { ACPI_ERROR((AE_INFO, "Could not map memory at %8.8X%8.8X, size %X", diff --git a/trunk/drivers/acpi/executer/exresop.c b/trunk/drivers/acpi/executer/exresop.c index 54085f16ec28..73e29e566a70 100644 --- a/trunk/drivers/acpi/executer/exresop.c +++ b/trunk/drivers/acpi/executer/exresop.c @@ -698,9 +698,5 @@ 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); } diff --git a/trunk/drivers/acpi/executer/exstore.c b/trunk/drivers/acpi/executer/exstore.c index 38b55e352495..76c875bc3154 100644 --- a/trunk/drivers/acpi/executer/exstore.c +++ b/trunk/drivers/acpi/executer/exstore.c @@ -343,6 +343,12 @@ acpi_ex_store(union acpi_operand_object *source_desc, acpi_ut_get_object_type_name(dest_desc), dest_desc)); + ACPI_DUMP_STACK_ENTRY(source_desc); + ACPI_DUMP_STACK_ENTRY(dest_desc); + ACPI_DUMP_OPERANDS(&dest_desc, ACPI_IMODE_EXECUTE, "ExStore", + 2, + "Target is not a Reference or Constant object"); + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } diff --git a/trunk/drivers/acpi/fan.c b/trunk/drivers/acpi/fan.c index 55c17afbe669..6cf10cbc1eee 100644 --- a/trunk/drivers/acpi/fan.c +++ b/trunk/drivers/acpi/fan.c @@ -148,7 +148,7 @@ acpi_fan_write_state(struct file *file, const char __user * buffer, int result = 0; struct seq_file *m = file->private_data; struct acpi_device *device = m->private; - char state_string[3] = { '\0' }; + char state_string[12] = { '\0' }; if (count > sizeof(state_string) - 1) return -EINVAL; @@ -157,12 +157,6 @@ acpi_fan_write_state(struct file *file, const char __user * buffer, return -EFAULT; state_string[count] = '\0'; - if ((state_string[0] < '0') || (state_string[0] > '3')) - return -EINVAL; - if (state_string[1] == '\n') - state_string[1] = '\0'; - if (state_string[1] != '\0') - return -EINVAL; result = acpi_bus_set_power(device->handle, simple_strtoul(state_string, NULL, 0)); diff --git a/trunk/drivers/acpi/glue.c b/trunk/drivers/acpi/glue.c index 6d18ca34b6aa..9b227d4dc9c9 100644 --- a/trunk/drivers/acpi/glue.c +++ b/trunk/drivers/acpi/glue.c @@ -333,9 +333,6 @@ static int __init acpi_rtc_init(void) { struct device *dev = get_rtc_dev(); - if (acpi_disabled) - return 0; - if (acpi_disabled) return 0; diff --git a/trunk/drivers/acpi/hardware/hwgpe.c b/trunk/drivers/acpi/hardware/hwgpe.c index 0b80db9d9197..14bc4f456ae8 100644 --- a/trunk/drivers/acpi/hardware/hwgpe.c +++ b/trunk/drivers/acpi/hardware/hwgpe.c @@ -53,54 +53,6 @@ static acpi_status acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, struct acpi_gpe_block_info *gpe_block); -/****************************************************************************** - * - * FUNCTION: acpi_hw_low_disable_gpe - * - * PARAMETERS: gpe_event_info - Info block for the GPE to be disabled - * - * RETURN: Status - * - * DESCRIPTION: Disable a single GPE in the enable register. - * - ******************************************************************************/ - -acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) -{ - struct acpi_gpe_register_info *gpe_register_info; - acpi_status status; - u32 enable_mask; - - /* Get the info block for the entire GPE register */ - - gpe_register_info = gpe_event_info->register_info; - if (!gpe_register_info) { - return (AE_NOT_EXIST); - } - - /* Get current value of the enable register that contains this GPE */ - - status = acpi_hw_low_level_read(ACPI_GPE_REGISTER_WIDTH, &enable_mask, - &gpe_register_info->enable_address); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* Clear just the bit that corresponds to this GPE */ - - ACPI_CLEAR_BIT(enable_mask, - ((u32) 1 << - (gpe_event_info->gpe_number - - gpe_register_info->base_gpe_number))); - - /* Write the updated enable mask */ - - status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, enable_mask, - &gpe_register_info->enable_address); - - return (status); -} - /****************************************************************************** * * FUNCTION: acpi_hw_write_gpe_enable_reg @@ -116,7 +68,7 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) ******************************************************************************/ acpi_status -acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info) +acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info *gpe_event_info) { struct acpi_gpe_register_info *gpe_register_info; acpi_status status; @@ -186,6 +138,7 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info) * ******************************************************************************/ +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, acpi_event_status * event_status) @@ -245,6 +198,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, unlock_and_exit: return (status); } +#endif /* ACPI_FUTURE_USAGE */ /****************************************************************************** * diff --git a/trunk/drivers/acpi/namespace/nsdump.c b/trunk/drivers/acpi/namespace/nsdump.c index 0ab22004728a..5445751b8a3e 100644 --- a/trunk/drivers/acpi/namespace/nsdump.c +++ b/trunk/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) { - u32 i; + acpi_native_uint i; ACPI_FUNCTION_NAME(ns_print_pathname); @@ -515,12 +515,12 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, if (obj_type > ACPI_TYPE_LOCAL_MAX) { acpi_os_printf - ("(Pointer to ACPI Object type %.2X [UNKNOWN])\n", + ("(Ptr to ACPI Object type %X [UNKNOWN])\n", obj_type); bytes_to_dump = 32; } else { acpi_os_printf - ("(Pointer to ACPI Object type %.2X [%s])\n", + ("(Ptr to ACPI Object type %X [%s])\n", obj_type, acpi_ut_get_type_name(obj_type)); bytes_to_dump = sizeof(union acpi_operand_object); diff --git a/trunk/drivers/acpi/namespace/nseval.c b/trunk/drivers/acpi/namespace/nseval.c index d369164e00b0..14bdfa92bea0 100644 --- a/trunk/drivers/acpi/namespace/nseval.c +++ b/trunk/drivers/acpi/namespace/nseval.c @@ -138,41 +138,6 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) return_ACPI_STATUS(AE_NULL_OBJECT); } - /* - * Calculate the number of arguments being passed to the method - */ - - info->param_count = 0; - if (info->parameters) { - while (info->parameters[info->param_count]) - info->param_count++; - } - - /* Error if too few arguments were passed in */ - - if (info->param_count < info->obj_desc->method.param_count) { - ACPI_ERROR((AE_INFO, - "Insufficient arguments - " - "method [%4.4s] needs %d, found %d", - acpi_ut_get_node_name(info->resolved_node), - info->obj_desc->method.param_count, - info->param_count)); - return_ACPI_STATUS(AE_MISSING_ARGUMENTS); - } - - /* Just a warning if too many arguments */ - - else if (info->param_count > - info->obj_desc->method.param_count) { - ACPI_WARNING((AE_INFO, - "Excess arguments - " - "method [%4.4s] needs %d, found %d", - acpi_ut_get_node_name(info-> - resolved_node), - info->obj_desc->method.param_count, - info->param_count)); - } - ACPI_DUMP_PATHNAME(info->resolved_node, "Execute Method:", ACPI_LV_INFO, _COMPONENT); diff --git a/trunk/drivers/acpi/namespace/nsinit.c b/trunk/drivers/acpi/namespace/nsinit.c index e4c57510d798..6d6d930c8e18 100644 --- a/trunk/drivers/acpi/namespace/nsinit.c +++ b/trunk/drivers/acpi/namespace/nsinit.c @@ -542,6 +542,7 @@ acpi_ns_init_one_device(acpi_handle obj_handle, info->prefix_node = device_node; info->pathname = METHOD_NAME__INI; info->parameters = NULL; + info->parameter_type = ACPI_PARAM_ARGS; info->flags = ACPI_IGNORE_RETURN_VALUE; /* diff --git a/trunk/drivers/acpi/namespace/nsload.c b/trunk/drivers/acpi/namespace/nsload.c index a4a412b7c029..2c92f6cf5ce1 100644 --- a/trunk/drivers/acpi/namespace/nsload.c +++ b/trunk/drivers/acpi/namespace/nsload.c @@ -71,7 +71,8 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle); ******************************************************************************/ acpi_status -acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node) +acpi_ns_load_table(acpi_native_uint table_index, + struct acpi_namespace_node *node) { acpi_status status; diff --git a/trunk/drivers/acpi/namespace/nsparse.c b/trunk/drivers/acpi/namespace/nsparse.c index a82271a9dbb3..46a79b0103b6 100644 --- a/trunk/drivers/acpi/namespace/nsparse.c +++ b/trunk/drivers/acpi/namespace/nsparse.c @@ -63,13 +63,13 @@ ACPI_MODULE_NAME("nsparse") * ******************************************************************************/ acpi_status -acpi_ns_one_complete_parse(u32 pass_number, - u32 table_index, - struct acpi_namespace_node *start_node) +acpi_ns_one_complete_parse(acpi_native_uint pass_number, + acpi_native_uint table_index, + struct acpi_namespace_node * start_node) { union acpi_parse_object *parse_root; acpi_status status; - u32 aml_length; + acpi_native_uint aml_length; u8 *aml_start; struct acpi_walk_state *walk_state; struct acpi_table_header *table; @@ -112,8 +112,8 @@ acpi_ns_one_complete_parse(u32 pass_number, aml_start = (u8 *) table + sizeof(struct acpi_table_header); aml_length = table->length - sizeof(struct acpi_table_header); status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL, - aml_start, aml_length, NULL, - (u8) pass_number); + aml_start, (u32) aml_length, + NULL, (u8) pass_number); } if (ACPI_FAILURE(status)) { @@ -158,7 +158,8 @@ acpi_ns_one_complete_parse(u32 pass_number, ******************************************************************************/ acpi_status -acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node) +acpi_ns_parse_table(acpi_native_uint table_index, + struct acpi_namespace_node *start_node) { acpi_status status; diff --git a/trunk/drivers/acpi/namespace/nsutils.c b/trunk/drivers/acpi/namespace/nsutils.c index b0817e1127b1..64c039843ed2 100644 --- a/trunk/drivers/acpi/namespace/nsutils.c +++ b/trunk/drivers/acpi/namespace/nsutils.c @@ -73,9 +73,9 @@ acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search); ******************************************************************************/ void -acpi_ns_report_error(const char *module_name, +acpi_ns_report_error(char *module_name, u32 line_number, - const char *internal_name, acpi_status lookup_status) + char *internal_name, acpi_status lookup_status) { acpi_status status; u32 bad_name; @@ -130,11 +130,11 @@ acpi_ns_report_error(const char *module_name, ******************************************************************************/ void -acpi_ns_report_method_error(const char *module_name, +acpi_ns_report_method_error(char *module_name, u32 line_number, - const char *message, + char *message, struct acpi_namespace_node *prefix_node, - const char *path, acpi_status method_status) + char *path, acpi_status method_status) { acpi_status status; struct acpi_namespace_node *node = prefix_node; @@ -167,8 +167,7 @@ acpi_ns_report_method_error(const char *module_name, ******************************************************************************/ void -acpi_ns_print_node_pathname(struct acpi_namespace_node *node, - const char *message) +acpi_ns_print_node_pathname(struct acpi_namespace_node *node, char *message) { struct acpi_buffer buffer; acpi_status status; @@ -297,7 +296,7 @@ u32 acpi_ns_local(acpi_object_type type) void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info) { - const char *next_external_char; + char *next_external_char; u32 i; ACPI_FUNCTION_ENTRY(); @@ -364,9 +363,9 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) { u32 num_segments = info->num_segments; char *internal_name = info->internal_name; - const char *external_name = info->next_external_char; + char *external_name = info->next_external_char; char *result = NULL; - u32 i; + acpi_native_uint i; ACPI_FUNCTION_TRACE(ns_build_internal_name); @@ -401,11 +400,12 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) result = &internal_name[i]; } else if (num_segments == 2) { internal_name[i] = AML_DUAL_NAME_PREFIX; - result = &internal_name[(acpi_size) i + 1]; + result = &internal_name[(acpi_native_uint) (i + 1)]; } else { internal_name[i] = AML_MULTI_NAME_PREFIX_OP; - internal_name[(acpi_size) i + 1] = (char)num_segments; - result = &internal_name[(acpi_size) i + 2]; + internal_name[(acpi_native_uint) (i + 1)] = + (char)num_segments; + result = &internal_name[(acpi_native_uint) (i + 2)]; } } @@ -472,8 +472,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) * *******************************************************************************/ -acpi_status -acpi_ns_internalize_name(const char *external_name, char **converted_name) +acpi_status acpi_ns_internalize_name(char *external_name, char **converted_name) { char *internal_name; struct acpi_namestring_info info; @@ -529,15 +528,15 @@ acpi_ns_internalize_name(const char *external_name, char **converted_name) acpi_status acpi_ns_externalize_name(u32 internal_name_length, - const char *internal_name, + char *internal_name, u32 * converted_name_length, char **converted_name) { - u32 names_index = 0; - u32 num_segments = 0; - u32 required_length; - u32 prefix_length = 0; - u32 i = 0; - u32 j = 0; + 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; ACPI_FUNCTION_TRACE(ns_externalize_name); @@ -583,8 +582,9 @@ acpi_ns_externalize_name(u32 internal_name_length, /* 4-byte names */ names_index = prefix_length + 2; - num_segments = (u8) - internal_name[(acpi_size) prefix_length + 1]; + num_segments = (acpi_native_uint) (u8) + internal_name[(acpi_native_uint) + (prefix_length + 1)]; break; case AML_DUAL_NAME_PREFIX: @@ -823,7 +823,7 @@ u32 acpi_ns_opens_scope(acpi_object_type type) acpi_status acpi_ns_get_node(struct acpi_namespace_node *prefix_node, - const char *pathname, + char *pathname, u32 flags, struct acpi_namespace_node **return_node) { union acpi_generic_state scope_info; diff --git a/trunk/drivers/acpi/namespace/nsxfeval.c b/trunk/drivers/acpi/namespace/nsxfeval.c index 38be5865d95d..a8d549187c84 100644 --- a/trunk/drivers/acpi/namespace/nsxfeval.c +++ b/trunk/drivers/acpi/namespace/nsxfeval.c @@ -182,6 +182,7 @@ acpi_evaluate_object(acpi_handle handle, } info->pathname = pathname; + info->parameter_type = ACPI_PARAM_ARGS; /* Convert and validate the device handle */ @@ -441,7 +442,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, u32 flags; struct acpica_device_id hid; struct acpi_compatible_id_list *cid; - u32 i; + acpi_native_uint i; int found; status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); diff --git a/trunk/drivers/acpi/numa.c b/trunk/drivers/acpi/numa.c index cb9864e39bae..658e5f3abae0 100644 --- a/trunk/drivers/acpi/numa.c +++ b/trunk/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 *)header; ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s\n", + "SRAT Memory (0x%lx length 0x%lx type 0x%x) in proximity domain %d %s%s\n", (unsigned long)p->base_address, (unsigned long)p->length, - p->proximity_domain, + p->memory_type, p->proximity_domain, (p->flags & ACPI_SRAT_MEM_ENABLED)? "enabled" : "disabled", (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)? diff --git a/trunk/drivers/acpi/parser/psargs.c b/trunk/drivers/acpi/parser/psargs.c index d830b29b85b1..e94463778845 100644 --- a/trunk/drivers/acpi/parser/psargs.c +++ b/trunk/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; u32 package_length = 0; - u32 byte_count; + acpi_native_uint byte_count; u8 byte_zero_mask = 0x3F; /* Default [0:5] */ ACPI_FUNCTION_TRACE(ps_get_next_package_length); @@ -86,7 +86,7 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state) * used to encode the package length, either 0,1,2, or 3 */ byte_count = (aml[0] >> 6); - parser_state->aml += ((acpi_size) byte_count + 1); + parser_state->aml += (byte_count + 1); /* Get bytes 3, 2, 1 as needed */ diff --git a/trunk/drivers/acpi/parser/psxface.c b/trunk/drivers/acpi/parser/psxface.c index 270469aae842..52581454c47c 100644 --- a/trunk/drivers/acpi/parser/psxface.c +++ b/trunk/drivers/acpi/parser/psxface.c @@ -333,9 +333,9 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) static void acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action) { - u32 i; + acpi_native_uint i; - if (info->parameters) { + if ((info->parameter_type == ACPI_PARAM_ARGS) && (info->parameters)) { /* Update reference count for each parameter */ diff --git a/trunk/drivers/acpi/pci_irq.c b/trunk/drivers/acpi/pci_irq.c index 11acaee14d66..89022a74faee 100644 --- a/trunk/drivers/acpi/pci_irq.c +++ b/trunk/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) && strlen(prt->source) >= strlen(quirk->actual_source)) { printk(KERN_WARNING PREFIX "firmware reports " - "%04x:%02x:%02x PCI INT %c connected to %s; " + "%04x:%02x:%02x[%c] connected to %s; " "changing to %s\n", entry->id.segment, entry->id.bus, entry->id.device, 'A' + entry->pin, @@ -429,7 +429,7 @@ acpi_pci_irq_derive(struct pci_dev *dev, { struct pci_dev *bridge = dev; int irq = -1; - u8 bridge_pin = 0, orig_pin = pin; + u8 bridge_pin = 0; if (!dev) @@ -463,8 +463,8 @@ acpi_pci_irq_derive(struct pci_dev *dev, } if (irq < 0) { - dev_warn(&dev->dev, "can't derive routing for PCI INT %c\n", - 'A' + orig_pin); + printk(KERN_WARNING PREFIX "Unable to derive IRQ for device %s\n", + pci_name(dev)); return -1; } @@ -487,7 +487,6 @@ int acpi_pci_irq_enable(struct pci_dev *dev) int triggering = ACPI_LEVEL_SENSITIVE; int polarity = ACPI_ACTIVE_LOW; char *link = NULL; - char link_desc[16]; int rc; @@ -504,7 +503,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) pin--; if (!dev->bus) { - dev_err(&dev->dev, "invalid (NULL) 'bus' field\n"); + printk(KERN_ERR PREFIX "Invalid (NULL) 'bus' field\n"); return -ENODEV; } @@ -539,7 +538,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev) * driver reported one, then use it. Exit in any case. */ if (irq < 0) { - dev_warn(&dev->dev, "PCI INT %c: no GSI", 'A' + pin); + printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: no GSI", + pci_name(dev), ('A' + pin)); /* Interrupt Line values above 0xF are forbidden */ if (dev->irq > 0 && (dev->irq <= 0xF)) { printk(" - using IRQ %d\n", dev->irq); @@ -554,21 +554,21 @@ int acpi_pci_irq_enable(struct pci_dev *dev) rc = acpi_register_gsi(irq, triggering, polarity); if (rc < 0) { - dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n", - 'A' + pin); + printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: failed " + "to register GSI\n", pci_name(dev), ('A' + pin)); return rc; } dev->irq = rc; + printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ", + pci_name(dev), 'A' + pin); + if (link) - snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link); - else - link_desc[0] = '\0'; + printk("Link [%s] -> ", link); - 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); + printk("GSI %u (%s, %s) -> IRQ %d\n", irq, + (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", + (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); return 0; } @@ -616,6 +616,10 @@ void acpi_pci_irq_disable(struct pci_dev *dev) * (e.g. PCI_UNDEFINED_IRQ). */ - dev_info(&dev->dev, "PCI INT %c disabled\n", 'A' + pin); + printk(KERN_INFO PREFIX "PCI interrupt for device %s disabled\n", + pci_name(dev)); + acpi_unregister_gsi(gsi); + + return; } diff --git a/trunk/drivers/acpi/processor_core.c b/trunk/drivers/acpi/processor_core.c index ec0f2d581ece..9dd0fa93b9e1 100644 --- a/trunk/drivers/acpi/processor_core.c +++ b/trunk/drivers/acpi/processor_core.c @@ -118,31 +118,8 @@ static const struct file_operations acpi_processor_info_fops = { .release = single_release, }; -DEFINE_PER_CPU(struct acpi_processor *, processors); +struct acpi_processor *processors[NR_CPUS]; 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 @@ -288,20 +265,7 @@ static int acpi_processor_set_pdc(struct acpi_processor *pr) if (!pdc_in) return status; - if (idle_nomwait) { - /* - * If mwait is disabled for CPU C-states, the C2C3_FFH access - * mode will be disabled in the parameter of _PDC object. - * Of course C1_FFH access mode will also be disabled. - */ - union acpi_object *obj; - u32 *buffer = NULL; - obj = pdc_in->pointer; - buffer = (u32 *)(obj->buffer.pointer); - buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); - - } status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL); if (ACPI_FAILURE(status)) @@ -650,14 +614,14 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) return 0; } -static DEFINE_PER_CPU(void *, processor_device_array); +static void *processor_device_array[NR_CPUS]; static int __cpuinit acpi_processor_start(struct acpi_device *device) { int result = 0; acpi_status status = AE_OK; struct acpi_processor *pr; - struct sys_device *sysdev; + pr = acpi_driver_data(device); @@ -674,24 +638,20 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) * ACPI id of processors can be reported wrongly by the BIOS. * Don't trust it blindly */ - if (per_cpu(processor_device_array, pr->id) != NULL && - per_cpu(processor_device_array, pr->id) != device) { + if (processor_device_array[pr->id] != NULL && + processor_device_array[pr->id] != device) { printk(KERN_WARNING "BIOS reported wrong ACPI id " "for the processor\n"); return -ENODEV; } - per_cpu(processor_device_array, pr->id) = device; + processor_device_array[pr->id] = device; - per_cpu(processors, pr->id) = pr; + processors[pr->id] = pr; result = acpi_processor_add_fs(device); if (result) goto end; - sysdev = get_cpu_sysdev(pr->id); - if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) - return -EFAULT; - status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, acpi_processor_notify, pr); @@ -789,7 +749,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; - struct acpi_processor *pr = per_cpu(processors, cpu); + struct acpi_processor *pr = processors[cpu]; if (action == CPU_ONLINE && pr) { acpi_processor_ppc_has_changed(pr); @@ -850,8 +810,6 @@ static int acpi_processor_remove(struct acpi_device *device, int type) status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, acpi_processor_notify); - sysfs_remove_link(&device->dev.kobj, "sysdev"); - acpi_processor_remove_fs(device); if (pr->cdev) { @@ -861,8 +819,8 @@ static int acpi_processor_remove(struct acpi_device *device, int type) pr->cdev = NULL; } - per_cpu(processors, pr->id) = NULL; - per_cpu(processor_device_array, pr->id) = NULL; + processors[pr->id] = NULL; + processor_device_array[pr->id] = NULL; kfree(pr); return 0; @@ -1056,9 +1014,9 @@ static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu) static int acpi_processor_handle_eject(struct acpi_processor *pr) { - if (cpu_online(pr->id)) - cpu_down(pr->id); - + if (cpu_online(pr->id)) { + return (-EINVAL); + } arch_unregister_cpu(pr->id); acpi_unmap_lsapic(pr->id); return (0); @@ -1110,6 +1068,8 @@ static int __init acpi_processor_init(void) { int result = 0; + + memset(&processors, 0, sizeof(processors)); memset(&errata, 0, sizeof(errata)); #ifdef CONFIG_SMP @@ -1123,11 +1083,6 @@ static int __init acpi_processor_init(void) return -ENOMEM; acpi_processor_dir->owner = THIS_MODULE; - /* - * Check whether the system is DMI table. If yes, OSPM - * should not use mwait for CPU-states. - */ - dmi_check_system(processor_idle_dmi_table); result = cpuidle_register_driver(&acpi_idle_driver); if (result < 0) goto out_proc; diff --git a/trunk/drivers/acpi/processor_idle.c b/trunk/drivers/acpi/processor_idle.c index d592dbb1d12a..4976e5db2b3f 100644 --- a/trunk/drivers/acpi/processor_idle.c +++ b/trunk/drivers/acpi/processor_idle.c @@ -41,7 +41,6 @@ #include #include #include -#include /* * Include the apic definitions for x86 to have the APIC timer related defines @@ -58,7 +57,6 @@ #include #include -#include #define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" @@ -403,7 +401,7 @@ static void acpi_processor_idle(void) */ local_irq_disable(); - pr = __get_cpu_var(processors); + pr = processors[smp_processor_id()]; if (!pr) { local_irq_enable(); return; @@ -957,21 +955,6 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) } else { continue; } - if (cx.type == ACPI_STATE_C1 && - (idle_halt || idle_nomwait)) { - /* - * In most cases the C1 space_id obtained from - * _CST object is FIXED_HARDWARE access mode. - * But when the option of idle=halt is added, - * the entry_method type should be changed from - * CSTATE_FFH to CSTATE_HALT. - * When the option of idle=nomwait is added, - * the C1 entry_method type should be - * CSTATE_HALT. - */ - cx.entry_method = ACPI_CSTATE_HALT; - snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT"); - } } else { snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI IOPORT 0x%x", cx.address); @@ -1448,7 +1431,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, struct acpi_processor *pr; struct acpi_processor_cx *cx = cpuidle_get_statedata(state); - pr = __get_cpu_var(processors); + pr = processors[smp_processor_id()]; if (unlikely(!pr)) return 0; @@ -1488,7 +1471,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, u32 t1, t2; int sleep_ticks = 0; - pr = __get_cpu_var(processors); + pr = processors[smp_processor_id()]; if (unlikely(!pr)) return 0; @@ -1566,7 +1549,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, u32 t1, t2; int sleep_ticks = 0; - pr = __get_cpu_var(processors); + pr = processors[smp_processor_id()]; if (unlikely(!pr)) return 0; @@ -1797,15 +1780,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, return 0; if (!first_run) { - if (idle_halt) { - /* - * When the boot option of "idle=halt" is added, halt - * is used for CPU IDLE. - * In such case C2/C3 is meaningless. So the max_cstate - * is set to one. - */ - max_cstate = 1; - } dmi_check_system(processor_power_dmi_table); max_cstate = acpi_processor_cstate_check(max_cstate); if (max_cstate < ACPI_C_STATES_MAX) diff --git a/trunk/drivers/acpi/processor_perflib.c b/trunk/drivers/acpi/processor_perflib.c index b4749969c6b4..d80b2d1441af 100644 --- a/trunk/drivers/acpi/processor_perflib.c +++ b/trunk/drivers/acpi/processor_perflib.c @@ -89,7 +89,7 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb, if (event != CPUFREQ_INCOMPATIBLE) goto out; - pr = per_cpu(processors, policy->cpu); + pr = processors[policy->cpu]; if (!pr || !pr->performance) goto out; @@ -572,7 +572,7 @@ int acpi_processor_preregister_performance( /* Call _PSD for all CPUs */ for_each_possible_cpu(i) { - pr = per_cpu(processors, i); + pr = processors[i]; if (!pr) { /* Look only at processors in ACPI namespace */ continue; @@ -603,7 +603,7 @@ int acpi_processor_preregister_performance( * domain info. */ for_each_possible_cpu(i) { - pr = per_cpu(processors, i); + pr = processors[i]; if (!pr) continue; @@ -624,7 +624,7 @@ int acpi_processor_preregister_performance( cpus_clear(covered_cpus); for_each_possible_cpu(i) { - pr = per_cpu(processors, i); + pr = processors[i]; if (!pr) continue; @@ -651,7 +651,7 @@ int acpi_processor_preregister_performance( if (i == j) continue; - match_pr = per_cpu(processors, j); + match_pr = processors[j]; if (!match_pr) continue; @@ -680,7 +680,7 @@ int acpi_processor_preregister_performance( if (i == j) continue; - match_pr = per_cpu(processors, j); + match_pr = processors[j]; if (!match_pr) continue; @@ -697,7 +697,7 @@ int acpi_processor_preregister_performance( err_ret: for_each_possible_cpu(i) { - pr = per_cpu(processors, i); + pr = processors[i]; if (!pr || !pr->performance) continue; @@ -728,7 +728,7 @@ acpi_processor_register_performance(struct acpi_processor_performance mutex_lock(&performance_mutex); - pr = per_cpu(processors, cpu); + pr = processors[cpu]; if (!pr) { mutex_unlock(&performance_mutex); return -ENODEV; @@ -766,7 +766,7 @@ acpi_processor_unregister_performance(struct acpi_processor_performance mutex_lock(&performance_mutex); - pr = per_cpu(processors, cpu); + pr = processors[cpu]; if (!pr) { mutex_unlock(&performance_mutex); return; diff --git a/trunk/drivers/acpi/processor_throttling.c b/trunk/drivers/acpi/processor_throttling.c index 0622ace05220..bb06738860c4 100644 --- a/trunk/drivers/acpi/processor_throttling.c +++ b/trunk/drivers/acpi/processor_throttling.c @@ -71,7 +71,7 @@ static int acpi_processor_update_tsd_coord(void) * coordination between all CPUs. */ for_each_possible_cpu(i) { - pr = per_cpu(processors, i); + pr = processors[i]; if (!pr) continue; @@ -93,7 +93,7 @@ static int acpi_processor_update_tsd_coord(void) cpus_clear(covered_cpus); for_each_possible_cpu(i) { - pr = per_cpu(processors, i); + pr = processors[i]; if (!pr) continue; @@ -119,7 +119,7 @@ static int acpi_processor_update_tsd_coord(void) if (i == j) continue; - match_pr = per_cpu(processors, j); + match_pr = processors[j]; if (!match_pr) continue; @@ -152,7 +152,7 @@ static int acpi_processor_update_tsd_coord(void) if (i == j) continue; - match_pr = per_cpu(processors, j); + match_pr = processors[j]; if (!match_pr) continue; @@ -172,7 +172,7 @@ static int acpi_processor_update_tsd_coord(void) err_ret: for_each_possible_cpu(i) { - pr = per_cpu(processors, i); + pr = processors[i]; if (!pr) continue; @@ -214,7 +214,7 @@ static int acpi_processor_throttling_notifier(unsigned long event, void *data) struct acpi_processor_throttling *p_throttling; cpu = p_tstate->cpu; - pr = per_cpu(processors, cpu); + pr = processors[cpu]; if (!pr) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid pr pointer\n")); return 0; @@ -1035,7 +1035,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state) * cpus. */ for_each_cpu_mask(i, online_throttling_cpus) { - match_pr = per_cpu(processors, i); + match_pr = processors[i]; /* * If the pointer is invalid, we will report the * error message and continue. @@ -1232,10 +1232,7 @@ static ssize_t acpi_processor_write_throttling(struct file *file, int result = 0; struct seq_file *m = file->private_data; struct acpi_processor *pr = m->private; - char state_string[5] = ""; - char *charp = NULL; - size_t state_val = 0; - char tmpbuf[5] = ""; + char state_string[12] = { '\0' }; if (!pr || (count > sizeof(state_string) - 1)) return -EINVAL; @@ -1244,23 +1241,10 @@ static ssize_t acpi_processor_write_throttling(struct file *file, return -EFAULT; state_string[count] = '\0'; - if ((count > 0) && (state_string[count-1] == '\n')) - state_string[count-1] = '\0'; - 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); + result = acpi_processor_set_throttling(pr, + simple_strtoul(state_string, + NULL, 0)); if (result) return result; diff --git a/trunk/drivers/acpi/reboot.c b/trunk/drivers/acpi/reboot.c deleted file mode 100644 index a6b662c00b67..000000000000 --- a/trunk/drivers/acpi/reboot.c +++ /dev/null @@ -1,50 +0,0 @@ - -#include -#include -#include - -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); -} diff --git a/trunk/drivers/acpi/resources/rscalc.c b/trunk/drivers/acpi/resources/rscalc.c index f61ebc679e66..8a112d11d491 100644 --- a/trunk/drivers/acpi/resources/rscalc.c +++ b/trunk/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) { - u8 bits_set; + acpi_native_uint bits_set; ACPI_FUNCTION_ENTRY(); @@ -84,7 +84,7 @@ static u8 acpi_rs_count_set_bits(u16 bit_field) bit_field &= (u16) (bit_field - 1); } - return bits_set; + return ((u8) bits_set); } /******************************************************************************* diff --git a/trunk/drivers/acpi/resources/rscreate.c b/trunk/drivers/acpi/resources/rscreate.c index 7804a8c40e7a..faddaee1bc07 100644 --- a/trunk/drivers/acpi/resources/rscreate.c +++ b/trunk/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; number_of_elements = package_object->package.count; @@ -240,7 +240,9 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* 1) First subobject: Dereference the PRT.Address */ obj_desc = sub_object_list[0]; - if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) { + if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + user_prt->address = obj_desc->integer.value; + } else { ACPI_ERROR((AE_INFO, "(PRT[%X].Address) Need Integer, found %s", index, @@ -248,12 +250,12 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, return_ACPI_STATUS(AE_BAD_DATA); } - user_prt->address = obj_desc->integer.value; - /* 2) Second subobject: Dereference the PRT.Pin */ obj_desc = sub_object_list[1]; - if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) { + if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + user_prt->pin = (u32) obj_desc->integer.value; + } else { ACPI_ERROR((AE_INFO, "(PRT[%X].Pin) Need Integer, found %s", index, @@ -282,25 +284,6 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, } } - user_prt->pin = (u32) obj_desc->integer.value; - - /* - * If the BIOS has erroneously reversed the _PRT source_name (index 2) - * and the source_index (index 3), fix it. _PRT is important enough to - * workaround this BIOS error. This also provides compatibility with - * other ACPI implementations. - */ - obj_desc = sub_object_list[3]; - if (!obj_desc - || (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) { - sub_object_list[3] = sub_object_list[2]; - sub_object_list[2] = obj_desc; - - ACPI_WARNING((AE_INFO, - "(PRT[%X].Source) SourceName and SourceIndex are reversed, fixed", - index)); - } - /* * 3) Third subobject: Dereference the PRT.source_name * The name may be unresolved (slack mode), so allow a null object @@ -381,7 +364,9 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* 4) Fourth subobject: Dereference the PRT.source_index */ obj_desc = sub_object_list[source_index_index]; - if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) { + if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + user_prt->source_index = (u32) obj_desc->integer.value; + } else { ACPI_ERROR((AE_INFO, "(PRT[%X].SourceIndex) Need Integer, found %s", index, @@ -389,8 +374,6 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, return_ACPI_STATUS(AE_BAD_DATA); } - user_prt->source_index = (u32) obj_desc->integer.value; - /* Point to the next union acpi_operand_object in the top level package */ top_object_list++; diff --git a/trunk/drivers/acpi/resources/rsmisc.c b/trunk/drivers/acpi/resources/rsmisc.c index 96a6c0353255..de1ac3881b22 100644 --- a/trunk/drivers/acpi/resources/rsmisc.c +++ b/trunk/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); - if (((acpi_size) resource) & 0x3) { + if (((acpi_native_uint) resource) & 0x3) { /* Each internal resource struct is expected to be 32-bit aligned */ diff --git a/trunk/drivers/acpi/resources/rsutils.c b/trunk/drivers/acpi/resources/rsutils.c index f7b3bcd59ba7..befe2302f41b 100644 --- a/trunk/drivers/acpi/resources/rsutils.c +++ b/trunk/drivers/acpi/resources/rsutils.c @@ -62,7 +62,7 @@ ACPI_MODULE_NAME("rsutils") ******************************************************************************/ u8 acpi_rs_decode_bitmask(u16 mask, u8 * list) { - u8 i; + acpi_native_uint i; u8 bit_count; ACPI_FUNCTION_ENTRY(); @@ -71,7 +71,7 @@ u8 acpi_rs_decode_bitmask(u16 mask, u8 * list) for (i = 0, bit_count = 0; mask; i++) { if (mask & 0x0001) { - list[bit_count] = i; + list[bit_count] = (u8) i; bit_count++; } @@ -96,8 +96,8 @@ u8 acpi_rs_decode_bitmask(u16 mask, u8 * list) u16 acpi_rs_encode_bitmask(u8 * list, u8 count) { - u32 i; - u16 mask; + acpi_native_uint i; + acpi_native_uint mask; ACPI_FUNCTION_ENTRY(); @@ -107,7 +107,7 @@ u16 acpi_rs_encode_bitmask(u8 * list, u8 count) mask |= (0x1 << list[i]); } - return mask; + return ((u16) mask); } /******************************************************************************* @@ -130,7 +130,7 @@ u16 acpi_rs_encode_bitmask(u8 * list, u8 count) void acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type) { - u32 i; + acpi_native_uint i; ACPI_FUNCTION_ENTRY(); @@ -679,6 +679,7 @@ acpi_rs_set_srs_method_data(struct acpi_namespace_node *node, info->prefix_node = node; info->pathname = METHOD_NAME__SRS; info->parameters = args; + info->parameter_type = ACPI_PARAM_ARGS; info->flags = ACPI_IGNORE_RETURN_VALUE; /* diff --git a/trunk/drivers/acpi/scan.c b/trunk/drivers/acpi/scan.c index 5b049cd79553..6d85289f1c12 100644 --- a/trunk/drivers/acpi/scan.c +++ b/trunk/drivers/acpi/scan.c @@ -6,8 +6,6 @@ #include #include #include -#include -#include #include #include /* for acpi_ex_eisa_id_to_string() */ @@ -94,37 +92,17 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha } static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); -static int acpi_bus_hot_remove_device(void *context) +static int acpi_eject_operation(acpi_handle handle, int lockable) { - struct acpi_device *device; - acpi_handle handle = context; struct acpi_object_list arg_list; union acpi_object arg; acpi_status status = AE_OK; - if (acpi_bus_get_device(handle, &device)) - return 0; - - 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")); + /* + * TBD: evaluate _PS3? + */ - if (device->flags.lockable) { + if (lockable) { arg_list.count = 1; arg_list.pointer = &arg; arg.type = ACPI_TYPE_INTEGER; @@ -140,22 +118,26 @@ static int acpi_bus_hot_remove_device(void *context) /* * TBD: _EJD support. */ + status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); - if (ACPI_FAILURE(status)) - return -ENODEV; + if (ACPI_FAILURE(status)) { + return (-ENODEV); + } - return 0; + return (0); } static ssize_t acpi_eject_store(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { + int result; int ret = count; + int islockable; acpi_status status; + acpi_handle handle; acpi_object_type type = 0; struct acpi_device *acpi_device = to_acpi_device(d); - struct task_struct *task; if ((!count) || (buf[0] != '1')) { return -EINVAL; @@ -172,12 +154,18 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, goto err; } - /* remove the device in another thread to fix the deadlock issue */ - task = kthread_run(acpi_bus_hot_remove_device, - acpi_device->handle, "acpi_hot_remove_device"); - if (IS_ERR(task)) - ret = PTR_ERR(task); -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: return ret; } diff --git a/trunk/drivers/acpi/sleep/main.c b/trunk/drivers/acpi/sleep/main.c index 244e352f7661..495c63a3e0af 100644 --- a/trunk/drivers/acpi/sleep/main.c +++ b/trunk/drivers/acpi/sleep/main.c @@ -61,6 +61,8 @@ static u32 acpi_suspend_states[] = { [PM_SUSPEND_MAX] = ACPI_STATE_S5 }; +static int init_8259A_after_S1; + /** * acpi_suspend_begin - Set the target system sleep state to the state * associated with given @pm_state, if supported. @@ -183,6 +185,13 @@ static void acpi_suspend_finish(void) acpi_set_firmware_waking_vector((acpi_physical_address) 0); acpi_target_sleep_state = ACPI_STATE_S0; + +#ifdef CONFIG_X86 + if (init_8259A_after_S1) { + printk("Broken toshiba laptop -> kicking interrupts\n"); + init_8259A(0); + } +#endif } /** @@ -222,6 +231,26 @@ static struct platform_suspend_ops acpi_suspend_ops = { .finish = acpi_suspend_finish, .end = acpi_suspend_end, }; + +/* + * Toshiba fails to preserve interrupts over S1, reinitialization + * of 8259 is needed after S1 resume. + */ +static int __init init_ints_after_s1(const struct dmi_system_id *d) +{ + printk(KERN_WARNING "%s with broken S1 detected.\n", d->ident); + init_8259A_after_S1 = 1; + return 0; +} + +static struct dmi_system_id __initdata acpisleep_dmi_table[] = { + { + .callback = init_ints_after_s1, + .ident = "Toshiba Satellite 4030cdt", + .matches = {DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),}, + }, + {}, +}; #endif /* CONFIG_SUSPEND */ #ifdef CONFIG_HIBERNATION @@ -339,8 +368,8 @@ int acpi_suspend(u32 acpi_state) /** * acpi_pm_device_sleep_state - return preferred power state of ACPI device * in the system sleep state given by %acpi_target_sleep_state - * @dev: device to examine; its driver model wakeup flags control - * whether it should be able to wake up the system + * @dev: device to examine + * @wake: if set, the device should be able to wake up the system * @d_min_p: used to store the upper limit of allowed states range * Return value: preferred power state of the device on success, -ENODEV on * failure (ie. if there's no 'struct acpi_device' for @dev) @@ -358,7 +387,7 @@ int acpi_suspend(u32 acpi_state) * via @wake. */ -int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) +int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p) { acpi_handle handle = DEVICE_ACPI_HANDLE(dev); struct acpi_device *adev; @@ -397,7 +426,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) * can wake the system. _S0W may be valid, too. */ if (acpi_target_sleep_state == ACPI_STATE_S0 || - (device_may_wakeup(dev) && adev->wakeup.state.enabled && + (wake && adev->wakeup.state.enabled && adev->wakeup.sleep_state <= acpi_target_sleep_state)) { acpi_status status; @@ -443,6 +472,8 @@ int __init acpi_sleep_init(void) u8 type_a, type_b; #ifdef CONFIG_SUSPEND int i = 0; + + dmi_check_system(acpisleep_dmi_table); #endif if (acpi_disabled) diff --git a/trunk/drivers/acpi/system.c b/trunk/drivers/acpi/system.c index d8e3f153b295..5bd2dec9a7ac 100644 --- a/trunk/drivers/acpi/system.c +++ b/trunk/drivers/acpi/system.c @@ -167,13 +167,7 @@ static int acpi_system_sysfs_init(void) #define COUNT_ERROR 2 /* other */ #define NUM_COUNTERS_EXTRA 3 -#define ACPI_EVENT_VALID 0x01 -struct event_counter { - u32 count; - u32 flags; -}; - -static struct event_counter *all_counters; +static u32 *all_counters; static u32 num_gpes; static u32 num_counters; static struct attribute **all_attrs; @@ -208,44 +202,9 @@ static int count_num_gpes(void) return count; } -static int get_gpe_device(int index, acpi_handle *handle) -{ - struct acpi_gpe_xrupt_info *gpe_xrupt_info; - struct acpi_gpe_block_info *gpe_block; - acpi_cpu_flags flags; - struct acpi_namespace_node *node; - - flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); - - gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head; - while (gpe_xrupt_info) { - gpe_block = gpe_xrupt_info->gpe_block_list_head; - node = gpe_block->node; - while (gpe_block) { - index -= gpe_block->register_count * - ACPI_GPE_REGISTER_WIDTH; - if (index < 0) { - acpi_os_release_lock(acpi_gbl_gpe_lock, flags); - /* return NULL if it's FADT GPE */ - if (node->type != ACPI_TYPE_DEVICE) - *handle = NULL; - else - *handle = node; - return 0; - } - node = gpe_block->node; - gpe_block = gpe_block->next; - } - gpe_xrupt_info = gpe_xrupt_info->next; - } - acpi_os_release_lock(acpi_gbl_gpe_lock, flags); - - return -ENODEV; -} - static void delete_gpe_attr_array(void) { - struct event_counter *tmp = all_counters; + u32 *tmp = all_counters; all_counters = NULL; kfree(tmp); @@ -271,10 +230,9 @@ void acpi_os_gpe_count(u32 gpe_number) return; if (gpe_number < num_gpes) - all_counters[gpe_number].count++; + all_counters[gpe_number]++; else - all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR]. - count++; + all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR]++; return; } @@ -285,144 +243,44 @@ void acpi_os_fixed_event_count(u32 event_number) return; if (event_number < ACPI_NUM_FIXED_EVENTS) - all_counters[num_gpes + event_number].count++; + all_counters[num_gpes + event_number]++; else - all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR]. - count++; + all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR]++; return; } -static int get_status(u32 index, acpi_event_status *status, acpi_handle *handle) -{ - int result = 0; - - if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS) - goto end; - - if (index < num_gpes) { - result = get_gpe_device(index, handle); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_NOT_FOUND, - "Invalid GPE 0x%x\n", index)); - goto end; - } - result = acpi_get_gpe_status(*handle, index, - ACPI_NOT_ISR, status); - } else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS)) - result = acpi_get_event_status(index - num_gpes, status); - - /* - * sleep/power button GPE/Fixed Event is enabled after acpi_system_init, - * check the status at runtime and mark it as valid once it's enabled - */ - if (!result && (*status & ACPI_EVENT_FLAG_ENABLED)) - all_counters[index].flags |= ACPI_EVENT_VALID; -end: - return result; -} - static ssize_t counter_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { - 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 = + all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI] = acpi_irq_handled; - all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE].count = + all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE] = acpi_gpe_count; - 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; + return sprintf(buf, "%d\n", all_counters[attr - counter_attrs]); } /* * counter_set() sets the specified counter. * setting the total "sci" file to any value clears all counters. - * enable/disable/clear a gpe/fixed event in user space. */ static ssize_t counter_set(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t size) { int index = attr - counter_attrs; - acpi_event_status status; - acpi_handle handle; - int result = 0; if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) { int i; for (i = 0; i < num_counters; ++i) - all_counters[i].count = 0; + all_counters[i] = 0; acpi_gpe_count = 0; acpi_irq_handled = 0; - goto end; - } - /* show the event status for both GPEs and Fixed Events */ - result = get_status(index, &status, &handle); - if (result) - goto end; - - if (!(all_counters[index].flags & ACPI_EVENT_VALID)) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Can not change Invalid GPE/Fixed Event status\n")); - return -EINVAL; - } - - if (index < num_gpes) { - if (!strcmp(buf, "disable\n") && - (status & ACPI_EVENT_FLAG_ENABLED)) - result = acpi_disable_gpe(handle, index, ACPI_NOT_ISR); - else if (!strcmp(buf, "enable\n") && - !(status & ACPI_EVENT_FLAG_ENABLED)) - result = acpi_enable_gpe(handle, index, ACPI_NOT_ISR); - else if (!strcmp(buf, "clear\n") && - (status & ACPI_EVENT_FLAG_SET)) - result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR); - else - all_counters[index].count = strtoul(buf, NULL, 0); - } else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) { - int event = index - num_gpes; - if (!strcmp(buf, "disable\n") && - (status & ACPI_EVENT_FLAG_ENABLED)) - result = acpi_disable_event(event, ACPI_NOT_ISR); - else if (!strcmp(buf, "enable\n") && - !(status & ACPI_EVENT_FLAG_ENABLED)) - result = acpi_enable_event(event, ACPI_NOT_ISR); - else if (!strcmp(buf, "clear\n") && - (status & ACPI_EVENT_FLAG_SET)) - result = acpi_clear_event(event); - else - all_counters[index].count = strtoul(buf, NULL, 0); } else - all_counters[index].count = strtoul(buf, NULL, 0); + all_counters[index] = strtoul(buf, NULL, 0); - if (ACPI_FAILURE(result)) - result = -EINVAL; -end: - return result ? result : size; + return size; } void acpi_irq_stats_init(void) @@ -440,8 +298,7 @@ void acpi_irq_stats_init(void) if (all_attrs == NULL) return; - all_counters = kzalloc(sizeof(struct event_counter) * (num_counters), - GFP_KERNEL); + all_counters = kzalloc(sizeof(u32) * (num_counters), GFP_KERNEL); if (all_counters == NULL) goto fail; diff --git a/trunk/drivers/acpi/tables/tbfadt.c b/trunk/drivers/acpi/tables/tbfadt.c index ccb5b64bbef3..949d4114eb9f 100644 --- a/trunk/drivers/acpi/tables/tbfadt.c +++ b/trunk/drivers/acpi/tables/tbfadt.c @@ -124,7 +124,7 @@ static struct acpi_fadt_info fadt_info_table[] = { static void inline acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, - u8 byte_width, u64 address) + u8 bit_width, u64 address) { /* @@ -136,7 +136,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, /* All other fields are byte-wide */ generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO; - generic_address->bit_width = byte_width << 3; + generic_address->bit_width = bit_width; generic_address->bit_offset = 0; generic_address->access_width = 0; } @@ -155,7 +155,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, * ******************************************************************************/ -void acpi_tb_parse_fadt(u32 table_index, u8 flags) +void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags) { u32 length; struct acpi_table_header *table; @@ -280,7 +280,7 @@ static void acpi_tb_convert_fadt(void) { u8 pm1_register_length; struct acpi_generic_address *target; - u32 i; + acpi_native_uint i; /* Update the local FADT table header length */ @@ -343,11 +343,9 @@ static void acpi_tb_convert_fadt(void) * * The PM event blocks are split into two register blocks, first is the * PM Status Register block, followed immediately by the PM Enable Register - * block. Each is of length (xpm1x_event_block.bit_width/2) + * block. Each is of length (pm1_event_length/2) */ - 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); + pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length); /* The PM1A register block is required */ @@ -362,17 +360,14 @@ static void acpi_tb_convert_fadt(void) /* The PM1B register block is optional, ignore if not present */ if (acpi_gbl_FADT.xpm1b_event_block.address) { - WARN_ON(ACPI_MOD_16(acpi_gbl_FADT.xpm1b_event_block.bit_width)); - pm1_register_length = (u8) ACPI_DIV_16(acpi_gbl_FADT - .xpm1b_event_block - .bit_width); acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, pm1_register_length, (acpi_gbl_FADT.xpm1b_event_block. address + pm1_register_length)); /* Don't forget to copy space_id of the GAS */ acpi_gbl_xpm1b_enable.space_id = - acpi_gbl_FADT.xpm1b_event_block.space_id; + acpi_gbl_FADT.xpm1a_event_block.space_id; + } } @@ -401,7 +396,7 @@ static void acpi_tb_validate_fadt(void) u32 *address32; struct acpi_generic_address *address64; u8 length; - u32 i; + acpi_native_uint i; /* Examine all of the 64-bit extended address fields (X fields) */ diff --git a/trunk/drivers/acpi/tables/tbfind.c b/trunk/drivers/acpi/tables/tbfind.c index 531584defbb8..9ca3afc98c80 100644 --- a/trunk/drivers/acpi/tables/tbfind.c +++ b/trunk/drivers/acpi/tables/tbfind.c @@ -65,9 +65,10 @@ ACPI_MODULE_NAME("tbfind") ******************************************************************************/ acpi_status acpi_tb_find_table(char *signature, - char *oem_id, char *oem_table_id, u32 *table_index) + char *oem_id, + char *oem_table_id, acpi_native_uint * table_index) { - u32 i; + acpi_native_uint i; acpi_status status; struct acpi_table_header header; diff --git a/trunk/drivers/acpi/tables/tbinstal.c b/trunk/drivers/acpi/tables/tbinstal.c index b22185f55a16..5336ce88f89f 100644 --- a/trunk/drivers/acpi/tables/tbinstal.c +++ b/trunk/drivers/acpi/tables/tbinstal.c @@ -107,10 +107,11 @@ acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc) ******************************************************************************/ acpi_status -acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) +acpi_tb_add_table(struct acpi_table_desc *table_desc, + acpi_native_uint * table_index) { - u32 i; - u32 length; + acpi_native_uint i; + acpi_native_uint length; acpi_status status = AE_OK; ACPI_FUNCTION_TRACE(tb_add_table); @@ -206,8 +207,8 @@ acpi_status acpi_tb_resize_root_table_list(void) /* Increase the Table Array size */ - tables = ACPI_ALLOCATE_ZEROED(((acpi_size) acpi_gbl_root_table_list. - size + ACPI_ROOT_TABLE_SIZE_INCREMENT) + tables = ACPI_ALLOCATE_ZEROED((acpi_gbl_root_table_list.size + + ACPI_ROOT_TABLE_SIZE_INCREMENT) * sizeof(struct acpi_table_desc)); if (!tables) { ACPI_ERROR((AE_INFO, @@ -219,7 +220,7 @@ acpi_status acpi_tb_resize_root_table_list(void) if (acpi_gbl_root_table_list.tables) { ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, - (acpi_size) acpi_gbl_root_table_list.size * + acpi_gbl_root_table_list.size * sizeof(struct acpi_table_desc)); if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { @@ -252,7 +253,7 @@ acpi_status acpi_tb_resize_root_table_list(void) acpi_status acpi_tb_store_table(acpi_physical_address address, struct acpi_table_header *table, - u32 length, u8 flags, u32 *table_index) + u32 length, u8 flags, acpi_native_uint * table_index) { acpi_status status = AE_OK; @@ -333,7 +334,7 @@ void acpi_tb_delete_table(struct acpi_table_desc *table_desc) void acpi_tb_terminate(void) { - u32 i; + acpi_native_uint i; ACPI_FUNCTION_TRACE(tb_terminate); @@ -373,7 +374,7 @@ void acpi_tb_terminate(void) * ******************************************************************************/ -void acpi_tb_delete_namespace_by_owner(u32 table_index) +void acpi_tb_delete_namespace_by_owner(acpi_native_uint table_index) { acpi_owner_id owner_id; @@ -402,7 +403,7 @@ void acpi_tb_delete_namespace_by_owner(u32 table_index) * ******************************************************************************/ -acpi_status acpi_tb_allocate_owner_id(u32 table_index) +acpi_status acpi_tb_allocate_owner_id(acpi_native_uint table_index) { acpi_status status = AE_BAD_PARAMETER; @@ -430,7 +431,7 @@ acpi_status acpi_tb_allocate_owner_id(u32 table_index) * ******************************************************************************/ -acpi_status acpi_tb_release_owner_id(u32 table_index) +acpi_status acpi_tb_release_owner_id(acpi_native_uint table_index) { acpi_status status = AE_BAD_PARAMETER; @@ -461,7 +462,8 @@ acpi_status acpi_tb_release_owner_id(u32 table_index) * ******************************************************************************/ -acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id) +acpi_status +acpi_tb_get_owner_id(acpi_native_uint table_index, acpi_owner_id * owner_id) { acpi_status status = AE_BAD_PARAMETER; @@ -488,7 +490,7 @@ acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id) * ******************************************************************************/ -u8 acpi_tb_is_table_loaded(u32 table_index) +u8 acpi_tb_is_table_loaded(acpi_native_uint table_index) { u8 is_loaded = FALSE; @@ -516,7 +518,7 @@ u8 acpi_tb_is_table_loaded(u32 table_index) * ******************************************************************************/ -void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded) +void acpi_tb_set_table_loaded_flag(acpi_native_uint table_index, u8 is_loaded) { (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); diff --git a/trunk/drivers/acpi/tables/tbutils.c b/trunk/drivers/acpi/tables/tbutils.c index 0cc92ef5236f..bc019b9b6a68 100644 --- a/trunk/drivers/acpi/tables/tbutils.c +++ b/trunk/drivers/acpi/tables/tbutils.c @@ -49,8 +49,8 @@ ACPI_MODULE_NAME("tbutils") /* Local prototypes */ static acpi_physical_address -acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size); - +acpi_tb_get_root_table_entry(u8 * table_entry, + acpi_native_uint table_entry_size); /******************************************************************************* * * FUNCTION: acpi_tb_check_xsdt @@ -238,7 +238,7 @@ acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) * ******************************************************************************/ -u8 acpi_tb_checksum(u8 *buffer, u32 length) +u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length) { u8 sum = 0; u8 *end = buffer + length; @@ -268,7 +268,7 @@ u8 acpi_tb_checksum(u8 *buffer, u32 length) void acpi_tb_install_table(acpi_physical_address address, - u8 flags, char *signature, u32 table_index) + u8 flags, char *signature, acpi_native_uint table_index) { struct acpi_table_header *table; @@ -336,7 +336,8 @@ acpi_tb_install_table(acpi_physical_address address, ******************************************************************************/ static acpi_physical_address -acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) +acpi_tb_get_root_table_entry(u8 * table_entry, + acpi_native_uint table_entry_size) { u64 address64; @@ -394,8 +395,8 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) { struct acpi_table_rsdp *rsdp; - u32 table_entry_size; - u32 i; + acpi_native_uint table_entry_size; + acpi_native_uint i; u32 table_count; struct acpi_table_header *table; acpi_physical_address address; diff --git a/trunk/drivers/acpi/tables/tbxface.c b/trunk/drivers/acpi/tables/tbxface.c index fd7770aa1061..0e319604d3e7 100644 --- a/trunk/drivers/acpi/tables/tbxface.c +++ b/trunk/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 */ ACPI_MEMSET(initial_table_array, 0, - (acpi_size) initial_table_count * + initial_table_count * sizeof(struct acpi_table_desc)); acpi_gbl_root_table_list.tables = initial_table_array; @@ -183,9 +183,9 @@ acpi_status acpi_reallocate_root_table(void) return_ACPI_STATUS(AE_SUPPORT); } - new_size = ((acpi_size) acpi_gbl_root_table_list.count + - ACPI_ROOT_TABLE_SIZE_INCREMENT) * - sizeof(struct acpi_table_desc); + new_size = + (acpi_gbl_root_table_list.count + + ACPI_ROOT_TABLE_SIZE_INCREMENT) * sizeof(struct acpi_table_desc); /* Create new array and copy the old array */ @@ -222,7 +222,7 @@ acpi_status acpi_reallocate_root_table(void) acpi_status acpi_load_table(struct acpi_table_header *table_ptr) { acpi_status status; - u32 table_index; + acpi_native_uint table_index; struct acpi_table_desc table_desc; if (!table_ptr) @@ -264,10 +264,11 @@ ACPI_EXPORT_SYMBOL(acpi_load_table) *****************************************************************************/ acpi_status acpi_get_table_header(char *signature, - u32 instance, struct acpi_table_header *out_table_header) + acpi_native_uint instance, + struct acpi_table_header * out_table_header) { - u32 i; - u32 j; + acpi_native_uint i; + acpi_native_uint j; struct acpi_table_header *header; /* Parameter validation */ @@ -377,10 +378,10 @@ ACPI_EXPORT_SYMBOL(acpi_unload_table_id) *****************************************************************************/ acpi_status acpi_get_table(char *signature, - u32 instance, struct acpi_table_header **out_table) + acpi_native_uint instance, struct acpi_table_header **out_table) { - u32 i; - u32 j; + acpi_native_uint i; + acpi_native_uint j; acpi_status status; /* Parameter validation */ @@ -434,7 +435,8 @@ ACPI_EXPORT_SYMBOL(acpi_get_table) * ******************************************************************************/ acpi_status -acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table) +acpi_get_table_by_index(acpi_native_uint table_index, + struct acpi_table_header ** table) { acpi_status status; @@ -491,7 +493,7 @@ static acpi_status acpi_tb_load_namespace(void) { acpi_status status; struct acpi_table_header *table; - u32 i; + acpi_native_uint i; ACPI_FUNCTION_TRACE(tb_load_namespace); diff --git a/trunk/drivers/acpi/tables/tbxfroot.c b/trunk/drivers/acpi/tables/tbxfroot.c index 2d157e0f98d2..b8c0dfa084f6 100644 --- a/trunk/drivers/acpi/tables/tbxfroot.c +++ b/trunk/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_size *table_address) +acpi_status acpi_find_root_pointer(acpi_native_uint * table_address) { u8 *table_ptr; u8 *mem_rover; @@ -153,7 +153,7 @@ acpi_status acpi_find_root_pointer(acpi_size *table_address) * 1b) Search EBDA paragraphs (EBDA is required to be a * minimum of 1_k length) */ - table_ptr = acpi_os_map_memory((acpi_physical_address) + table_ptr = acpi_os_map_memory((acpi_native_uint) physical_address, ACPI_EBDA_WINDOW_SIZE); if (!table_ptr) { diff --git a/trunk/drivers/acpi/utilities/utalloc.c b/trunk/drivers/acpi/utilities/utalloc.c index 3dfb8a442b26..ede084829a70 100644 --- a/trunk/drivers/acpi/utilities/utalloc.c +++ b/trunk/drivers/acpi/utilities/utalloc.c @@ -309,8 +309,7 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer, * ******************************************************************************/ -void *acpi_ut_allocate(acpi_size size, - u32 component, const char *module, u32 line) +void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line) { void *allocation; @@ -354,7 +353,7 @@ void *acpi_ut_allocate(acpi_size size, ******************************************************************************/ void *acpi_ut_allocate_zeroed(acpi_size size, - u32 component, const char *module, u32 line) + u32 component, char *module, u32 line) { void *allocation; diff --git a/trunk/drivers/acpi/utilities/utcopy.c b/trunk/drivers/acpi/utilities/utcopy.c index 53499ac90988..655c290aca7b 100644 --- a/trunk/drivers/acpi/utilities/utcopy.c +++ b/trunk/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; union acpi_operand_object *package_object; union acpi_operand_object **package_elements; - u32 i; + acpi_native_uint i; ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage); @@ -599,7 +599,7 @@ acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object, /* Truncate package and delete it */ - package_object->package.count = i; + package_object->package.count = (u32) i; package_elements[i] = NULL; acpi_ut_remove_reference(package_object); return_ACPI_STATUS(status); diff --git a/trunk/drivers/acpi/utilities/utdebug.c b/trunk/drivers/acpi/utilities/utdebug.c index fd66ecb6741e..f938f465efa4 100644 --- a/trunk/drivers/acpi/utilities/utdebug.c +++ b/trunk/drivers/acpi/utilities/utdebug.c @@ -157,8 +157,7 @@ void ACPI_INTERNAL_VAR_XFACE acpi_ut_debug_print(u32 requested_debug_level, u32 line_number, const char *function_name, - const char *module_name, - u32 component_id, const char *format, ...) + char *module_name, u32 component_id, char *format, ...) { acpi_thread_id thread_id; va_list args; @@ -229,8 +228,7 @@ void ACPI_INTERNAL_VAR_XFACE acpi_ut_debug_print_raw(u32 requested_debug_level, u32 line_number, const char *function_name, - const char *module_name, - u32 component_id, const char *format, ...) + char *module_name, u32 component_id, char *format, ...) { va_list args; @@ -263,8 +261,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_debug_print_raw) ******************************************************************************/ void acpi_ut_trace(u32 line_number, - const char *function_name, - const char *module_name, u32 component_id) + const char *function_name, char *module_name, u32 component_id) { acpi_gbl_nesting_level++; @@ -296,7 +293,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_trace) void acpi_ut_trace_ptr(u32 line_number, const char *function_name, - const char *module_name, u32 component_id, void *pointer) + char *module_name, u32 component_id, void *pointer) { acpi_gbl_nesting_level++; acpi_ut_track_stack_ptr(); @@ -327,7 +324,7 @@ acpi_ut_trace_ptr(u32 line_number, void acpi_ut_trace_str(u32 line_number, const char *function_name, - const char *module_name, u32 component_id, char *string) + char *module_name, u32 component_id, char *string) { acpi_gbl_nesting_level++; @@ -359,7 +356,7 @@ acpi_ut_trace_str(u32 line_number, void acpi_ut_trace_u32(u32 line_number, const char *function_name, - const char *module_name, u32 component_id, u32 integer) + char *module_name, u32 component_id, u32 integer) { acpi_gbl_nesting_level++; @@ -389,8 +386,7 @@ acpi_ut_trace_u32(u32 line_number, void acpi_ut_exit(u32 line_number, - const char *function_name, - const char *module_name, u32 component_id) + const char *function_name, char *module_name, u32 component_id) { acpi_ut_debug_print(ACPI_LV_FUNCTIONS, @@ -421,8 +417,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_exit) void acpi_ut_status_exit(u32 line_number, const char *function_name, - const char *module_name, - u32 component_id, acpi_status status) + char *module_name, u32 component_id, acpi_status status) { if (ACPI_SUCCESS(status)) { @@ -463,8 +458,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_status_exit) void acpi_ut_value_exit(u32 line_number, const char *function_name, - const char *module_name, - u32 component_id, acpi_integer value) + char *module_name, u32 component_id, acpi_integer value) { acpi_ut_debug_print(ACPI_LV_FUNCTIONS, @@ -496,7 +490,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_value_exit) void acpi_ut_ptr_exit(u32 line_number, const char *function_name, - const char *module_name, u32 component_id, u8 *ptr) + char *module_name, u32 component_id, u8 * ptr) { acpi_ut_debug_print(ACPI_LV_FUNCTIONS, @@ -525,8 +519,8 @@ acpi_ut_ptr_exit(u32 line_number, void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display) { - u32 i = 0; - u32 j; + acpi_native_uint i = 0; + acpi_native_uint j; u32 temp32; u8 buf_char; @@ -545,7 +539,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display) /* Print current offset */ - acpi_os_printf("%6.4X: ", i); + acpi_os_printf("%6.4X: ", (u32) i); /* Print 16 hex chars */ @@ -555,7 +549,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display) /* Dump fill spaces */ acpi_os_printf("%*s", ((display * 2) + 1), " "); - j += display; + j += (acpi_native_uint) display; continue; } @@ -563,38 +557,32 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display) case DB_BYTE_DISPLAY: default: /* Default is BYTE display */ - acpi_os_printf("%02X ", - buffer[(acpi_size) i + j]); + acpi_os_printf("%02X ", buffer[i + j]); break; case DB_WORD_DISPLAY: - ACPI_MOVE_16_TO_32(&temp32, - &buffer[(acpi_size) i + j]); + ACPI_MOVE_16_TO_32(&temp32, &buffer[i + j]); acpi_os_printf("%04X ", temp32); break; case DB_DWORD_DISPLAY: - ACPI_MOVE_32_TO_32(&temp32, - &buffer[(acpi_size) i + j]); + ACPI_MOVE_32_TO_32(&temp32, &buffer[i + j]); acpi_os_printf("%08X ", temp32); break; case DB_QWORD_DISPLAY: - ACPI_MOVE_32_TO_32(&temp32, - &buffer[(acpi_size) i + j]); + ACPI_MOVE_32_TO_32(&temp32, &buffer[i + j]); acpi_os_printf("%08X", temp32); - ACPI_MOVE_32_TO_32(&temp32, - &buffer[(acpi_size) i + j + - 4]); + ACPI_MOVE_32_TO_32(&temp32, &buffer[i + j + 4]); acpi_os_printf("%08X ", temp32); break; } - j += display; + j += (acpi_native_uint) display; } /* @@ -608,7 +596,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display) return; } - buf_char = buffer[(acpi_size) i + j]; + buf_char = buffer[i + j]; if (ACPI_IS_PRINT(buf_char)) { acpi_os_printf("%c", buf_char); } else { diff --git a/trunk/drivers/acpi/utilities/utdelete.c b/trunk/drivers/acpi/utilities/utdelete.c index c5c791a575c9..1fbc35139e84 100644 --- a/trunk/drivers/acpi/utilities/utdelete.c +++ b/trunk/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_operand_object *next_object = NULL; union acpi_generic_state *state; - u32 i; + acpi_native_uint i; ACPI_FUNCTION_TRACE_PTR(ut_update_object_reference, object); diff --git a/trunk/drivers/acpi/utilities/uteval.c b/trunk/drivers/acpi/utilities/uteval.c index 352747e49c7a..05e61be267d5 100644 --- a/trunk/drivers/acpi/utilities/uteval.c +++ b/trunk/drivers/acpi/utilities/uteval.c @@ -97,7 +97,7 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) acpi_status status; union acpi_operand_object *string_desc; union acpi_operand_object *return_desc; - u32 i; + acpi_native_uint i; ACPI_FUNCTION_TRACE(ut_osi_implementation); @@ -217,6 +217,7 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, info->prefix_node = prefix_node; info->pathname = path; + info->parameter_type = ACPI_PARAM_ARGS; /* Evaluate the object/method */ @@ -513,7 +514,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node * device_node, u32 count; u32 size; struct acpi_compatible_id_list *cid_list; - u32 i; + acpi_native_uint i; ACPI_FUNCTION_TRACE(ut_execute_CID); diff --git a/trunk/drivers/acpi/utilities/utmisc.c b/trunk/drivers/acpi/utilities/utmisc.c index f34be6773556..1f057b71db1a 100644 --- a/trunk/drivers/acpi/utilities/utmisc.c +++ b/trunk/drivers/acpi/utilities/utmisc.c @@ -64,7 +64,7 @@ ACPI_MODULE_NAME("utmisc") ******************************************************************************/ const char *acpi_ut_validate_exception(acpi_status status) { - u32 sub_status; + acpi_status sub_status; const char *exception = NULL; ACPI_FUNCTION_ENTRY(); @@ -85,28 +85,32 @@ const char *acpi_ut_validate_exception(acpi_status status) case AE_CODE_PROGRAMMER: if (sub_status <= AE_CODE_PGM_MAX) { - exception = acpi_gbl_exception_names_pgm[sub_status]; + exception = + acpi_gbl_exception_names_pgm[sub_status - 1]; } break; case AE_CODE_ACPI_TABLES: if (sub_status <= AE_CODE_TBL_MAX) { - exception = acpi_gbl_exception_names_tbl[sub_status]; + exception = + acpi_gbl_exception_names_tbl[sub_status - 1]; } break; case AE_CODE_AML: if (sub_status <= AE_CODE_AML_MAX) { - exception = acpi_gbl_exception_names_aml[sub_status]; + exception = + acpi_gbl_exception_names_aml[sub_status - 1]; } break; case AE_CODE_CONTROL: if (sub_status <= AE_CODE_CTRL_MAX) { - exception = acpi_gbl_exception_names_ctrl[sub_status]; + exception = + acpi_gbl_exception_names_ctrl[sub_status - 1]; } break; @@ -161,9 +165,9 @@ u8 acpi_ut_is_aml_table(struct acpi_table_header *table) acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) { - u32 i; - u32 j; - u32 k; + acpi_native_uint i; + acpi_native_uint j; + acpi_native_uint k; acpi_status status; ACPI_FUNCTION_TRACE(ut_allocate_owner_id); @@ -269,7 +273,7 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) { acpi_owner_id owner_id = *owner_id_ptr; acpi_status status; - u32 index; + acpi_native_uint index; u32 bit; ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id); @@ -589,7 +593,7 @@ acpi_ut_display_init_pathname(u8 type, * ******************************************************************************/ -u8 acpi_ut_valid_acpi_char(char character, u32 position) +u8 acpi_ut_valid_acpi_char(char character, acpi_native_uint position) { if (!((character >= 'A' && character <= 'Z') || @@ -624,7 +628,7 @@ u8 acpi_ut_valid_acpi_char(char character, u32 position) u8 acpi_ut_valid_acpi_name(u32 name) { - u32 i; + acpi_native_uint i; ACPI_FUNCTION_ENTRY(); @@ -653,7 +657,7 @@ u8 acpi_ut_valid_acpi_name(u32 name) acpi_name acpi_ut_repair_name(char *name) { - u32 i; + acpi_native_uint i; char new_name[ACPI_NAME_SIZE]; for (i = 0; i < ACPI_NAME_SIZE; i++) { @@ -1020,7 +1024,7 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object, ******************************************************************************/ void ACPI_INTERNAL_VAR_XFACE -acpi_ut_error(const char *module_name, u32 line_number, const char *format, ...) +acpi_ut_error(char *module_name, u32 line_number, char *format, ...) { va_list args; @@ -1033,8 +1037,8 @@ acpi_ut_error(const char *module_name, u32 line_number, const char *format, ...) } void ACPI_INTERNAL_VAR_XFACE -acpi_ut_exception(const char *module_name, - u32 line_number, acpi_status status, const char *format, ...) +acpi_ut_exception(char *module_name, + u32 line_number, acpi_status status, char *format, ...) { va_list args; @@ -1050,8 +1054,7 @@ acpi_ut_exception(const char *module_name, EXPORT_SYMBOL(acpi_ut_exception); void ACPI_INTERNAL_VAR_XFACE -acpi_ut_warning(const char *module_name, - u32 line_number, const char *format, ...) +acpi_ut_warning(char *module_name, u32 line_number, char *format, ...) { va_list args; @@ -1064,7 +1067,7 @@ acpi_ut_warning(const char *module_name, } void ACPI_INTERNAL_VAR_XFACE -acpi_ut_info(const char *module_name, u32 line_number, const char *format, ...) +acpi_ut_info(char *module_name, u32 line_number, char *format, ...) { va_list args; diff --git a/trunk/drivers/acpi/utilities/utmutex.c b/trunk/drivers/acpi/utilities/utmutex.c index 7331dde9e1b3..f7d602b1a894 100644 --- a/trunk/drivers/acpi/utilities/utmutex.c +++ b/trunk/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 ACPI subsystem code. */ - for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) { + for (i = mutex_id; i < ACPI_MAX_MUTEX; i++) { if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) { if (i == mutex_id) { ACPI_ERROR((AE_INFO, @@ -315,7 +315,7 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) * ordering rule. This indicates a coding error somewhere in * the ACPI subsystem code. */ - for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) { + for (i = mutex_id; i < ACPI_MAX_MUTEX; i++) { if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) { if (i == mutex_id) { continue; diff --git a/trunk/drivers/acpi/utilities/utobject.c b/trunk/drivers/acpi/utilities/utobject.c index e25484495e65..e68466de8044 100644 --- a/trunk/drivers/acpi/utilities/utobject.c +++ b/trunk/drivers/acpi/utilities/utobject.c @@ -83,8 +83,7 @@ acpi_ut_get_element_length(u8 object_type, * ******************************************************************************/ -union acpi_operand_object *acpi_ut_create_internal_object_dbg(const char - *module_name, +union acpi_operand_object *acpi_ut_create_internal_object_dbg(char *module_name, u32 line_number, u32 component_id, acpi_object_type @@ -176,8 +175,8 @@ union acpi_operand_object *acpi_ut_create_package_object(u32 count) * Create the element array. Count+1 allows the array to be null * terminated. */ - package_elements = ACPI_ALLOCATE_ZEROED(((acpi_size) count + - 1) * sizeof(void *)); + package_elements = ACPI_ALLOCATE_ZEROED((acpi_size) + (count + 1) * sizeof(void *)); if (!package_elements) { acpi_ut_remove_reference(package_desc); return_PTR(NULL); @@ -348,7 +347,7 @@ u8 acpi_ut_valid_internal_object(void *object) * ******************************************************************************/ -void *acpi_ut_allocate_object_desc_dbg(const char *module_name, +void *acpi_ut_allocate_object_desc_dbg(char *module_name, u32 line_number, u32 component_id) { union acpi_operand_object *object; diff --git a/trunk/drivers/acpi/video.c b/trunk/drivers/acpi/video.c index 64c889331f3b..d089c4519d45 100644 --- a/trunk/drivers/acpi/video.c +++ b/trunk/drivers/acpi/video.c @@ -631,76 +631,6 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) * device : video output device (LCD, CRT, ..) * * Return Value: - * Maximum brightness level - * - * Allocate and initialize device->brightness. - */ - -static int -acpi_video_init_brightness(struct acpi_video_device *device) -{ - union acpi_object *obj = NULL; - int i, max_level = 0, count = 0; - union acpi_object *o; - struct acpi_video_device_brightness *br = NULL; - - if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available " - "LCD brightness level\n")); - goto out; - } - - if (obj->package.count < 2) - goto out; - - br = kzalloc(sizeof(*br), GFP_KERNEL); - if (!br) { - printk(KERN_ERR "can't allocate memory\n"); - goto out; - } - - br->levels = kmalloc(obj->package.count * sizeof *(br->levels), - GFP_KERNEL); - if (!br->levels) - goto out_free; - - for (i = 0; i < obj->package.count; i++) { - o = (union acpi_object *)&obj->package.elements[i]; - if (o->type != ACPI_TYPE_INTEGER) { - printk(KERN_ERR PREFIX "Invalid data\n"); - continue; - } - br->levels[count] = (u32) o->integer.value; - - if (br->levels[count] > max_level) - max_level = br->levels[count]; - count++; - } - - if (count < 2) - goto out_free_levels; - - br->count = count; - device->brightness = br; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "found %d brightness levels\n", count)); - kfree(obj); - return max_level; - -out_free_levels: - kfree(br->levels); -out_free: - kfree(br); -out: - device->brightness = NULL; - kfree(obj); - return 0; -} - -/* - * Arg: - * device : video output device (LCD, CRT, ..) - * - * Return Value: * None * * Find out all required AML methods defined under the output @@ -710,7 +640,10 @@ acpi_video_init_brightness(struct acpi_video_device *device) static void acpi_video_device_find_cap(struct acpi_video_device *device) { acpi_handle h_dummy1; + int i; u32 max_level = 0; + union acpi_object *obj = NULL; + struct acpi_video_device_brightness *br = NULL; memset(&device->cap, 0, sizeof(device->cap)); @@ -739,7 +672,53 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) device->cap._DSS = 1; } - max_level = acpi_video_init_brightness(device); + 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); if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){ int result; @@ -1716,8 +1695,6 @@ static void acpi_video_switch_brightness(struct acpi_video_device *device, int event) { unsigned long level_current, level_next; - if (!device->brightness) - return; acpi_video_device_lcd_get_level_current(device, &level_current); level_next = acpi_video_get_next_level(device, level_current, event); acpi_video_device_lcd_set_level(device, level_next); diff --git a/trunk/drivers/char/apm-emulation.c b/trunk/drivers/char/apm-emulation.c index aaca40283be9..da8a1658a273 100644 --- a/trunk/drivers/char/apm-emulation.c +++ b/trunk/drivers/char/apm-emulation.c @@ -58,55 +58,6 @@ struct apm_queue { apm_event_t events[APM_MAX_EVENTS]; }; -/* - * thread states (for threads using a writable /dev/apm_bios fd): - * - * SUSPEND_NONE: nothing happening - * SUSPEND_PENDING: suspend event queued for thread and pending to be read - * SUSPEND_READ: suspend event read, pending acknowledgement - * SUSPEND_ACKED: acknowledgement received from thread (via ioctl), - * waiting for resume - * SUSPEND_ACKTO: acknowledgement timeout - * SUSPEND_DONE: thread had acked suspend and is now notified of - * resume - * - * SUSPEND_WAIT: this thread invoked suspend and is waiting for resume - * - * A thread migrates in one of three paths: - * NONE -1-> PENDING -2-> READ -3-> ACKED -4-> DONE -5-> NONE - * -6-> ACKTO -7-> NONE - * NONE -8-> WAIT -9-> NONE - * - * While in PENDING or READ, the thread is accounted for in the - * suspend_acks_pending counter. - * - * The transitions are invoked as follows: - * 1: suspend event is signalled from the core PM code - * 2: the suspend event is read from the fd by the userspace thread - * 3: userspace thread issues the APM_IOC_SUSPEND ioctl (as ack) - * 4: core PM code signals that we have resumed - * 5: APM_IOC_SUSPEND ioctl returns - * - * 6: the notifier invoked from the core PM code timed out waiting - * for all relevant threds to enter ACKED state and puts those - * that haven't into ACKTO - * 7: those threads issue APM_IOC_SUSPEND ioctl too late, - * get an error - * - * 8: userspace thread issues the APM_IOC_SUSPEND ioctl (to suspend), - * ioctl code invokes pm_suspend() - * 9: pm_suspend() returns indicating resume - */ -enum apm_suspend_state { - SUSPEND_NONE, - SUSPEND_PENDING, - SUSPEND_READ, - SUSPEND_ACKED, - SUSPEND_ACKTO, - SUSPEND_WAIT, - SUSPEND_DONE, -}; - /* * The per-file APM data */ @@ -118,7 +69,13 @@ struct apm_user { unsigned int reader: 1; int suspend_result; - enum apm_suspend_state suspend_state; + 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 */ struct apm_queue queue; }; @@ -126,8 +83,7 @@ struct apm_user { /* * Local variables */ -static atomic_t suspend_acks_pending = ATOMIC_INIT(0); -static atomic_t userspace_notification_inhibit = ATOMIC_INIT(0); +static int suspends_pending; static int apm_disabled; static struct task_struct *kapmd_tsk; @@ -210,6 +166,78 @@ static void queue_event(apm_event_t event) wake_up_interruptible(&apm_waitqueue); } +/* + * queue_suspend_event - queue an APM suspend event. + * + * Check that we're in a state where we can suspend. If not, + * return -EBUSY. Otherwise, queue an event to all "writer" + * users. If there are no "writer" users, return '1' to + * indicate that we can immediately suspend. + */ +static int queue_suspend_event(apm_event_t event, struct apm_user *sender) +{ + struct apm_user *as; + int ret = 1; + + mutex_lock(&state_lock); + down_read(&user_list_lock); + + /* + * If a thread is still processing, we can't suspend, so reject + * the request. + */ + list_for_each_entry(as, &apm_user_list, list) { + if (as != sender && as->reader && as->writer && as->suser && + as->suspend_state != SUSPEND_NONE) { + ret = -EBUSY; + goto out; + } + } + + list_for_each_entry(as, &apm_user_list, list) { + if (as != sender && as->reader && as->writer && as->suser) { + as->suspend_state = SUSPEND_PENDING; + suspends_pending++; + queue_add_event(&as->queue, event); + ret = 0; + } + } + out: + up_read(&user_list_lock); + mutex_unlock(&state_lock); + wake_up_interruptible(&apm_waitqueue); + return ret; +} + +static void apm_suspend(void) +{ + struct apm_user *as; + int err = pm_suspend(PM_SUSPEND_MEM); + + /* + * Anyone on the APM queues will think we're still suspended. + * Send a message so everyone knows we're now awake again. + */ + queue_event(APM_NORMAL_RESUME); + + /* + * Finally, wake up anyone who is sleeping on the suspend. + */ + mutex_lock(&state_lock); + down_read(&user_list_lock); + list_for_each_entry(as, &apm_user_list, list) { + if (as->suspend_state == SUSPEND_WAIT || + as->suspend_state == SUSPEND_ACKED) { + as->suspend_result = err; + as->suspend_state = SUSPEND_DONE; + } + } + up_read(&user_list_lock); + mutex_unlock(&state_lock); + + wake_up(&apm_suspend_waitqueue); +} + static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos) { struct apm_user *as = fp->private_data; @@ -280,22 +308,25 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) as->suspend_result = -EINTR; - switch (as->suspend_state) { - case SUSPEND_READ: + if (as->suspend_state == SUSPEND_READ) { + int pending; + /* * If we read a suspend command from /dev/apm_bios, * then the corresponding APM_IOC_SUSPEND ioctl is * interpreted as an acknowledge. */ as->suspend_state = SUSPEND_ACKED; - atomic_dec(&suspend_acks_pending); + suspends_pending--; + pending = suspends_pending == 0; mutex_unlock(&state_lock); /* - * suspend_acks_pending changed, the notifier needs to - * be woken up for this + * If there are no further acknowledges required, + * suspend the system. */ - wake_up(&apm_suspend_waitqueue); + if (pending) + apm_suspend(); /* * Wait for the suspend/resume to complete. If there @@ -311,21 +342,35 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) * try_to_freeze() in freezer_count() will not trigger */ freezer_count(); - break; - case SUSPEND_ACKTO: - as->suspend_result = -ETIMEDOUT; - mutex_unlock(&state_lock); - break; - default: + } else { as->suspend_state = SUSPEND_WAIT; mutex_unlock(&state_lock); /* * Otherwise it is a request to suspend the system. - * Just invoke pm_suspend(), we'll handle it from - * there via the notifier. + * 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. */ - as->suspend_result = pm_suspend(PM_SUSPEND_MEM); + wait_event_freezable(apm_suspend_waitqueue, + as->suspend_state == SUSPEND_DONE); } mutex_lock(&state_lock); @@ -341,6 +386,7 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) static int apm_release(struct inode * inode, struct file * filp) { struct apm_user *as = filp->private_data; + int pending = 0; filp->private_data = NULL; @@ -350,15 +396,18 @@ static int apm_release(struct inode * inode, struct file * filp) /* * We are now unhooked from the chain. As far as new - * events are concerned, we no longer exist. + * events are concerned, we no longer exist. However, we + * need to balance suspends_pending, which means the + * possibility of sleeping. */ mutex_lock(&state_lock); - if (as->suspend_state == SUSPEND_PENDING || - as->suspend_state == SUSPEND_READ) - atomic_dec(&suspend_acks_pending); + if (as->suspend_state != SUSPEND_NONE) { + suspends_pending -= 1; + pending = suspends_pending == 0; + } mutex_unlock(&state_lock); - - wake_up(&apm_suspend_waitqueue); + if (pending) + apm_suspend(); kfree(as); return 0; @@ -496,6 +545,7 @@ static int kapmd(void *arg) { do { apm_event_t event; + int ret; wait_event_interruptible(kapmd_wait, !queue_empty(&kapmd_queue) || kthread_should_stop()); @@ -520,13 +570,20 @@ static int kapmd(void *arg) case APM_USER_SUSPEND: case APM_SYS_SUSPEND: - pm_suspend(PM_SUSPEND_MEM); + 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(); break; case APM_CRITICAL_SUSPEND: - atomic_inc(&userspace_notification_inhibit); - pm_suspend(PM_SUSPEND_MEM); - atomic_dec(&userspace_notification_inhibit); + apm_suspend(); break; } } while (1); @@ -534,120 +591,6 @@ static int kapmd(void *arg) return 0; } -static int apm_suspend_notifier(struct notifier_block *nb, - unsigned long event, - void *dummy) -{ - struct apm_user *as; - int err; - - /* short-cut emergency suspends */ - if (atomic_read(&userspace_notification_inhibit)) - return NOTIFY_DONE; - - switch (event) { - case PM_SUSPEND_PREPARE: - /* - * Queue an event to all "writer" users that we want - * to suspend and need their ack. - */ - mutex_lock(&state_lock); - down_read(&user_list_lock); - - list_for_each_entry(as, &apm_user_list, list) { - if (as->suspend_state != SUSPEND_WAIT && as->reader && - as->writer && as->suser) { - as->suspend_state = SUSPEND_PENDING; - atomic_inc(&suspend_acks_pending); - queue_add_event(&as->queue, APM_USER_SUSPEND); - } - } - - up_read(&user_list_lock); - mutex_unlock(&state_lock); - wake_up_interruptible(&apm_waitqueue); - - /* - * Wait for the the suspend_acks_pending variable to drop to - * zero, meaning everybody acked the suspend event (or the - * process was killed.) - * - * If the app won't answer within a short while we assume it - * locked up and ignore it. - */ - err = wait_event_interruptible_timeout( - apm_suspend_waitqueue, - atomic_read(&suspend_acks_pending) == 0, - 5*HZ); - - /* timed out */ - if (err == 0) { - /* - * Move anybody who timed out to "ack timeout" state. - * - * We could time out and the userspace does the ACK - * right after we time out but before we enter the - * locked section here, but that's fine. - */ - mutex_lock(&state_lock); - down_read(&user_list_lock); - list_for_each_entry(as, &apm_user_list, list) { - if (as->suspend_state == SUSPEND_PENDING || - as->suspend_state == SUSPEND_READ) { - as->suspend_state = SUSPEND_ACKTO; - atomic_dec(&suspend_acks_pending); - } - } - up_read(&user_list_lock); - mutex_unlock(&state_lock); - } - - /* let suspend proceed */ - if (err >= 0) - return NOTIFY_OK; - - /* interrupted by signal */ - return NOTIFY_BAD; - - case PM_POST_SUSPEND: - /* - * Anyone on the APM queues will think we're still suspended. - * Send a message so everyone knows we're now awake again. - */ - queue_event(APM_NORMAL_RESUME); - - /* - * Finally, wake up anyone who is sleeping on the suspend. - */ - mutex_lock(&state_lock); - down_read(&user_list_lock); - list_for_each_entry(as, &apm_user_list, list) { - if (as->suspend_state == SUSPEND_ACKED) { - /* - * TODO: maybe grab error code, needs core - * changes to push the error to the notifier - * chain (could use the second parameter if - * implemented) - */ - as->suspend_result = 0; - as->suspend_state = SUSPEND_DONE; - } - } - up_read(&user_list_lock); - mutex_unlock(&state_lock); - - wake_up(&apm_suspend_waitqueue); - return NOTIFY_OK; - - default: - return NOTIFY_DONE; - } -} - -static struct notifier_block apm_notif_block = { - .notifier_call = apm_suspend_notifier, -}; - static int __init apm_init(void) { int ret; @@ -661,7 +604,7 @@ static int __init apm_init(void) if (IS_ERR(kapmd_tsk)) { ret = PTR_ERR(kapmd_tsk); kapmd_tsk = NULL; - goto out; + return ret; } wake_up_process(kapmd_tsk); @@ -670,27 +613,16 @@ static int __init apm_init(void) #endif ret = misc_register(&apm_device); - if (ret) - goto out_stop; - - ret = register_pm_notifier(&apm_notif_block); - if (ret) - goto out_unregister; - - return 0; + if (ret != 0) { + remove_proc_entry("apm", NULL); + kthread_stop(kapmd_tsk); + } - out_unregister: - misc_deregister(&apm_device); - out_stop: - remove_proc_entry("apm", NULL); - kthread_stop(kapmd_tsk); - out: return ret; } static void __exit apm_exit(void) { - unregister_pm_notifier(&apm_notif_block); misc_deregister(&apm_device); remove_proc_entry("apm", NULL); diff --git a/trunk/drivers/hwmon/ad7418.c b/trunk/drivers/hwmon/ad7418.c index f97b5b356875..466b9ee92797 100644 --- a/trunk/drivers/hwmon/ad7418.c +++ b/trunk/drivers/hwmon/ad7418.c @@ -23,9 +23,12 @@ #include "lm75.h" -#define DRV_VERSION "0.4" +#define DRV_VERSION "0.3" -enum chips { ad7416, ad7417, ad7418 }; +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x28, I2C_CLIENT_END }; +/* Insmod parameters */ +I2C_CLIENT_INSMOD_3(ad7416, ad7417, ad7418); /* AD7418 registers */ #define AD7418_REG_TEMP_IN 0x00 @@ -43,6 +46,7 @@ static const u8 AD7418_REG_TEMP[] = { AD7418_REG_TEMP_IN, AD7418_REG_TEMP_OS }; struct ad7418_data { + struct i2c_client client; struct device *hwmon_dev; struct attribute_group attrs; enum chips type; @@ -54,25 +58,16 @@ struct ad7418_data { u16 in[4]; }; -static int ad7418_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int ad7418_remove(struct i2c_client *client); - -static const struct i2c_device_id ad7418_id[] = { - { "ad7416", ad7416 }, - { "ad7417", ad7417 }, - { "ad7418", ad7418 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ad7418_id); +static int ad7418_attach_adapter(struct i2c_adapter *adapter); +static int ad7418_detect(struct i2c_adapter *adapter, int address, int kind); +static int ad7418_detach_client(struct i2c_client *client); static struct i2c_driver ad7418_driver = { .driver = { .name = "ad7418", }, - .probe = ad7418_probe, - .remove = ad7418_remove, - .id_table = ad7418_id, + .attach_adapter = ad7418_attach_adapter, + .detach_client = ad7418_detach_client, }; /* All registers are word-sized, except for the configuration registers. @@ -197,6 +192,13 @@ static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_adc, NULL, 1); static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_adc, NULL, 2); static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_adc, NULL, 3); +static int ad7418_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, ad7418_detect); +} + static struct attribute *ad7416_attributes[] = { &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, @@ -223,46 +225,98 @@ static struct attribute *ad7418_attributes[] = { NULL }; -static int ad7418_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ad7418_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = client->adapter; + struct i2c_client *client; struct ad7418_data *data; - int err; + int err = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA)) { - err = -EOPNOTSUPP; + I2C_FUNC_SMBUS_WORD_DATA)) goto exit; - } if (!(data = kzalloc(sizeof(struct ad7418_data), GFP_KERNEL))) { err = -ENOMEM; goto exit; } + client = &data->client; + client->addr = address; + client->adapter = adapter; + client->driver = &ad7418_driver; + i2c_set_clientdata(client, data); mutex_init(&data->lock); - data->type = id->driver_data; + + /* AD7418 has a curious behaviour on registers 6 and 7. They + * both always read 0xC071 and are not documented on the datasheet. + * We use them to detect the chip. + */ + if (kind <= 0) { + int reg, reg6, reg7; + + /* the AD7416 lies within this address range, but I have + * no means to check. + */ + if (address >= 0x48 && address <= 0x4f) { + /* XXX add tests for AD7416 here */ + /* data->type = ad7416; */ + } + /* here we might have AD7417 or AD7418 */ + else if (address >= 0x28 && address <= 0x2f) { + reg6 = i2c_smbus_read_word_data(client, 0x06); + reg7 = i2c_smbus_read_word_data(client, 0x07); + + if (address == 0x28 && reg6 == 0xC071 && reg7 == 0xC071) + data->type = ad7418; + + /* XXX add tests for AD7417 here */ + + + /* both AD7417 and AD7418 have bits 0-5 of + * the CONF2 register at 0 + */ + reg = i2c_smbus_read_byte_data(client, + AD7418_REG_CONF2); + if (reg & 0x3F) + data->type = any_chip; /* detection failed */ + } + } else { + dev_dbg(&adapter->dev, "detection forced\n"); + } + + if (kind > 0) + data->type = kind; + else if (kind < 0 && data->type == any_chip) { + err = -ENODEV; + goto exit_free; + } switch (data->type) { + case any_chip: case ad7416: data->adc_max = 0; data->attrs.attrs = ad7416_attributes; + strlcpy(client->name, "ad7416", I2C_NAME_SIZE); break; case ad7417: data->adc_max = 4; data->attrs.attrs = ad7417_attributes; + strlcpy(client->name, "ad7417", I2C_NAME_SIZE); break; case ad7418: data->adc_max = 1; data->attrs.attrs = ad7418_attributes; + strlcpy(client->name, "ad7418", I2C_NAME_SIZE); break; } + if ((err = i2c_attach_client(client))) + goto exit_free; + dev_info(&client->dev, "%s chip found\n", client->name); /* Initialize the AD7418 chip */ @@ -270,7 +324,7 @@ static int ad7418_probe(struct i2c_client *client, /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs))) - goto exit_free; + goto exit_detach; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -282,17 +336,20 @@ static int ad7418_probe(struct i2c_client *client, exit_remove: sysfs_remove_group(&client->dev.kobj, &data->attrs); +exit_detach: + i2c_detach_client(client); exit_free: kfree(data); exit: return err; } -static int ad7418_remove(struct i2c_client *client) +static int ad7418_detach_client(struct i2c_client *client) { struct ad7418_data *data = i2c_get_clientdata(client); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &data->attrs); + i2c_detach_client(client); kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/adm1021.c b/trunk/drivers/hwmon/adm1021.c index b11e06f644b1..ecbf69484bf5 100644 --- a/trunk/drivers/hwmon/adm1021.c +++ b/trunk/drivers/hwmon/adm1021.c @@ -78,6 +78,7 @@ clearing it. Weird, ey? --Phil */ /* Each client has this additional data */ struct adm1021_data { + struct i2c_client client; struct device *hwmon_dev; enum chips type; @@ -97,42 +98,23 @@ struct adm1021_data { u8 remote_temp_offset_prec; }; -static int adm1021_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm1021_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); +static int adm1021_attach_adapter(struct i2c_adapter *adapter); +static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind); static void adm1021_init_client(struct i2c_client *client); -static int adm1021_remove(struct i2c_client *client); +static int adm1021_detach_client(struct i2c_client *client); static struct adm1021_data *adm1021_update_device(struct device *dev); /* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */ static int read_only; -static const struct i2c_device_id adm1021_id[] = { - { "adm1021", adm1021 }, - { "adm1023", adm1023 }, - { "max1617", max1617 }, - { "max1617a", max1617a }, - { "thmc10", thmc10 }, - { "lm84", lm84 }, - { "gl523sm", gl523sm }, - { "mc1066", mc1066 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm1021_id); - /* This is the driver that will be inserted */ static struct i2c_driver adm1021_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "adm1021", }, - .probe = adm1021_probe, - .remove = adm1021_remove, - .id_table = adm1021_id, - .detect = adm1021_detect, - .address_data = &addr_data, + .attach_adapter = adm1021_attach_adapter, + .detach_client = adm1021_detach_client, }; static ssize_t show_temp(struct device *dev, @@ -234,6 +216,13 @@ static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2); static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); +static int adm1021_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, adm1021_detect); +} + static struct attribute *adm1021_attributes[] = { &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_min.dev_attr.attr, @@ -254,21 +243,36 @@ static const struct attribute_group adm1021_group = { .attrs = adm1021_attributes, }; -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int adm1021_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = client->adapter; int i; + struct i2c_client *client; + struct adm1021_data *data; + int err = 0; const char *type_name = ""; int conv_rate, status, config; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { pr_debug("adm1021: detect failed, " "smbus byte data not supported!\n"); - return -ENODEV; + goto error0; + } + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access adm1021 register values. */ + + if (!(data = kzalloc(sizeof(struct adm1021_data), GFP_KERNEL))) { + pr_debug("adm1021: detect failed, kzalloc failed!\n"); + err = -ENOMEM; + goto error0; } + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &adm1021_driver; status = i2c_smbus_read_byte_data(client, ADM1021_REG_STATUS); conv_rate = i2c_smbus_read_byte_data(client, ADM1021_REG_CONV_RATE_R); @@ -280,7 +284,8 @@ static int adm1021_detect(struct i2c_client *client, int kind, || (conv_rate & 0xF8) != 0x00) { pr_debug("adm1021: detect failed, " "chip not detected!\n"); - return -ENODEV; + err = -ENODEV; + goto error1; } } @@ -331,36 +336,24 @@ static int adm1021_detect(struct i2c_client *client, int kind, type_name = "mc1066"; } pr_debug("adm1021: Detected chip %s at adapter %d, address 0x%02x.\n", - type_name, i2c_adapter_id(adapter), client->addr); - strlcpy(info->type, type_name, I2C_NAME_SIZE); - - return 0; -} - -static int adm1021_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adm1021_data *data; - int err; - - data = kzalloc(sizeof(struct adm1021_data), GFP_KERNEL); - if (!data) { - pr_debug("adm1021: detect failed, kzalloc failed!\n"); - err = -ENOMEM; - goto error0; - } + type_name, i2c_adapter_id(adapter), address); - i2c_set_clientdata(client, data); - data->type = id->driver_data; + /* Fill in the remaining client fields */ + strlcpy(client->name, type_name, I2C_NAME_SIZE); + data->type = kind; mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto error1; + /* Initialize the ADM1021 chip */ - if (data->type != lm84 && !read_only) + if (kind != lm84 && !read_only) adm1021_init_client(client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &adm1021_group))) - goto error1; + goto error2; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -372,6 +365,8 @@ static int adm1021_probe(struct i2c_client *client, error3: sysfs_remove_group(&client->dev.kobj, &adm1021_group); +error2: + i2c_detach_client(client); error1: kfree(data); error0: @@ -387,13 +382,17 @@ static void adm1021_init_client(struct i2c_client *client) i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04); } -static int adm1021_remove(struct i2c_client *client) +static int adm1021_detach_client(struct i2c_client *client) { struct adm1021_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &adm1021_group); + if ((err = i2c_detach_client(client))) + return err; + kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/adm1025.c b/trunk/drivers/hwmon/adm1025.c index 4db04d603ec9..1d76de7d75c7 100644 --- a/trunk/drivers/hwmon/adm1025.c +++ b/trunk/drivers/hwmon/adm1025.c @@ -2,7 +2,7 @@ * adm1025.c * * Copyright (C) 2000 Chen-Yuan Wu - * Copyright (C) 2003-2008 Jean Delvare + * Copyright (C) 2003-2004 Jean Delvare * * The ADM1025 is a sensor chip made by Analog Devices. It reports up to 6 * voltages (including its own power source) and up to two temperatures @@ -109,35 +109,22 @@ static const int in_scale[6] = { 2500, 2250, 3300, 5000, 12000, 3300 }; * Functions declaration */ -static int adm1025_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm1025_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); +static int adm1025_attach_adapter(struct i2c_adapter *adapter); +static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind); static void adm1025_init_client(struct i2c_client *client); -static int adm1025_remove(struct i2c_client *client); +static int adm1025_detach_client(struct i2c_client *client); static struct adm1025_data *adm1025_update_device(struct device *dev); /* * Driver data (common to all clients) */ -static const struct i2c_device_id adm1025_id[] = { - { "adm1025", adm1025 }, - { "ne1619", ne1619 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm1025_id); - static struct i2c_driver adm1025_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "adm1025", }, - .probe = adm1025_probe, - .remove = adm1025_remove, - .id_table = adm1025_id, - .detect = adm1025_detect, - .address_data = &addr_data, + .attach_adapter = adm1025_attach_adapter, + .detach_client = adm1025_detach_client, }; /* @@ -145,6 +132,7 @@ static struct i2c_driver adm1025_driver = { */ struct adm1025_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -356,6 +344,13 @@ static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); * Real code */ +static int adm1025_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, adm1025_detect); +} + static struct attribute *adm1025_attributes[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, @@ -408,16 +403,31 @@ static const struct attribute_group adm1025_group_in4 = { .attrs = adm1025_attributes_in4, }; -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int adm1025_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +/* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. + */ +static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = client->adapter; + struct i2c_client *client; + struct adm1025_data *data; + int err = 0; const char *name = ""; u8 config; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + goto exit; + + if (!(data = kzalloc(sizeof(struct adm1025_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &adm1025_driver; /* * Now we do the remaining detection. A negative kind means that @@ -438,8 +448,8 @@ static int adm1025_detect(struct i2c_client *client, int kind, ADM1025_REG_STATUS2) & 0xBC) != 0x00) { dev_dbg(&adapter->dev, "ADM1025 detection failed at 0x%02x.\n", - client->addr); - return -ENODEV; + address); + goto exit_free; } } @@ -455,7 +465,7 @@ static int adm1025_detect(struct i2c_client *client, int kind, } } else if (man_id == 0xA1) { /* Philips */ - if (client->addr != 0x2E + if (address != 0x2E && (chip_id & 0xF0) == 0x20) { /* NE1619 */ kind = ne1619; } @@ -465,7 +475,7 @@ static int adm1025_detect(struct i2c_client *client, int kind, dev_info(&adapter->dev, "Unsupported chip (man_id=0x%02X, " "chip_id=0x%02X).\n", man_id, chip_id); - return -ENODEV; + goto exit_free; } } @@ -474,36 +484,23 @@ static int adm1025_detect(struct i2c_client *client, int kind, } else if (kind == ne1619) { name = "ne1619"; } - strlcpy(info->type, name, I2C_NAME_SIZE); - - return 0; -} - -static int adm1025_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adm1025_data *data; - int err; - u8 config; - - data = kzalloc(sizeof(struct adm1025_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - i2c_set_clientdata(client, data); + /* We can fill in the remaining client fields */ + strlcpy(client->name, name, I2C_NAME_SIZE); mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; + /* Initialize the ADM1025 chip */ adm1025_init_client(client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &adm1025_group))) - goto exit_free; + goto exit_detach; /* Pin 11 is either in4 (+12V) or VID4 */ - config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG); if (!(config & 0x20)) { if ((err = sysfs_create_group(&client->dev.kobj, &adm1025_group_in4))) @@ -521,6 +518,8 @@ static int adm1025_probe(struct i2c_client *client, exit_remove: sysfs_remove_group(&client->dev.kobj, &adm1025_group); sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4); +exit_detach: + i2c_detach_client(client); exit_free: kfree(data); exit: @@ -569,14 +568,18 @@ static void adm1025_init_client(struct i2c_client *client) (reg&0x7E)|0x01); } -static int adm1025_remove(struct i2c_client *client) +static int adm1025_detach_client(struct i2c_client *client) { struct adm1025_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &adm1025_group); sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4); + if ((err = i2c_detach_client(client))) + return err; + kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/adm1026.c b/trunk/drivers/hwmon/adm1026.c index 7fe2441fc845..904c6ce9d83f 100644 --- a/trunk/drivers/hwmon/adm1026.c +++ b/trunk/drivers/hwmon/adm1026.c @@ -259,6 +259,7 @@ struct pwm_data { }; struct adm1026_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; @@ -292,11 +293,10 @@ struct adm1026_data { u8 config3; /* Register value */ }; -static int adm1026_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm1026_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); -static int adm1026_remove(struct i2c_client *client); +static int adm1026_attach_adapter(struct i2c_adapter *adapter); +static int adm1026_detect(struct i2c_adapter *adapter, int address, + int kind); +static int adm1026_detach_client(struct i2c_client *client); static int adm1026_read_value(struct i2c_client *client, u8 reg); static int adm1026_write_value(struct i2c_client *client, u8 reg, int value); static void adm1026_print_gpio(struct i2c_client *client); @@ -305,24 +305,22 @@ static struct adm1026_data *adm1026_update_device(struct device *dev); static void adm1026_init_client(struct i2c_client *client); -static const struct i2c_device_id adm1026_id[] = { - { "adm1026", adm1026 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm1026_id); - static struct i2c_driver adm1026_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "adm1026", }, - .probe = adm1026_probe, - .remove = adm1026_remove, - .id_table = adm1026_id, - .detect = adm1026_detect, - .address_data = &addr_data, + .attach_adapter = adm1026_attach_adapter, + .detach_client = adm1026_detach_client, }; +static int adm1026_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) { + return 0; + } + return i2c_probe(adapter, &addr_data, adm1026_detect); +} + static int adm1026_read_value(struct i2c_client *client, u8 reg) { int res; @@ -1649,32 +1647,48 @@ static const struct attribute_group adm1026_group_in8_9 = { .attrs = adm1026_attributes_in8_9, }; -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int adm1026_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int adm1026_detect(struct i2c_adapter *adapter, int address, + int kind) { - struct i2c_adapter *adapter = client->adapter; - int address = client->addr; int company, verstep; + struct i2c_client *client; + struct adm1026_data *data; + int err = 0; + const char *type_name = ""; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { /* We need to be able to do byte I/O */ - return -ENODEV; + goto exit; }; + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access adm1026_{read,write}_value. */ + + if (!(data = kzalloc(sizeof(struct adm1026_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &adm1026_driver; + /* Now, we do the remaining detection. */ company = adm1026_read_value(client, ADM1026_REG_COMPANY); verstep = adm1026_read_value(client, ADM1026_REG_VERSTEP); - dev_dbg(&adapter->dev, "Detecting device at %d,0x%02x with" + dev_dbg(&client->dev, "Detecting device at %d,0x%02x with" " COMPANY: 0x%02x and VERSTEP: 0x%02x\n", i2c_adapter_id(client->adapter), client->addr, company, verstep); /* If auto-detecting, Determine the chip type. */ if (kind <= 0) { - dev_dbg(&adapter->dev, "Autodetecting device at %d,0x%02x " + dev_dbg(&client->dev, "Autodetecting device at %d,0x%02x " "...\n", i2c_adapter_id(adapter), address); if (company == ADM1026_COMPANY_ANALOG_DEV && verstep == ADM1026_VERSTEP_ADM1026) { @@ -1690,7 +1704,7 @@ static int adm1026_detect(struct i2c_client *client, int kind, verstep); kind = any_chip; } else { - dev_dbg(&adapter->dev, ": Autodetection " + dev_dbg(&client->dev, ": Autodetection " "failed\n"); /* Not an ADM1026 ... */ if (kind == 0) { /* User used force=x,y */ @@ -1699,29 +1713,33 @@ static int adm1026_detect(struct i2c_client *client, int kind, "force_adm1026.\n", i2c_adapter_id(adapter), address); } - return -ENODEV; + goto exitfree; } } - strlcpy(info->type, "adm1026", I2C_NAME_SIZE); - - return 0; -} - -static int adm1026_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adm1026_data *data; - int err; - data = kzalloc(sizeof(struct adm1026_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; + /* Fill in the chip specific driver values */ + switch (kind) { + case any_chip : + type_name = "adm1026"; + break; + case adm1026 : + type_name = "adm1026"; + break; + default : + dev_err(&adapter->dev, ": Internal error, invalid " + "kind (%d)!\n", kind); + err = -EFAULT; + goto exitfree; } + strlcpy(client->name, type_name, I2C_NAME_SIZE); - i2c_set_clientdata(client, data); + /* Fill in the remaining client fields */ mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exitfree; + /* Set the VRM version */ data->vrm = vid_which_vrm(); @@ -1730,7 +1748,7 @@ static int adm1026_probe(struct i2c_client *client, /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &adm1026_group))) - goto exitfree; + goto exitdetach; if (data->config1 & CFG1_AIN8_9) err = sysfs_create_group(&client->dev.kobj, &adm1026_group_in8_9); @@ -1755,13 +1773,15 @@ static int adm1026_probe(struct i2c_client *client, sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9); else sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3); +exitdetach: + i2c_detach_client(client); exitfree: kfree(data); exit: return err; } -static int adm1026_remove(struct i2c_client *client) +static int adm1026_detach_client(struct i2c_client *client) { struct adm1026_data *data = i2c_get_clientdata(client); hwmon_device_unregister(data->hwmon_dev); @@ -1770,6 +1790,7 @@ static int adm1026_remove(struct i2c_client *client) sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9); else sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3); + i2c_detach_client(client); kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/adm1029.c b/trunk/drivers/hwmon/adm1029.c index ba84ca5923f9..2c6608d453c2 100644 --- a/trunk/drivers/hwmon/adm1029.c +++ b/trunk/drivers/hwmon/adm1029.c @@ -115,11 +115,9 @@ static const u8 ADM1029_REG_FAN_DIV[] = { * Functions declaration */ -static int adm1029_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm1029_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); -static int adm1029_remove(struct i2c_client *client); +static int adm1029_attach_adapter(struct i2c_adapter *adapter); +static int adm1029_detect(struct i2c_adapter *adapter, int address, int kind); +static int adm1029_detach_client(struct i2c_client *client); static struct adm1029_data *adm1029_update_device(struct device *dev); static int adm1029_init_client(struct i2c_client *client); @@ -127,22 +125,12 @@ static int adm1029_init_client(struct i2c_client *client); * Driver data (common to all clients) */ -static const struct i2c_device_id adm1029_id[] = { - { "adm1029", adm1029 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm1029_id); - static struct i2c_driver adm1029_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "adm1029", }, - .probe = adm1029_probe, - .remove = adm1029_remove, - .id_table = adm1029_id, - .detect = adm1029_detect, - .address_data = &addr_data, + .attach_adapter = adm1029_attach_adapter, + .detach_client = adm1029_detach_client, }; /* @@ -150,6 +138,7 @@ static struct i2c_driver adm1029_driver = { */ struct adm1029_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -295,14 +284,37 @@ static const struct attribute_group adm1029_group = { * Real code */ -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int adm1029_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int adm1029_attach_adapter(struct i2c_adapter *adapter) { - struct i2c_adapter *adapter = client->adapter; + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, adm1029_detect); +} +/* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. + */ + +static int adm1029_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct adm1029_data *data; + int err = 0; + const char *name = ""; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + goto exit; + + if (!(data = kzalloc(sizeof(struct adm1029_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &adm1029_driver; /* Now we do the detection and identification. A negative kind * means that the driver was loaded with no force parameter @@ -350,41 +362,32 @@ static int adm1029_detect(struct i2c_client *client, int kind, if (kind <= 0) { /* identification failed */ pr_debug("adm1029: Unsupported chip (man_id=0x%02X, " "chip_id=0x%02X)\n", man_id, chip_id); - return -ENODEV; + goto exit_free; } } - strlcpy(info->type, "adm1029", I2C_NAME_SIZE); - return 0; -} - -static int adm1029_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adm1029_data *data; - int err; - - data = kzalloc(sizeof(struct adm1029_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; + if (kind == adm1029) { + name = "adm1029"; } - i2c_set_clientdata(client, data); + /* We can fill in the remaining client fields */ + strlcpy(client->name, name, I2C_NAME_SIZE); mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; + /* * Initialize the ADM1029 chip * Check config register */ - if (adm1029_init_client(client) == 0) { - err = -ENODEV; - goto exit_free; - } + if (adm1029_init_client(client) == 0) + goto exit_detach; /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &adm1029_group))) - goto exit_free; + goto exit_detach; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -396,6 +399,8 @@ static int adm1029_probe(struct i2c_client *client, exit_remove_files: sysfs_remove_group(&client->dev.kobj, &adm1029_group); + exit_detach: + i2c_detach_client(client); exit_free: kfree(data); exit: @@ -419,13 +424,17 @@ static int adm1029_init_client(struct i2c_client *client) return 1; } -static int adm1029_remove(struct i2c_client *client) +static int adm1029_detach_client(struct i2c_client *client) { struct adm1029_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &adm1029_group); + if ((err = i2c_detach_client(client))) + return err; + kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/adm1031.c b/trunk/drivers/hwmon/adm1031.c index 789441830cd8..2bffcab7dc9f 100644 --- a/trunk/drivers/hwmon/adm1031.c +++ b/trunk/drivers/hwmon/adm1031.c @@ -70,6 +70,7 @@ typedef u8 auto_chan_table_t[8][2]; /* Each client has this additional data */ struct adm1031_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; int chip_type; @@ -98,32 +99,19 @@ struct adm1031_data { s8 temp_crit[3]; }; -static int adm1031_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm1031_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); +static int adm1031_attach_adapter(struct i2c_adapter *adapter); +static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind); static void adm1031_init_client(struct i2c_client *client); -static int adm1031_remove(struct i2c_client *client); +static int adm1031_detach_client(struct i2c_client *client); static struct adm1031_data *adm1031_update_device(struct device *dev); -static const struct i2c_device_id adm1031_id[] = { - { "adm1030", adm1030 }, - { "adm1031", adm1031 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm1031_id); - /* This is the driver that will be inserted */ static struct i2c_driver adm1031_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "adm1031", }, - .probe = adm1031_probe, - .remove = adm1031_remove, - .id_table = adm1031_id, - .detect = adm1031_detect, - .address_data = &addr_data, + .attach_adapter = adm1031_attach_adapter, + .detach_client = adm1031_detach_client, }; static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg) @@ -705,6 +693,13 @@ static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12); static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13); static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14); +static int adm1031_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, adm1031_detect); +} + static struct attribute *adm1031_attributes[] = { &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_div.dev_attr.attr, @@ -775,15 +770,27 @@ static const struct attribute_group adm1031_group_opt = { .attrs = adm1031_attributes_opt, }; -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int adm1031_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +/* This function is called by i2c_probe */ +static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = client->adapter; + struct i2c_client *client; + struct adm1031_data *data; + int err = 0; const char *name = ""; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + goto exit; + + if (!(data = kzalloc(sizeof(struct adm1031_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &adm1031_driver; if (kind < 0) { int id, co; @@ -791,7 +798,7 @@ static int adm1031_detect(struct i2c_client *client, int kind, co = i2c_smbus_read_byte_data(client, 0x3e); if (!((id == 0x31 || id == 0x30) && co == 0x41)) - return -ENODEV; + goto exit_free; kind = (id == 0x30) ? adm1030 : adm1031; } @@ -802,43 +809,28 @@ static int adm1031_detect(struct i2c_client *client, int kind, * auto fan control helper table. */ if (kind == adm1030) { name = "adm1030"; + data->chan_select_table = &auto_channel_select_table_adm1030; } else if (kind == adm1031) { name = "adm1031"; + data->chan_select_table = &auto_channel_select_table_adm1031; } - strlcpy(info->type, name, I2C_NAME_SIZE); - - return 0; -} - -static int adm1031_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adm1031_data *data; - int err; - - data = kzalloc(sizeof(struct adm1031_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } + data->chip_type = kind; - i2c_set_clientdata(client, data); - data->chip_type = id->driver_data; + strlcpy(client->name, name, I2C_NAME_SIZE); mutex_init(&data->update_lock); - if (data->chip_type == adm1030) - data->chan_select_table = &auto_channel_select_table_adm1030; - else - data->chan_select_table = &auto_channel_select_table_adm1031; + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; /* Initialize the ADM1031 chip */ adm1031_init_client(client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group))) - goto exit_free; + goto exit_detach; - if (data->chip_type == adm1031) { + if (kind == adm1031) { if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group_opt))) goto exit_remove; @@ -855,19 +847,25 @@ static int adm1031_probe(struct i2c_client *client, exit_remove: sysfs_remove_group(&client->dev.kobj, &adm1031_group); sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt); +exit_detach: + i2c_detach_client(client); exit_free: kfree(data); exit: return err; } -static int adm1031_remove(struct i2c_client *client) +static int adm1031_detach_client(struct i2c_client *client) { struct adm1031_data *data = i2c_get_clientdata(client); + int ret; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &adm1031_group); sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt); + if ((ret = i2c_detach_client(client)) != 0) { + return ret; + } kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/adm9240.c b/trunk/drivers/hwmon/adm9240.c index 2444b15f2e9d..149ef25252e7 100644 --- a/trunk/drivers/hwmon/adm9240.c +++ b/trunk/drivers/hwmon/adm9240.c @@ -130,37 +130,25 @@ static inline unsigned int AOUT_FROM_REG(u8 reg) return SCALE(reg, 1250, 255); } -static int adm9240_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm9240_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); +static int adm9240_attach_adapter(struct i2c_adapter *adapter); +static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind); static void adm9240_init_client(struct i2c_client *client); -static int adm9240_remove(struct i2c_client *client); +static int adm9240_detach_client(struct i2c_client *client); static struct adm9240_data *adm9240_update_device(struct device *dev); /* driver data */ -static const struct i2c_device_id adm9240_id[] = { - { "adm9240", adm9240 }, - { "ds1780", ds1780 }, - { "lm81", lm81 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm9240_id); - static struct i2c_driver adm9240_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "adm9240", }, - .probe = adm9240_probe, - .remove = adm9240_remove, - .id_table = adm9240_id, - .detect = adm9240_detect, - .address_data = &addr_data, + .attach_adapter = adm9240_attach_adapter, + .detach_client = adm9240_detach_client, }; /* per client data */ struct adm9240_data { + enum chips type; + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; @@ -544,17 +532,28 @@ static const struct attribute_group adm9240_group = { /*** sensor chip detect and driver install ***/ -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int adm9240_detect(struct i2c_client *new_client, int kind, - struct i2c_board_info *info) +static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = new_client->adapter; + struct i2c_client *new_client; + struct adm9240_data *data; + int err = 0; const char *name = ""; - int address = new_client->addr; u8 man_id, die_rev; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + goto exit; + + if (!(data = kzalloc(sizeof(*data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &adm9240_driver; + new_client->flags = 0; if (kind == 0) { kind = adm9240; @@ -567,7 +566,7 @@ static int adm9240_detect(struct i2c_client *new_client, int kind, != address) { dev_err(&adapter->dev, "detect fail: address match, " "0x%02x\n", address); - return -ENODEV; + goto exit_free; } /* check known chip manufacturer */ @@ -582,7 +581,7 @@ static int adm9240_detect(struct i2c_client *new_client, int kind, } else { dev_err(&adapter->dev, "detect fail: unknown manuf, " "0x%02x\n", man_id); - return -ENODEV; + goto exit_free; } /* successful detect, print chip info */ @@ -601,31 +600,20 @@ static int adm9240_detect(struct i2c_client *new_client, int kind, } else if (kind == lm81) { name = "lm81"; } - strlcpy(info->type, name, I2C_NAME_SIZE); - - return 0; -} -static int adm9240_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct adm9240_data *data; - int err; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(new_client, data); + /* fill in the remaining client fields and attach */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); + data->type = kind; mutex_init(&data->update_lock); + if ((err = i2c_attach_client(new_client))) + goto exit_free; + adm9240_init_client(new_client); /* populate sysfs filesystem */ if ((err = sysfs_create_group(&new_client->dev.kobj, &adm9240_group))) - goto exit_free; + goto exit_detach; data->hwmon_dev = hwmon_device_register(&new_client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -637,19 +625,32 @@ static int adm9240_probe(struct i2c_client *new_client, exit_remove: sysfs_remove_group(&new_client->dev.kobj, &adm9240_group); +exit_detach: + i2c_detach_client(new_client); exit_free: kfree(data); exit: return err; } -static int adm9240_remove(struct i2c_client *client) +static int adm9240_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, adm9240_detect); +} + +static int adm9240_detach_client(struct i2c_client *client) { struct adm9240_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &adm9240_group); + if ((err = i2c_detach_client(client))) + return err; + kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/ads7828.c b/trunk/drivers/hwmon/ads7828.c index 5c39b4af1b23..5c8b6e0ff47c 100644 --- a/trunk/drivers/hwmon/ads7828.c +++ b/trunk/drivers/hwmon/ads7828.c @@ -64,6 +64,7 @@ static unsigned int ads7828_lsb_resol; /* resolution of the ADC sample lsb */ /* Each client has this additional data */ struct ads7828_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; /* mutex protect updates */ char valid; /* !=0 if following fields are valid */ @@ -72,10 +73,7 @@ struct ads7828_data { }; /* Function declaration - necessary due to function dependencies */ -static int ads7828_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); -static int ads7828_probe(struct i2c_client *client, - const struct i2c_device_id *id); +static int ads7828_detect(struct i2c_adapter *adapter, int address, int kind); /* The ADS7828 returns the 12-bit sample in two bytes, these are read as a word then byte-swapped */ @@ -158,43 +156,58 @@ static const struct attribute_group ads7828_group = { .attrs = ads7828_attributes, }; -static int ads7828_remove(struct i2c_client *client) +static int ads7828_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, ads7828_detect); +} + +static int ads7828_detach_client(struct i2c_client *client) { struct ads7828_data *data = i2c_get_clientdata(client); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &ads7828_group); + i2c_detach_client(client); kfree(i2c_get_clientdata(client)); return 0; } -static const struct i2c_device_id ads7828_id[] = { - { "ads7828", ads7828 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ads7828_id); - /* This is the driver that will be inserted */ static struct i2c_driver ads7828_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "ads7828", }, - .probe = ads7828_probe, - .remove = ads7828_remove, - .id_table = ads7828_id, - .detect = ads7828_detect, - .address_data = &addr_data, + .attach_adapter = ads7828_attach_adapter, + .detach_client = ads7828_detach_client, }; -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int ads7828_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +/* This function is called by i2c_probe */ +static int ads7828_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = client->adapter; + struct i2c_client *client; + struct ads7828_data *data; + int err = 0; + const char *name = ""; /* Check we have a valid client */ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) - return -ENODEV; + goto exit; + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access ads7828_read_value. */ + data = kzalloc(sizeof(struct ads7828_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &ads7828_driver; /* Now, we do the remaining detection. There is no identification dedicated register so attempt to sanity check using knowledge of @@ -212,34 +225,32 @@ static int ads7828_detect(struct i2c_client *client, int kind, printk(KERN_DEBUG "%s : Doesn't look like an ads7828 device\n", __func__); - return -ENODEV; + goto exit_free; } } } - strlcpy(info->type, "ads7828", I2C_NAME_SIZE); - return 0; -} + /* Determine the chip type - only one kind supported! */ + if (kind <= 0) + kind = ads7828; -static int ads7828_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct ads7828_data *data; - int err; + if (kind == ads7828) + name = "ads7828"; - data = kzalloc(sizeof(struct ads7828_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } + /* Fill in the remaining client fields, put it into the global list */ + strlcpy(client->name, name, I2C_NAME_SIZE); - i2c_set_clientdata(client, data); mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + err = i2c_attach_client(client); + if (err) + goto exit_free; + /* Register sysfs hooks */ err = sysfs_create_group(&client->dev.kobj, &ads7828_group); if (err) - goto exit_free; + goto exit_detach; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -251,6 +262,8 @@ static int ads7828_probe(struct i2c_client *client, exit_remove: sysfs_remove_group(&client->dev.kobj, &ads7828_group); +exit_detach: + i2c_detach_client(client); exit_free: kfree(data); exit: diff --git a/trunk/drivers/hwmon/adt7470.c b/trunk/drivers/hwmon/adt7470.c index d368d8f845e1..6b5325f33a2c 100644 --- a/trunk/drivers/hwmon/adt7470.c +++ b/trunk/drivers/hwmon/adt7470.c @@ -138,6 +138,7 @@ I2C_CLIENT_INSMOD_1(adt7470); #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) struct adt7470_data { + struct i2c_client client; struct device *hwmon_dev; struct attribute_group attrs; struct mutex lock; @@ -163,28 +164,16 @@ struct adt7470_data { u8 pwm_auto_temp[ADT7470_PWM_COUNT]; }; -static int adt7470_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adt7470_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); -static int adt7470_remove(struct i2c_client *client); - -static const struct i2c_device_id adt7470_id[] = { - { "adt7470", adt7470 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adt7470_id); +static int adt7470_attach_adapter(struct i2c_adapter *adapter); +static int adt7470_detect(struct i2c_adapter *adapter, int address, int kind); +static int adt7470_detach_client(struct i2c_client *client); static struct i2c_driver adt7470_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "adt7470", }, - .probe = adt7470_probe, - .remove = adt7470_remove, - .id_table = adt7470_id, - .detect = adt7470_detect, - .address_data = &addr_data, + .attach_adapter = adt7470_attach_adapter, + .detach_client = adt7470_detach_client, }; /* @@ -1015,52 +1004,64 @@ static struct attribute *adt7470_attr[] = NULL }; -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int adt7470_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int adt7470_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, adt7470_detect); +} + +static int adt7470_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = client->adapter; + struct i2c_client *client; + struct adt7470_data *data; + int err = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + goto exit; + + if (!(data = kzalloc(sizeof(struct adt7470_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + client->addr = address; + client->adapter = adapter; + client->driver = &adt7470_driver; + + i2c_set_clientdata(client, data); + + mutex_init(&data->lock); if (kind <= 0) { int vendor, device, revision; vendor = i2c_smbus_read_byte_data(client, ADT7470_REG_VENDOR); - if (vendor != ADT7470_VENDOR) - return -ENODEV; + if (vendor != ADT7470_VENDOR) { + err = -ENODEV; + goto exit_free; + } device = i2c_smbus_read_byte_data(client, ADT7470_REG_DEVICE); - if (device != ADT7470_DEVICE) - return -ENODEV; + if (device != ADT7470_DEVICE) { + err = -ENODEV; + goto exit_free; + } revision = i2c_smbus_read_byte_data(client, ADT7470_REG_REVISION); - if (revision != ADT7470_REVISION) - return -ENODEV; + if (revision != ADT7470_REVISION) { + err = -ENODEV; + goto exit_free; + } } else dev_dbg(&adapter->dev, "detection forced\n"); - strlcpy(info->type, "adt7470", I2C_NAME_SIZE); - - return 0; -} - -static int adt7470_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adt7470_data *data; - int err; + strlcpy(client->name, "adt7470", I2C_NAME_SIZE); - data = kzalloc(sizeof(struct adt7470_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->lock); + if ((err = i2c_attach_client(client))) + goto exit_free; dev_info(&client->dev, "%s chip found\n", client->name); @@ -1070,7 +1071,7 @@ static int adt7470_probe(struct i2c_client *client, /* Register sysfs hooks */ data->attrs.attrs = adt7470_attr; if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs))) - goto exit_free; + goto exit_detach; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -1082,18 +1083,21 @@ static int adt7470_probe(struct i2c_client *client, exit_remove: sysfs_remove_group(&client->dev.kobj, &data->attrs); +exit_detach: + i2c_detach_client(client); exit_free: kfree(data); exit: return err; } -static int adt7470_remove(struct i2c_client *client) +static int adt7470_detach_client(struct i2c_client *client) { struct adt7470_data *data = i2c_get_clientdata(client); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &data->attrs); + i2c_detach_client(client); kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/adt7473.c b/trunk/drivers/hwmon/adt7473.c index ce4a7cb5a116..93dbf5e7ff8a 100644 --- a/trunk/drivers/hwmon/adt7473.c +++ b/trunk/drivers/hwmon/adt7473.c @@ -143,6 +143,7 @@ I2C_CLIENT_INSMOD_1(adt7473); #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) struct adt7473_data { + struct i2c_client client; struct device *hwmon_dev; struct attribute_group attrs; struct mutex lock; @@ -177,28 +178,16 @@ struct adt7473_data { u8 max_duty_at_overheat; }; -static int adt7473_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adt7473_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); -static int adt7473_remove(struct i2c_client *client); - -static const struct i2c_device_id adt7473_id[] = { - { "adt7473", adt7473 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adt7473_id); +static int adt7473_attach_adapter(struct i2c_adapter *adapter); +static int adt7473_detect(struct i2c_adapter *adapter, int address, int kind); +static int adt7473_detach_client(struct i2c_client *client); static struct i2c_driver adt7473_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "adt7473", }, - .probe = adt7473_probe, - .remove = adt7473_remove, - .id_table = adt7473_id, - .detect = adt7473_detect, - .address_data = &addr_data, + .attach_adapter = adt7473_attach_adapter, + .detach_client = adt7473_detach_client, }; /* @@ -1053,52 +1042,66 @@ static struct attribute *adt7473_attr[] = NULL }; -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int adt7473_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int adt7473_attach_adapter(struct i2c_adapter *adapter) { - struct i2c_adapter *adapter = client->adapter; + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, adt7473_detect); +} + +static int adt7473_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct adt7473_data *data; + int err = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + goto exit; + + data = kzalloc(sizeof(struct adt7473_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + client->addr = address; + client->adapter = adapter; + client->driver = &adt7473_driver; + + i2c_set_clientdata(client, data); + + mutex_init(&data->lock); if (kind <= 0) { int vendor, device, revision; vendor = i2c_smbus_read_byte_data(client, ADT7473_REG_VENDOR); - if (vendor != ADT7473_VENDOR) - return -ENODEV; + if (vendor != ADT7473_VENDOR) { + err = -ENODEV; + goto exit_free; + } device = i2c_smbus_read_byte_data(client, ADT7473_REG_DEVICE); - if (device != ADT7473_DEVICE) - return -ENODEV; + if (device != ADT7473_DEVICE) { + err = -ENODEV; + goto exit_free; + } revision = i2c_smbus_read_byte_data(client, ADT7473_REG_REVISION); - if (revision != ADT7473_REV_68 && revision != ADT7473_REV_69) - return -ENODEV; + if (revision != ADT7473_REV_68 && revision != ADT7473_REV_69) { + err = -ENODEV; + goto exit_free; + } } else dev_dbg(&adapter->dev, "detection forced\n"); - strlcpy(info->type, "adt7473", I2C_NAME_SIZE); + strlcpy(client->name, "adt7473", I2C_NAME_SIZE); - return 0; -} - -static int adt7473_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adt7473_data *data; - int err; - - data = kzalloc(sizeof(struct adt7473_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->lock); + err = i2c_attach_client(client); + if (err) + goto exit_free; dev_info(&client->dev, "%s chip found\n", client->name); @@ -1109,7 +1112,7 @@ static int adt7473_probe(struct i2c_client *client, data->attrs.attrs = adt7473_attr; err = sysfs_create_group(&client->dev.kobj, &data->attrs); if (err) - goto exit_free; + goto exit_detach; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -1121,18 +1124,21 @@ static int adt7473_probe(struct i2c_client *client, exit_remove: sysfs_remove_group(&client->dev.kobj, &data->attrs); +exit_detach: + i2c_detach_client(client); exit_free: kfree(data); exit: return err; } -static int adt7473_remove(struct i2c_client *client) +static int adt7473_detach_client(struct i2c_client *client) { struct adt7473_data *data = i2c_get_clientdata(client); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &data->attrs); + i2c_detach_client(client); kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/asb100.c b/trunk/drivers/hwmon/asb100.c index 8a45a2e6ba8a..fe2eea4d799b 100644 --- a/trunk/drivers/hwmon/asb100.c +++ b/trunk/drivers/hwmon/asb100.c @@ -176,8 +176,10 @@ static u8 DIV_TO_REG(long val) data is pointed to by client->data. The structure itself is dynamically allocated, at the same time the client itself is allocated. */ struct asb100_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex lock; + enum chips type; struct mutex update_lock; unsigned long last_updated; /* In jiffies */ @@ -204,30 +206,18 @@ struct asb100_data { static int asb100_read_value(struct i2c_client *client, u16 reg); static void asb100_write_value(struct i2c_client *client, u16 reg, u16 val); -static int asb100_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int asb100_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); -static int asb100_remove(struct i2c_client *client); +static int asb100_attach_adapter(struct i2c_adapter *adapter); +static int asb100_detect(struct i2c_adapter *adapter, int address, int kind); +static int asb100_detach_client(struct i2c_client *client); static struct asb100_data *asb100_update_device(struct device *dev); static void asb100_init_client(struct i2c_client *client); -static const struct i2c_device_id asb100_id[] = { - { "asb100", asb100 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, asb100_id); - static struct i2c_driver asb100_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "asb100", }, - .probe = asb100_probe, - .remove = asb100_remove, - .id_table = asb100_id, - .detect = asb100_detect, - .address_data = &addr_data, + .attach_adapter = asb100_attach_adapter, + .detach_client = asb100_detach_client, }; /* 7 Voltages */ @@ -629,13 +619,35 @@ static const struct attribute_group asb100_group = { .attrs = asb100_attributes, }; -static int asb100_detect_subclients(struct i2c_client *client) +/* This function is called when: + asb100_driver is inserted (when this module is loaded), for each + available adapter + when a new adapter is inserted (and asb100_driver is still present) + */ +static int asb100_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, asb100_detect); +} + +static int asb100_detect_subclients(struct i2c_adapter *adapter, int address, + int kind, struct i2c_client *client) { int i, id, err; - int address = client->addr; - unsigned short sc_addr[2]; struct asb100_data *data = i2c_get_clientdata(client); - struct i2c_adapter *adapter = client->adapter; + + data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (!(data->lm75[0])) { + err = -ENOMEM; + goto ERROR_SC_0; + } + + data->lm75[1] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (!(data->lm75[1])) { + err = -ENOMEM; + goto ERROR_SC_1; + } id = i2c_adapter_id(adapter); @@ -653,34 +665,37 @@ static int asb100_detect_subclients(struct i2c_client *client) asb100_write_value(client, ASB100_REG_I2C_SUBADDR, (force_subclients[2] & 0x07) | ((force_subclients[3] & 0x07) << 4)); - sc_addr[0] = force_subclients[2]; - sc_addr[1] = force_subclients[3]; + data->lm75[0]->addr = force_subclients[2]; + data->lm75[1]->addr = force_subclients[3]; } else { int val = asb100_read_value(client, ASB100_REG_I2C_SUBADDR); - sc_addr[0] = 0x48 + (val & 0x07); - sc_addr[1] = 0x48 + ((val >> 4) & 0x07); + data->lm75[0]->addr = 0x48 + (val & 0x07); + data->lm75[1]->addr = 0x48 + ((val >> 4) & 0x07); } - if (sc_addr[0] == sc_addr[1]) { + if (data->lm75[0]->addr == data->lm75[1]->addr) { dev_err(&client->dev, "duplicate addresses 0x%x " - "for subclients\n", sc_addr[0]); + "for subclients\n", data->lm75[0]->addr); err = -ENODEV; goto ERROR_SC_2; } - data->lm75[0] = i2c_new_dummy(adapter, sc_addr[0]); - if (!data->lm75[0]) { + for (i = 0; i <= 1; i++) { + i2c_set_clientdata(data->lm75[i], NULL); + data->lm75[i]->adapter = adapter; + data->lm75[i]->driver = &asb100_driver; + strlcpy(data->lm75[i]->name, "asb100 subclient", I2C_NAME_SIZE); + } + + if ((err = i2c_attach_client(data->lm75[0]))) { dev_err(&client->dev, "subclient %d registration " - "at address 0x%x failed.\n", 1, sc_addr[0]); - err = -ENOMEM; + "at address 0x%x failed.\n", i, data->lm75[0]->addr); goto ERROR_SC_2; } - data->lm75[1] = i2c_new_dummy(adapter, sc_addr[1]); - if (!data->lm75[1]) { + if ((err = i2c_attach_client(data->lm75[1]))) { dev_err(&client->dev, "subclient %d registration " - "at address 0x%x failed.\n", 2, sc_addr[1]); - err = -ENOMEM; + "at address 0x%x failed.\n", i, data->lm75[1]->addr); goto ERROR_SC_3; } @@ -688,31 +703,55 @@ static int asb100_detect_subclients(struct i2c_client *client) /* Undo inits in case of errors */ ERROR_SC_3: - i2c_unregister_device(data->lm75[0]); + i2c_detach_client(data->lm75[0]); ERROR_SC_2: + kfree(data->lm75[1]); +ERROR_SC_1: + kfree(data->lm75[0]); +ERROR_SC_0: return err; } -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int asb100_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = client->adapter; + int err; + struct i2c_client *client; + struct asb100_data *data; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { pr_debug("asb100.o: detect failed, " "smbus byte data not supported!\n"); - return -ENODEV; + err = -ENODEV; + goto ERROR0; } + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access asb100_{read,write}_value. */ + + if (!(data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL))) { + pr_debug("asb100.o: detect failed, kzalloc failed!\n"); + err = -ENOMEM; + goto ERROR0; + } + + client = &data->client; + mutex_init(&data->lock); + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &asb100_driver; + + /* Now, we do the remaining detection. */ + /* The chip may be stuck in some other bank than bank 0. This may make reading other information impossible. Specify a force=... or force_*=... parameter, and the chip will be reset to the right bank. */ if (kind < 0) { - int val1 = i2c_smbus_read_byte_data(client, ASB100_REG_BANK); - int val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN); + int val1 = asb100_read_value(client, ASB100_REG_BANK); + int val2 = asb100_read_value(client, ASB100_REG_CHIPMAN); /* If we're in bank 0 */ if ((!(val1 & 0x07)) && @@ -722,61 +761,49 @@ static int asb100_detect(struct i2c_client *client, int kind, ((val1 & 0x80) && (val2 != 0x06)))) { pr_debug("asb100.o: detect failed, " "bad chip id 0x%02x!\n", val2); - return -ENODEV; + err = -ENODEV; + goto ERROR1; } } /* kind < 0 */ /* We have either had a force parameter, or we have already detected Winbond. Put it now into bank 0 and Vendor ID High Byte */ - i2c_smbus_write_byte_data(client, ASB100_REG_BANK, - (i2c_smbus_read_byte_data(client, ASB100_REG_BANK) & 0x78) - | 0x80); + asb100_write_value(client, ASB100_REG_BANK, + (asb100_read_value(client, ASB100_REG_BANK) & 0x78) | 0x80); /* Determine the chip type. */ if (kind <= 0) { - int val1 = i2c_smbus_read_byte_data(client, ASB100_REG_WCHIPID); - int val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN); + int val1 = asb100_read_value(client, ASB100_REG_WCHIPID); + int val2 = asb100_read_value(client, ASB100_REG_CHIPMAN); if ((val1 == 0x31) && (val2 == 0x06)) kind = asb100; else { if (kind == 0) - dev_warn(&adapter->dev, "ignoring " + dev_warn(&client->dev, "ignoring " "'force' parameter for unknown chip " "at adapter %d, address 0x%02x.\n", - i2c_adapter_id(adapter), client->addr); - return -ENODEV; + i2c_adapter_id(adapter), address); + err = -ENODEV; + goto ERROR1; } } - strlcpy(info->type, "asb100", I2C_NAME_SIZE); - - return 0; -} - -static int asb100_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int err; - struct asb100_data *data; - - data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL); - if (!data) { - pr_debug("asb100.o: probe failed, kzalloc failed!\n"); - err = -ENOMEM; - goto ERROR0; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->lock); + /* Fill in remaining client fields and put it into the global list */ + strlcpy(client->name, "asb100", I2C_NAME_SIZE); + data->type = kind; mutex_init(&data->update_lock); - /* Attach secondary lm75 clients */ - err = asb100_detect_subclients(client); - if (err) + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) goto ERROR1; + /* Attach secondary lm75 clients */ + if ((err = asb100_detect_subclients(adapter, address, kind, + client))) + goto ERROR2; + /* Initialize the chip */ asb100_init_client(client); @@ -800,25 +827,39 @@ static int asb100_probe(struct i2c_client *client, ERROR4: sysfs_remove_group(&client->dev.kobj, &asb100_group); ERROR3: - i2c_unregister_device(data->lm75[1]); - i2c_unregister_device(data->lm75[0]); + i2c_detach_client(data->lm75[1]); + i2c_detach_client(data->lm75[0]); + kfree(data->lm75[1]); + kfree(data->lm75[0]); +ERROR2: + i2c_detach_client(client); ERROR1: kfree(data); ERROR0: return err; } -static int asb100_remove(struct i2c_client *client) +static int asb100_detach_client(struct i2c_client *client) { struct asb100_data *data = i2c_get_clientdata(client); + int err; - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &asb100_group); + /* main client */ + if (data) { + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &asb100_group); + } - i2c_unregister_device(data->lm75[1]); - i2c_unregister_device(data->lm75[0]); + if ((err = i2c_detach_client(client))) + return err; - kfree(data); + /* main client */ + if (data) + kfree(data); + + /* subclient */ + else + kfree(client); return 0; } diff --git a/trunk/drivers/hwmon/atxp1.c b/trunk/drivers/hwmon/atxp1.c index d191118ba0cb..01c17e387f03 100644 --- a/trunk/drivers/hwmon/atxp1.c +++ b/trunk/drivers/hwmon/atxp1.c @@ -46,32 +46,21 @@ static const unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END }; I2C_CLIENT_INSMOD_1(atxp1); -static int atxp1_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int atxp1_remove(struct i2c_client *client); +static int atxp1_attach_adapter(struct i2c_adapter * adapter); +static int atxp1_detach_client(struct i2c_client * client); static struct atxp1_data * atxp1_update_device(struct device *dev); -static int atxp1_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); - -static const struct i2c_device_id atxp1_id[] = { - { "atxp1", atxp1 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, atxp1_id); +static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind); static struct i2c_driver atxp1_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "atxp1", }, - .probe = atxp1_probe, - .remove = atxp1_remove, - .id_table = atxp1_id, - .detect = atxp1_detect, - .address_data = &addr_data, + .attach_adapter = atxp1_attach_adapter, + .detach_client = atxp1_detach_client, }; struct atxp1_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; unsigned long last_updated; @@ -274,16 +263,35 @@ static const struct attribute_group atxp1_group = { }; -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int atxp1_detect(struct i2c_client *new_client, int kind, - struct i2c_board_info *info) +static int atxp1_attach_adapter(struct i2c_adapter *adapter) { - struct i2c_adapter *adapter = new_client->adapter; + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, &atxp1_detect); +}; +static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client * new_client; + struct atxp1_data * data; + int err = 0; u8 temp; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + goto exit; + + if (!(data = kzalloc(sizeof(struct atxp1_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + new_client = &data->client; + i2c_set_clientdata(new_client, data); + + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &atxp1_driver; + new_client->flags = 0; /* Detect ATXP1, checking if vendor ID registers are all zero */ if (!((i2c_smbus_read_byte_data(new_client, 0x3e) == 0) && @@ -297,46 +305,35 @@ static int atxp1_detect(struct i2c_client *new_client, int kind, if (!((i2c_smbus_read_byte_data(new_client, 0x10) == temp) && (i2c_smbus_read_byte_data(new_client, 0x11) == temp) )) - return -ENODEV; + goto exit_free; } /* Get VRM */ - temp = vid_which_vrm(); - - if ((temp != 90) && (temp != 91)) { - dev_err(&adapter->dev, "atxp1: Not supporting VRM %d.%d\n", - temp / 10, temp % 10); - return -ENODEV; - } - - strlcpy(info->type, "atxp1", I2C_NAME_SIZE); - - return 0; -} - -static int atxp1_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct atxp1_data *data; - int err; + data->vrm = vid_which_vrm(); - data = kzalloc(sizeof(struct atxp1_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; + if ((data->vrm != 90) && (data->vrm != 91)) { + dev_err(&new_client->dev, "Not supporting VRM %d.%d\n", + data->vrm / 10, data->vrm % 10); + goto exit_free; } - /* Get VRM */ - data->vrm = vid_which_vrm(); + strncpy(new_client->name, "atxp1", I2C_NAME_SIZE); - i2c_set_clientdata(new_client, data); data->valid = 0; mutex_init(&data->update_lock); + err = i2c_attach_client(new_client); + + if (err) + { + dev_err(&new_client->dev, "Attach client error.\n"); + goto exit_free; + } + /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group))) - goto exit_free; + goto exit_detach; data->hwmon_dev = hwmon_device_register(&new_client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -351,22 +348,30 @@ static int atxp1_probe(struct i2c_client *new_client, exit_remove_files: sysfs_remove_group(&new_client->dev.kobj, &atxp1_group); +exit_detach: + i2c_detach_client(new_client); exit_free: kfree(data); exit: return err; }; -static int atxp1_remove(struct i2c_client *client) +static int atxp1_detach_client(struct i2c_client * client) { struct atxp1_data * data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &atxp1_group); - kfree(data); + err = i2c_detach_client(client); - return 0; + if (err) + dev_err(&client->dev, "Failed to detach client.\n"); + else + kfree(data); + + return err; }; static int __init atxp1_init(void) diff --git a/trunk/drivers/hwmon/ds1621.c b/trunk/drivers/hwmon/ds1621.c index 7415381601c3..5f300ffed657 100644 --- a/trunk/drivers/hwmon/ds1621.c +++ b/trunk/drivers/hwmon/ds1621.c @@ -72,6 +72,7 @@ static const u8 DS1621_REG_TEMP[3] = { /* Each client has this additional data */ struct ds1621_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ @@ -81,32 +82,20 @@ struct ds1621_data { u8 conf; /* Register encoding, combined */ }; -static int ds1621_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int ds1621_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); +static int ds1621_attach_adapter(struct i2c_adapter *adapter); +static int ds1621_detect(struct i2c_adapter *adapter, int address, + int kind); static void ds1621_init_client(struct i2c_client *client); -static int ds1621_remove(struct i2c_client *client); +static int ds1621_detach_client(struct i2c_client *client); static struct ds1621_data *ds1621_update_client(struct device *dev); -static const struct i2c_device_id ds1621_id[] = { - { "ds1621", ds1621 }, - { "ds1625", ds1621 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ds1621_id); - /* This is the driver that will be inserted */ static struct i2c_driver ds1621_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "ds1621", }, - .probe = ds1621_probe, - .remove = ds1621_remove, - .id_table = ds1621_id, - .detect = ds1621_detect, - .address_data = &addr_data, + .attach_adapter = ds1621_attach_adapter, + .detach_client = ds1621_detach_client, }; /* All registers are word-sized, except for the configuration register. @@ -210,18 +199,40 @@ static const struct attribute_group ds1621_group = { }; -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int ds1621_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int ds1621_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, ds1621_detect); +} + +/* This function is called by i2c_probe */ +static int ds1621_detect(struct i2c_adapter *adapter, int address, + int kind) { - struct i2c_adapter *adapter = client->adapter; int conf, temp; - int i; + struct i2c_client *client; + struct ds1621_data *data; + int i, err = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_WRITE_BYTE)) - return -ENODEV; + goto exit; + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access ds1621_{read,write}_value. */ + if (!(data = kzalloc(sizeof(struct ds1621_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &ds1621_driver; /* Now, we do the remaining detection. It is lousy. */ if (kind < 0) { @@ -230,41 +241,29 @@ static int ds1621_detect(struct i2c_client *client, int kind, improbable in our case. */ conf = ds1621_read_value(client, DS1621_REG_CONF); if (conf & DS1621_REG_CONFIG_NVB) - return -ENODEV; + goto exit_free; /* The 7 lowest bits of a temperature should always be 0. */ - for (i = 0; i < ARRAY_SIZE(DS1621_REG_TEMP); i++) { + for (i = 0; i < ARRAY_SIZE(data->temp); i++) { temp = ds1621_read_value(client, DS1621_REG_TEMP[i]); if (temp & 0x007f) - return -ENODEV; + goto exit_free; } } - strlcpy(info->type, "ds1621", I2C_NAME_SIZE); - - return 0; -} - -static int ds1621_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct ds1621_data *data; - int err; - - data = kzalloc(sizeof(struct ds1621_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); + /* Fill in remaining client fields and put it into the global list */ + strlcpy(client->name, "ds1621", I2C_NAME_SIZE); mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; + /* Initialize the DS1621 chip */ ds1621_init_client(client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &ds1621_group))) - goto exit_free; + goto exit_detach; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -276,19 +275,25 @@ static int ds1621_probe(struct i2c_client *client, exit_remove_files: sysfs_remove_group(&client->dev.kobj, &ds1621_group); + exit_detach: + i2c_detach_client(client); exit_free: kfree(data); exit: return err; } -static int ds1621_remove(struct i2c_client *client) +static int ds1621_detach_client(struct i2c_client *client) { struct ds1621_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &ds1621_group); + if ((err = i2c_detach_client(client))) + return err; + kfree(data); return 0; diff --git a/trunk/drivers/hwmon/f75375s.c b/trunk/drivers/hwmon/f75375s.c index 1692de369969..dc1f30e432ea 100644 --- a/trunk/drivers/hwmon/f75375s.c +++ b/trunk/drivers/hwmon/f75375s.c @@ -87,6 +87,7 @@ I2C_CLIENT_INSMOD_2(f75373, f75375); struct f75375_data { unsigned short addr; + struct i2c_client *client; struct device *hwmon_dev; const char *name; @@ -113,12 +114,21 @@ struct f75375_data { s8 temp_max_hyst[2]; }; -static int f75375_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); +static int f75375_attach_adapter(struct i2c_adapter *adapter); +static int f75375_detect(struct i2c_adapter *adapter, int address, int kind); +static int f75375_detach_client(struct i2c_client *client); static int f75375_probe(struct i2c_client *client, const struct i2c_device_id *id); static int f75375_remove(struct i2c_client *client); +static struct i2c_driver f75375_legacy_driver = { + .driver = { + .name = "f75375_legacy", + }, + .attach_adapter = f75375_attach_adapter, + .detach_client = f75375_detach_client, +}; + static const struct i2c_device_id f75375_id[] = { { "f75373", f75373 }, { "f75375", f75375 }, @@ -127,15 +137,12 @@ static const struct i2c_device_id f75375_id[] = { MODULE_DEVICE_TABLE(i2c, f75375_id); static struct i2c_driver f75375_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "f75375", }, .probe = f75375_probe, .remove = f75375_remove, .id_table = f75375_id, - .detect = f75375_detect, - .address_data = &addr_data, }; static inline int f75375_read8(struct i2c_client *client, u8 reg) @@ -600,6 +607,22 @@ static const struct attribute_group f75375_group = { .attrs = f75375_attributes, }; +static int f75375_detach_client(struct i2c_client *client) +{ + int err; + + f75375_remove(client); + err = i2c_detach_client(client); + if (err) { + dev_err(&client->dev, + "Client deregistration failed, " + "client not detached.\n"); + return err; + } + kfree(client); + return 0; +} + static void f75375_init(struct i2c_client *client, struct f75375_data *data, struct f75375s_platform_data *f75375s_pdata) { @@ -628,6 +651,7 @@ static int f75375_probe(struct i2c_client *client, return -ENOMEM; i2c_set_clientdata(client, data); + data->client = client; mutex_init(&data->update_lock); data->kind = id->driver_data; @@ -676,13 +700,29 @@ static int f75375_remove(struct i2c_client *client) return 0; } -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int f75375_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int f75375_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, f75375_detect); +} + +/* This function is called by i2c_probe */ +static int f75375_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = client->adapter; + struct i2c_client *client; u8 version = 0; + int err = 0; const char *name = ""; + struct i2c_device_id id; + + if (!(client = kzalloc(sizeof(*client), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + client->addr = address; + client->adapter = adapter; + client->driver = &f75375_legacy_driver; if (kind < 0) { u16 vendid = f75375_read16(client, F75375_REG_VENDOR); @@ -696,7 +736,7 @@ static int f75375_detect(struct i2c_client *client, int kind, dev_err(&adapter->dev, "failed,%02X,%02X,%02X\n", chipid, version, vendid); - return -ENODEV; + goto exit_free; } } @@ -706,18 +746,43 @@ static int f75375_detect(struct i2c_client *client, int kind, name = "f75373"; } dev_info(&adapter->dev, "found %s version: %02X\n", name, version); - strlcpy(info->type, name, I2C_NAME_SIZE); + strlcpy(client->name, name, I2C_NAME_SIZE); + + if ((err = i2c_attach_client(client))) + goto exit_free; + + strlcpy(id.name, name, I2C_NAME_SIZE); + id.driver_data = kind; + if ((err = f75375_probe(client, &id)) < 0) + goto exit_detach; return 0; + +exit_detach: + i2c_detach_client(client); +exit_free: + kfree(client); +exit: + return err; } static int __init sensors_f75375_init(void) { - return i2c_add_driver(&f75375_driver); + int status; + status = i2c_add_driver(&f75375_driver); + if (status) + return status; + + status = i2c_add_driver(&f75375_legacy_driver); + if (status) + i2c_del_driver(&f75375_driver); + + return status; } static void __exit sensors_f75375_exit(void) { + i2c_del_driver(&f75375_legacy_driver); i2c_del_driver(&f75375_driver); } diff --git a/trunk/drivers/hwmon/fscher.c b/trunk/drivers/hwmon/fscher.c index 12c70e402cb2..ed26b66e0831 100644 --- a/trunk/drivers/hwmon/fscher.c +++ b/trunk/drivers/hwmon/fscher.c @@ -106,11 +106,9 @@ I2C_CLIENT_INSMOD_1(fscher); * Functions declaration */ -static int fscher_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int fscher_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); -static int fscher_remove(struct i2c_client *client); +static int fscher_attach_adapter(struct i2c_adapter *adapter); +static int fscher_detect(struct i2c_adapter *adapter, int address, int kind); +static int fscher_detach_client(struct i2c_client *client); static struct fscher_data *fscher_update_device(struct device *dev); static void fscher_init_client(struct i2c_client *client); @@ -121,21 +119,12 @@ static int fscher_write_value(struct i2c_client *client, u8 reg, u8 value); * Driver data (common to all clients) */ -static const struct i2c_device_id fscher_id[] = { - { "fscher", fscher }, - { } -}; - static struct i2c_driver fscher_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "fscher", }, - .probe = fscher_probe, - .remove = fscher_remove, - .id_table = fscher_id, - .detect = fscher_detect, - .address_data = &addr_data, + .attach_adapter = fscher_attach_adapter, + .detach_client = fscher_detach_client, }; /* @@ -143,6 +132,7 @@ static struct i2c_driver fscher_driver = { */ struct fscher_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -293,14 +283,38 @@ static const struct attribute_group fscher_group = { * Real code */ -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int fscher_detect(struct i2c_client *new_client, int kind, - struct i2c_board_info *info) +static int fscher_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, fscher_detect); +} + +static int fscher_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = new_client->adapter; + struct i2c_client *new_client; + struct fscher_data *data; + int err = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + goto exit; + + /* OK. For now, we presume we have a valid client. We now create the + * client structure, even though we cannot fill it completely yet. + * But it allows us to access i2c_smbus_read_byte_data. */ + if (!(data = kzalloc(sizeof(struct fscher_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + /* The common I2C client data is placed right before the + * Hermes-specific data. */ + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &fscher_driver; + new_client->flags = 0; /* Do the remaining detection unless force or force_fscher parameter */ if (kind < 0) { @@ -310,35 +324,24 @@ static int fscher_detect(struct i2c_client *new_client, int kind, FSCHER_REG_IDENT_1) != 0x45) /* 'E' */ || (i2c_smbus_read_byte_data(new_client, FSCHER_REG_IDENT_2) != 0x52)) /* 'R' */ - return -ENODEV; - } - - strlcpy(info->type, "fscher", I2C_NAME_SIZE); - - return 0; -} - -static int fscher_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct fscher_data *data; - int err; - - data = kzalloc(sizeof(struct fscher_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; + goto exit_free; } - i2c_set_clientdata(new_client, data); + /* Fill in the remaining client fields and put it into the + * global list */ + strlcpy(new_client->name, "fscher", I2C_NAME_SIZE); data->valid = 0; mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) + goto exit_free; + fscher_init_client(new_client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &fscher_group))) - goto exit_free; + goto exit_detach; data->hwmon_dev = hwmon_device_register(&new_client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -350,19 +353,25 @@ static int fscher_probe(struct i2c_client *new_client, exit_remove_files: sysfs_remove_group(&new_client->dev.kobj, &fscher_group); +exit_detach: + i2c_detach_client(new_client); exit_free: kfree(data); exit: return err; } -static int fscher_remove(struct i2c_client *client) +static int fscher_detach_client(struct i2c_client *client) { struct fscher_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &fscher_group); + if ((err = i2c_detach_client(client))) + return err; + kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/fschmd.c b/trunk/drivers/hwmon/fschmd.c index 967170368933..bd89d270a5ed 100644 --- a/trunk/drivers/hwmon/fschmd.c +++ b/trunk/drivers/hwmon/fschmd.c @@ -171,37 +171,20 @@ static const int FSCHMD_NO_TEMP_SENSORS[5] = { 3, 3, 4, 3, 5 }; * Functions declarations */ -static int fschmd_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int fschmd_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); -static int fschmd_remove(struct i2c_client *client); +static int fschmd_attach_adapter(struct i2c_adapter *adapter); +static int fschmd_detach_client(struct i2c_client *client); static struct fschmd_data *fschmd_update_device(struct device *dev); /* * Driver data (common to all clients) */ -static const struct i2c_device_id fschmd_id[] = { - { "fscpos", fscpos }, - { "fscher", fscher }, - { "fscscy", fscscy }, - { "fschrc", fschrc }, - { "fschmd", fschmd }, - { } -}; -MODULE_DEVICE_TABLE(i2c, fschmd_id); - static struct i2c_driver fschmd_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = FSCHMD_NAME, }, - .probe = fschmd_probe, - .remove = fschmd_remove, - .id_table = fschmd_id, - .detect = fschmd_detect, - .address_data = &addr_data, + .attach_adapter = fschmd_attach_adapter, + .detach_client = fschmd_detach_client, }; /* @@ -209,6 +192,7 @@ static struct i2c_driver fschmd_driver = { */ struct fschmd_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; int kind; @@ -285,7 +269,7 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute v = SENSORS_LIMIT(v, -128, 127) + 128; mutex_lock(&data->update_lock); - i2c_smbus_write_byte_data(to_i2c_client(dev), + i2c_smbus_write_byte_data(&data->client, FSCHMD_REG_TEMP_LIMIT[data->kind][index], v); data->temp_max[index] = v; mutex_unlock(&data->update_lock); @@ -362,14 +346,14 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute mutex_lock(&data->update_lock); - reg = i2c_smbus_read_byte_data(to_i2c_client(dev), + reg = i2c_smbus_read_byte_data(&data->client, FSCHMD_REG_FAN_RIPPLE[data->kind][index]); /* bits 2..7 reserved => mask with 0x03 */ reg &= ~0x03; reg |= v; - i2c_smbus_write_byte_data(to_i2c_client(dev), + i2c_smbus_write_byte_data(&data->client, FSCHMD_REG_FAN_RIPPLE[data->kind][index], reg); data->fan_ripple[index] = reg; @@ -432,7 +416,7 @@ static ssize_t store_pwm_auto_point1_pwm(struct device *dev, mutex_lock(&data->update_lock); - i2c_smbus_write_byte_data(to_i2c_client(dev), + i2c_smbus_write_byte_data(&data->client, FSCHMD_REG_FAN_MIN[data->kind][index], v); data->fan_min[index] = v; @@ -464,14 +448,14 @@ static ssize_t store_alert_led(struct device *dev, mutex_lock(&data->update_lock); - reg = i2c_smbus_read_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL); + reg = i2c_smbus_read_byte_data(&data->client, FSCHMD_REG_CONTROL); if (v) reg |= FSCHMD_CONTROL_ALERT_LED_MASK; else reg &= ~FSCHMD_CONTROL_ALERT_LED_MASK; - i2c_smbus_write_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL, reg); + i2c_smbus_write_byte_data(&data->client, FSCHMD_REG_CONTROL, reg); data->global_control = reg; @@ -616,15 +600,32 @@ static void fschmd_dmi_decode(const struct dmi_header *header) } } -static int fschmd_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = client->adapter; + struct i2c_client *client; + struct fschmd_data *data; + u8 revision; + const char * const names[5] = { "Poseidon", "Hermes", "Scylla", + "Heracles", "Heimdall" }; const char * const client_names[5] = { "fscpos", "fscher", "fscscy", "fschrc", "fschmd" }; + int i, err = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + return 0; + + /* OK. For now, we presume we have a valid client. We now create the + * client structure, even though we cannot fill it completely yet. + * But it allows us to access i2c_smbus_read_byte_data. */ + if (!(data = kzalloc(sizeof(struct fschmd_data), GFP_KERNEL))) + return -ENOMEM; + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &fschmd_driver; + mutex_init(&data->update_lock); /* Detect & Identify the chip */ if (kind <= 0) { @@ -649,31 +650,9 @@ static int fschmd_detect(struct i2c_client *client, int kind, else if (!strcmp(id, "HMD")) kind = fschmd; else - return -ENODEV; + goto exit_free; } - strlcpy(info->type, client_names[kind - 1], I2C_NAME_SIZE); - - return 0; -} - -static int fschmd_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct fschmd_data *data; - u8 revision; - const char * const names[5] = { "Poseidon", "Hermes", "Scylla", - "Heracles", "Heimdall" }; - int i, err; - enum chips kind = id->driver_data; - - data = kzalloc(sizeof(struct fschmd_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - if (kind == fscpos) { /* The Poseidon has hardwired temp limits, fill these in for the alarm resetting code */ @@ -695,6 +674,11 @@ static int fschmd_probe(struct i2c_client *client, /* i2c kind goes from 1-5, we want from 0-4 to address arrays */ data->kind = kind - 1; + strlcpy(client->name, client_names[data->kind], I2C_NAME_SIZE); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; for (i = 0; i < ARRAY_SIZE(fschmd_attr); i++) { err = device_create_file(&client->dev, @@ -742,14 +726,25 @@ static int fschmd_probe(struct i2c_client *client, return 0; exit_detach: - fschmd_remove(client); /* will also free data for us */ + fschmd_detach_client(client); /* will also free data for us */ + return err; + +exit_free: + kfree(data); return err; } -static int fschmd_remove(struct i2c_client *client) +static int fschmd_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, fschmd_detect); +} + +static int fschmd_detach_client(struct i2c_client *client) { struct fschmd_data *data = i2c_get_clientdata(client); - int i; + int i, err; /* Check if registered in case we're called from fschmd_detect to cleanup after an error */ @@ -765,6 +760,9 @@ static int fschmd_remove(struct i2c_client *client) device_remove_file(&client->dev, &fschmd_fan_attr[i].dev_attr); + if ((err = i2c_detach_client(client))) + return err; + kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/fscpos.c b/trunk/drivers/hwmon/fscpos.c index 8a7bcf500b4e..00f48484e54b 100644 --- a/trunk/drivers/hwmon/fscpos.c +++ b/trunk/drivers/hwmon/fscpos.c @@ -87,11 +87,9 @@ static u8 FSCPOS_REG_TEMP_STATE[] = { 0x71, 0x81, 0x91 }; /* * Functions declaration */ -static int fscpos_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int fscpos_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); -static int fscpos_remove(struct i2c_client *client); +static int fscpos_attach_adapter(struct i2c_adapter *adapter); +static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind); +static int fscpos_detach_client(struct i2c_client *client); static int fscpos_read_value(struct i2c_client *client, u8 reg); static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value); @@ -103,27 +101,19 @@ static void reset_fan_alarm(struct i2c_client *client, int nr); /* * Driver data (common to all clients) */ -static const struct i2c_device_id fscpos_id[] = { - { "fscpos", fscpos }, - { } -}; - static struct i2c_driver fscpos_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "fscpos", }, - .probe = fscpos_probe, - .remove = fscpos_remove, - .id_table = fscpos_id, - .detect = fscpos_detect, - .address_data = &addr_data, + .attach_adapter = fscpos_attach_adapter, + .detach_client = fscpos_detach_client, }; /* * Client data (each client gets its own) */ struct fscpos_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* 0 until following fields are valid */ @@ -480,14 +470,39 @@ static const struct attribute_group fscpos_group = { .attrs = fscpos_attributes, }; -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int fscpos_detect(struct i2c_client *new_client, int kind, - struct i2c_board_info *info) +static int fscpos_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, fscpos_detect); +} + +static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = new_client->adapter; + struct i2c_client *new_client; + struct fscpos_data *data; + int err = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + goto exit; + + /* + * OK. For now, we presume we have a valid client. We now create the + * client structure, even though we cannot fill it completely yet. + * But it allows us to access fscpos_{read,write}_value. + */ + + if (!(data = kzalloc(sizeof(struct fscpos_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &fscpos_driver; + new_client->flags = 0; /* Do the remaining detection unless force or force_fscpos parameter */ if (kind < 0) { @@ -497,30 +512,22 @@ static int fscpos_detect(struct i2c_client *new_client, int kind, != 0x45) /* 'E' */ || (fscpos_read_value(new_client, FSCPOS_REG_IDENT_2) != 0x47))/* 'G' */ - return -ENODEV; + { + dev_dbg(&new_client->dev, "fscpos detection failed\n"); + goto exit_free; + } } - strlcpy(info->type, "fscpos", I2C_NAME_SIZE); + /* Fill in the remaining client fields and put it in the global list */ + strlcpy(new_client->name, "fscpos", I2C_NAME_SIZE); - return 0; -} - -static int fscpos_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct fscpos_data *data; - int err; - - data = kzalloc(sizeof(struct fscpos_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(new_client, data); data->valid = 0; mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) + goto exit_free; + /* Inizialize the fscpos chip */ fscpos_init_client(new_client); @@ -529,7 +536,7 @@ static int fscpos_probe(struct i2c_client *new_client, /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &fscpos_group))) - goto exit_free; + goto exit_detach; data->hwmon_dev = hwmon_device_register(&new_client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -541,19 +548,24 @@ static int fscpos_probe(struct i2c_client *new_client, exit_remove_files: sysfs_remove_group(&new_client->dev.kobj, &fscpos_group); +exit_detach: + i2c_detach_client(new_client); exit_free: kfree(data); exit: return err; } -static int fscpos_remove(struct i2c_client *client) +static int fscpos_detach_client(struct i2c_client *client) { struct fscpos_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &fscpos_group); + if ((err = i2c_detach_client(client))) + return err; kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/gl518sm.c b/trunk/drivers/hwmon/gl518sm.c index 7820df45d77a..33e9e8a8d1ce 100644 --- a/trunk/drivers/hwmon/gl518sm.c +++ b/trunk/drivers/hwmon/gl518sm.c @@ -114,6 +114,7 @@ static inline u8 FAN_TO_REG(long rpm, int div) /* Each client has this additional data */ struct gl518_data { + struct i2c_client client; struct device *hwmon_dev; enum chips type; @@ -137,33 +138,21 @@ struct gl518_data { u8 beep_enable; /* Boolean */ }; -static int gl518_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int gl518_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); +static int gl518_attach_adapter(struct i2c_adapter *adapter); +static int gl518_detect(struct i2c_adapter *adapter, int address, int kind); static void gl518_init_client(struct i2c_client *client); -static int gl518_remove(struct i2c_client *client); +static int gl518_detach_client(struct i2c_client *client); static int gl518_read_value(struct i2c_client *client, u8 reg); static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value); static struct gl518_data *gl518_update_device(struct device *dev); -static const struct i2c_device_id gl518_id[] = { - { "gl518sm", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, gl518_id); - /* This is the driver that will be inserted */ static struct i2c_driver gl518_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "gl518sm", }, - .probe = gl518_probe, - .remove = gl518_remove, - .id_table = gl518_id, - .detect = gl518_detect, - .address_data = &addr_data, + .attach_adapter = gl518_attach_adapter, + .detach_client = gl518_detach_client, }; /* @@ -483,23 +472,46 @@ static const struct attribute_group gl518_group_r80 = { * Real code */ -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int gl518_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int gl518_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, gl518_detect); +} + +static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = client->adapter; int i; + struct i2c_client *client; + struct gl518_data *data; + int err = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) - return -ENODEV; + goto exit; + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access gl518_{read,write}_value. */ + + if (!(data = kzalloc(sizeof(struct gl518_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + i2c_set_clientdata(client, data); + + client->addr = address; + client->adapter = adapter; + client->driver = &gl518_driver; /* Now, we do the remaining detection. */ if (kind < 0) { if ((gl518_read_value(client, GL518_REG_CHIP_ID) != 0x80) || (gl518_read_value(client, GL518_REG_CONF) & 0x80)) - return -ENODEV; + goto exit_free; } /* Determine the chip type. */ @@ -514,40 +526,27 @@ static int gl518_detect(struct i2c_client *client, int kind, dev_info(&adapter->dev, "Ignoring 'force' parameter for unknown " "chip at adapter %d, address 0x%02x\n", - i2c_adapter_id(adapter), client->addr); - return -ENODEV; + i2c_adapter_id(adapter), address); + goto exit_free; } } - strlcpy(info->type, "gl518sm", I2C_NAME_SIZE); - - return 0; -} - -static int gl518_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct gl518_data *data; - int err, revision; - - data = kzalloc(sizeof(struct gl518_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - revision = gl518_read_value(client, GL518_REG_REVISION); - data->type = revision == 0x80 ? gl518sm_r80 : gl518sm_r00; + /* Fill in the remaining client fields */ + strlcpy(client->name, "gl518sm", I2C_NAME_SIZE); + data->type = kind; mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; + /* Initialize the GL518SM chip */ data->alarm_mask = 0xff; gl518_init_client(client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &gl518_group))) - goto exit_free; + goto exit_detach; if (data->type == gl518sm_r80) if ((err = sysfs_create_group(&client->dev.kobj, &gl518_group_r80))) @@ -565,6 +564,8 @@ static int gl518_probe(struct i2c_client *client, sysfs_remove_group(&client->dev.kobj, &gl518_group); if (data->type == gl518sm_r80) sysfs_remove_group(&client->dev.kobj, &gl518_group_r80); +exit_detach: + i2c_detach_client(client); exit_free: kfree(data); exit: @@ -590,15 +591,19 @@ static void gl518_init_client(struct i2c_client *client) gl518_write_value(client, GL518_REG_CONF, 0x40 | regvalue); } -static int gl518_remove(struct i2c_client *client) +static int gl518_detach_client(struct i2c_client *client) { struct gl518_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &gl518_group); if (data->type == gl518sm_r80) sysfs_remove_group(&client->dev.kobj, &gl518_group_r80); + if ((err = i2c_detach_client(client))) + return err; + kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/gl520sm.c b/trunk/drivers/hwmon/gl520sm.c index 19616f2242b0..8984ef141627 100644 --- a/trunk/drivers/hwmon/gl520sm.c +++ b/trunk/drivers/hwmon/gl520sm.c @@ -79,37 +79,26 @@ static const u8 GL520_REG_TEMP_MAX_HYST[] = { 0x06, 0x18 }; * Function declarations */ -static int gl520_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int gl520_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); +static int gl520_attach_adapter(struct i2c_adapter *adapter); +static int gl520_detect(struct i2c_adapter *adapter, int address, int kind); static void gl520_init_client(struct i2c_client *client); -static int gl520_remove(struct i2c_client *client); +static int gl520_detach_client(struct i2c_client *client); static int gl520_read_value(struct i2c_client *client, u8 reg); static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value); static struct gl520_data *gl520_update_device(struct device *dev); /* Driver data */ -static const struct i2c_device_id gl520_id[] = { - { "gl520sm", gl520sm }, - { } -}; -MODULE_DEVICE_TABLE(i2c, gl520_id); - static struct i2c_driver gl520_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "gl520sm", }, - .probe = gl520_probe, - .remove = gl520_remove, - .id_table = gl520_id, - .detect = gl520_detect, - .address_data = &addr_data, + .attach_adapter = gl520_attach_adapter, + .detach_client = gl520_detach_client, }; /* Client data */ struct gl520_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until the following fields are valid */ @@ -680,15 +669,37 @@ static const struct attribute_group gl520_group_opt = { * Real code */ -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int gl520_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int gl520_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, gl520_detect); +} + +static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = client->adapter; + struct i2c_client *client; + struct gl520_data *data; + int err = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) - return -ENODEV; + goto exit; + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access gl520_{read,write}_value. */ + + if (!(data = kzalloc(sizeof(struct gl520_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &gl520_driver; /* Determine the chip type. */ if (kind < 0) { @@ -696,36 +707,24 @@ static int gl520_detect(struct i2c_client *client, int kind, ((gl520_read_value(client, GL520_REG_REVISION) & 0x7f) != 0x00) || ((gl520_read_value(client, GL520_REG_CONF) & 0x80) != 0x00)) { dev_dbg(&client->dev, "Unknown chip type, skipping\n"); - return -ENODEV; + goto exit_free; } } - strlcpy(info->type, "gl520sm", I2C_NAME_SIZE); - - return 0; -} - -static int gl520_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct gl520_data *data; - int err; - - data = kzalloc(sizeof(struct gl520_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); + /* Fill in the remaining client fields */ + strlcpy(client->name, "gl520sm", I2C_NAME_SIZE); mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; + /* Initialize the GL520SM chip */ gl520_init_client(client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &gl520_group))) - goto exit_free; + goto exit_detach; if (data->two_temps) { if ((err = device_create_file(&client->dev, @@ -765,6 +764,8 @@ static int gl520_probe(struct i2c_client *client, exit_remove_files: sysfs_remove_group(&client->dev.kobj, &gl520_group); sysfs_remove_group(&client->dev.kobj, &gl520_group_opt); +exit_detach: + i2c_detach_client(client); exit_free: kfree(data); exit: @@ -810,14 +811,18 @@ static void gl520_init_client(struct i2c_client *client) gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask); } -static int gl520_remove(struct i2c_client *client) +static int gl520_detach_client(struct i2c_client *client) { struct gl520_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &gl520_group); sysfs_remove_group(&client->dev.kobj, &gl520_group_opt); + if ((err = i2c_detach_client(client))) + return err; + kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/lm63.c b/trunk/drivers/hwmon/lm63.c index 3195a265f0e9..116287008083 100644 --- a/trunk/drivers/hwmon/lm63.c +++ b/trunk/drivers/hwmon/lm63.c @@ -1,7 +1,7 @@ /* * lm63.c - driver for the National Semiconductor LM63 temperature sensor * with integrated fan control - * Copyright (C) 2004-2008 Jean Delvare + * Copyright (C) 2004-2006 Jean Delvare * Based on the lm90 driver. * * The LM63 is a sensor chip made by National Semiconductor. It measures @@ -128,36 +128,24 @@ I2C_CLIENT_INSMOD_1(lm63); * Functions declaration */ -static int lm63_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int lm63_remove(struct i2c_client *client); +static int lm63_attach_adapter(struct i2c_adapter *adapter); +static int lm63_detach_client(struct i2c_client *client); static struct lm63_data *lm63_update_device(struct device *dev); -static int lm63_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); +static int lm63_detect(struct i2c_adapter *adapter, int address, int kind); static void lm63_init_client(struct i2c_client *client); /* * Driver data (common to all clients) */ -static const struct i2c_device_id lm63_id[] = { - { "lm63", lm63 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm63_id); - static struct i2c_driver lm63_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "lm63", }, - .probe = lm63_probe, - .remove = lm63_remove, - .id_table = lm63_id, - .detect = lm63_detect, - .address_data = &addr_data, + .attach_adapter = lm63_attach_adapter, + .detach_client = lm63_detach_client, }; /* @@ -165,6 +153,7 @@ static struct i2c_driver lm63_driver = { */ struct lm63_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -422,14 +411,43 @@ static const struct attribute_group lm63_group_fan1 = { * Real code */ -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm63_detect(struct i2c_client *new_client, int kind, - struct i2c_board_info *info) +static int lm63_attach_adapter(struct i2c_adapter *adapter) { - struct i2c_adapter *adapter = new_client->adapter; + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, lm63_detect); +} + +/* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. + */ +static int lm63_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *new_client; + struct lm63_data *data; + int err = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + goto exit; + + if (!(data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + /* The common I2C client data is placed right before the + LM63-specific data. */ + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &lm63_driver; + new_client->flags = 0; + + /* Default to an LM63 if forced */ + if (kind == 0) + kind = lm63; if (kind < 0) { /* must identify */ u8 man_id, chip_id, reg_config1, reg_config2; @@ -459,38 +477,25 @@ static int lm63_detect(struct i2c_client *new_client, int kind, dev_dbg(&adapter->dev, "Unsupported chip " "(man_id=0x%02X, chip_id=0x%02X).\n", man_id, chip_id); - return -ENODEV; + goto exit_free; } } - strlcpy(info->type, "lm63", I2C_NAME_SIZE); - - return 0; -} - -static int lm63_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct lm63_data *data; - int err; - - data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(new_client, data); + strlcpy(new_client->name, "lm63", I2C_NAME_SIZE); data->valid = 0; mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) + goto exit_free; + /* Initialize the LM63 chip */ lm63_init_client(new_client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &lm63_group))) - goto exit_free; + goto exit_detach; if (data->config & 0x04) { /* tachometer enabled */ if ((err = sysfs_create_group(&new_client->dev.kobj, &lm63_group_fan1))) @@ -508,6 +513,8 @@ static int lm63_probe(struct i2c_client *new_client, exit_remove_files: sysfs_remove_group(&new_client->dev.kobj, &lm63_group); sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1); +exit_detach: + i2c_detach_client(new_client); exit_free: kfree(data); exit: @@ -549,14 +556,18 @@ static void lm63_init_client(struct i2c_client *client) (data->config_fan & 0x20) ? "manual" : "auto"); } -static int lm63_remove(struct i2c_client *client) +static int lm63_detach_client(struct i2c_client *client) { struct lm63_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm63_group); sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1); + if ((err = i2c_detach_client(client))) + return err; + kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/lm77.c b/trunk/drivers/hwmon/lm77.c index 866b401ab6e8..36d5a8c3ad8c 100644 --- a/trunk/drivers/hwmon/lm77.c +++ b/trunk/drivers/hwmon/lm77.c @@ -52,6 +52,7 @@ I2C_CLIENT_INSMOD_1(lm77); /* Each client has this additional data */ struct lm77_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; @@ -64,35 +65,23 @@ struct lm77_data { u8 alarms; }; -static int lm77_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int lm77_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); +static int lm77_attach_adapter(struct i2c_adapter *adapter); +static int lm77_detect(struct i2c_adapter *adapter, int address, int kind); static void lm77_init_client(struct i2c_client *client); -static int lm77_remove(struct i2c_client *client); +static int lm77_detach_client(struct i2c_client *client); static u16 lm77_read_value(struct i2c_client *client, u8 reg); static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value); static struct lm77_data *lm77_update_device(struct device *dev); -static const struct i2c_device_id lm77_id[] = { - { "lm77", lm77 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm77_id); - /* This is the driver that will be inserted */ static struct i2c_driver lm77_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "lm77", }, - .probe = lm77_probe, - .remove = lm77_remove, - .id_table = lm77_id, - .detect = lm77_detect, - .address_data = &addr_data, + .attach_adapter = lm77_attach_adapter, + .detach_client = lm77_detach_client, }; /* straight from the datasheet */ @@ -226,6 +215,13 @@ static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 2); static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0); static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1); +static int lm77_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, lm77_detect); +} + static struct attribute *lm77_attributes[] = { &dev_attr_temp1_input.attr, &dev_attr_temp1_crit.attr, @@ -244,15 +240,32 @@ static const struct attribute_group lm77_group = { .attrs = lm77_attributes, }; -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm77_detect(struct i2c_client *new_client, int kind, - struct i2c_board_info *info) +/* This function is called by i2c_probe */ +static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = new_client->adapter; + struct i2c_client *new_client; + struct lm77_data *data; + int err = 0; + const char *name = ""; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) - return -ENODEV; + goto exit; + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access lm77_{read,write}_value. */ + if (!(data = kzalloc(sizeof(struct lm77_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &lm77_driver; + new_client->flags = 0; /* Here comes the remaining detection. Since the LM77 has no register dedicated to identification, we have to rely on the @@ -281,7 +294,7 @@ static int lm77_detect(struct i2c_client *new_client, int kind, || i2c_smbus_read_word_data(new_client, i + 3) != crit || i2c_smbus_read_word_data(new_client, i + 4) != min || i2c_smbus_read_word_data(new_client, i + 5) != max) - return -ENODEV; + goto exit_free; /* sign bits */ if (((cur & 0x00f0) != 0xf0 && (cur & 0x00f0) != 0x0) @@ -289,55 +302,51 @@ static int lm77_detect(struct i2c_client *new_client, int kind, || ((crit & 0x00f0) != 0xf0 && (crit & 0x00f0) != 0x0) || ((min & 0x00f0) != 0xf0 && (min & 0x00f0) != 0x0) || ((max & 0x00f0) != 0xf0 && (max & 0x00f0) != 0x0)) - return -ENODEV; + goto exit_free; /* unused bits */ if (conf & 0xe0) - return -ENODEV; + goto exit_free; /* 0x06 and 0x07 return the last read value */ cur = i2c_smbus_read_word_data(new_client, 0); if (i2c_smbus_read_word_data(new_client, 6) != cur || i2c_smbus_read_word_data(new_client, 7) != cur) - return -ENODEV; + goto exit_free; hyst = i2c_smbus_read_word_data(new_client, 2); if (i2c_smbus_read_word_data(new_client, 6) != hyst || i2c_smbus_read_word_data(new_client, 7) != hyst) - return -ENODEV; + goto exit_free; min = i2c_smbus_read_word_data(new_client, 4); if (i2c_smbus_read_word_data(new_client, 6) != min || i2c_smbus_read_word_data(new_client, 7) != min) - return -ENODEV; + goto exit_free; } - strlcpy(info->type, "lm77", I2C_NAME_SIZE); + /* Determine the chip type - only one kind supported! */ + if (kind <= 0) + kind = lm77; - return 0; -} - -static int lm77_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct lm77_data *data; - int err; - - data = kzalloc(sizeof(struct lm77_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; + if (kind == lm77) { + name = "lm77"; } - i2c_set_clientdata(new_client, data); + /* Fill in the remaining client fields and put it into the global list */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) + goto exit_free; + /* Initialize the LM77 chip */ lm77_init_client(new_client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &lm77_group))) - goto exit_free; + goto exit_detach; data->hwmon_dev = hwmon_device_register(&new_client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -349,17 +358,20 @@ static int lm77_probe(struct i2c_client *new_client, exit_remove: sysfs_remove_group(&new_client->dev.kobj, &lm77_group); +exit_detach: + i2c_detach_client(new_client); exit_free: kfree(data); exit: return err; } -static int lm77_remove(struct i2c_client *client) +static int lm77_detach_client(struct i2c_client *client) { struct lm77_data *data = i2c_get_clientdata(client); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm77_group); + i2c_detach_client(client); kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/lm80.c b/trunk/drivers/hwmon/lm80.c index bcffc1899403..26c91c9d4769 100644 --- a/trunk/drivers/hwmon/lm80.c +++ b/trunk/drivers/hwmon/lm80.c @@ -108,6 +108,7 @@ static inline long TEMP_FROM_REG(u16 temp) */ struct lm80_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ @@ -131,12 +132,10 @@ struct lm80_data { * Functions declaration */ -static int lm80_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int lm80_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); +static int lm80_attach_adapter(struct i2c_adapter *adapter); +static int lm80_detect(struct i2c_adapter *adapter, int address, int kind); static void lm80_init_client(struct i2c_client *client); -static int lm80_remove(struct i2c_client *client); +static int lm80_detach_client(struct i2c_client *client); static struct lm80_data *lm80_update_device(struct device *dev); static int lm80_read_value(struct i2c_client *client, u8 reg); static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value); @@ -145,22 +144,12 @@ static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value); * Driver data (common to all clients) */ -static const struct i2c_device_id lm80_id[] = { - { "lm80", lm80 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm80_id); - static struct i2c_driver lm80_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "lm80", }, - .probe = lm80_probe, - .remove = lm80_remove, - .id_table = lm80_id, - .detect = lm80_detect, - .address_data = &addr_data, + .attach_adapter = lm80_attach_adapter, + .detach_client = lm80_detach_client, }; /* @@ -394,6 +383,13 @@ static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 13); * Real code */ +static int lm80_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, lm80_detect); +} + static struct attribute *lm80_attributes[] = { &sensor_dev_attr_in0_min.dev_attr.attr, &sensor_dev_attr_in1_min.dev_attr.attr, @@ -446,47 +442,54 @@ static const struct attribute_group lm80_group = { .attrs = lm80_attributes, }; -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm80_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = client->adapter; int i, cur; + struct i2c_client *client; + struct lm80_data *data; + int err = 0; + const char *name; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + goto exit; + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access lm80_{read,write}_value. */ + if (!(data = kzalloc(sizeof(struct lm80_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &lm80_driver; /* Now, we do the remaining detection. It is lousy. */ if (lm80_read_value(client, LM80_REG_ALARM2) & 0xc0) - return -ENODEV; + goto error_free; for (i = 0x2a; i <= 0x3d; i++) { cur = i2c_smbus_read_byte_data(client, i); if ((i2c_smbus_read_byte_data(client, i + 0x40) != cur) || (i2c_smbus_read_byte_data(client, i + 0x80) != cur) || (i2c_smbus_read_byte_data(client, i + 0xc0) != cur)) - return -ENODEV; + goto error_free; } - strlcpy(info->type, "lm80", I2C_NAME_SIZE); - - return 0; -} - -static int lm80_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct lm80_data *data; - int err; + /* Determine the chip type - only one kind supported! */ + kind = lm80; + name = "lm80"; - data = kzalloc(sizeof(struct lm80_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); + /* Fill in the remaining client fields */ + strlcpy(client->name, name, I2C_NAME_SIZE); mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto error_free; + /* Initialize the LM80 chip */ lm80_init_client(client); @@ -496,7 +499,7 @@ static int lm80_probe(struct i2c_client *client, /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &lm80_group))) - goto error_free; + goto error_detach; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -508,18 +511,23 @@ static int lm80_probe(struct i2c_client *client, error_remove: sysfs_remove_group(&client->dev.kobj, &lm80_group); +error_detach: + i2c_detach_client(client); error_free: kfree(data); exit: return err; } -static int lm80_remove(struct i2c_client *client) +static int lm80_detach_client(struct i2c_client *client) { struct lm80_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm80_group); + if ((err = i2c_detach_client(client))) + return err; kfree(data); return 0; diff --git a/trunk/drivers/hwmon/lm83.c b/trunk/drivers/hwmon/lm83.c index e59e2d1f080c..6a8642fa25fb 100644 --- a/trunk/drivers/hwmon/lm83.c +++ b/trunk/drivers/hwmon/lm83.c @@ -1,7 +1,7 @@ /* * lm83.c - Part of lm_sensors, Linux kernel modules for hardware * monitoring - * Copyright (C) 2003-2008 Jean Delvare + * Copyright (C) 2003-2006 Jean Delvare * * Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is * a sensor chip made by National Semiconductor. It reports up to four @@ -118,34 +118,21 @@ static const u8 LM83_REG_W_HIGH[] = { * Functions declaration */ -static int lm83_detect(struct i2c_client *new_client, int kind, - struct i2c_board_info *info); -static int lm83_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int lm83_remove(struct i2c_client *client); +static int lm83_attach_adapter(struct i2c_adapter *adapter); +static int lm83_detect(struct i2c_adapter *adapter, int address, int kind); +static int lm83_detach_client(struct i2c_client *client); static struct lm83_data *lm83_update_device(struct device *dev); /* * Driver data (common to all clients) */ -static const struct i2c_device_id lm83_id[] = { - { "lm83", lm83 }, - { "lm82", lm82 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm83_id); - static struct i2c_driver lm83_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "lm83", }, - .probe = lm83_probe, - .remove = lm83_remove, - .id_table = lm83_id, - .detect = lm83_detect, - .address_data = &addr_data, + .attach_adapter = lm83_attach_adapter, + .detach_client = lm83_detach_client, }; /* @@ -153,6 +140,7 @@ static struct i2c_driver lm83_driver = { */ struct lm83_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -290,15 +278,40 @@ static const struct attribute_group lm83_group_opt = { * Real code */ -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm83_detect(struct i2c_client *new_client, int kind, - struct i2c_board_info *info) +static int lm83_attach_adapter(struct i2c_adapter *adapter) { - struct i2c_adapter *adapter = new_client->adapter; + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, lm83_detect); +} + +/* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. + */ +static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *new_client; + struct lm83_data *data; + int err = 0; const char *name = ""; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + goto exit; + + if (!(data = kzalloc(sizeof(struct lm83_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + /* The common I2C client data is placed right after the + * LM83-specific data. */ + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &lm83_driver; + new_client->flags = 0; /* Now we do the detection and identification. A negative kind * means that the driver was loaded with no force parameter @@ -322,9 +335,8 @@ static int lm83_detect(struct i2c_client *new_client, int kind, ((i2c_smbus_read_byte_data(new_client, LM83_REG_R_CONFIG) & 0x41) != 0x00)) { dev_dbg(&adapter->dev, - "LM83 detection failed at 0x%02x.\n", - new_client->addr); - return -ENODEV; + "LM83 detection failed at 0x%02x.\n", address); + goto exit_free; } } @@ -349,7 +361,7 @@ static int lm83_detect(struct i2c_client *new_client, int kind, dev_info(&adapter->dev, "Unsupported chip (man_id=0x%02X, " "chip_id=0x%02X).\n", man_id, chip_id); - return -ENODEV; + goto exit_free; } } @@ -360,27 +372,15 @@ static int lm83_detect(struct i2c_client *new_client, int kind, name = "lm82"; } - strlcpy(info->type, name, I2C_NAME_SIZE); - - return 0; -} - -static int lm83_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct lm83_data *data; - int err; - - data = kzalloc(sizeof(struct lm83_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(new_client, data); + /* We can fill in the remaining client fields */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) + goto exit_free; + /* * Register sysfs hooks * The LM82 can only monitor one external diode which is @@ -389,9 +389,9 @@ static int lm83_probe(struct i2c_client *new_client, */ if ((err = sysfs_create_group(&new_client->dev.kobj, &lm83_group))) - goto exit_free; + goto exit_detach; - if (id->driver_data == lm83) { + if (kind == lm83) { if ((err = sysfs_create_group(&new_client->dev.kobj, &lm83_group_opt))) goto exit_remove_files; @@ -408,20 +408,26 @@ static int lm83_probe(struct i2c_client *new_client, exit_remove_files: sysfs_remove_group(&new_client->dev.kobj, &lm83_group); sysfs_remove_group(&new_client->dev.kobj, &lm83_group_opt); +exit_detach: + i2c_detach_client(new_client); exit_free: kfree(data); exit: return err; } -static int lm83_remove(struct i2c_client *client) +static int lm83_detach_client(struct i2c_client *client) { struct lm83_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm83_group); sysfs_remove_group(&client->dev.kobj, &lm83_group_opt); + if ((err = i2c_detach_client(client))) + return err; + kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/lm87.c b/trunk/drivers/hwmon/lm87.c index 21970f0d53a1..e1c183f0aae0 100644 --- a/trunk/drivers/hwmon/lm87.c +++ b/trunk/drivers/hwmon/lm87.c @@ -5,7 +5,7 @@ * Philip Edelbrock * Stephen Rousset * Dan Eaton - * Copyright (C) 2004-2008 Jean Delvare + * Copyright (C) 2004,2007 Jean Delvare * * Original port to Linux 2.6 by Jeff Oliver. * @@ -157,35 +157,22 @@ static u8 LM87_REG_TEMP_LOW[3] = { 0x3A, 0x38, 0x2C }; * Functions declaration */ -static int lm87_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int lm87_detect(struct i2c_client *new_client, int kind, - struct i2c_board_info *info); +static int lm87_attach_adapter(struct i2c_adapter *adapter); +static int lm87_detect(struct i2c_adapter *adapter, int address, int kind); static void lm87_init_client(struct i2c_client *client); -static int lm87_remove(struct i2c_client *client); +static int lm87_detach_client(struct i2c_client *client); static struct lm87_data *lm87_update_device(struct device *dev); /* * Driver data (common to all clients) */ -static const struct i2c_device_id lm87_id[] = { - { "lm87", lm87 }, - { "adm1024", adm1024 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm87_id); - static struct i2c_driver lm87_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "lm87", }, - .probe = lm87_probe, - .remove = lm87_remove, - .id_table = lm87_id, - .detect = lm87_detect, - .address_data = &addr_data, + .attach_adapter = lm87_attach_adapter, + .detach_client = lm87_detach_client, }; /* @@ -193,6 +180,7 @@ static struct i2c_driver lm87_driver = { */ struct lm87_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -574,6 +562,13 @@ static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 15); * Real code */ +static int lm87_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, lm87_detect); +} + static struct attribute *lm87_attributes[] = { &dev_attr_in1_input.attr, &dev_attr_in1_min.attr, @@ -661,15 +656,33 @@ static const struct attribute_group lm87_group_opt = { .attrs = lm87_attributes_opt, }; -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm87_detect(struct i2c_client *new_client, int kind, - struct i2c_board_info *info) +/* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. + */ +static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = new_client->adapter; + struct i2c_client *new_client; + struct lm87_data *data; + int err = 0; static const char *names[] = { "lm87", "adm1024" }; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + goto exit; + + if (!(data = kzalloc(sizeof(struct lm87_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + /* The common I2C client data is placed right before the + LM87-specific data. */ + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &lm87_driver; + new_client->flags = 0; /* Default to an LM87 if forced */ if (kind == 0) @@ -691,32 +704,20 @@ static int lm87_detect(struct i2c_client *new_client, int kind, || (lm87_read_value(new_client, LM87_REG_CONFIG) & 0x80)) { dev_dbg(&adapter->dev, "LM87 detection failed at 0x%02x.\n", - new_client->addr); - return -ENODEV; + address); + goto exit_free; } } - strlcpy(info->type, names[kind - 1], I2C_NAME_SIZE); - - return 0; -} - -static int lm87_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct lm87_data *data; - int err; - - data = kzalloc(sizeof(struct lm87_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(new_client, data); + /* We can fill in the remaining client fields */ + strlcpy(new_client->name, names[kind - 1], I2C_NAME_SIZE); data->valid = 0; mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) + goto exit_free; + /* Initialize the LM87 chip */ lm87_init_client(new_client); @@ -731,7 +732,7 @@ static int lm87_probe(struct i2c_client *new_client, /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &lm87_group))) - goto exit_free; + goto exit_detach; if (data->channel & CHAN_NO_FAN(0)) { if ((err = device_create_file(&new_client->dev, @@ -831,6 +832,8 @@ static int lm87_probe(struct i2c_client *new_client, exit_remove: sysfs_remove_group(&new_client->dev.kobj, &lm87_group); sysfs_remove_group(&new_client->dev.kobj, &lm87_group_opt); +exit_detach: + i2c_detach_client(new_client); exit_free: kfree(data); exit: @@ -874,14 +877,18 @@ static void lm87_init_client(struct i2c_client *client) } } -static int lm87_remove(struct i2c_client *client) +static int lm87_detach_client(struct i2c_client *client) { struct lm87_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm87_group); sysfs_remove_group(&client->dev.kobj, &lm87_group_opt); + if ((err = i2c_detach_client(client))) + return err; + kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/lm90.c b/trunk/drivers/hwmon/lm90.c index c24fe36ac787..d1a3da3dd8e0 100644 --- a/trunk/drivers/hwmon/lm90.c +++ b/trunk/drivers/hwmon/lm90.c @@ -187,44 +187,23 @@ I2C_CLIENT_INSMOD_7(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680); * Functions declaration */ -static int lm90_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); -static int lm90_probe(struct i2c_client *client, - const struct i2c_device_id *id); +static int lm90_attach_adapter(struct i2c_adapter *adapter); +static int lm90_detect(struct i2c_adapter *adapter, int address, + int kind); static void lm90_init_client(struct i2c_client *client); -static int lm90_remove(struct i2c_client *client); +static int lm90_detach_client(struct i2c_client *client); static struct lm90_data *lm90_update_device(struct device *dev); /* * Driver data (common to all clients) */ -static const struct i2c_device_id lm90_id[] = { - { "adm1032", adm1032 }, - { "adt7461", adt7461 }, - { "lm90", lm90 }, - { "lm86", lm86 }, - { "lm89", lm99 }, - { "lm99", lm99 }, /* Missing temperature offset */ - { "max6657", max6657 }, - { "max6658", max6657 }, - { "max6659", max6657 }, - { "max6680", max6680 }, - { "max6681", max6680 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm90_id); - static struct i2c_driver lm90_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "lm90", }, - .probe = lm90_probe, - .remove = lm90_remove, - .id_table = lm90_id, - .detect = lm90_detect, - .address_data = &addr_data, + .attach_adapter = lm90_attach_adapter, + .detach_client = lm90_detach_client, }; /* @@ -232,6 +211,7 @@ static struct i2c_driver lm90_driver = { */ struct lm90_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -497,16 +477,40 @@ static int lm90_read_reg(struct i2c_client* client, u8 reg, u8 *value) return 0; } -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm90_detect(struct i2c_client *new_client, int kind, - struct i2c_board_info *info) +static int lm90_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, lm90_detect); +} + +/* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. + */ +static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = new_client->adapter; - int address = new_client->addr; + struct i2c_client *new_client; + struct lm90_data *data; + int err = 0; const char *name = ""; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + goto exit; + + if (!(data = kzalloc(sizeof(struct lm90_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + /* The common I2C client data is placed right before the + LM90-specific data. */ + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &lm90_driver; + new_client->flags = 0; /* * Now we do the remaining detection. A negative kind means that @@ -534,7 +538,7 @@ static int lm90_detect(struct i2c_client *new_client, int kind, LM90_REG_R_CONFIG1)) < 0 || (reg_convrate = i2c_smbus_read_byte_data(new_client, LM90_REG_R_CONVRATE)) < 0) - return -ENODEV; + goto exit_free; if ((address == 0x4C || address == 0x4D) && man_id == 0x01) { /* National Semiconductor */ @@ -542,7 +546,7 @@ static int lm90_detect(struct i2c_client *new_client, int kind, if ((reg_config2 = i2c_smbus_read_byte_data(new_client, LM90_REG_R_CONFIG2)) < 0) - return -ENODEV; + goto exit_free; if ((reg_config1 & 0x2A) == 0x00 && (reg_config2 & 0xF8) == 0x00 @@ -606,11 +610,10 @@ static int lm90_detect(struct i2c_client *new_client, int kind, dev_info(&adapter->dev, "Unsupported chip (man_id=0x%02X, " "chip_id=0x%02X).\n", man_id, chip_id); - return -ENODEV; + goto exit_free; } } - /* Fill the i2c board info */ if (kind == lm90) { name = "lm90"; } else if (kind == adm1032) { @@ -618,7 +621,7 @@ static int lm90_detect(struct i2c_client *new_client, int kind, /* The ADM1032 supports PEC, but only if combined transactions are not used. */ if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) - info->flags |= I2C_CLIENT_PEC; + new_client->flags |= I2C_CLIENT_PEC; } else if (kind == lm99) { name = "lm99"; } else if (kind == lm86) { @@ -630,39 +633,23 @@ static int lm90_detect(struct i2c_client *new_client, int kind, } else if (kind == adt7461) { name = "adt7461"; } - strlcpy(info->type, name, I2C_NAME_SIZE); - - return 0; -} - -static int lm90_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct i2c_adapter *adapter = to_i2c_adapter(new_client->dev.parent); - struct lm90_data *data; - int err; - data = kzalloc(sizeof(struct lm90_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - i2c_set_clientdata(new_client, data); + /* We can fill in the remaining client fields */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); + data->valid = 0; + data->kind = kind; mutex_init(&data->update_lock); - /* Set the device type */ - data->kind = id->driver_data; - if (data->kind == adm1032) { - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) - new_client->flags &= ~I2C_CLIENT_PEC; - } + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) + goto exit_free; /* Initialize the LM90 chip */ lm90_init_client(new_client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &lm90_group))) - goto exit_free; + goto exit_detach; if (new_client->flags & I2C_CLIENT_PEC) { if ((err = device_create_file(&new_client->dev, &dev_attr_pec))) @@ -685,6 +672,8 @@ static int lm90_probe(struct i2c_client *new_client, exit_remove_files: sysfs_remove_group(&new_client->dev.kobj, &lm90_group); device_remove_file(&new_client->dev, &dev_attr_pec); +exit_detach: + i2c_detach_client(new_client); exit_free: kfree(data); exit: @@ -721,9 +710,10 @@ static void lm90_init_client(struct i2c_client *client) i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config); } -static int lm90_remove(struct i2c_client *client) +static int lm90_detach_client(struct i2c_client *client) { struct lm90_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm90_group); @@ -732,6 +722,9 @@ static int lm90_remove(struct i2c_client *client) device_remove_file(&client->dev, &sensor_dev_attr_temp2_offset.dev_attr); + if ((err = i2c_detach_client(client))) + return err; + kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/lm92.c b/trunk/drivers/hwmon/lm92.c index b2e00c5a7eec..c31942e08246 100644 --- a/trunk/drivers/hwmon/lm92.c +++ b/trunk/drivers/hwmon/lm92.c @@ -1,6 +1,6 @@ /* * lm92 - Hardware monitoring driver - * Copyright (C) 2005-2008 Jean Delvare + * Copyright (C) 2005 Jean Delvare * * Based on the lm90 driver, with some ideas taken from the lm_sensors * lm92 driver as well. @@ -96,6 +96,7 @@ static struct i2c_driver lm92_driver; /* Client data (each client gets its own) */ struct lm92_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -318,15 +319,32 @@ static const struct attribute_group lm92_group = { .attrs = lm92_attributes, }; -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm92_detect(struct i2c_client *new_client, int kind, - struct i2c_board_info *info) +/* The following function does more than just detection. If detection + succeeds, it also registers the new chip. */ +static int lm92_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = new_client->adapter; + struct i2c_client *new_client; + struct lm92_data *data; + int err = 0; + char *name; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) - return -ENODEV; + goto exit; + + if (!(data = kzalloc(sizeof(struct lm92_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + /* Fill in enough client fields so that we can read from the chip, + which is required for identication */ + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &lm92_driver; + new_client->flags = 0; /* A negative kind means that the driver was loaded with no force parameter (default), so we must identify the chip. */ @@ -346,36 +364,34 @@ static int lm92_detect(struct i2c_client *new_client, int kind, kind = lm92; /* No separate prefix */ } else - return -ENODEV; - } - - strlcpy(info->type, "lm92", I2C_NAME_SIZE); - - return 0; -} - -static int lm92_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct lm92_data *data; - int err; - - data = kzalloc(sizeof(struct lm92_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; + goto exit_free; + } else + if (kind == 0) /* Default to an LM92 if forced */ + kind = lm92; + + /* Give it the proper name */ + if (kind == lm92) { + name = "lm92"; + } else { /* Supposedly cannot happen */ + dev_dbg(&new_client->dev, "Kind out of range?\n"); + goto exit_free; } - i2c_set_clientdata(new_client, data); + /* Fill in the remaining client fields */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; mutex_init(&data->update_lock); + /* Tell the i2c subsystem a new client has arrived */ + if ((err = i2c_attach_client(new_client))) + goto exit_free; + /* Initialize the chipset */ lm92_init_client(new_client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &lm92_group))) - goto exit_free; + goto exit_detach; data->hwmon_dev = hwmon_device_register(&new_client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -387,19 +403,32 @@ static int lm92_probe(struct i2c_client *new_client, exit_remove: sysfs_remove_group(&new_client->dev.kobj, &lm92_group); +exit_detach: + i2c_detach_client(new_client); exit_free: kfree(data); exit: return err; } -static int lm92_remove(struct i2c_client *client) +static int lm92_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, lm92_detect); +} + +static int lm92_detach_client(struct i2c_client *client) { struct lm92_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm92_group); + if ((err = i2c_detach_client(client))) + return err; + kfree(data); return 0; } @@ -409,23 +438,12 @@ static int lm92_remove(struct i2c_client *client) * Module and driver stuff */ -static const struct i2c_device_id lm92_id[] = { - { "lm92", lm92 }, - /* max6635 could be added here */ - { } -}; -MODULE_DEVICE_TABLE(i2c, lm92_id); - static struct i2c_driver lm92_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "lm92", }, - .probe = lm92_probe, - .remove = lm92_remove, - .id_table = lm92_id, - .detect = lm92_detect, - .address_data = &addr_data, + .attach_adapter = lm92_attach_adapter, + .detach_client = lm92_detach_client, }; static int __init sensors_lm92_init(void) diff --git a/trunk/drivers/hwmon/lm93.c b/trunk/drivers/hwmon/lm93.c index fc36cadf36fb..5e678f5c883d 100644 --- a/trunk/drivers/hwmon/lm93.c +++ b/trunk/drivers/hwmon/lm93.c @@ -200,6 +200,7 @@ struct block1_t { * Client-specific data */ struct lm93_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; @@ -2500,14 +2501,45 @@ static void lm93_init_client(struct i2c_client *client) "chip to signal ready!\n"); } -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm93_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int lm93_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = client->adapter; + struct lm93_data *data; + struct i2c_client *client; + + int err = -ENODEV, func; + void (*update)(struct lm93_data *, struct i2c_client *); + + /* choose update routine based on bus capabilities */ + func = i2c_get_functionality(adapter); + if ( ((LM93_SMBUS_FUNC_FULL & func) == LM93_SMBUS_FUNC_FULL) && + (!disable_block) ) { + dev_dbg(&adapter->dev,"using SMBus block data transactions\n"); + update = lm93_update_client_full; + } else if ((LM93_SMBUS_FUNC_MIN & func) == LM93_SMBUS_FUNC_MIN) { + dev_dbg(&adapter->dev,"disabled SMBus block data " + "transactions\n"); + update = lm93_update_client_min; + } else { + dev_dbg(&adapter->dev,"detect failed, " + "smbus byte and/or word data not supported!\n"); + goto err_out; + } - if (!i2c_check_functionality(adapter, LM93_SMBUS_FUNC_MIN)) - return -ENODEV; + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access lm78_{read,write}_value. */ + + if ( !(data = kzalloc(sizeof(struct lm93_data), GFP_KERNEL))) { + dev_dbg(&adapter->dev,"out of memory!\n"); + err = -ENOMEM; + goto err_out; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &lm93_driver; /* detection */ if (kind < 0) { @@ -2516,7 +2548,7 @@ static int lm93_detect(struct i2c_client *client, int kind, if (mfr != 0x01) { dev_dbg(&adapter->dev,"detect failed, " "bad manufacturer id 0x%02x!\n", mfr); - return -ENODEV; + goto err_free; } } @@ -2531,61 +2563,31 @@ static int lm93_detect(struct i2c_client *client, int kind, if (kind == 0) dev_dbg(&adapter->dev, "(ignored 'force' parameter)\n"); - return -ENODEV; + goto err_free; } } - strlcpy(info->type, "lm93", I2C_NAME_SIZE); + /* fill in remaining client fields */ + strlcpy(client->name, "lm93", I2C_NAME_SIZE); dev_dbg(&adapter->dev,"loading %s at %d,0x%02x\n", client->name, i2c_adapter_id(client->adapter), client->addr); - return 0; -} - -static int lm93_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct lm93_data *data; - int err, func; - void (*update)(struct lm93_data *, struct i2c_client *); - - /* choose update routine based on bus capabilities */ - func = i2c_get_functionality(client->adapter); - if (((LM93_SMBUS_FUNC_FULL & func) == LM93_SMBUS_FUNC_FULL) && - (!disable_block)) { - dev_dbg(&client->dev, "using SMBus block data transactions\n"); - update = lm93_update_client_full; - } else if ((LM93_SMBUS_FUNC_MIN & func) == LM93_SMBUS_FUNC_MIN) { - dev_dbg(&client->dev, "disabled SMBus block data " - "transactions\n"); - update = lm93_update_client_min; - } else { - dev_dbg(&client->dev, "detect failed, " - "smbus byte and/or word data not supported!\n"); - err = -ENODEV; - goto err_out; - } - - data = kzalloc(sizeof(struct lm93_data), GFP_KERNEL); - if (!data) { - dev_dbg(&client->dev, "out of memory!\n"); - err = -ENOMEM; - goto err_out; - } - i2c_set_clientdata(client, data); - /* housekeeping */ data->valid = 0; data->update = update; mutex_init(&data->update_lock); + /* tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto err_free; + /* initialize the chip */ lm93_init_client(client); err = sysfs_create_group(&client->dev.kobj, &lm93_attr_grp); if (err) - goto err_free; + goto err_detach; /* Register hwmon driver class */ data->hwmon_dev = hwmon_device_register(&client->dev); @@ -2595,39 +2597,43 @@ static int lm93_probe(struct i2c_client *client, err = PTR_ERR(data->hwmon_dev); dev_err(&client->dev, "error registering hwmon device.\n"); sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp); +err_detach: + i2c_detach_client(client); err_free: kfree(data); err_out: return err; } -static int lm93_remove(struct i2c_client *client) +/* This function is called when: + * lm93_driver is inserted (when this module is loaded), for each + available adapter + * when a new adapter is inserted (and lm93_driver is still present) */ +static int lm93_attach_adapter(struct i2c_adapter *adapter) +{ + return i2c_probe(adapter, &addr_data, lm93_detect); +} + +static int lm93_detach_client(struct i2c_client *client) { struct lm93_data *data = i2c_get_clientdata(client); + int err = 0; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp); - kfree(data); - return 0; + err = i2c_detach_client(client); + if (!err) + kfree(data); + return err; } -static const struct i2c_device_id lm93_id[] = { - { "lm93", lm93 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm93_id); - static struct i2c_driver lm93_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "lm93", }, - .probe = lm93_probe, - .remove = lm93_remove, - .id_table = lm93_id, - .detect = lm93_detect, - .address_data = &addr_data, + .attach_adapter = lm93_attach_adapter, + .detach_client = lm93_detach_client, }; static int __init lm93_init(void) diff --git a/trunk/drivers/hwmon/max1619.c b/trunk/drivers/hwmon/max1619.c index 1ab1cacad598..7e7267a04544 100644 --- a/trunk/drivers/hwmon/max1619.c +++ b/trunk/drivers/hwmon/max1619.c @@ -79,34 +79,23 @@ I2C_CLIENT_INSMOD_1(max1619); * Functions declaration */ -static int max1619_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int max1619_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); +static int max1619_attach_adapter(struct i2c_adapter *adapter); +static int max1619_detect(struct i2c_adapter *adapter, int address, + int kind); static void max1619_init_client(struct i2c_client *client); -static int max1619_remove(struct i2c_client *client); +static int max1619_detach_client(struct i2c_client *client); static struct max1619_data *max1619_update_device(struct device *dev); /* * Driver data (common to all clients) */ -static const struct i2c_device_id max1619_id[] = { - { "max1619", max1619 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, max1619_id); - static struct i2c_driver max1619_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "max1619", }, - .probe = max1619_probe, - .remove = max1619_remove, - .id_table = max1619_id, - .detect = max1619_detect, - .address_data = &addr_data, + .attach_adapter = max1619_attach_adapter, + .detach_client = max1619_detach_client, }; /* @@ -114,6 +103,7 @@ static struct i2c_driver max1619_driver = { */ struct max1619_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -218,15 +208,41 @@ static const struct attribute_group max1619_group = { * Real code */ -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int max1619_detect(struct i2c_client *new_client, int kind, - struct i2c_board_info *info) +static int max1619_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, max1619_detect); +} + +/* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. + */ +static int max1619_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = new_client->adapter; + struct i2c_client *new_client; + struct max1619_data *data; + int err = 0; + const char *name = ""; u8 reg_config=0, reg_convrate=0, reg_status=0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + goto exit; + + if (!(data = kzalloc(sizeof(struct max1619_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + /* The common I2C client data is placed right before the + MAX1619-specific data. */ + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &max1619_driver; + new_client->flags = 0; /* * Now we do the remaining detection. A negative kind means that @@ -249,8 +265,8 @@ static int max1619_detect(struct i2c_client *new_client, int kind, || reg_convrate > 0x07 || (reg_status & 0x61 ) !=0x00) { dev_dbg(&adapter->dev, "MAX1619 detection failed at 0x%02x.\n", - new_client->addr); - return -ENODEV; + address); + goto exit_free; } } @@ -269,37 +285,28 @@ static int max1619_detect(struct i2c_client *new_client, int kind, dev_info(&adapter->dev, "Unsupported chip (man_id=0x%02X, " "chip_id=0x%02X).\n", man_id, chip_id); - return -ENODEV; + goto exit_free; } } - strlcpy(info->type, "max1619", I2C_NAME_SIZE); - - return 0; -} - -static int max1619_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct max1619_data *data; - int err; - - data = kzalloc(sizeof(struct max1619_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } + if (kind == max1619) + name = "max1619"; - i2c_set_clientdata(new_client, data); + /* We can fill in the remaining client fields */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) + goto exit_free; + /* Initialize the MAX1619 chip */ max1619_init_client(new_client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &max1619_group))) - goto exit_free; + goto exit_detach; data->hwmon_dev = hwmon_device_register(&new_client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -311,6 +318,8 @@ static int max1619_probe(struct i2c_client *new_client, exit_remove_files: sysfs_remove_group(&new_client->dev.kobj, &max1619_group); +exit_detach: + i2c_detach_client(new_client); exit_free: kfree(data); exit: @@ -332,13 +341,17 @@ static void max1619_init_client(struct i2c_client *client) config & 0xBF); /* run */ } -static int max1619_remove(struct i2c_client *client) +static int max1619_detach_client(struct i2c_client *client) { struct max1619_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &max1619_group); + if ((err = i2c_detach_client(client))) + return err; + kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/max6650.c b/trunk/drivers/hwmon/max6650.c index f27af6a9da41..52d528b76cc3 100644 --- a/trunk/drivers/hwmon/max6650.c +++ b/trunk/drivers/hwmon/max6650.c @@ -104,34 +104,22 @@ I2C_CLIENT_INSMOD_1(max6650); #define DIV_FROM_REG(reg) (1 << (reg & 7)) -static int max6650_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int max6650_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); +static int max6650_attach_adapter(struct i2c_adapter *adapter); +static int max6650_detect(struct i2c_adapter *adapter, int address, int kind); static int max6650_init_client(struct i2c_client *client); -static int max6650_remove(struct i2c_client *client); +static int max6650_detach_client(struct i2c_client *client); static struct max6650_data *max6650_update_device(struct device *dev); /* * Driver data (common to all clients) */ -static const struct i2c_device_id max6650_id[] = { - { "max6650", max6650 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, max6650_id); - static struct i2c_driver max6650_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "max6650", }, - .probe = max6650_probe, - .remove = max6650_remove, - .id_table = max6650_id, - .detect = max6650_detect, - .address_data = &addr_data, + .attach_adapter = max6650_attach_adapter, + .detach_client = max6650_detach_client, }; /* @@ -140,6 +128,7 @@ static struct i2c_driver max6650_driver = { struct max6650_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -448,21 +437,47 @@ static struct attribute_group max6650_attr_grp = { * Real code */ -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int max6650_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int max6650_attach_adapter(struct i2c_adapter *adapter) { - struct i2c_adapter *adapter = client->adapter; - int address = client->addr; + if (!(adapter->class & I2C_CLASS_HWMON)) { + dev_dbg(&adapter->dev, + "FATAL: max6650_attach_adapter class HWMON not set\n"); + return 0; + } + + return i2c_probe(adapter, &addr_data, max6650_detect); +} + +/* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. + */ + +static int max6650_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct max6650_data *data; + int err = -ENODEV; dev_dbg(&adapter->dev, "max6650_detect called, kind = %d\n", kind); if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { dev_dbg(&adapter->dev, "max6650: I2C bus doesn't support " "byte read mode, skipping.\n"); - return -ENODEV; + return 0; + } + + if (!(data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL))) { + dev_err(&adapter->dev, "max6650: out of memory.\n"); + return -ENOMEM; } + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &max6650_driver; + /* * Now we do the remaining detection. A negative kind means that * the driver was loaded with no force parameter (default), so we @@ -486,40 +501,28 @@ static int max6650_detect(struct i2c_client *client, int kind, ||(i2c_smbus_read_byte_data(client, MAX6650_REG_COUNT) & 0xFC))) { dev_dbg(&adapter->dev, "max6650: detection failed at 0x%02x.\n", address); - return -ENODEV; + goto err_free; } dev_info(&adapter->dev, "max6650: chip found at 0x%02x.\n", address); - strlcpy(info->type, "max6650", I2C_NAME_SIZE); - - return 0; -} - -static int max6650_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct max6650_data *data; - int err; + strlcpy(client->name, "max6650", I2C_NAME_SIZE); + mutex_init(&data->update_lock); - if (!(data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL))) { - dev_err(&client->dev, "out of memory.\n"); - return -ENOMEM; + if ((err = i2c_attach_client(client))) { + dev_err(&adapter->dev, "max6650: failed to attach client.\n"); + goto err_free; } - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - /* * Initialize the max6650 chip */ - err = max6650_init_client(client); - if (err) - goto err_free; + if (max6650_init_client(client)) + goto err_detach; err = sysfs_create_group(&client->dev.kobj, &max6650_attr_grp); if (err) - goto err_free; + goto err_detach; data->hwmon_dev = hwmon_device_register(&client->dev); if (!IS_ERR(data->hwmon_dev)) @@ -528,19 +531,24 @@ static int max6650_probe(struct i2c_client *client, err = PTR_ERR(data->hwmon_dev); dev_err(&client->dev, "error registering hwmon device.\n"); sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); +err_detach: + i2c_detach_client(client); err_free: kfree(data); return err; } -static int max6650_remove(struct i2c_client *client) +static int max6650_detach_client(struct i2c_client *client) { struct max6650_data *data = i2c_get_clientdata(client); + int err; sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); hwmon_device_unregister(data->hwmon_dev); - kfree(data); - return 0; + err = i2c_detach_client(client); + if (!err) + kfree(data); + return err; } static int max6650_init_client(struct i2c_client *client) diff --git a/trunk/drivers/hwmon/smsc47m192.c b/trunk/drivers/hwmon/smsc47m192.c index 8bb5cb532d4d..3c9db6598ba7 100644 --- a/trunk/drivers/hwmon/smsc47m192.c +++ b/trunk/drivers/hwmon/smsc47m192.c @@ -96,6 +96,7 @@ static inline int TEMP_FROM_REG(s8 val) } struct smsc47m192_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ @@ -113,29 +114,18 @@ struct smsc47m192_data { u8 vrm; }; -static int smsc47m192_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int smsc47m192_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); -static int smsc47m192_remove(struct i2c_client *client); +static int smsc47m192_attach_adapter(struct i2c_adapter *adapter); +static int smsc47m192_detect(struct i2c_adapter *adapter, int address, + int kind); +static int smsc47m192_detach_client(struct i2c_client *client); static struct smsc47m192_data *smsc47m192_update_device(struct device *dev); -static const struct i2c_device_id smsc47m192_id[] = { - { "smsc47m192", smsc47m192 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, smsc47m192_id); - static struct i2c_driver smsc47m192_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "smsc47m192", }, - .probe = smsc47m192_probe, - .remove = smsc47m192_remove, - .id_table = smsc47m192_id, - .detect = smsc47m192_detect, - .address_data = &addr_data, + .attach_adapter = smsc47m192_attach_adapter, + .detach_client = smsc47m192_detach_client, }; /* Voltages */ @@ -450,6 +440,17 @@ static const struct attribute_group smsc47m192_group_in4 = { .attrs = smsc47m192_attributes_in4, }; +/* This function is called when: + * smsc47m192_driver is inserted (when this module is loaded), for each + available adapter + * when a new adapter is inserted (and smsc47m192_driver is still present) */ +static int smsc47m192_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, smsc47m192_detect); +} + static void smsc47m192_init_client(struct i2c_client *client) { int i; @@ -480,15 +481,31 @@ static void smsc47m192_init_client(struct i2c_client *client) } } -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int smsc47m192_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +/* This function is called by i2c_probe */ +static int smsc47m192_detect(struct i2c_adapter *adapter, int address, + int kind) { - struct i2c_adapter *adapter = client->adapter; - int version; + struct i2c_client *client; + struct smsc47m192_data *data; + int err = 0; + int version, config; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + goto exit; + + if (!(data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &smsc47m192_driver; + + if (kind == 0) + kind = smsc47m192; /* Detection criteria from sensors_detect script */ if (kind < 0) { @@ -506,39 +523,26 @@ static int smsc47m192_detect(struct i2c_client *client, int kind, } else { dev_dbg(&adapter->dev, "SMSC47M192 detection failed at 0x%02x\n", - client->addr); - return -ENODEV; + address); + goto exit_free; } } - strlcpy(info->type, "smsc47m192", I2C_NAME_SIZE); - - return 0; -} - -static int smsc47m192_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct smsc47m192_data *data; - int config; - int err; - - data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); + /* Fill in the remaining client fields and put into the global list */ + strlcpy(client->name, "smsc47m192", I2C_NAME_SIZE); data->vrm = vid_which_vrm(); mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; + /* Initialize the SMSC47M192 chip */ smsc47m192_init_client(client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group))) - goto exit_free; + goto exit_detach; /* Pin 110 is either in4 (+12V) or VID4 */ config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); @@ -559,20 +563,26 @@ static int smsc47m192_probe(struct i2c_client *client, exit_remove_files: sysfs_remove_group(&client->dev.kobj, &smsc47m192_group); sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); +exit_detach: + i2c_detach_client(client); exit_free: kfree(data); exit: return err; } -static int smsc47m192_remove(struct i2c_client *client) +static int smsc47m192_detach_client(struct i2c_client *client) { struct smsc47m192_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &smsc47m192_group); sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); + if ((err = i2c_detach_client(client))) + return err; + kfree(data); return 0; diff --git a/trunk/drivers/hwmon/thmc50.c b/trunk/drivers/hwmon/thmc50.c index 3b01001108c1..76a3859c3fbe 100644 --- a/trunk/drivers/hwmon/thmc50.c +++ b/trunk/drivers/hwmon/thmc50.c @@ -60,6 +60,7 @@ static const u8 THMC50_REG_TEMP_MAX[] = { 0x39, 0x37, 0x2B }; /* Each client has this additional data */ struct thmc50_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; @@ -76,31 +77,17 @@ struct thmc50_data { u8 alarms; }; -static int thmc50_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); -static int thmc50_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int thmc50_remove(struct i2c_client *client); +static int thmc50_attach_adapter(struct i2c_adapter *adapter); +static int thmc50_detach_client(struct i2c_client *client); static void thmc50_init_client(struct i2c_client *client); static struct thmc50_data *thmc50_update_device(struct device *dev); -static const struct i2c_device_id thmc50_id[] = { - { "adm1022", adm1022 }, - { "thmc50", thmc50 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, thmc50_id); - static struct i2c_driver thmc50_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "thmc50", }, - .probe = thmc50_probe, - .remove = thmc50_remove, - .id_table = thmc50_id, - .detect = thmc50_detect, - .address_data = &addr_data, + .attach_adapter = thmc50_attach_adapter, + .detach_client = thmc50_detach_client, }; static ssize_t show_analog_out(struct device *dev, @@ -263,23 +250,39 @@ static const struct attribute_group temp3_group = { .attrs = temp3_attributes, }; -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int thmc50_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int thmc50_detect(struct i2c_adapter *adapter, int address, int kind) { unsigned company; unsigned revision; unsigned config; - struct i2c_adapter *adapter = client->adapter; + struct i2c_client *client; + struct thmc50_data *data; + struct device *dev; int err = 0; const char *type_name; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { pr_debug("thmc50: detect failed, " "smbus byte data not supported!\n"); - return -ENODEV; + goto exit; + } + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access thmc50 registers. */ + if (!(data = kzalloc(sizeof(struct thmc50_data), GFP_KERNEL))) { + pr_debug("thmc50: detect failed, kzalloc failed!\n"); + err = -ENOMEM; + goto exit; } + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &thmc50_driver; + dev = &client->dev; + pr_debug("thmc50: Probing for THMC50 at 0x%2X on bus %d\n", client->addr, i2c_adapter_id(client->adapter)); @@ -304,22 +307,21 @@ static int thmc50_detect(struct i2c_client *client, int kind, } if (err == -ENODEV) { pr_debug("thmc50: Detection of THMC50/ADM1022 failed\n"); - return err; + goto exit_free; } + data->type = kind; if (kind == adm1022) { int id = i2c_adapter_id(client->adapter); int i; type_name = "adm1022"; + data->has_temp3 = (config >> 7) & 1; /* config MSB */ for (i = 0; i + 1 < adm1022_temp3_num; i += 2) if (adm1022_temp3[i] == id && - adm1022_temp3[i + 1] == client->addr) { + adm1022_temp3[i + 1] == address) { /* enable 2nd remote temp */ - config |= (1 << 7); - i2c_smbus_write_byte_data(client, - THMC50_REG_CONF, - config); + data->has_temp3 = 1; break; } } else { @@ -328,33 +330,19 @@ static int thmc50_detect(struct i2c_client *client, int kind, pr_debug("thmc50: Detected %s (version %x, revision %x)\n", type_name, (revision >> 4) - 0xc, revision & 0xf); - strlcpy(info->type, type_name, I2C_NAME_SIZE); - - return 0; -} - -static int thmc50_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct thmc50_data *data; - int err; - - data = kzalloc(sizeof(struct thmc50_data), GFP_KERNEL); - if (!data) { - pr_debug("thmc50: detect failed, kzalloc failed!\n"); - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - data->type = id->driver_data; + /* Fill in the remaining client fields & put it into the global list */ + strlcpy(client->name, type_name, I2C_NAME_SIZE); mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; + thmc50_init_client(client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &thmc50_group))) - goto exit_free; + goto exit_detach; /* Register ADM1022 sysfs hooks */ if (data->has_temp3) @@ -376,21 +364,34 @@ static int thmc50_probe(struct i2c_client *client, sysfs_remove_group(&client->dev.kobj, &temp3_group); exit_remove_sysfs_thmc50: sysfs_remove_group(&client->dev.kobj, &thmc50_group); +exit_detach: + i2c_detach_client(client); exit_free: kfree(data); exit: return err; } -static int thmc50_remove(struct i2c_client *client) +static int thmc50_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, thmc50_detect); +} + +static int thmc50_detach_client(struct i2c_client *client) { struct thmc50_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &thmc50_group); if (data->has_temp3) sysfs_remove_group(&client->dev.kobj, &temp3_group); + if ((err = i2c_detach_client(client))) + return err; + kfree(data); return 0; @@ -411,8 +412,8 @@ static void thmc50_init_client(struct i2c_client *client) } config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF); config |= 0x1; /* start the chip if it is in standby mode */ - if (data->type == adm1022 && (config & (1 << 7))) - data->has_temp3 = 1; + if (data->has_temp3) + config |= 0x80; /* enable 2nd remote temp */ i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config); } diff --git a/trunk/drivers/hwmon/w83791d.c b/trunk/drivers/hwmon/w83791d.c index e4e91c9d480a..85077c4c8039 100644 --- a/trunk/drivers/hwmon/w83791d.c +++ b/trunk/drivers/hwmon/w83791d.c @@ -247,6 +247,7 @@ static u8 div_to_reg(int nr, long val) } struct w83791d_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; @@ -285,11 +286,9 @@ struct w83791d_data { u8 vrm; /* hwmon-vid */ }; -static int w83791d_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int w83791d_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); -static int w83791d_remove(struct i2c_client *client); +static int w83791d_attach_adapter(struct i2c_adapter *adapter); +static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind); +static int w83791d_detach_client(struct i2c_client *client); static int w83791d_read(struct i2c_client *client, u8 register); static int w83791d_write(struct i2c_client *client, u8 register, u8 value); @@ -301,22 +300,12 @@ static void w83791d_print_debug(struct w83791d_data *data, struct device *dev); static void w83791d_init_client(struct i2c_client *client); -static const struct i2c_device_id w83791d_id[] = { - { "w83791d", w83791d }, - { } -}; -MODULE_DEVICE_TABLE(i2c, w83791d_id); - static struct i2c_driver w83791d_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "w83791d", }, - .probe = w83791d_probe, - .remove = w83791d_remove, - .id_table = w83791d_id, - .detect = w83791d_detect, - .address_data = &addr_data, + .attach_adapter = w83791d_attach_adapter, + .detach_client = w83791d_detach_client, }; /* following are the sysfs callback functions */ @@ -916,12 +905,49 @@ static const struct attribute_group w83791d_group = { .attrs = w83791d_attributes, }; +/* This function is called when: + * w83791d_driver is inserted (when this module is loaded), for each + available adapter + * when a new adapter is inserted (and w83791d_driver is still present) */ +static int w83791d_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, w83791d_detect); +} + -static int w83791d_detect_subclients(struct i2c_client *client) +static int w83791d_create_subclient(struct i2c_adapter *adapter, + struct i2c_client *client, int addr, + struct i2c_client **sub_cli) +{ + int err; + struct i2c_client *sub_client; + + (*sub_cli) = sub_client = + kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (!(sub_client)) { + return -ENOMEM; + } + sub_client->addr = 0x48 + addr; + i2c_set_clientdata(sub_client, NULL); + sub_client->adapter = adapter; + sub_client->driver = &w83791d_driver; + strlcpy(sub_client->name, "w83791d subclient", I2C_NAME_SIZE); + if ((err = i2c_attach_client(sub_client))) { + dev_err(&client->dev, "subclient registration " + "at address 0x%x failed\n", sub_client->addr); + kfree(sub_client); + return err; + } + return 0; +} + + +static int w83791d_detect_subclients(struct i2c_adapter *adapter, int address, + int kind, struct i2c_client *client) { - struct i2c_adapter *adapter = client->adapter; struct w83791d_data *data = i2c_get_clientdata(client); - int address = client->addr; int i, id, err; u8 val; @@ -945,7 +971,10 @@ static int w83791d_detect_subclients(struct i2c_client *client) val = w83791d_read(client, W83791D_REG_I2C_SUBADDR); if (!(val & 0x08)) { - data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (val & 0x7)); + err = w83791d_create_subclient(adapter, client, + val & 0x7, &data->lm75[0]); + if (err < 0) + goto error_sc_0; } if (!(val & 0x80)) { if ((data->lm75[0] != NULL) && @@ -957,8 +986,10 @@ static int w83791d_detect_subclients(struct i2c_client *client) err = -ENODEV; goto error_sc_1; } - data->lm75[1] = i2c_new_dummy(adapter, - 0x48 + ((val >> 4) & 0x7)); + err = w83791d_create_subclient(adapter, client, + (val >> 4) & 0x7, &data->lm75[1]); + if (err < 0) + goto error_sc_1; } return 0; @@ -966,31 +997,53 @@ static int w83791d_detect_subclients(struct i2c_client *client) /* Undo inits in case of errors */ error_sc_1: - if (data->lm75[0] != NULL) - i2c_unregister_device(data->lm75[0]); + if (data->lm75[0] != NULL) { + i2c_detach_client(data->lm75[0]); + kfree(data->lm75[0]); + } error_sc_0: return err; } -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int w83791d_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = client->adapter; - int val1, val2; - unsigned short address = client->addr; + struct i2c_client *client; + struct device *dev; + struct w83791d_data *data; + int i, val1, val2; + int err = 0; + const char *client_name = ""; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - return -ENODEV; + goto error0; } + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access w83791d_{read,write}_value. */ + if (!(data = kzalloc(sizeof(struct w83791d_data), GFP_KERNEL))) { + err = -ENOMEM; + goto error0; + } + + client = &data->client; + dev = &client->dev; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &w83791d_driver; + mutex_init(&data->update_lock); + + /* Now, we do the remaining detection. */ + /* The w83791d may be stuck in some other bank than bank 0. This may make reading other information impossible. Specify a force=... parameter, and the Winbond will be reset to the right bank. */ if (kind < 0) { if (w83791d_read(client, W83791D_REG_CONFIG) & 0x80) { - return -ENODEV; + dev_dbg(dev, "Detection failed at step 1\n"); + goto error1; } val1 = w83791d_read(client, W83791D_REG_BANK); val2 = w83791d_read(client, W83791D_REG_CHIPMAN); @@ -999,13 +1052,15 @@ static int w83791d_detect(struct i2c_client *client, int kind, /* yes it is Bank0 */ if (((!(val1 & 0x80)) && (val2 != 0xa3)) || ((val1 & 0x80) && (val2 != 0x5c))) { - return -ENODEV; + dev_dbg(dev, "Detection failed at step 2\n"); + goto error1; } } /* If Winbond chip, address of chip and W83791D_REG_I2C_ADDR should match */ if (w83791d_read(client, W83791D_REG_I2C_ADDR) != address) { - return -ENODEV; + dev_dbg(dev, "Detection failed at step 3\n"); + goto error1; } } @@ -1020,33 +1075,30 @@ static int w83791d_detect(struct i2c_client *client, int kind, /* get vendor ID */ val2 = w83791d_read(client, W83791D_REG_CHIPMAN); if (val2 != 0x5c) { /* the vendor is NOT Winbond */ - return -ENODEV; + dev_dbg(dev, "Detection failed at step 4\n"); + goto error1; } val1 = w83791d_read(client, W83791D_REG_WCHIPID); if (val1 == 0x71) { kind = w83791d; } else { if (kind == 0) - dev_warn(&adapter->dev, + dev_warn(dev, "w83791d: Ignoring 'force' parameter " "for unknown chip at adapter %d, " "address 0x%02x\n", i2c_adapter_id(adapter), address); - return -ENODEV; + goto error1; } } - strlcpy(info->type, "w83791d", I2C_NAME_SIZE); - - return 0; -} - -static int w83791d_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct w83791d_data *data; - struct device *dev = &client->dev; - int i, val1, err; + if (kind == w83791d) { + client_name = "w83791d"; + } else { + dev_err(dev, "w83791d: Internal error: unknown kind (%d)?!?\n", + kind); + goto error1; + } #ifdef DEBUG val1 = w83791d_read(client, W83791D_REG_DID_VID4); @@ -1054,19 +1106,16 @@ static int w83791d_probe(struct i2c_client *client, (val1 >> 5) & 0x07, (val1 >> 1) & 0x0f, val1); #endif - data = kzalloc(sizeof(struct w83791d_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto error0; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); + /* Fill in the remaining client fields and put into the global list */ + strlcpy(client->name, client_name, I2C_NAME_SIZE); - err = w83791d_detect_subclients(client); - if (err) + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) goto error1; + if ((err = w83791d_detect_subclients(adapter, address, kind, client))) + goto error2; + /* Initialize the chip */ w83791d_init_client(client); @@ -1092,29 +1141,43 @@ static int w83791d_probe(struct i2c_client *client, error4: sysfs_remove_group(&client->dev.kobj, &w83791d_group); error3: - if (data->lm75[0] != NULL) - i2c_unregister_device(data->lm75[0]); - if (data->lm75[1] != NULL) - i2c_unregister_device(data->lm75[1]); + if (data->lm75[0] != NULL) { + i2c_detach_client(data->lm75[0]); + kfree(data->lm75[0]); + } + if (data->lm75[1] != NULL) { + i2c_detach_client(data->lm75[1]); + kfree(data->lm75[1]); + } +error2: + i2c_detach_client(client); error1: kfree(data); error0: return err; } -static int w83791d_remove(struct i2c_client *client) +static int w83791d_detach_client(struct i2c_client *client) { struct w83791d_data *data = i2c_get_clientdata(client); + int err; - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &w83791d_group); + /* main client */ + if (data) { + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &w83791d_group); + } - if (data->lm75[0] != NULL) - i2c_unregister_device(data->lm75[0]); - if (data->lm75[1] != NULL) - i2c_unregister_device(data->lm75[1]); + if ((err = i2c_detach_client(client))) + return err; + + /* main client */ + if (data) + kfree(data); + /* subclient */ + else + kfree(client); - kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/w83792d.c b/trunk/drivers/hwmon/w83792d.c index cf94c5b0c879..299629d47ed6 100644 --- a/trunk/drivers/hwmon/w83792d.c +++ b/trunk/drivers/hwmon/w83792d.c @@ -267,7 +267,9 @@ DIV_TO_REG(long val) } struct w83792d_data { + struct i2c_client client; struct device *hwmon_dev; + enum chips type; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ @@ -297,11 +299,9 @@ struct w83792d_data { u8 sf2_levels[3][4]; /* Smart FanII: Fan1,2,3 duty cycle levels */ }; -static int w83792d_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int w83792d_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); -static int w83792d_remove(struct i2c_client *client); +static int w83792d_attach_adapter(struct i2c_adapter *adapter); +static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind); +static int w83792d_detach_client(struct i2c_client *client); static struct w83792d_data *w83792d_update_device(struct device *dev); #ifdef DEBUG @@ -310,22 +310,12 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev); static void w83792d_init_client(struct i2c_client *client); -static const struct i2c_device_id w83792d_id[] = { - { "w83792d", w83792d }, - { } -}; -MODULE_DEVICE_TABLE(i2c, w83792d_id); - static struct i2c_driver w83792d_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "w83792d", }, - .probe = w83792d_probe, - .remove = w83792d_remove, - .id_table = w83792d_id, - .detect = w83792d_detect, - .address_data = &addr_data, + .attach_adapter = w83792d_attach_adapter, + .detach_client = w83792d_detach_client, }; static inline long in_count_from_reg(int nr, struct w83792d_data *data) @@ -874,14 +864,53 @@ store_sf2_level(struct device *dev, struct device_attribute *attr, return count; } +/* This function is called when: + * w83792d_driver is inserted (when this module is loaded), for each + available adapter + * when a new adapter is inserted (and w83792d_driver is still present) */ +static int +w83792d_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, w83792d_detect); +} + + +static int +w83792d_create_subclient(struct i2c_adapter *adapter, + struct i2c_client *new_client, int addr, + struct i2c_client **sub_cli) +{ + int err; + struct i2c_client *sub_client; + + (*sub_cli) = sub_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (!(sub_client)) { + return -ENOMEM; + } + sub_client->addr = 0x48 + addr; + i2c_set_clientdata(sub_client, NULL); + sub_client->adapter = adapter; + sub_client->driver = &w83792d_driver; + sub_client->flags = 0; + strlcpy(sub_client->name, "w83792d subclient", I2C_NAME_SIZE); + if ((err = i2c_attach_client(sub_client))) { + dev_err(&new_client->dev, "subclient registration " + "at address 0x%x failed\n", sub_client->addr); + kfree(sub_client); + return err; + } + return 0; +} + static int -w83792d_detect_subclients(struct i2c_client *new_client) +w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind, + struct i2c_client *new_client) { int i, id, err; - int address = new_client->addr; u8 val; - struct i2c_adapter *adapter = new_client->adapter; struct w83792d_data *data = i2c_get_clientdata(new_client); id = i2c_adapter_id(adapter); @@ -903,7 +932,10 @@ w83792d_detect_subclients(struct i2c_client *new_client) val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR); if (!(val & 0x08)) { - data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (val & 0x7)); + err = w83792d_create_subclient(adapter, new_client, val & 0x7, + &data->lm75[0]); + if (err < 0) + goto ERROR_SC_0; } if (!(val & 0x80)) { if ((data->lm75[0] != NULL) && @@ -913,8 +945,10 @@ w83792d_detect_subclients(struct i2c_client *new_client) err = -ENODEV; goto ERROR_SC_1; } - data->lm75[1] = i2c_new_dummy(adapter, - 0x48 + ((val >> 4) & 0x7)); + err = w83792d_create_subclient(adapter, new_client, + (val >> 4) & 0x7, &data->lm75[1]); + if (err < 0) + goto ERROR_SC_1; } return 0; @@ -922,8 +956,10 @@ w83792d_detect_subclients(struct i2c_client *new_client) /* Undo inits in case of errors */ ERROR_SC_1: - if (data->lm75[0] != NULL) - i2c_unregister_device(data->lm75[0]); + if (data->lm75[0] != NULL) { + i2c_detach_client(data->lm75[0]); + kfree(data->lm75[0]); + } ERROR_SC_0: return err; } @@ -1258,25 +1294,47 @@ static const struct attribute_group w83792d_group = { .attrs = w83792d_attributes, }; -/* Return 0 if detection is successful, -ENODEV otherwise */ static int -w83792d_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) +w83792d_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = client->adapter; - int val1, val2; - unsigned short address = client->addr; + int i = 0, val1 = 0, val2; + struct i2c_client *client; + struct device *dev; + struct w83792d_data *data; + int err = 0; + const char *client_name = ""; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - return -ENODEV; + goto ERROR0; + } + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access w83792d_{read,write}_value. */ + + if (!(data = kzalloc(sizeof(struct w83792d_data), GFP_KERNEL))) { + err = -ENOMEM; + goto ERROR0; } + client = &data->client; + dev = &client->dev; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &w83792d_driver; + client->flags = 0; + + /* Now, we do the remaining detection. */ + /* The w83792d may be stuck in some other bank than bank 0. This may make reading other information impossible. Specify a force=... or force_*=... parameter, and the Winbond will be reset to the right bank. */ if (kind < 0) { if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) { - return -ENODEV; + dev_dbg(dev, "Detection failed at step 1\n"); + goto ERROR1; } val1 = w83792d_read_value(client, W83792D_REG_BANK); val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); @@ -1284,14 +1342,16 @@ w83792d_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) if (!(val1 & 0x07)) { /* is Bank0 */ if (((!(val1 & 0x80)) && (val2 != 0xa3)) || ((val1 & 0x80) && (val2 != 0x5c))) { - return -ENODEV; + dev_dbg(dev, "Detection failed at step 2\n"); + goto ERROR1; } } /* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR should match */ if (w83792d_read_value(client, W83792D_REG_I2C_ADDR) != address) { - return -ENODEV; + dev_dbg(dev, "Detection failed at step 3\n"); + goto ERROR1; } } @@ -1307,48 +1367,45 @@ w83792d_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) /* get vendor ID */ val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); if (val2 != 0x5c) { /* the vendor is NOT Winbond */ - return -ENODEV; + goto ERROR1; } val1 = w83792d_read_value(client, W83792D_REG_WCHIPID); if (val1 == 0x7a) { kind = w83792d; } else { if (kind == 0) - dev_warn(&adapter->dev, + dev_warn(dev, "w83792d: Ignoring 'force' parameter for" " unknown chip at adapter %d, address" " 0x%02x\n", i2c_adapter_id(adapter), address); - return -ENODEV; + goto ERROR1; } } - strlcpy(info->type, "w83792d", I2C_NAME_SIZE); - - return 0; -} - -static int -w83792d_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct w83792d_data *data; - struct device *dev = &client->dev; - int i, val1, err; - - data = kzalloc(sizeof(struct w83792d_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto ERROR0; + if (kind == w83792d) { + client_name = "w83792d"; + } else { + dev_err(dev, "w83792d: Internal error: unknown kind (%d)?!?\n", + kind); + goto ERROR1; } - i2c_set_clientdata(client, data); + /* Fill in the remaining client fields and put into the global list */ + strlcpy(client->name, client_name, I2C_NAME_SIZE); + data->type = kind; + data->valid = 0; mutex_init(&data->update_lock); - err = w83792d_detect_subclients(client); - if (err) + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) goto ERROR1; + if ((err = w83792d_detect_subclients(adapter, address, + kind, client))) + goto ERROR2; + /* Initialize the chip */ w83792d_init_client(client); @@ -1400,10 +1457,16 @@ w83792d_probe(struct i2c_client *client, const struct i2c_device_id *id) for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) sysfs_remove_group(&dev->kobj, &w83792d_group_fan[i]); ERROR3: - if (data->lm75[0] != NULL) - i2c_unregister_device(data->lm75[0]); - if (data->lm75[1] != NULL) - i2c_unregister_device(data->lm75[1]); + if (data->lm75[0] != NULL) { + i2c_detach_client(data->lm75[0]); + kfree(data->lm75[0]); + } + if (data->lm75[1] != NULL) { + i2c_detach_client(data->lm75[1]); + kfree(data->lm75[1]); + } +ERROR2: + i2c_detach_client(client); ERROR1: kfree(data); ERROR0: @@ -1411,23 +1474,30 @@ w83792d_probe(struct i2c_client *client, const struct i2c_device_id *id) } static int -w83792d_remove(struct i2c_client *client) +w83792d_detach_client(struct i2c_client *client) { struct w83792d_data *data = i2c_get_clientdata(client); - int i; + int err, i; + + /* main client */ + if (data) { + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &w83792d_group); + for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) + sysfs_remove_group(&client->dev.kobj, + &w83792d_group_fan[i]); + } - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &w83792d_group); - for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) - sysfs_remove_group(&client->dev.kobj, - &w83792d_group_fan[i]); + if ((err = i2c_detach_client(client))) + return err; - if (data->lm75[0] != NULL) - i2c_unregister_device(data->lm75[0]); - if (data->lm75[1] != NULL) - i2c_unregister_device(data->lm75[1]); + /* main client */ + if (data) + kfree(data); + /* subclient */ + else + kfree(client); - kfree(data); return 0; } diff --git a/trunk/drivers/hwmon/w83793.c b/trunk/drivers/hwmon/w83793.c index 0a739f1c69be..ed3c019b78c7 100644 --- a/trunk/drivers/hwmon/w83793.c +++ b/trunk/drivers/hwmon/w83793.c @@ -179,6 +179,7 @@ static inline s8 TEMP_TO_REG(long val, s8 min, s8 max) } struct w83793_data { + struct i2c_client client; struct i2c_client *lm75[2]; struct device *hwmon_dev; struct mutex update_lock; @@ -225,31 +226,19 @@ struct w83793_data { static u8 w83793_read_value(struct i2c_client *client, u16 reg); static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value); -static int w83793_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int w83793_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); -static int w83793_remove(struct i2c_client *client); +static int w83793_attach_adapter(struct i2c_adapter *adapter); +static int w83793_detect(struct i2c_adapter *adapter, int address, int kind); +static int w83793_detach_client(struct i2c_client *client); static void w83793_init_client(struct i2c_client *client); static void w83793_update_nonvolatile(struct device *dev); static struct w83793_data *w83793_update_device(struct device *dev); -static const struct i2c_device_id w83793_id[] = { - { "w83793", w83793 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, w83793_id); - static struct i2c_driver w83793_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "w83793", }, - .probe = w83793_probe, - .remove = w83793_remove, - .id_table = w83793_id, - .detect = w83793_detect, - .address_data = &addr_data, + .attach_adapter = w83793_attach_adapter, + .detach_client = w83793_detach_client, }; static ssize_t @@ -1064,51 +1053,89 @@ static void w83793_init_client(struct i2c_client *client) } -static int w83793_remove(struct i2c_client *client) +static int w83793_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, w83793_detect); +} + +static int w83793_detach_client(struct i2c_client *client) { struct w83793_data *data = i2c_get_clientdata(client); struct device *dev = &client->dev; - int i; + int err, i; - hwmon_device_unregister(data->hwmon_dev); + /* main client */ + if (data) { + hwmon_device_unregister(data->hwmon_dev); - for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) - device_remove_file(dev, - &w83793_sensor_attr_2[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) + device_remove_file(dev, + &w83793_sensor_attr_2[i].dev_attr); - for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) - device_remove_file(dev, &sda_single_files[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) + device_remove_file(dev, &sda_single_files[i].dev_attr); - for (i = 0; i < ARRAY_SIZE(w83793_vid); i++) - device_remove_file(dev, &w83793_vid[i].dev_attr); - device_remove_file(dev, &dev_attr_vrm); + for (i = 0; i < ARRAY_SIZE(w83793_vid); i++) + device_remove_file(dev, &w83793_vid[i].dev_attr); + device_remove_file(dev, &dev_attr_vrm); - for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++) - device_remove_file(dev, &w83793_left_fan[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++) + device_remove_file(dev, &w83793_left_fan[i].dev_attr); - for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++) - device_remove_file(dev, &w83793_left_pwm[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++) + device_remove_file(dev, &w83793_left_pwm[i].dev_attr); - for (i = 0; i < ARRAY_SIZE(w83793_temp); i++) - device_remove_file(dev, &w83793_temp[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(w83793_temp); i++) + device_remove_file(dev, &w83793_temp[i].dev_attr); + } - if (data->lm75[0] != NULL) - i2c_unregister_device(data->lm75[0]); - if (data->lm75[1] != NULL) - i2c_unregister_device(data->lm75[1]); + if ((err = i2c_detach_client(client))) + return err; - kfree(data); + /* main client */ + if (data) + kfree(data); + /* subclient */ + else + kfree(client); return 0; } static int -w83793_detect_subclients(struct i2c_client *client) +w83793_create_subclient(struct i2c_adapter *adapter, + struct i2c_client *client, int addr, + struct i2c_client **sub_cli) +{ + int err = 0; + struct i2c_client *sub_client; + + (*sub_cli) = sub_client = + kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (!(sub_client)) { + return -ENOMEM; + } + sub_client->addr = 0x48 + addr; + i2c_set_clientdata(sub_client, NULL); + sub_client->adapter = adapter; + sub_client->driver = &w83793_driver; + strlcpy(sub_client->name, "w83793 subclient", I2C_NAME_SIZE); + if ((err = i2c_attach_client(sub_client))) { + dev_err(&client->dev, "subclient registration " + "at address 0x%x failed\n", sub_client->addr); + kfree(sub_client); + } + return err; +} + +static int +w83793_detect_subclients(struct i2c_adapter *adapter, int address, + int kind, struct i2c_client *client) { int i, id, err; - int address = client->addr; u8 tmp; - struct i2c_adapter *adapter = client->adapter; struct w83793_data *data = i2c_get_clientdata(client); id = i2c_adapter_id(adapter); @@ -1131,7 +1158,11 @@ w83793_detect_subclients(struct i2c_client *client) tmp = w83793_read_value(client, W83793_REG_I2C_SUBADDR); if (!(tmp & 0x08)) { - data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (tmp & 0x7)); + err = + w83793_create_subclient(adapter, client, tmp & 0x7, + &data->lm75[0]); + if (err < 0) + goto ERROR_SC_0; } if (!(tmp & 0x80)) { if ((data->lm75[0] != NULL) @@ -1142,8 +1173,10 @@ w83793_detect_subclients(struct i2c_client *client) err = -ENODEV; goto ERROR_SC_1; } - data->lm75[1] = i2c_new_dummy(adapter, - 0x48 + ((tmp >> 4) & 0x7)); + err = w83793_create_subclient(adapter, client, + (tmp >> 4) & 0x7, &data->lm75[1]); + if (err < 0) + goto ERROR_SC_1; } return 0; @@ -1151,44 +1184,69 @@ w83793_detect_subclients(struct i2c_client *client) /* Undo inits in case of errors */ ERROR_SC_1: - if (data->lm75[0] != NULL) - i2c_unregister_device(data->lm75[0]); + if (data->lm75[0] != NULL) { + i2c_detach_client(data->lm75[0]); + kfree(data->lm75[0]); + } ERROR_SC_0: return err; } -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int w83793_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int w83793_detect(struct i2c_adapter *adapter, int address, int kind) { - u8 tmp, bank; - struct i2c_adapter *adapter = client->adapter; - unsigned short address = client->addr; + int i; + u8 tmp, val; + struct i2c_client *client; + struct device *dev; + struct w83793_data *data; + int files_fan = ARRAY_SIZE(w83793_left_fan) / 7; + int files_pwm = ARRAY_SIZE(w83793_left_pwm) / 5; + int files_temp = ARRAY_SIZE(w83793_temp) / 6; + int err = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - return -ENODEV; + goto exit; } - bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL); + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access w83793_{read,write}_value. */ + + if (!(data = kzalloc(sizeof(struct w83793_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + dev = &client->dev; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &w83793_driver; + data->bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL); + + /* Now, we do the remaining detection. */ if (kind < 0) { - tmp = bank & 0x80 ? 0x5c : 0xa3; + tmp = data->bank & 0x80 ? 0x5c : 0xa3; /* Check Winbond vendor ID */ if (tmp != i2c_smbus_read_byte_data(client, W83793_REG_VENDORID)) { pr_debug("w83793: Detection failed at check " "vendor id\n"); - return -ENODEV; + err = -ENODEV; + goto free_mem; } /* If Winbond chip, address of chip and W83793_REG_I2C_ADDR should match */ - if ((bank & 0x07) == 0 + if ((data->bank & 0x07) == 0 && i2c_smbus_read_byte_data(client, W83793_REG_I2C_ADDR) != (address << 1)) { pr_debug("w83793: Detection failed at check " "i2c addr\n"); - return -ENODEV; + err = -ENODEV; + goto free_mem; } } @@ -1197,47 +1255,30 @@ static int w83793_detect(struct i2c_client *client, int kind, Winbond. Determine the chip type now */ if (kind <= 0) { - if (0x7b == i2c_smbus_read_byte_data(client, - W83793_REG_CHIPID)) { + if (0x7b == w83793_read_value(client, W83793_REG_CHIPID)) { kind = w83793; } else { if (kind == 0) dev_warn(&adapter->dev, "w83793: Ignoring " "'force' parameter for unknown chip " "at address 0x%02x\n", address); - return -ENODEV; + err = -ENODEV; + goto free_mem; } } - strlcpy(info->type, "w83793", I2C_NAME_SIZE); - - return 0; -} + /* Fill in the remaining client fields and put into the global list */ + strlcpy(client->name, "w83793", I2C_NAME_SIZE); -static int w83793_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct device *dev = &client->dev; - struct w83793_data *data; - int i, tmp, val, err; - int files_fan = ARRAY_SIZE(w83793_left_fan) / 7; - int files_pwm = ARRAY_SIZE(w83793_left_pwm) / 5; - int files_temp = ARRAY_SIZE(w83793_temp) / 6; - - data = kzalloc(sizeof(struct w83793_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - data->bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL); mutex_init(&data->update_lock); - err = w83793_detect_subclients(client); - if (err) + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) goto free_mem; + if ((err = w83793_detect_subclients(adapter, address, kind, client))) + goto detach_client; + /* Initialize the chip */ w83793_init_client(client); @@ -1418,10 +1459,16 @@ static int w83793_probe(struct i2c_client *client, for (i = 0; i < ARRAY_SIZE(w83793_temp); i++) device_remove_file(dev, &w83793_temp[i].dev_attr); - if (data->lm75[0] != NULL) - i2c_unregister_device(data->lm75[0]); - if (data->lm75[1] != NULL) - i2c_unregister_device(data->lm75[1]); + if (data->lm75[0] != NULL) { + i2c_detach_client(data->lm75[0]); + kfree(data->lm75[0]); + } + if (data->lm75[1] != NULL) { + i2c_detach_client(data->lm75[1]); + kfree(data->lm75[1]); + } +detach_client: + i2c_detach_client(client); free_mem: kfree(data); exit: diff --git a/trunk/drivers/hwmon/w83l785ts.c b/trunk/drivers/hwmon/w83l785ts.c index ea295b9fc4f4..52e268e25dab 100644 --- a/trunk/drivers/hwmon/w83l785ts.c +++ b/trunk/drivers/hwmon/w83l785ts.c @@ -81,11 +81,10 @@ I2C_CLIENT_INSMOD_1(w83l785ts); * Functions declaration */ -static int w83l785ts_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int w83l785ts_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); -static int w83l785ts_remove(struct i2c_client *client); +static int w83l785ts_attach_adapter(struct i2c_adapter *adapter); +static int w83l785ts_detect(struct i2c_adapter *adapter, int address, + int kind); +static int w83l785ts_detach_client(struct i2c_client *client); static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval); static struct w83l785ts_data *w83l785ts_update_device(struct device *dev); @@ -93,22 +92,12 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev); * Driver data (common to all clients) */ -static const struct i2c_device_id w83l785ts_id[] = { - { "w83l785ts", w83l785ts }, - { } -}; -MODULE_DEVICE_TABLE(i2c, w83l785ts_id); - static struct i2c_driver w83l785ts_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "w83l785ts", }, - .probe = w83l785ts_probe, - .remove = w83l785ts_remove, - .id_table = w83l785ts_id, - .detect = w83l785ts_detect, - .address_data = &addr_data, + .attach_adapter = w83l785ts_attach_adapter, + .detach_client = w83l785ts_detach_client, }; /* @@ -116,6 +105,7 @@ static struct i2c_driver w83l785ts_driver = { */ struct w83l785ts_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -145,14 +135,40 @@ static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 1); * Real code */ -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int w83l785ts_detect(struct i2c_client *new_client, int kind, - struct i2c_board_info *info) +static int w83l785ts_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, w83l785ts_detect); +} + +/* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. + */ +static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = new_client->adapter; + struct i2c_client *new_client; + struct w83l785ts_data *data; + int err = 0; + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + goto exit; + + if (!(data = kzalloc(sizeof(struct w83l785ts_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + /* The common I2C client data is placed right before the + * W83L785TS-specific data. */ + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &w83l785ts_driver; + new_client->flags = 0; /* * Now we do the remaining detection. A negative kind means that @@ -172,8 +188,8 @@ static int w83l785ts_detect(struct i2c_client *new_client, int kind, W83L785TS_REG_TYPE, 0) & 0xFC) != 0x00)) { dev_dbg(&adapter->dev, "W83L785TS-S detection failed at 0x%02x.\n", - new_client->addr); - return -ENODEV; + address); + goto exit_free; } } @@ -198,34 +214,22 @@ static int w83l785ts_detect(struct i2c_client *new_client, int kind, dev_info(&adapter->dev, "Unsupported chip (man_id=0x%04X, " "chip_id=0x%02X).\n", man_id, chip_id); - return -ENODEV; + goto exit_free; } } - strlcpy(info->type, "w83l785ts", I2C_NAME_SIZE); - - return 0; -} - -static int w83l785ts_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct w83l785ts_data *data; - int err = 0; - - data = kzalloc(sizeof(struct w83l785ts_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(new_client, data); + /* We can fill in the remaining client fields. */ + strlcpy(new_client->name, "w83l785ts", I2C_NAME_SIZE); data->valid = 0; mutex_init(&data->update_lock); /* Default values in case the first read fails (unlikely). */ data->temp[1] = data->temp[0] = 0; + /* Tell the I2C layer a new client has arrived. */ + if ((err = i2c_attach_client(new_client))) + goto exit_free; + /* * Initialize the W83L785TS chip * Nothing yet, assume it is already started. @@ -255,20 +259,25 @@ static int w83l785ts_probe(struct i2c_client *new_client, &sensor_dev_attr_temp1_input.dev_attr); device_remove_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr); + i2c_detach_client(new_client); +exit_free: kfree(data); exit: return err; } -static int w83l785ts_remove(struct i2c_client *client) +static int w83l785ts_detach_client(struct i2c_client *client) { struct w83l785ts_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); device_remove_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr); device_remove_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr); + if ((err = i2c_detach_client(client))) + return err; kfree(data); return 0; @@ -277,18 +286,6 @@ static int w83l785ts_remove(struct i2c_client *client) static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval) { int value, i; - struct device *dev; - const char *prefix; - - /* We might be called during detection, at which point the client - isn't yet fully initialized, so we can't use dev_dbg on it */ - if (i2c_get_clientdata(client)) { - dev = &client->dev; - prefix = ""; - } else { - dev = &client->adapter->dev; - prefix = "w83l785ts: "; - } /* Frequent read errors have been reported on Asus boards, so we * retry on read errors. If it still fails (unlikely), return the @@ -296,15 +293,15 @@ static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval) for (i = 1; i <= MAX_RETRIES; i++) { value = i2c_smbus_read_byte_data(client, reg); if (value >= 0) { - dev_dbg(dev, "%sRead 0x%02x from register 0x%02x.\n", - prefix, value, reg); + dev_dbg(&client->dev, "Read 0x%02x from register " + "0x%02x.\n", value, reg); return value; } - dev_dbg(dev, "%sRead failed, will retry in %d.\n", prefix, i); + dev_dbg(&client->dev, "Read failed, will retry in %d.\n", i); msleep(i); } - dev_err(dev, "%sCouldn't read value from register 0x%02x.\n", prefix, + dev_err(&client->dev, "Couldn't read value from register 0x%02x.\n", reg); return defval; } diff --git a/trunk/drivers/hwmon/w83l786ng.c b/trunk/drivers/hwmon/w83l786ng.c index badca769f350..41e22ddb568a 100644 --- a/trunk/drivers/hwmon/w83l786ng.c +++ b/trunk/drivers/hwmon/w83l786ng.c @@ -121,6 +121,7 @@ DIV_TO_REG(long val) } struct w83l786ng_data { + struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ @@ -145,30 +146,18 @@ struct w83l786ng_data { u8 tolerance[2]; }; -static int w83l786ng_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int w83l786ng_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); -static int w83l786ng_remove(struct i2c_client *client); +static int w83l786ng_attach_adapter(struct i2c_adapter *adapter); +static int w83l786ng_detect(struct i2c_adapter *adapter, int address, int kind); +static int w83l786ng_detach_client(struct i2c_client *client); static void w83l786ng_init_client(struct i2c_client *client); static struct w83l786ng_data *w83l786ng_update_device(struct device *dev); -static const struct i2c_device_id w83l786ng_id[] = { - { "w83l786ng", w83l786ng }, - { } -}; -MODULE_DEVICE_TABLE(i2c, w83l786ng_id); - static struct i2c_driver w83l786ng_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "w83l786ng", }, - .probe = w83l786ng_probe, - .remove = w83l786ng_remove, - .id_table = w83l786ng_id, - .detect = w83l786ng_detect, - .address_data = &addr_data, + .attach_adapter = w83l786ng_attach_adapter, + .detach_client = w83l786ng_detach_client, }; static u8 @@ -586,15 +575,42 @@ static const struct attribute_group w83l786ng_group = { }; static int -w83l786ng_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +w83l786ng_attach_adapter(struct i2c_adapter *adapter) { - struct i2c_adapter *adapter = client->adapter; + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, w83l786ng_detect); +} + +static int +w83l786ng_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct device *dev; + struct w83l786ng_data *data; + int i, err = 0; + u8 reg_tmp; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - return -ENODEV; + goto exit; + } + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access w83l786ng_{read,write}_value. */ + + if (!(data = kzalloc(sizeof(struct w83l786ng_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; } + client = &data->client; + dev = &client->dev; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &w83l786ng_driver; + /* * Now we do the remaining detection. A negative kind means that * the driver was loaded with no force parameter (default), so we @@ -611,8 +627,8 @@ w83l786ng_detect(struct i2c_client *client, int kind, W83L786NG_REG_CONFIG) & 0x80) != 0x00)) { dev_dbg(&adapter->dev, "W83L786NG detection failed at 0x%02x.\n", - client->addr); - return -ENODEV; + address); + goto exit_free; } } @@ -635,32 +651,18 @@ w83l786ng_detect(struct i2c_client *client, int kind, dev_info(&adapter->dev, "Unsupported chip (man_id=0x%04X, " "chip_id=0x%02X).\n", man_id, chip_id); - return -ENODEV; + goto exit_free; } } - strlcpy(info->type, "w83l786ng", I2C_NAME_SIZE); - - return 0; -} - -static int -w83l786ng_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct device *dev = &client->dev; - struct w83l786ng_data *data; - int i, err = 0; - u8 reg_tmp; - - data = kzalloc(sizeof(struct w83l786ng_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); + /* Fill in the remaining client fields and put into the global list */ + strlcpy(client->name, "w83l786ng", I2C_NAME_SIZE); mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; + /* Initialize the chip */ w83l786ng_init_client(client); @@ -691,19 +693,25 @@ w83l786ng_probe(struct i2c_client *client, const struct i2c_device_id *id) exit_remove: sysfs_remove_group(&client->dev.kobj, &w83l786ng_group); + i2c_detach_client(client); +exit_free: kfree(data); exit: return err; } static int -w83l786ng_remove(struct i2c_client *client) +w83l786ng_detach_client(struct i2c_client *client) { struct w83l786ng_data *data = i2c_get_clientdata(client); + int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &w83l786ng_group); + if ((err = i2c_detach_client(client))) + return err; + kfree(data); return 0; diff --git a/trunk/drivers/i2c/busses/i2c-amd756-s4882.c b/trunk/drivers/i2c/busses/i2c-amd756-s4882.c index 72872d1e63ef..2f150e33c74c 100644 --- a/trunk/drivers/i2c/busses/i2c-amd756-s4882.c +++ b/trunk/drivers/i2c/busses/i2c-amd756-s4882.c @@ -155,16 +155,6 @@ static int __init amd756_s4882_init(void) int i, error; union i2c_smbus_data ioconfig; - /* Configure the PCA9556 multiplexer */ - ioconfig.byte = 0x00; /* All I/O to output mode */ - error = i2c_smbus_xfer(&amd756_smbus, 0x18, 0, I2C_SMBUS_WRITE, 0x03, - I2C_SMBUS_BYTE_DATA, &ioconfig); - if (error) { - dev_err(&amd756_smbus.dev, "PCA9556 configuration failed\n"); - error = -EIO; - goto ERROR0; - } - /* Unregister physical bus */ error = i2c_del_adapter(&amd756_smbus); if (error) { @@ -208,11 +198,22 @@ static int __init amd756_s4882_init(void) s4882_algo[3].smbus_xfer = amd756_access_virt3; s4882_algo[4].smbus_xfer = amd756_access_virt4; + /* Configure the PCA9556 multiplexer */ + ioconfig.byte = 0x00; /* All I/O to output mode */ + error = amd756_smbus.algo->smbus_xfer(&amd756_smbus, 0x18, 0, + I2C_SMBUS_WRITE, 0x03, + I2C_SMBUS_BYTE_DATA, &ioconfig); + if (error) { + dev_err(&amd756_smbus.dev, "PCA9556 configuration failed\n"); + error = -EIO; + goto ERROR3; + } + /* Register virtual adapters */ for (i = 0; i < 5; i++) { error = i2c_add_adapter(s4882_adapter+i); if (error) { - printk(KERN_ERR "i2c-amd756-s4882: " + dev_err(&amd756_smbus.dev, "Virtual adapter %d registration " "failed, module not inserted\n", i); for (i--; i >= 0; i--) @@ -251,8 +252,8 @@ static void __exit amd756_s4882_exit(void) /* Restore physical bus */ if (i2c_add_adapter(&amd756_smbus)) - printk(KERN_ERR "i2c-amd756-s4882: " - "Physical bus restoration failed\n"); + dev_err(&amd756_smbus.dev, "Physical bus restoration " + "failed\n"); } MODULE_AUTHOR("Jean Delvare "); diff --git a/trunk/drivers/i2c/busses/i2c-nforce2-s4985.c b/trunk/drivers/i2c/busses/i2c-nforce2-s4985.c index d1a4cbcf2aa4..6a8995dfd0bb 100644 --- a/trunk/drivers/i2c/busses/i2c-nforce2-s4985.c +++ b/trunk/drivers/i2c/busses/i2c-nforce2-s4985.c @@ -150,16 +150,6 @@ static int __init nforce2_s4985_init(void) int i, error; union i2c_smbus_data ioconfig; - /* Configure the PCA9556 multiplexer */ - ioconfig.byte = 0x00; /* All I/O to output mode */ - error = i2c_smbus_xfer(nforce2_smbus, 0x18, 0, I2C_SMBUS_WRITE, 0x03, - I2C_SMBUS_BYTE_DATA, &ioconfig); - if (error) { - dev_err(&nforce2_smbus->dev, "PCA9556 configuration failed\n"); - error = -EIO; - goto ERROR0; - } - /* Unregister physical bus */ if (!nforce2_smbus) return -ENODEV; @@ -201,13 +191,24 @@ static int __init nforce2_s4985_init(void) s4985_algo[3].smbus_xfer = nforce2_access_virt3; s4985_algo[4].smbus_xfer = nforce2_access_virt4; + /* Configure the PCA9556 multiplexer */ + ioconfig.byte = 0x00; /* All I/O to output mode */ + error = nforce2_smbus->algo->smbus_xfer(nforce2_smbus, 0x18, 0, + I2C_SMBUS_WRITE, 0x03, + I2C_SMBUS_BYTE_DATA, &ioconfig); + if (error) { + dev_err(&nforce2_smbus->dev, "PCA9556 configuration failed\n"); + error = -EIO; + goto ERROR3; + } + /* Register virtual adapters */ for (i = 0; i < 5; i++) { error = i2c_add_adapter(s4985_adapter + i); if (error) { - printk(KERN_ERR "i2c-nforce2-s4985: " - "Virtual adapter %d registration " - "failed, module not inserted\n", i); + dev_err(&nforce2_smbus->dev, + "Virtual adapter %d registration " + "failed, module not inserted\n", i); for (i--; i >= 0; i--) i2c_del_adapter(s4985_adapter + i); goto ERROR3; @@ -244,8 +245,8 @@ static void __exit nforce2_s4985_exit(void) /* Restore physical bus */ if (i2c_add_adapter(nforce2_smbus)) - printk(KERN_ERR "i2c-nforce2-s4985: " - "Physical bus restoration failed\n"); + dev_err(&nforce2_smbus->dev, "Physical bus restoration " + "failed\n"); } MODULE_AUTHOR("Jean Delvare "); diff --git a/trunk/drivers/i2c/chips/eeprom.c b/trunk/drivers/i2c/chips/eeprom.c index 2c27193aeaa0..373ea8d8fe8f 100644 --- a/trunk/drivers/i2c/chips/eeprom.c +++ b/trunk/drivers/i2c/chips/eeprom.c @@ -47,6 +47,7 @@ enum eeprom_nature { /* Each client has this additional data */ struct eeprom_data { + struct i2c_client client; struct mutex update_lock; u8 valid; /* bitfield, bit!=0 if slice is valid */ unsigned long last_updated[8]; /* In jiffies, 8 slices */ @@ -55,6 +56,19 @@ struct eeprom_data { }; +static int eeprom_attach_adapter(struct i2c_adapter *adapter); +static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind); +static int eeprom_detach_client(struct i2c_client *client); + +/* This is the driver that will be inserted */ +static struct i2c_driver eeprom_driver = { + .driver = { + .name = "eeprom", + }, + .attach_adapter = eeprom_attach_adapter, + .detach_client = eeprom_detach_client, +}; + static void eeprom_update_client(struct i2c_client *client, u8 slice) { struct eeprom_data *data = i2c_get_clientdata(client); @@ -134,17 +148,25 @@ static struct bin_attribute eeprom_attr = { .read = eeprom_read, }; -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int eeprom_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int eeprom_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & (I2C_CLASS_DDC | I2C_CLASS_SPD))) + return 0; + return i2c_probe(adapter, &addr_data, eeprom_detect); +} + +/* This function is called by i2c_probe */ +static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = client->adapter; + struct i2c_client *client; + struct eeprom_data *data; + int err = 0; /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all addresses 0x50-0x57, but we only care about 0x50. So decline attaching to addresses >= 0x51 on DDC buses */ - if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51) - return -ENODEV; + if (!(adapter->class & I2C_CLASS_SPD) && address >= 0x51) + goto exit; /* There are four ways we can read the EEPROM data: (1) I2C block reads (faster, but unsupported by most adapters) @@ -155,33 +177,32 @@ static int eeprom_detect(struct i2c_client *client, int kind, because all known adapters support one of the first two. */ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA) && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) - return -ENODEV; - - strlcpy(info->type, "eeprom", I2C_NAME_SIZE); - - return 0; -} - -static int eeprom_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct i2c_adapter *adapter = client->adapter; - struct eeprom_data *data; - int err; + goto exit; if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { err = -ENOMEM; goto exit; } + client = &data->client; memset(data->data, 0xff, EEPROM_SIZE); i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &eeprom_driver; + + /* Fill in the remaining client fields */ + strlcpy(client->name, "eeprom", I2C_NAME_SIZE); mutex_init(&data->update_lock); data->nature = UNKNOWN; + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_kfree; + /* Detect the Vaio nature of EEPROMs. We use the "PCG-" or "VGN-" prefix as the signature. */ - if (client->addr == 0x57 + if (address == 0x57 && i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) { char name[4]; @@ -200,42 +221,33 @@ static int eeprom_probe(struct i2c_client *client, /* create the sysfs eeprom file */ err = sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr); if (err) - goto exit_kfree; + goto exit_detach; return 0; +exit_detach: + i2c_detach_client(client); exit_kfree: kfree(data); exit: return err; } -static int eeprom_remove(struct i2c_client *client) +static int eeprom_detach_client(struct i2c_client *client) { + int err; + sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); + + err = i2c_detach_client(client); + if (err) + return err; + kfree(i2c_get_clientdata(client)); return 0; } -static const struct i2c_device_id eeprom_id[] = { - { "eeprom", 0 }, - { } -}; - -static struct i2c_driver eeprom_driver = { - .driver = { - .name = "eeprom", - }, - .probe = eeprom_probe, - .remove = eeprom_remove, - .id_table = eeprom_id, - - .class = I2C_CLASS_DDC | I2C_CLASS_SPD, - .detect = eeprom_detect, - .address_data = &addr_data, -}; - static int __init eeprom_init(void) { return i2c_add_driver(&eeprom_driver); diff --git a/trunk/drivers/i2c/chips/max6875.c b/trunk/drivers/i2c/chips/max6875.c index 033d9d81ec8a..5a0285d8b6f9 100644 --- a/trunk/drivers/i2c/chips/max6875.c +++ b/trunk/drivers/i2c/chips/max6875.c @@ -53,7 +53,7 @@ I2C_CLIENT_INSMOD_1(max6875); /* Each client has this additional data */ struct max6875_data { - struct i2c_client *fake_client; + struct i2c_client client; struct mutex update_lock; u32 valid; @@ -61,6 +61,19 @@ struct max6875_data { unsigned long last_updated[USER_EEPROM_SLICES]; }; +static int max6875_attach_adapter(struct i2c_adapter *adapter); +static int max6875_detect(struct i2c_adapter *adapter, int address, int kind); +static int max6875_detach_client(struct i2c_client *client); + +/* This is the driver that will be inserted */ +static struct i2c_driver max6875_driver = { + .driver = { + .name = "max6875", + }, + .attach_adapter = max6875_attach_adapter, + .detach_client = max6875_detach_client, +}; + static void max6875_update_slice(struct i2c_client *client, int slice) { struct max6875_data *data = i2c_get_clientdata(client); @@ -146,87 +159,96 @@ static struct bin_attribute user_eeprom_attr = { .read = max6875_read, }; -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int max6875_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int max6875_attach_adapter(struct i2c_adapter *adapter) { - struct i2c_adapter *adapter = client->adapter; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA - | I2C_FUNC_SMBUS_READ_BYTE)) - return -ENODEV; - - /* Only check even addresses */ - if (client->addr & 1) - return -ENODEV; - - strlcpy(info->type, "max6875", I2C_NAME_SIZE); - - return 0; + return i2c_probe(adapter, &addr_data, max6875_detect); } -static int max6875_probe(struct i2c_client *client, - const struct i2c_device_id *id) +/* This function is called by i2c_probe */ +static int max6875_detect(struct i2c_adapter *adapter, int address, int kind) { + struct i2c_client *real_client; + struct i2c_client *fake_client; struct max6875_data *data; int err; + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA + | I2C_FUNC_SMBUS_READ_BYTE)) + return 0; + + /* Only check even addresses */ + if (address & 1) + return 0; + if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL))) return -ENOMEM; /* A fake client is created on the odd address */ - data->fake_client = i2c_new_dummy(client->adapter, client->addr + 1); - if (!data->fake_client) { + if (!(fake_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { err = -ENOMEM; - goto exit_kfree; + goto exit_kfree1; } /* Init real i2c_client */ - i2c_set_clientdata(client, data); + real_client = &data->client; + i2c_set_clientdata(real_client, data); + real_client->addr = address; + real_client->adapter = adapter; + real_client->driver = &max6875_driver; + strlcpy(real_client->name, "max6875", I2C_NAME_SIZE); mutex_init(&data->update_lock); - err = sysfs_create_bin_file(&client->dev.kobj, &user_eeprom_attr); + /* Init fake client data */ + i2c_set_clientdata(fake_client, NULL); + fake_client->addr = address | 1; + fake_client->adapter = adapter; + fake_client->driver = &max6875_driver; + strlcpy(fake_client->name, "max6875 subclient", I2C_NAME_SIZE); + + if ((err = i2c_attach_client(real_client)) != 0) + goto exit_kfree2; + + if ((err = i2c_attach_client(fake_client)) != 0) + goto exit_detach1; + + err = sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr); if (err) - goto exit_remove_fake; + goto exit_detach2; return 0; -exit_remove_fake: - i2c_unregister_device(data->fake_client); -exit_kfree: +exit_detach2: + i2c_detach_client(fake_client); +exit_detach1: + i2c_detach_client(real_client); +exit_kfree2: + kfree(fake_client); +exit_kfree1: kfree(data); return err; } -static int max6875_remove(struct i2c_client *client) +/* Will be called for both the real client and the fake client */ +static int max6875_detach_client(struct i2c_client *client) { + int err; struct max6875_data *data = i2c_get_clientdata(client); - i2c_unregister_device(data->fake_client); + /* data is NULL for the fake client */ + if (data) + sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr); - sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr); - kfree(data); + err = i2c_detach_client(client); + if (err) + return err; + if (data) /* real client */ + kfree(data); + else /* fake client */ + kfree(client); return 0; } -static const struct i2c_device_id max6875_id[] = { - { "max6875", 0 }, - { } -}; - -static struct i2c_driver max6875_driver = { - .driver = { - .name = "max6875", - }, - .probe = max6875_probe, - .remove = max6875_remove, - .id_table = max6875_id, - - .detect = max6875_detect, - .address_data = &addr_data, -}; - static int __init max6875_init(void) { return i2c_add_driver(&max6875_driver); diff --git a/trunk/drivers/i2c/chips/pca9539.c b/trunk/drivers/i2c/chips/pca9539.c index 270de4e56a81..58ab7f26be26 100644 --- a/trunk/drivers/i2c/chips/pca9539.c +++ b/trunk/drivers/i2c/chips/pca9539.c @@ -14,8 +14,8 @@ #include #include -/* Addresses to scan: none, device is not autodetected */ -static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; +/* Addresses to scan */ +static unsigned short normal_i2c[] = {0x74, 0x75, 0x76, 0x77, I2C_CLIENT_END}; /* Insmod parameters */ I2C_CLIENT_INSMOD_1(pca9539); @@ -32,6 +32,23 @@ enum pca9539_cmd PCA9539_DIRECTION_1 = 7, }; +static int pca9539_attach_adapter(struct i2c_adapter *adapter); +static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind); +static int pca9539_detach_client(struct i2c_client *client); + +/* This is the driver that will be inserted */ +static struct i2c_driver pca9539_driver = { + .driver = { + .name = "pca9539", + }, + .attach_adapter = pca9539_attach_adapter, + .detach_client = pca9539_detach_client, +}; + +struct pca9539_data { + struct i2c_client client; +}; + /* following are the sysfs callback functions */ static ssize_t pca9539_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -88,50 +105,76 @@ static struct attribute_group pca9539_defattr_group = { .attrs = pca9539_attributes, }; -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int pca9539_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int pca9539_attach_adapter(struct i2c_adapter *adapter) { - struct i2c_adapter *adapter = client->adapter; + return i2c_probe(adapter, &addr_data, pca9539_detect); +} + +/* This function is called by i2c_probe */ +static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct pca9539_data *data; + int err = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; + goto exit; + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. */ + if (!(data = kzalloc(sizeof(struct pca9539_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &pca9539_driver; + + if (kind < 0) { + /* Detection: the pca9539 only has 8 registers (0-7). + A read of 7 should succeed, but a read of 8 should fail. */ + if ((i2c_smbus_read_byte_data(client, 7) < 0) || + (i2c_smbus_read_byte_data(client, 8) >= 0)) + goto exit_kfree; + } + + strlcpy(client->name, "pca9539", I2C_NAME_SIZE); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_kfree; - strlcpy(info->type, "pca9539", I2C_NAME_SIZE); + /* Register sysfs hooks */ + err = sysfs_create_group(&client->dev.kobj, + &pca9539_defattr_group); + if (err) + goto exit_detach; return 0; -} -static int pca9539_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - /* Register sysfs hooks */ - return sysfs_create_group(&client->dev.kobj, - &pca9539_defattr_group); +exit_detach: + i2c_detach_client(client); +exit_kfree: + kfree(data); +exit: + return err; } -static int pca9539_remove(struct i2c_client *client) +static int pca9539_detach_client(struct i2c_client *client) { - sysfs_remove_group(&client->dev.kobj, &pca9539_defattr_group); - return 0; -} + int err; -static const struct i2c_device_id pca9539_id[] = { - { "pca9539", 0 }, - { } -}; + sysfs_remove_group(&client->dev.kobj, &pca9539_defattr_group); -static struct i2c_driver pca9539_driver = { - .driver = { - .name = "pca9539", - }, - .probe = pca9539_probe, - .remove = pca9539_remove, - .id_table = pca9539_id, + if ((err = i2c_detach_client(client))) + return err; - .detect = pca9539_detect, - .address_data = &addr_data, -}; + kfree(i2c_get_clientdata(client)); + return 0; +} static int __init pca9539_init(void) { diff --git a/trunk/drivers/i2c/chips/pcf8574.c b/trunk/drivers/i2c/chips/pcf8574.c index 6ec309894c88..1b3db2b3ada9 100644 --- a/trunk/drivers/i2c/chips/pcf8574.c +++ b/trunk/drivers/i2c/chips/pcf8574.c @@ -38,19 +38,37 @@ #include #include -/* Addresses to scan: none, device can't be detected */ -static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + I2C_CLIENT_END +}; /* Insmod parameters */ I2C_CLIENT_INSMOD_2(pcf8574, pcf8574a); /* Each client has this additional data */ struct pcf8574_data { + struct i2c_client client; + int write; /* Remember last written value */ }; +static int pcf8574_attach_adapter(struct i2c_adapter *adapter); +static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind); +static int pcf8574_detach_client(struct i2c_client *client); static void pcf8574_init_client(struct i2c_client *client); +/* This is the driver that will be inserted */ +static struct i2c_driver pcf8574_driver = { + .driver = { + .name = "pcf8574", + }, + .attach_adapter = pcf8574_attach_adapter, + .detach_client = pcf8574_detach_client, +}; + /* following are the sysfs callback functions */ static ssize_t show_read(struct device *dev, struct device_attribute *attr, char *buf) { @@ -101,22 +119,41 @@ static const struct attribute_group pcf8574_attr_group = { * Real code */ -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int pcf8574_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int pcf8574_attach_adapter(struct i2c_adapter *adapter) +{ + return i2c_probe(adapter, &addr_data, pcf8574_detect); +} + +/* This function is called by i2c_probe */ +static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_adapter *adapter = client->adapter; - const char *client_name; + struct i2c_client *client; + struct pcf8574_data *data; + int err = 0; + const char *client_name = ""; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) - return -ENODEV; + goto exit; + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. */ + if (!(data = kzalloc(sizeof(struct pcf8574_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &pcf8574_driver; /* Now, we would do the remaining detection. But the PCF8574 is plainly impossible to detect! Stupid chip. */ /* Determine the chip type */ if (kind <= 0) { - if (client->addr >= 0x38 && client->addr <= 0x3f) + if (address >= 0x38 && address <= 0x3f) kind = pcf8574a; else kind = pcf8574; @@ -126,43 +163,40 @@ static int pcf8574_detect(struct i2c_client *client, int kind, client_name = "pcf8574a"; else client_name = "pcf8574"; - strlcpy(info->type, client_name, I2C_NAME_SIZE); - - return 0; -} - -static int pcf8574_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct pcf8574_data *data; - int err; - - data = kzalloc(sizeof(struct pcf8574_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - i2c_set_clientdata(client, data); + /* Fill in the remaining client fields and put it into the global list */ + strlcpy(client->name, client_name, I2C_NAME_SIZE); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; + /* Initialize the PCF8574 chip */ pcf8574_init_client(client); /* Register sysfs hooks */ err = sysfs_create_group(&client->dev.kobj, &pcf8574_attr_group); if (err) - goto exit_free; + goto exit_detach; return 0; + exit_detach: + i2c_detach_client(client); exit_free: kfree(data); exit: return err; } -static int pcf8574_remove(struct i2c_client *client) +static int pcf8574_detach_client(struct i2c_client *client) { + int err; + sysfs_remove_group(&client->dev.kobj, &pcf8574_attr_group); + + if ((err = i2c_detach_client(client))) + return err; + kfree(i2c_get_clientdata(client)); return 0; } @@ -174,24 +208,6 @@ static void pcf8574_init_client(struct i2c_client *client) data->write = -EAGAIN; } -static const struct i2c_device_id pcf8574_id[] = { - { "pcf8574", 0 }, - { "pcf8574a", 0 }, - { } -}; - -static struct i2c_driver pcf8574_driver = { - .driver = { - .name = "pcf8574", - }, - .probe = pcf8574_probe, - .remove = pcf8574_remove, - .id_table = pcf8574_id, - - .detect = pcf8574_detect, - .address_data = &addr_data, -}; - static int __init pcf8574_init(void) { return i2c_add_driver(&pcf8574_driver); diff --git a/trunk/drivers/i2c/chips/pcf8575.c b/trunk/drivers/i2c/chips/pcf8575.c index 07fd7cb3c57d..3ea08ac0bfa3 100644 --- a/trunk/drivers/i2c/chips/pcf8575.c +++ b/trunk/drivers/i2c/chips/pcf8575.c @@ -32,8 +32,11 @@ #include /* kzalloc() */ #include /* sysfs_create_group() */ -/* Addresses to scan: none, device can't be detected */ -static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + I2C_CLIENT_END +}; /* Insmod parameters */ I2C_CLIENT_INSMOD; @@ -41,9 +44,24 @@ I2C_CLIENT_INSMOD; /* Each client has this additional data */ struct pcf8575_data { + struct i2c_client client; int write; /* last written value, or error code */ }; +static int pcf8575_attach_adapter(struct i2c_adapter *adapter); +static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind); +static int pcf8575_detach_client(struct i2c_client *client); + +/* This is the driver that will be inserted */ +static struct i2c_driver pcf8575_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "pcf8575", + }, + .attach_adapter = pcf8575_attach_adapter, + .detach_client = pcf8575_detach_client, +}; + /* following are the sysfs callback functions */ static ssize_t show_read(struct device *dev, struct device_attribute *attr, char *buf) @@ -108,77 +126,75 @@ static const struct attribute_group pcf8575_attr_group = { * Real code */ -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int pcf8575_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int pcf8575_attach_adapter(struct i2c_adapter *adapter) { - struct i2c_adapter *adapter = client->adapter; - - if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) - return -ENODEV; - - /* This is the place to detect whether the chip at the specified - address really is a PCF8575 chip. However, there is no method known - to detect whether an I2C chip is a PCF8575 or any other I2C chip. */ - - strlcpy(info->type, "pcf8575", I2C_NAME_SIZE); - - return 0; + return i2c_probe(adapter, &addr_data, pcf8575_detect); } -static int pcf8575_probe(struct i2c_client *client, - const struct i2c_device_id *id) +/* This function is called by i2c_probe */ +static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind) { + struct i2c_client *client; struct pcf8575_data *data; - int err; + int err = 0; + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) + goto exit; + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. */ data = kzalloc(sizeof(struct pcf8575_data), GFP_KERNEL); if (!data) { err = -ENOMEM; goto exit; } + client = &data->client; i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &pcf8575_driver; + strlcpy(client->name, "pcf8575", I2C_NAME_SIZE); data->write = -EAGAIN; + /* This is the place to detect whether the chip at the specified + address really is a PCF8575 chip. However, there is no method known + to detect whether an I2C chip is a PCF8575 or any other I2C chip. */ + + /* Tell the I2C layer a new client has arrived */ + err = i2c_attach_client(client); + if (err) + goto exit_free; + /* Register sysfs hooks */ err = sysfs_create_group(&client->dev.kobj, &pcf8575_attr_group); if (err) - goto exit_free; + goto exit_detach; return 0; +exit_detach: + i2c_detach_client(client); exit_free: kfree(data); exit: return err; } -static int pcf8575_remove(struct i2c_client *client) +static int pcf8575_detach_client(struct i2c_client *client) { + int err; + sysfs_remove_group(&client->dev.kobj, &pcf8575_attr_group); + + err = i2c_detach_client(client); + if (err) + return err; + kfree(i2c_get_clientdata(client)); return 0; } -static const struct i2c_device_id pcf8575_id[] = { - { "pcf8575", 0 }, - { } -}; - -static struct i2c_driver pcf8575_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "pcf8575", - }, - .probe = pcf8575_probe, - .remove = pcf8575_remove, - .id_table = pcf8575_id, - - .detect = pcf8575_detect, - .address_data = &addr_data, -}; - static int __init pcf8575_init(void) { return i2c_add_driver(&pcf8575_driver); diff --git a/trunk/drivers/i2c/chips/pcf8591.c b/trunk/drivers/i2c/chips/pcf8591.c index 16ce3e193776..db735379f22f 100644 --- a/trunk/drivers/i2c/chips/pcf8591.c +++ b/trunk/drivers/i2c/chips/pcf8591.c @@ -72,15 +72,28 @@ MODULE_PARM_DESC(input_mode, #define REG_TO_SIGNED(reg) (((reg) & 0x80)?((reg) - 256):(reg)) struct pcf8591_data { + struct i2c_client client; struct mutex update_lock; u8 control; u8 aout; }; +static int pcf8591_attach_adapter(struct i2c_adapter *adapter); +static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind); +static int pcf8591_detach_client(struct i2c_client *client); static void pcf8591_init_client(struct i2c_client *client); static int pcf8591_read_channel(struct device *dev, int channel); +/* This is the driver that will be inserted */ +static struct i2c_driver pcf8591_driver = { + .driver = { + .name = "pcf8591", + }, + .attach_adapter = pcf8591_attach_adapter, + .detach_client = pcf8591_detach_client, +}; + /* following are the sysfs callback functions */ #define show_in_channel(channel) \ static ssize_t show_in##channel##_input(struct device *dev, struct device_attribute *attr, char *buf) \ @@ -167,46 +180,58 @@ static const struct attribute_group pcf8591_attr_group_opt = { /* * Real code */ - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int pcf8591_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +static int pcf8591_attach_adapter(struct i2c_adapter *adapter) { - struct i2c_adapter *adapter = client->adapter; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE - | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) - return -ENODEV; - - /* Now, we would do the remaining detection. But the PCF8591 is plainly - impossible to detect! Stupid chip. */ - - strlcpy(info->type, "pcf8591", I2C_NAME_SIZE); - - return 0; + return i2c_probe(adapter, &addr_data, pcf8591_detect); } -static int pcf8591_probe(struct i2c_client *client, - const struct i2c_device_id *id) +/* This function is called by i2c_probe */ +static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind) { + struct i2c_client *client; struct pcf8591_data *data; - int err; + int err = 0; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE + | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) + goto exit; + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. */ if (!(data = kzalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) { err = -ENOMEM; goto exit; } + client = &data->client; i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &pcf8591_driver; + + /* Now, we would do the remaining detection. But the PCF8591 is plainly + impossible to detect! Stupid chip. */ + + /* Determine the chip type - only one kind supported! */ + if (kind <= 0) + kind = pcf8591; + + /* Fill in the remaining client fields and put it into the global + list */ + strlcpy(client->name, "pcf8591", I2C_NAME_SIZE); mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_kfree; + /* Initialize the PCF8591 chip */ pcf8591_init_client(client); /* Register sysfs hooks */ err = sysfs_create_group(&client->dev.kobj, &pcf8591_attr_group); if (err) - goto exit_kfree; + goto exit_detach; /* Register input2 if not in "two differential inputs" mode */ if (input_mode != 3) { @@ -227,16 +252,24 @@ static int pcf8591_probe(struct i2c_client *client, exit_sysfs_remove: sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt); sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group); +exit_detach: + i2c_detach_client(client); exit_kfree: kfree(data); exit: return err; } -static int pcf8591_remove(struct i2c_client *client) +static int pcf8591_detach_client(struct i2c_client *client) { + int err; + sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt); sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group); + + if ((err = i2c_detach_client(client))) + return err; + kfree(i2c_get_clientdata(client)); return 0; } @@ -283,25 +316,6 @@ static int pcf8591_read_channel(struct device *dev, int channel) return (10 * value); } -static const struct i2c_device_id pcf8591_id[] = { - { "pcf8591", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, pcf8591_id); - -static struct i2c_driver pcf8591_driver = { - .driver = { - .name = "pcf8591", - }, - .probe = pcf8591_probe, - .remove = pcf8591_remove, - .id_table = pcf8591_id, - - .class = I2C_CLASS_HWMON, /* Nearest choice */ - .detect = pcf8591_detect, - .address_data = &addr_data, -}; - static int __init pcf8591_init(void) { if (input_mode < 0 || input_mode > 3) { diff --git a/trunk/drivers/i2c/i2c-core.c b/trunk/drivers/i2c/i2c-core.c index 7608df83d6d1..0a79f7661017 100644 --- a/trunk/drivers/i2c/i2c-core.c +++ b/trunk/drivers/i2c/i2c-core.c @@ -654,10 +654,6 @@ int i2c_del_adapter(struct i2c_adapter *adap) dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); - /* Clear the device structure in case this adapter is ever going to be - added again */ - memset(&adap->dev, 0, sizeof(adap->dev)); - out_unlock: mutex_unlock(&core_lock); return res; diff --git a/trunk/drivers/ide/pci/it821x.c b/trunk/drivers/ide/pci/it821x.c index 6ab04115286b..cbf647202994 100644 --- a/trunk/drivers/ide/pci/it821x.c +++ b/trunk/drivers/ide/pci/it821x.c @@ -512,8 +512,14 @@ static void __devinit it821x_quirkproc(ide_drive_t *drive) } static struct ide_dma_ops it821x_pass_through_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, .dma_start = it821x_dma_start, .dma_end = it821x_dma_end, + .dma_test_irq = ide_dma_test_irq, + .dma_timeout = ide_dma_timeout, + .dma_lost_irq = ide_dma_lost_irq, }; /** diff --git a/trunk/drivers/misc/Kconfig b/trunk/drivers/misc/Kconfig index 1921b8dbb242..636af2862308 100644 --- a/trunk/drivers/misc/Kconfig +++ b/trunk/drivers/misc/Kconfig @@ -179,29 +179,17 @@ config FUJITSU_LAPTOP tristate "Fujitsu Laptop Extras" depends on X86 depends on ACPI - depends on INPUT depends on BACKLIGHT_CLASS_DEVICE ---help--- This is a driver for laptops built by Fujitsu: * P2xxx/P5xxx/S6xxx/S7xxx series Lifebooks * Possibly other Fujitsu laptop models - * Tested with S6410 and S7020 - It adds support for LCD brightness control and some hotkeys. + It adds support for LCD brightness control. If you have a Fujitsu laptop, say Y or M here. -config FUJITSU_LAPTOP_DEBUG - bool "Verbose debug mode for Fujitsu Laptop Extras" - depends on FUJITSU_LAPTOP - default n - ---help--- - Enables extra debug output from the fujitsu extras driver, at the - expense of a slight increase in driver size. - - If you are not sure, say N here. - config TC1100_WMI tristate "HP Compaq TC1100 Tablet WMI Extras (EXPERIMENTAL)" depends on X86 && !X86_64 @@ -231,23 +219,6 @@ config MSI_LAPTOP If you have an MSI S270 laptop, say Y or M here. -config COMPAL_LAPTOP - tristate "Compal Laptop Extras" - depends on X86 - depends on ACPI_EC - depends on BACKLIGHT_CLASS_DEVICE - ---help--- - This is a driver for laptops built by Compal: - - Compal FL90/IFL90 - Compal FL91/IFL91 - Compal FL92/JFL92 - Compal FT00/IFT00 - - It adds support for Bluetooth, WLAN and LCD brightness control. - - If you have an Compal FL9x/IFL9x/FT00 laptop, say Y or M here. - config SONY_LAPTOP tristate "Sony Laptop Extras" depends on X86 && ACPI diff --git a/trunk/drivers/misc/Makefile b/trunk/drivers/misc/Makefile index a6dac6a2e7e5..1952875a272e 100644 --- a/trunk/drivers/misc/Makefile +++ b/trunk/drivers/misc/Makefile @@ -5,11 +5,10 @@ obj- := misc.o # Dummy rule to force built-in.o to be made obj-$(CONFIG_IBM_ASM) += ibmasm/ obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/ +obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o +obj-$(CONFIG_ACER_WMI) += acer-wmi.o obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o -obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o -obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o -obj-$(CONFIG_ACER_WMI) += acer-wmi.o obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o diff --git a/trunk/drivers/misc/acer-wmi.c b/trunk/drivers/misc/acer-wmi.c index e7a3fe508dff..dd13a3749927 100644 --- a/trunk/drivers/misc/acer-wmi.c +++ b/trunk/drivers/misc/acer-wmi.c @@ -22,18 +22,18 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define ACER_WMI_VERSION "0.1" + #include #include #include #include #include -#include #include #include #include #include #include -#include #include @@ -87,7 +87,6 @@ struct acer_quirks { * Acer ACPI method GUIDs */ #define AMW0_GUID1 "67C3371D-95A3-4C37-BB61-DD47B491DAAB" -#define AMW0_GUID2 "431F16ED-0C2B-444C-B267-27DEB140CF9C" #define WMID_GUID1 "6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3" #define WMID_GUID2 "95764E09-FB56-4e83-B31A-37761F60994A" @@ -151,12 +150,6 @@ struct acer_data { int brightness; }; -struct acer_debug { - struct dentry *root; - struct dentry *devices; - u32 wmid_devices; -}; - /* Each low-level interface must define at least some of the following */ struct wmi_interface { /* The WMI device type */ @@ -167,9 +160,6 @@ struct wmi_interface { /* Private data for the current interface */ struct acer_data data; - - /* debugfs entries associated with this interface */ - struct acer_debug debug; }; /* The static interface pointer, points to the currently detected interface */ @@ -184,7 +174,7 @@ static struct wmi_interface *interface; struct quirk_entry { u8 wireless; u8 mailled; - s8 brightness; + u8 brightness; u8 bluetooth; }; @@ -208,10 +198,6 @@ static int dmi_matched(const struct dmi_system_id *dmi) static struct quirk_entry quirk_unknown = { }; -static struct quirk_entry quirk_acer_aspire_1520 = { - .brightness = -1, -}; - static struct quirk_entry quirk_acer_travelmate_2490 = { .mailled = 1, }; @@ -221,29 +207,7 @@ static struct quirk_entry quirk_medion_md_98300 = { .wireless = 1, }; -static struct quirk_entry quirk_fujitsu_amilo_li_1718 = { - .wireless = 2, -}; - static struct dmi_system_id acer_quirks[] = { - { - .callback = dmi_matched, - .ident = "Acer Aspire 1360", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"), - }, - .driver_data = &quirk_acer_aspire_1520, - }, - { - .callback = dmi_matched, - .ident = "Acer Aspire 1520", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1520"), - }, - .driver_data = &quirk_acer_aspire_1520, - }, { .callback = dmi_matched, .ident = "Acer Aspire 3100", @@ -334,15 +298,6 @@ static struct dmi_system_id acer_quirks[] = { }, .driver_data = &quirk_acer_travelmate_2490, }, - { - .callback = dmi_matched, - .ident = "Fujitsu Siemens Amilo Li 1718", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), - DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Li 1718"), - }, - .driver_data = &quirk_fujitsu_amilo_li_1718, - }, { .callback = dmi_matched, .ident = "Medion MD 98300", @@ -438,12 +393,6 @@ struct wmi_interface *iface) return AE_ERROR; *value = result & 0x1; return AE_OK; - case 2: - err = ec_read(0x71, &result); - if (err) - return AE_ERROR; - *value = result & 0x1; - return AE_OK; default: err = ec_read(0xA, &result); if (err) @@ -557,15 +506,6 @@ static acpi_status AMW0_set_capabilities(void) struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; - /* - * On laptops with this strange GUID (non Acer), normal probing doesn't - * work. - */ - if (wmi_has_guid(AMW0_GUID2)) { - interface->capability |= ACER_CAP_WIRELESS; - return AE_OK; - } - args.eax = ACER_AMW0_WRITE; args.ecx = args.edx = 0; @@ -612,8 +552,7 @@ static acpi_status AMW0_set_capabilities(void) * appear to use the same EC register for brightness, even if they * differ for wireless, etc */ - if (quirks->brightness >= 0) - interface->capability |= ACER_CAP_BRIGHTNESS; + interface->capability |= ACER_CAP_BRIGHTNESS; return AE_OK; } @@ -868,15 +807,7 @@ static int read_brightness(struct backlight_device *bd) static int update_bl_status(struct backlight_device *bd) { - 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); - + set_u32(bd->props.brightness, ACER_CAP_BRIGHTNESS); return 0; } @@ -898,9 +829,8 @@ static int __devinit acer_backlight_init(struct device *dev) acer_backlight_device = bd; - bd->props.power = FB_BLANK_UNBLANK; - bd->props.brightness = max_brightness; bd->props.max_brightness = max_brightness; + bd->props.brightness = read_brightness(NULL); backlight_update_status(bd); return 0; } @@ -963,28 +893,6 @@ static ssize_t show_interface(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(interface, S_IWUGO | S_IRUGO | S_IWUSR, show_interface, NULL); -/* - * debugfs functions - */ -static u32 get_wmid_devices(void) -{ - struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; - union acpi_object *obj; - acpi_status status; - - status = wmi_query_block(WMID_GUID2, 1, &out); - if (ACPI_FAILURE(status)) - return 0; - - obj = (union acpi_object *) out.pointer; - if (obj && obj->type == ACPI_TYPE_BUFFER && - obj->buffer.length == sizeof(u32)) { - return *((u32 *) obj->buffer.pointer); - } else { - return 0; - } -} - /* * Platform device */ @@ -1144,40 +1052,12 @@ static int create_sysfs(void) return retval; } -static void remove_debugfs(void) -{ - debugfs_remove(interface->debug.devices); - debugfs_remove(interface->debug.root); -} - -static int create_debugfs(void) -{ - interface->debug.root = debugfs_create_dir("acer-wmi", NULL); - if (!interface->debug.root) { - printk(ACER_ERR "Failed to create debugfs directory"); - return -ENOMEM; - } - - interface->debug.devices = debugfs_create_u32("devices", S_IRUGO, - interface->debug.root, - &interface->debug.wmid_devices); - if (!interface->debug.devices) - goto error_debugfs; - - return 0; - -error_debugfs: - remove_debugfs(); - return -ENOMEM; -} - static int __init acer_wmi_init(void) { int err; - printk(ACER_INFO "Acer Laptop ACPI-WMI Extras\n"); - - find_quirks(); + printk(ACER_INFO "Acer Laptop ACPI-WMI Extras version %s\n", + ACER_WMI_VERSION); /* * Detect which ACPI-WMI interface we're using. @@ -1212,6 +1092,8 @@ static int __init acer_wmi_init(void) if (wmi_has_guid(AMW0_GUID1)) AMW0_find_mailled(); + find_quirks(); + if (!interface) { printk(ACER_ERR "No or unsupported WMI interface, unable to " "load\n"); @@ -1229,13 +1111,6 @@ static int __init acer_wmi_init(void) if (err) return err; - if (wmi_has_guid(WMID_GUID2)) { - interface->debug.wmid_devices = get_wmid_devices(); - err = create_debugfs(); - if (err) - return err; - } - /* Override any initial settings with values from the commandline */ acer_commandline_init(); diff --git a/trunk/drivers/misc/compal-laptop.c b/trunk/drivers/misc/compal-laptop.c deleted file mode 100644 index 344b790a6253..000000000000 --- a/trunk/drivers/misc/compal-laptop.c +++ /dev/null @@ -1,404 +0,0 @@ -/*-*-linux-c-*-*/ - -/* - Copyright (C) 2008 Cezary Jackiewicz - - based on MSI driver - - Copyright (C) 2006 Lennart Poettering - - 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 -#include -#include -#include -#include -#include -#include -#include - -#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:*"); diff --git a/trunk/drivers/misc/eeepc-laptop.c b/trunk/drivers/misc/eeepc-laptop.c index 9e8d79e7e9f4..6d727609097f 100644 --- a/trunk/drivers/misc/eeepc-laptop.c +++ b/trunk/drivers/misc/eeepc-laptop.c @@ -87,7 +87,7 @@ enum { CM_ASL_LID }; -static const char *cm_getv[] = { +const char *cm_getv[] = { "WLDG", NULL, NULL, NULL, "CAMG", NULL, NULL, NULL, NULL, "PBLG", NULL, NULL, @@ -96,7 +96,7 @@ static const char *cm_getv[] = { "CRDG", "LIDG" }; -static const char *cm_setv[] = { +const char *cm_setv[] = { "WLDS", NULL, NULL, NULL, "CAMS", NULL, NULL, NULL, "SDSP", "PBLS", "HDPS", NULL, diff --git a/trunk/drivers/misc/fujitsu-laptop.c b/trunk/drivers/misc/fujitsu-laptop.c index 7a1ef6c262de..6d14e8fe1537 100644 --- a/trunk/drivers/misc/fujitsu-laptop.c +++ b/trunk/drivers/misc/fujitsu-laptop.c @@ -1,14 +1,12 @@ /*-*-linux-c-*-*/ /* - Copyright (C) 2007,2008 Jonathan Woithe - Copyright (C) 2008 Peter Gruber + Copyright (C) 2007 Jonathan Woithe Based on earlier work: Copyright (C) 2003 Shane Spencer Adrian Yee - Templated from msi-laptop.c and thinkpad_acpi.c which is copyright - by its respective authors. + Templated from msi-laptop.c which is copyright by its respective authors. 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 @@ -41,17 +39,8 @@ * registers itself in the Linux backlight control subsystem and is * available to userspace under /sys/class/backlight/fujitsu-laptop/. * - * 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. - * + * This driver has been tested on a Fujitsu Lifebook S7020. It should + * work on most P-series and S-series Lifebooks, but YMMV. */ #include @@ -60,105 +49,30 @@ #include #include #include -#include -#include -#include #include -#define FUJITSU_DRIVER_VERSION "0.4.2" +#define FUJITSU_DRIVER_VERSION "0.3" #define FUJITSU_LCD_N_LEVELS 8 #define ACPI_FUJITSU_CLASS "fujitsu" #define ACPI_FUJITSU_HID "FUJ02B1" -#define ACPI_FUJITSU_DRIVER_NAME "Fujitsu laptop FUJ02B1 ACPI brightness driver" +#define ACPI_FUJITSU_DRIVER_NAME "Fujitsu laptop FUJ02B1 ACPI extras driver" #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 { acpi_handle acpi_handle; - struct acpi_device *dev; - struct input_dev *input; - char phys[32]; struct backlight_device *bl_device; struct platform_device *pf_device; - unsigned int max_brightness; + unsigned long fuj02b1_state; unsigned int brightness_changed; unsigned int brightness_level; }; 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 */ -}; -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 */ +/* Hardware access */ static int set_lcd_level(int level) { @@ -167,10 +81,7 @@ static int set_lcd_level(int level) struct acpi_object_list arg_list = { 1, &arg0 }; acpi_handle handle = NULL; - vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBLL [%d]\n", - level); - - if (level < 0 || level >= fujitsu->max_brightness) + if (level < 0 || level >= FUJITSU_LCD_N_LEVELS) return -EINVAL; if (!fujitsu) @@ -178,38 +89,7 @@ static int set_lcd_level(int level) status = acpi_get_handle(fujitsu->acpi_handle, "SBLL", &handle); if (ACPI_FAILURE(status)) { - 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"); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SBLL not present\n")); return -ENODEV; } @@ -227,52 +107,13 @@ static int get_lcd_level(void) unsigned long state = 0; acpi_status status = AE_OK; - vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLL\n"); - + // Get the Brightness status = acpi_evaluate_integer(fujitsu->acpi_handle, "GBLL", NULL, &state); if (status < 0) return status; - 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->fuj02b1_state = state; fujitsu->brightness_level = state & 0x0fffffff; if (state & 0x80000000) @@ -287,18 +128,12 @@ static int get_lcd_level_alt(void) static int bl_get_brightness(struct backlight_device *b) { - if (use_alt_lcd_levels) - return get_lcd_level_alt(); - else - return get_lcd_level(); + return get_lcd_level(); } static int bl_update_status(struct backlight_device *b) { - if (use_alt_lcd_levels) - return set_lcd_level_alt(b->props.brightness); - else - return set_lcd_level(b->props.brightness); + return set_lcd_level(b->props.brightness); } static struct backlight_ops fujitsubl_ops = { @@ -306,35 +141,7 @@ static struct backlight_ops fujitsubl_ops = { .update_status = bl_update_status, }; -/* 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); -} +/* Platform device */ static ssize_t show_lcd_level(struct device *dev, struct device_attribute *attr, char *buf) @@ -342,10 +149,7 @@ static ssize_t show_lcd_level(struct device *dev, int ret; - if (use_alt_lcd_levels) - ret = get_lcd_level_alt(); - else - ret = get_lcd_level(); + ret = get_lcd_level(); if (ret < 0) return ret; @@ -360,61 +164,19 @@ static ssize_t store_lcd_level(struct device *dev, int level, ret; if (sscanf(buf, "%i", &level) != 1 - || (level < 0 || level >= fujitsu->max_brightness)) + || (level < 0 || level >= FUJITSU_LCD_N_LEVELS)) return -EINVAL; - 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(); + ret = set_lcd_level(level); if (ret < 0) return ret; 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 struct attribute *fujitsupf_attributes[] = { - &dev_attr_brightness_changed.attr, - &dev_attr_max_brightness.attr, &dev_attr_lcd_level.attr, NULL }; @@ -430,52 +192,14 @@ static struct platform_driver fujitsupf_driver = { } }; -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 */ +/* ACPI device */ static int acpi_fujitsu_add(struct acpi_device *device) { - acpi_status status; - acpi_handle handle; int result = 0; int state = 0; - struct input_dev *input; - int error; + + ACPI_FUNCTION_TRACE("acpi_fujitsu_add"); if (!device) return -EINVAL; @@ -485,42 +209,10 @@ static int acpi_fujitsu_add(struct acpi_device *device) sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS); 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); if (result) { - printk(KERN_ERR "Error reading power state\n"); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error reading power state\n")); goto end; } @@ -528,373 +220,22 @@ static int acpi_fujitsu_add(struct acpi_device *device) acpi_device_name(device), acpi_device_bid(device), !device->power.state ? "on" : "off"); - 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: + end: return result; } static int acpi_fujitsu_remove(struct acpi_device *device, int type) { - acpi_status status; - struct fujitsu_t *fujitsu = NULL; + ACPI_FUNCTION_TRACE("acpi_fujitsu_remove"); if (!device || !acpi_driver_data(device)) 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; 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[] = { {ACPI_FUJITSU_HID, 0}, {"", 0}, @@ -910,24 +251,11 @@ static struct acpi_driver acpi_fujitsu_driver = { }, }; -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, - }, -}; +/* Initialization */ static int __init fujitsu_init(void) { - int ret, result, max_brightness; + int ret, result; if (acpi_disabled) return -ENODEV; @@ -943,6 +271,19 @@ static int __init fujitsu_init(void) 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 */ fujitsu->pf_device = platform_device_alloc("fujitsu-laptop", -1); @@ -961,68 +302,28 @@ static int __init fujitsu_init(void) if (ret) 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 " successfully loaded.\n"); return 0; -fail_hotkey1: - - kfree(fujitsu_hotkey); - -fail_hotkey: - - platform_driver_unregister(&fujitsupf_driver); - -fail_backlight: - - backlight_device_unregister(fujitsu->bl_device); - -fail_platform_device2: + fail_platform_device2: platform_device_del(fujitsu->pf_device); -fail_platform_device1: + fail_platform_device1: platform_device_put(fujitsu->pf_device); -fail_platform_driver: + fail_platform_driver: - acpi_bus_unregister_driver(&acpi_fujitsu_driver); + platform_driver_unregister(&fujitsupf_driver); + + fail_backlight: + + backlight_device_unregister(fujitsu->bl_device); -fail_acpi: + fail_acpi: kfree(fujitsu); @@ -1041,43 +342,19 @@ static void __exit fujitsu_cleanup(void) kfree(fujitsu); - acpi_bus_unregister_driver(&acpi_fujitsu_hotkey_driver); - - kfree(fujitsu_hotkey); - printk(KERN_INFO "fujitsu-laptop: driver unloaded.\n"); } module_init(fujitsu_init); module_exit(fujitsu_cleanup); -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_AUTHOR("Jonathan Woithe"); MODULE_DESCRIPTION("Fujitsu laptop extras support"); MODULE_VERSION(FUJITSU_DRIVER_VERSION); 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[] = { { .id = "FUJ02bf" }, - { .id = "FUJ02B1" }, - { .id = "FUJ02E3" }, { .id = "" } }; MODULE_DEVICE_TABLE(pnp, pnp_ids); diff --git a/trunk/drivers/pci/pci-acpi.c b/trunk/drivers/pci/pci-acpi.c index dab9d471914c..9d6fc8e6285d 100644 --- a/trunk/drivers/pci/pci-acpi.c +++ b/trunk/drivers/pci/pci-acpi.c @@ -293,11 +293,13 @@ EXPORT_SYMBOL(pci_osc_control_set); * choose highest power _SxD or any lower power */ -static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev) +static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev, + pm_message_t state) { int acpi_state; - acpi_state = acpi_pm_device_sleep_state(&pdev->dev, NULL); + acpi_state = acpi_pm_device_sleep_state(&pdev->dev, + device_may_wakeup(&pdev->dev), NULL); if (acpi_state < 0) return PCI_POWER_ERROR; diff --git a/trunk/drivers/pci/pci.c b/trunk/drivers/pci/pci.c index 75c60239cadd..e4548ab2a93c 100644 --- a/trunk/drivers/pci/pci.c +++ b/trunk/drivers/pci/pci.c @@ -508,7 +508,7 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) return 0; } -pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev); +pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state); /** * pci_choose_state - Choose the power state of a PCI device @@ -528,7 +528,7 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) return PCI_D0; if (platform_pci_choose_state) { - ret = platform_pci_choose_state(dev); + ret = platform_pci_choose_state(dev, state); if (ret != PCI_POWER_ERROR) return ret; } diff --git a/trunk/drivers/pci/pci.h b/trunk/drivers/pci/pci.h index 312daff834b6..00408c97e5fc 100644 --- a/trunk/drivers/pci/pci.h +++ b/trunk/drivers/pci/pci.h @@ -6,7 +6,8 @@ extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev); extern void pci_cleanup_rom(struct pci_dev *dev); /* Firmware callbacks */ -extern pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev); +extern pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev, + pm_message_t state); extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state); diff --git a/trunk/drivers/pnp/base.h b/trunk/drivers/pnp/base.h index e3fa9a2d9a3d..886dac823ed6 100644 --- a/trunk/drivers/pnp/base.h +++ b/trunk/drivers/pnp/base.h @@ -1,8 +1,3 @@ -/* - * Copyright (C) 2008 Hewlett-Packard Development Company, L.P. - * Bjorn Helgaas - */ - extern spinlock_t pnp_lock; void *pnp_alloc(long size); @@ -24,118 +19,22 @@ void pnp_remove_card(struct pnp_card *card); int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev); void pnp_remove_card_device(struct pnp_dev *dev); -struct pnp_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); - +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); void pnp_init_resources(struct pnp_dev *dev); void pnp_fixup_device(struct pnp_dev *dev); -void pnp_free_options(struct pnp_dev *dev); +void pnp_free_option(struct pnp_option *option); int __pnp_add_device(struct pnp_dev *dev); void __pnp_remove_device(struct pnp_dev *dev); @@ -144,18 +43,29 @@ int pnp_check_mem(struct pnp_dev *dev, struct resource *res); int pnp_check_irq(struct pnp_dev *dev, struct resource *res); int pnp_check_dma(struct pnp_dev *dev, struct resource *res); -char *pnp_resource_type_name(struct resource *res); void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc); -void pnp_free_resources(struct pnp_dev *dev); -int pnp_resource_type(struct resource *res); +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 struct pnp_resource { - struct list_head list; struct resource res; + unsigned int index; /* ISAPNP config register index */ }; -void pnp_free_resource(struct pnp_resource *pnp_res); +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]; +}; struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, int flags); diff --git a/trunk/drivers/pnp/core.c b/trunk/drivers/pnp/core.c index a411582bcd72..20771b7d4482 100644 --- a/trunk/drivers/pnp/core.c +++ b/trunk/drivers/pnp/core.c @@ -99,28 +99,14 @@ static void pnp_free_ids(struct pnp_dev *dev) } } -void pnp_free_resource(struct pnp_resource *pnp_res) -{ - list_del(&pnp_res->list); - kfree(pnp_res); -} - -void pnp_free_resources(struct pnp_dev *dev) -{ - struct pnp_resource *pnp_res, *tmp; - - list_for_each_entry_safe(pnp_res, tmp, &dev->resources, list) { - pnp_free_resource(pnp_res); - } -} - static void pnp_release_device(struct device *dmdev) { struct pnp_dev *dev = to_pnp_dev(dmdev); + pnp_free_option(dev->independent); + pnp_free_option(dev->dependent); pnp_free_ids(dev); - pnp_free_resources(dev); - pnp_free_options(dev); + kfree(dev->res); kfree(dev); } @@ -133,8 +119,12 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid if (!dev) return NULL; - INIT_LIST_HEAD(&dev->resources); - INIT_LIST_HEAD(&dev->options); + dev->res = kzalloc(sizeof(struct pnp_resource_table), GFP_KERNEL); + if (!dev->res) { + kfree(dev); + return NULL; + } + dev->protocol = protocol; dev->number = id; dev->dma_mask = DMA_24BIT_MASK; @@ -150,6 +140,7 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid dev_id = pnp_add_id(dev, pnpid); if (!dev_id) { + kfree(dev->res); kfree(dev); return NULL; } diff --git a/trunk/drivers/pnp/interface.c b/trunk/drivers/pnp/interface.c index a876ecf7028c..5695a79f3a52 100644 --- a/trunk/drivers/pnp/interface.c +++ b/trunk/drivers/pnp/interface.c @@ -3,8 +3,6 @@ * * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela * Copyright 2002 Adam Belay - * Copyright (C) 2008 Hewlett-Packard Development Company, L.P. - * Bjorn Helgaas */ #include @@ -55,13 +53,11 @@ static int pnp_printf(pnp_info_buffer_t * buffer, char *fmt, ...) static void pnp_print_port(pnp_info_buffer_t * buffer, char *space, struct pnp_port *port) { - pnp_printf(buffer, "%sport %#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); + 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); } static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space, @@ -71,7 +67,7 @@ static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space, pnp_printf(buffer, "%sirq ", space); for (i = 0; i < PNP_IRQ_NR; i++) - if (test_bit(i, irq->map.bits)) { + if (test_bit(i, irq->map)) { if (!first) { pnp_printf(buffer, ","); } else { @@ -82,7 +78,7 @@ static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space, else pnp_printf(buffer, "%i", i); } - if (bitmap_empty(irq->map.bits, PNP_IRQ_NR)) + if (bitmap_empty(irq->map, PNP_IRQ_NR)) pnp_printf(buffer, ""); if (irq->flags & IORESOURCE_IRQ_HIGHEDGE) pnp_printf(buffer, " High-Edge"); @@ -92,8 +88,6 @@ static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space, pnp_printf(buffer, " High-Level"); if (irq->flags & IORESOURCE_IRQ_LOWLEVEL) pnp_printf(buffer, " Low-Level"); - if (irq->flags & IORESOURCE_IRQ_OPTIONAL) - pnp_printf(buffer, " (optional)"); pnp_printf(buffer, "\n"); } @@ -154,11 +148,8 @@ static void pnp_print_mem(pnp_info_buffer_t * buffer, char *space, { char *s; - 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); + pnp_printf(buffer, "%sMemory 0x%x-0x%x, align 0x%x, size 0x%x", + space, mem->min, mem->max, mem->align, mem->size); if (mem->flags & IORESOURCE_MEM_WRITEABLE) pnp_printf(buffer, ", writeable"); if (mem->flags & IORESOURCE_MEM_CACHEABLE) @@ -186,58 +177,65 @@ static void pnp_print_mem(pnp_info_buffer_t * buffer, char *space, } static void pnp_print_option(pnp_info_buffer_t * buffer, char *space, - struct pnp_option *option) + struct pnp_option *option, int dep) { - 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; + 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); } + + for (port = option->port; port; port = port->next) + pnp_print_port(buffer, space, port); + for (irq = option->irq; irq; irq = irq->next) + pnp_print_irq(buffer, space, irq); + for (dma = option->dma; dma; dma = dma->next) + pnp_print_dma(buffer, space, dma); + for (mem = option->mem; mem; mem = mem->next) + pnp_print_mem(buffer, space, mem); } static ssize_t pnp_show_options(struct device *dmdev, struct device_attribute *attr, char *buf) { struct pnp_dev *dev = to_pnp_dev(dmdev); - pnp_info_buffer_t *buffer; - struct pnp_option *option; - int ret, dep = 0, set = 0; - char *indent; + struct pnp_option *independent = dev->independent; + struct pnp_option *dependent = dev->dependent; + int ret, dep = 1; - buffer = pnp_alloc(sizeof(pnp_info_buffer_t)); + pnp_info_buffer_t *buffer = (pnp_info_buffer_t *) + pnp_alloc(sizeof(pnp_info_buffer_t)); if (!buffer) return -ENOMEM; buffer->len = PAGE_SIZE; buffer->buffer = buf; buffer->curr = buffer->buffer; + if (independent) + pnp_print_option(buffer, "", independent, 0); - 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); + while (dependent) { + pnp_print_option(buffer, " ", dependent, dep); + dependent = dependent->next; + dep++; } - ret = (buffer->curr - buf); kfree(buffer); return ret; @@ -250,59 +248,79 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf) { struct pnp_dev *dev = to_pnp_dev(dmdev); - pnp_info_buffer_t *buffer; - struct pnp_resource *pnp_res; struct resource *res; - int ret; + int i, ret; + pnp_info_buffer_t *buffer; if (!dev) return -EINVAL; - buffer = pnp_alloc(sizeof(pnp_info_buffer_t)); + buffer = (pnp_info_buffer_t *) pnp_alloc(sizeof(pnp_info_buffer_t)); if (!buffer) return -ENOMEM; - buffer->len = PAGE_SIZE; buffer->buffer = buf; buffer->curr = buffer->buffer; - pnp_printf(buffer, "state = %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; + 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); } - - 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; + } + for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) { + if (pnp_resource_valid(res)) { + pnp_printf(buffer, "mem"); + if (res->flags & IORESOURCE_DISABLED) + pnp_printf(buffer, " disabled\n"); + else + pnp_printf(buffer, " 0x%llx-0x%llx\n", + (unsigned long long) res->start, + (unsigned long long) res->end); + } + } + for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) { + if (pnp_resource_valid(res)) { + pnp_printf(buffer, "irq"); + if (res->flags & IORESOURCE_DISABLED) + pnp_printf(buffer, " disabled\n"); + else + pnp_printf(buffer, " %lld\n", + (unsigned long long) res->start); + } + } + for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) { + if (pnp_resource_valid(res)) { + pnp_printf(buffer, "dma"); + if (res->flags & IORESOURCE_DISABLED) + pnp_printf(buffer, " disabled\n"); + else + pnp_printf(buffer, " %lld\n", + (unsigned long long) res->start); } } - ret = (buffer->curr - buf); kfree(buffer); return ret; } -static ssize_t pnp_set_current_resources(struct device *dmdev, - struct device_attribute *attr, - const char *ubuf, size_t count) +static ssize_t +pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, + const char *ubuf, size_t count) { struct pnp_dev *dev = to_pnp_dev(dmdev); + struct pnp_resource *pnp_res; char *buf = (void *)ubuf; int retval = 0; resource_size_t start, end; @@ -350,6 +368,7 @@ static ssize_t pnp_set_current_resources(struct device *dmdev, goto done; } if (!strnicmp(buf, "set", 3)) { + int nport = 0, nmem = 0, nirq = 0, ndma = 0; if (dev->active) goto done; buf += 3; @@ -372,7 +391,10 @@ static ssize_t pnp_set_current_resources(struct device *dmdev, end = simple_strtoul(buf, &buf, 0); } else end = start; - pnp_add_io_resource(dev, start, end, 0); + pnp_res = pnp_add_io_resource(dev, start, end, + 0); + if (pnp_res) + pnp_res->index = nport++; continue; } if (!strnicmp(buf, "mem", 3)) { @@ -389,7 +411,10 @@ static ssize_t pnp_set_current_resources(struct device *dmdev, end = simple_strtoul(buf, &buf, 0); } else end = start; - pnp_add_mem_resource(dev, start, end, 0); + pnp_res = pnp_add_mem_resource(dev, start, end, + 0); + if (pnp_res) + pnp_res->index = nmem++; continue; } if (!strnicmp(buf, "irq", 3)) { @@ -397,7 +422,9 @@ static ssize_t pnp_set_current_resources(struct device *dmdev, while (isspace(*buf)) ++buf; start = simple_strtoul(buf, &buf, 0); - pnp_add_irq_resource(dev, start, 0); + pnp_res = pnp_add_irq_resource(dev, start, 0); + if (pnp_res) + pnp_res->index = nirq++; continue; } if (!strnicmp(buf, "dma", 3)) { @@ -405,7 +432,9 @@ static ssize_t pnp_set_current_resources(struct device *dmdev, while (isspace(*buf)) ++buf; start = simple_strtoul(buf, &buf, 0); - pnp_add_dma_resource(dev, start, 0); + pnp_res = pnp_add_dma_resource(dev, start, 0); + if (pnp_res) + pnp_res->index = ndma++; continue; } break; diff --git a/trunk/drivers/pnp/isapnp/core.c b/trunk/drivers/pnp/isapnp/core.c index 101a835e8759..f1bccdbdeb08 100644 --- a/trunk/drivers/pnp/isapnp/core.c +++ b/trunk/drivers/pnp/isapnp/core.c @@ -429,135 +429,154 @@ static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card, * Add IRQ resource to resources list. */ static void __init isapnp_parse_irq_resource(struct pnp_dev *dev, - unsigned int option_flags, + struct pnp_option *option, int size) { unsigned char tmp[3]; + struct pnp_irq *irq; unsigned long bits; - pnp_irq_mask_t map; - unsigned char flags = IORESOURCE_IRQ_HIGHEDGE; isapnp_peek(tmp, size); + irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL); + if (!irq) + return; bits = (tmp[1] << 8) | tmp[0]; - - bitmap_zero(map.bits, PNP_IRQ_NR); - bitmap_copy(map.bits, &bits, 16); - + bitmap_copy(irq->map, &bits, 16); if (size > 2) - flags = tmp[2]; - - pnp_register_irq_resource(dev, option_flags, &map, flags); + irq->flags = tmp[2]; + else + irq->flags = IORESOURCE_IRQ_HIGHEDGE; + pnp_register_irq_resource(dev, option, irq); } /* * Add DMA resource to resources list. */ static void __init isapnp_parse_dma_resource(struct pnp_dev *dev, - unsigned int option_flags, + struct pnp_option *option, int size) { unsigned char tmp[2]; + struct pnp_dma *dma; isapnp_peek(tmp, size); - pnp_register_dma_resource(dev, option_flags, tmp[0], tmp[1]); + 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); } /* * Add port resource to resources list. */ static void __init isapnp_parse_port_resource(struct pnp_dev *dev, - unsigned int option_flags, + struct pnp_option *option, int size) { unsigned char tmp[7]; - resource_size_t min, max, align, len; - unsigned char flags; + struct pnp_port *port; isapnp_peek(tmp, size); - 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); + 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); } /* * Add fixed port resource to resources list. */ static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev, - unsigned int option_flags, + struct pnp_option *option, int size) { unsigned char tmp[3]; - resource_size_t base, len; + struct pnp_port *port; isapnp_peek(tmp, size); - base = (tmp[1] << 8) | tmp[0]; - len = tmp[2]; - pnp_register_port_resource(dev, option_flags, base, base, 0, len, - IORESOURCE_IO_FIXED); + 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); } /* * Add memory resource to resources list. */ static void __init isapnp_parse_mem_resource(struct pnp_dev *dev, - unsigned int option_flags, + struct pnp_option *option, int size) { unsigned char tmp[9]; - resource_size_t min, max, align, len; - unsigned char flags; + struct pnp_mem *mem; isapnp_peek(tmp, size); - 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); + 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); } /* * Add 32-bit memory resource to resources list. */ static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev, - unsigned int option_flags, + struct pnp_option *option, int size) { unsigned char tmp[17]; - resource_size_t min, max, align, len; - unsigned char flags; + struct pnp_mem *mem; isapnp_peek(tmp, size); - 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); + 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); } /* * Add 32-bit fixed memory resource to resources list. */ static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev, - unsigned int option_flags, + struct pnp_option *option, int size) { unsigned char tmp[9]; - resource_size_t base, len; - unsigned char flags; + struct pnp_mem *mem; isapnp_peek(tmp, size); - 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); + 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); } /* @@ -585,16 +604,20 @@ isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size) static int __init isapnp_create_device(struct pnp_card *card, unsigned short size) { - int number = 0, skip = 0, priority, compat = 0; + int number = 0, skip = 0, priority = 0, compat = 0; unsigned char type, tmp[17]; - unsigned int option_flags; + struct pnp_option *option; struct pnp_dev *dev; u32 eisa_id; char id[8]; if ((dev = isapnp_parse_device(card, size, number++)) == NULL) return 1; - option_flags = 0; + option = pnp_register_independent_option(dev); + if (!option) { + kfree(dev); + return 1; + } pnp_add_card_device(card, dev); while (1) { @@ -611,11 +634,16 @@ static int __init isapnp_create_device(struct pnp_card *card, return 1; size = 0; skip = 0; - option_flags = 0; + option = pnp_register_independent_option(dev); + if (!option) { + kfree(dev); + return 1; + } pnp_add_card_device(card, dev); } else { skip = 1; } + priority = 0; compat = 0; break; case _STAG_COMPATDEVID: @@ -632,42 +660,44 @@ static int __init isapnp_create_device(struct pnp_card *card, case _STAG_IRQ: if (size < 2 || size > 3) goto __skip; - isapnp_parse_irq_resource(dev, option_flags, size); + isapnp_parse_irq_resource(dev, option, size); size = 0; break; case _STAG_DMA: if (size != 2) goto __skip; - isapnp_parse_dma_resource(dev, option_flags, size); + isapnp_parse_dma_resource(dev, option, size); size = 0; break; case _STAG_STARTDEP: if (size > 1) goto __skip; - priority = PNP_RES_PRIORITY_ACCEPTABLE; + priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE; if (size > 0) { isapnp_peek(tmp, size); - priority = tmp[0]; + priority = 0x100 | tmp[0]; size = 0; } - option_flags = pnp_new_dependent_set(dev, priority); + option = pnp_register_dependent_option(dev, priority); + if (!option) + return 1; break; case _STAG_ENDDEP: if (size != 0) goto __skip; - option_flags = 0; + priority = 0; + dev_dbg(&dev->dev, "end dependent options\n"); break; case _STAG_IOPORT: if (size != 7) goto __skip; - isapnp_parse_port_resource(dev, option_flags, size); + isapnp_parse_port_resource(dev, option, size); size = 0; break; case _STAG_FIXEDIO: if (size != 3) goto __skip; - isapnp_parse_fixed_port_resource(dev, option_flags, - size); + isapnp_parse_fixed_port_resource(dev, option, size); size = 0; break; case _STAG_VENDOR: @@ -675,7 +705,7 @@ static int __init isapnp_create_device(struct pnp_card *card, case _LTAG_MEMRANGE: if (size != 9) goto __skip; - isapnp_parse_mem_resource(dev, option_flags, size); + isapnp_parse_mem_resource(dev, option, size); size = 0; break; case _LTAG_ANSISTR: @@ -690,14 +720,13 @@ static int __init isapnp_create_device(struct pnp_card *card, case _LTAG_MEM32RANGE: if (size != 17) goto __skip; - isapnp_parse_mem32_resource(dev, option_flags, size); + isapnp_parse_mem32_resource(dev, option, size); size = 0; break; case _LTAG_FIXEDMEM32RANGE: if (size != 9) goto __skip; - isapnp_parse_fixed_mem32_resource(dev, option_flags, - size); + isapnp_parse_fixed_mem32_resource(dev, option, size); size = 0; break; case _STAG_END: @@ -899,6 +928,7 @@ EXPORT_SYMBOL(isapnp_write_byte); static int isapnp_get_resources(struct pnp_dev *dev) { + struct pnp_resource *pnp_res; int i, ret; dev_dbg(&dev->dev, "get resources\n"); @@ -910,23 +940,35 @@ static int isapnp_get_resources(struct pnp_dev *dev) for (i = 0; i < ISAPNP_MAX_PORT; i++) { ret = isapnp_read_word(ISAPNP_CFG_PORT + (i << 1)); - pnp_add_io_resource(dev, ret, ret, - ret == 0 ? IORESOURCE_DISABLED : 0); + if (ret) { + pnp_res = pnp_add_io_resource(dev, ret, ret, 0); + if (pnp_res) + pnp_res->index = i; + } } for (i = 0; i < ISAPNP_MAX_MEM; i++) { ret = isapnp_read_word(ISAPNP_CFG_MEM + (i << 3)) << 8; - pnp_add_mem_resource(dev, ret, ret, - ret == 0 ? IORESOURCE_DISABLED : 0); + if (ret) { + pnp_res = pnp_add_mem_resource(dev, ret, ret, 0); + if (pnp_res) + pnp_res->index = i; + } } for (i = 0; i < ISAPNP_MAX_IRQ; i++) { ret = isapnp_read_word(ISAPNP_CFG_IRQ + (i << 1)) >> 8; - pnp_add_irq_resource(dev, ret, - ret == 0 ? IORESOURCE_DISABLED : 0); + if (ret) { + pnp_res = pnp_add_irq_resource(dev, ret, 0); + if (pnp_res) + pnp_res->index = i; + } } for (i = 0; i < ISAPNP_MAX_DMA; i++) { ret = isapnp_read_byte(ISAPNP_CFG_DMA + i); - pnp_add_dma_resource(dev, ret, - ret == 4 ? IORESOURCE_DISABLED : 0); + if (ret != 4) { + pnp_res = pnp_add_dma_resource(dev, ret, 0); + if (pnp_res) + pnp_res->index = i; + } } __end: @@ -936,45 +978,62 @@ static int isapnp_get_resources(struct pnp_dev *dev) static int isapnp_set_resources(struct pnp_dev *dev) { + struct pnp_resource *pnp_res; struct resource *res; - int tmp; + int tmp, index; dev_dbg(&dev->dev, "set resources\n"); isapnp_cfg_begin(dev->card->number, dev->number); dev->active = 1; for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) { - res = pnp_get_resource(dev, IORESOURCE_IO, tmp); - if (pnp_resource_enabled(res)) { + 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; dev_dbg(&dev->dev, " set io %d to %#llx\n", - tmp, (unsigned long long) res->start); - isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1), + index, (unsigned long long) res->start); + isapnp_write_word(ISAPNP_CFG_PORT + (index << 1), res->start); } } for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) { - res = pnp_get_resource(dev, IORESOURCE_IRQ, tmp); - if (pnp_resource_enabled(res)) { + pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, tmp); + if (!pnp_res) + continue; + res = &pnp_res->res; + if (pnp_resource_valid(res)) { int irq = res->start; if (irq == 2) irq = 9; - dev_dbg(&dev->dev, " set irq %d to %d\n", tmp, irq); - isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq); + 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); } } for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) { - res = pnp_get_resource(dev, IORESOURCE_DMA, tmp); - if (pnp_resource_enabled(res)) { + 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; dev_dbg(&dev->dev, " set dma %d to %lld\n", - tmp, (unsigned long long) res->start); - isapnp_write_byte(ISAPNP_CFG_DMA + tmp, res->start); + index, (unsigned long long) res->start); + isapnp_write_byte(ISAPNP_CFG_DMA + index, res->start); } } for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) { - res = pnp_get_resource(dev, IORESOURCE_MEM, tmp); - if (pnp_resource_enabled(res)) { + 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; dev_dbg(&dev->dev, " set mem %d to %#llx\n", - tmp, (unsigned long long) res->start); - isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3), + index, (unsigned long long) res->start); + isapnp_write_word(ISAPNP_CFG_MEM + (index << 3), (res->start >> 8) & 0xffff); } } diff --git a/trunk/drivers/pnp/manager.c b/trunk/drivers/pnp/manager.c index b526eaad3f6c..bea0914ff947 100644 --- a/trunk/drivers/pnp/manager.c +++ b/trunk/drivers/pnp/manager.c @@ -3,8 +3,6 @@ * * based on isapnp.c resource management (c) Jaroslav Kysela * Copyright 2003 Adam Belay - * Copyright (C) 2008 Hewlett-Packard Development Company, L.P. - * Bjorn Helgaas */ #include @@ -21,64 +19,82 @@ DEFINE_MUTEX(pnp_res_mutex); static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) { - struct resource *res, local_res; + 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; - res = pnp_get_resource(dev, IORESOURCE_IO, idx); - if (res) { + /* check if this resource has been manually set, if so skip */ + if (!(res->flags & IORESOURCE_AUTO)) { dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx " "flags %#lx\n", idx, (unsigned long long) res->start, (unsigned long long) res->end, res->flags); - return 0; + return 1; } - res = &local_res; - res->flags = rule->flags | IORESOURCE_AUTO; - res->start = 0; - res->end = 0; + /* set the initial values */ + pnp_res->index = idx; + res->flags |= rule->flags | IORESOURCE_IO; + res->flags &= ~IORESOURCE_UNSET; if (!rule->size) { res->flags |= IORESOURCE_DISABLED; dev_dbg(&dev->dev, " io %d disabled\n", idx); - goto __add; + return 1; /* skip disabled resource requests */ } res->start = rule->min; res->end = res->start + rule->size - 1; + /* run through until pnp_check_port is happy */ while (!pnp_check_port(dev, res)) { res->start += rule->align; res->end = res->start + rule->size - 1; if (res->start > rule->max || !rule->align) { - dev_dbg(&dev->dev, " couldn't assign io %d " - "(min %#llx max %#llx)\n", idx, - (unsigned long long) rule->min, - (unsigned long long) rule->max); - return -EBUSY; + dev_dbg(&dev->dev, " couldn't assign io %d\n", idx); + return 0; } } - -__add: - pnp_add_io_resource(dev, res->start, res->end, res->flags); - return 0; + dev_dbg(&dev->dev, " assign io %d %#llx-%#llx\n", idx, + (unsigned long long) res->start, (unsigned long long) res->end); + return 1; } static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) { - struct resource *res, local_res; + 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; + } - res = pnp_get_resource(dev, IORESOURCE_MEM, idx); - if (res) { + res = &pnp_res->res; + + /* check if this resource has been manually set, if so skip */ + if (!(res->flags & IORESOURCE_AUTO)) { dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx " "flags %#lx\n", idx, (unsigned long long) res->start, (unsigned long long) res->end, res->flags); - return 0; + return 1; } - res = &local_res; - res->flags = rule->flags | IORESOURCE_AUTO; - res->start = 0; - res->end = 0; + /* set the initial values */ + pnp_res->index = idx; + res->flags |= rule->flags | IORESOURCE_MEM; + res->flags &= ~IORESOURCE_UNSET; + /* convert pnp flags to standard Linux flags */ if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) res->flags |= IORESOURCE_READONLY; if (rule->flags & IORESOURCE_MEM_CACHEABLE) @@ -91,32 +107,30 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) if (!rule->size) { res->flags |= IORESOURCE_DISABLED; dev_dbg(&dev->dev, " mem %d disabled\n", idx); - goto __add; + return 1; /* skip disabled resource requests */ } res->start = rule->min; res->end = res->start + rule->size - 1; + /* run through until pnp_check_mem is happy */ while (!pnp_check_mem(dev, res)) { res->start += rule->align; res->end = res->start + rule->size - 1; if (res->start > rule->max || !rule->align) { - dev_dbg(&dev->dev, " couldn't assign mem %d " - "(min %#llx max %#llx)\n", idx, - (unsigned long long) rule->min, - (unsigned long long) rule->max); - return -EBUSY; + dev_dbg(&dev->dev, " couldn't assign mem %d\n", idx); + return 0; } } - -__add: - pnp_add_mem_resource(dev, res->start, res->end, res->flags); - return 0; + dev_dbg(&dev->dev, " assign mem %d %#llx-%#llx\n", idx, + (unsigned long long) res->start, (unsigned long long) res->end); + return 1; } static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) { - struct resource *res, local_res; + struct pnp_resource *pnp_res; + struct resource *res; int i; /* IRQ priority: this table is good for i386 */ @@ -124,57 +138,59 @@ 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 }; - res = pnp_get_resource(dev, IORESOURCE_IRQ, idx); - if (res) { + 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)) { dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n", idx, (int) res->start, res->flags); - return 0; + return 1; } - res = &local_res; - res->flags = rule->flags | IORESOURCE_AUTO; - res->start = -1; - res->end = -1; + /* set the initial values */ + pnp_res->index = idx; + res->flags |= rule->flags | IORESOURCE_IRQ; + res->flags &= ~IORESOURCE_UNSET; - if (bitmap_empty(rule->map.bits, PNP_IRQ_NR)) { + if (bitmap_empty(rule->map, PNP_IRQ_NR)) { res->flags |= IORESOURCE_DISABLED; dev_dbg(&dev->dev, " irq %d disabled\n", idx); - goto __add; + return 1; /* skip disabled resource requests */ } /* TBD: need check for >16 IRQ */ - res->start = find_next_bit(rule->map.bits, PNP_IRQ_NR, 16); + res->start = find_next_bit(rule->map, PNP_IRQ_NR, 16); if (res->start < PNP_IRQ_NR) { res->end = res->start; - goto __add; + dev_dbg(&dev->dev, " assign irq %d %d\n", idx, + (int) res->start); + return 1; } for (i = 0; i < 16; i++) { - if (test_bit(xtab[i], rule->map.bits)) { + if (test_bit(xtab[i], rule->map)) { res->start = res->end = xtab[i]; - if (pnp_check_irq(dev, res)) - goto __add; + if (pnp_check_irq(dev, res)) { + dev_dbg(&dev->dev, " assign irq %d %d\n", idx, + (int) res->start); + return 1; + } } } - - if (rule->flags & IORESOURCE_IRQ_OPTIONAL) { - res->start = -1; - res->end = -1; - res->flags |= IORESOURCE_DISABLED; - dev_dbg(&dev->dev, " irq %d disabled (optional)\n", idx); - goto __add; - } - dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx); - return -EBUSY; - -__add: - pnp_add_irq_resource(dev, res->start, res->flags); return 0; } -static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) +static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) { - struct resource *res, local_res; + struct pnp_resource *pnp_res; + struct resource *res; int i; /* DMA priority: this table is good for i386 */ @@ -182,99 +198,231 @@ static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) 1, 3, 5, 6, 7, 0, 2, 4 }; - res = pnp_get_resource(dev, IORESOURCE_DMA, idx); - if (res) { + 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)) { dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n", idx, (int) res->start, res->flags); - return 0; + return; } - res = &local_res; - res->flags = rule->flags | IORESOURCE_AUTO; - res->start = -1; - res->end = -1; + /* set the initial values */ + pnp_res->index = idx; + res->flags |= rule->flags | IORESOURCE_DMA; + res->flags &= ~IORESOURCE_UNSET; for (i = 0; i < 8; i++) { if (rule->map & (1 << xtab[i])) { res->start = res->end = xtab[i]; - if (pnp_check_dma(dev, res)) - goto __add; + if (pnp_check_dma(dev, res)) { + dev_dbg(&dev->dev, " assign dma %d %d\n", idx, + (int) res->start); + return; + } } } #ifdef MAX_DMA_CHANNELS res->start = res->end = MAX_DMA_CHANNELS; #endif - res->flags |= IORESOURCE_DISABLED; + res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; dev_dbg(&dev->dev, " disable dma %d\n", idx); +} -__add: - pnp_add_dma_resource(dev, res->start, res->flags); - return 0; +void pnp_init_resource(struct resource *res) +{ + unsigned long type; + + type = res->flags & (IORESOURCE_IO | IORESOURCE_MEM | + IORESOURCE_IRQ | IORESOURCE_DMA); + + res->name = NULL; + res->flags = type | IORESOURCE_AUTO | IORESOURCE_UNSET; + if (type == IORESOURCE_IRQ || type == IORESOURCE_DMA) { + res->start = -1; + res->end = -1; + } else { + res->start = 0; + res->end = 0; + } } +/** + * pnp_init_resources - Resets a resource table to default values. + * @table: pointer to the desired resource table + */ void pnp_init_resources(struct pnp_dev *dev) { - pnp_free_resources(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_clean_resources - clears resources that were not manually set + * @res: the resources to clean + */ static void pnp_clean_resource_table(struct pnp_dev *dev) { - struct 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); + 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); + } } } /** * pnp_assign_resources - assigns resources to the device based on the specified dependent number * @dev: pointer to the desired device - * @set: the dependent function number + * @depnum: the dependent function number + * + * Only set depnum to 0 if the device does not have dependent options. */ -static int pnp_assign_resources(struct pnp_dev *dev, int set) +static int pnp_assign_resources(struct pnp_dev *dev, int depnum) { - struct pnp_option *option; + struct pnp_port *port; + struct pnp_mem *mem; + struct pnp_irq *irq; + struct pnp_dma *dma; int nport = 0, nmem = 0, nirq = 0, ndma = 0; - int ret = 0; - dev_dbg(&dev->dev, "pnp_assign_resources, try dependent set %d\n", set); + if (!pnp_can_configure(dev)) + return -ENODEV; + + dbg_pnp_show_resources(dev, "before pnp_assign_resources"); mutex_lock(&pnp_res_mutex); pnp_clean_resource_table(dev); - - list_for_each_entry(option, &dev->options, list) { - if (pnp_option_is_dependent(option) && - pnp_option_set(option) != set) - continue; - - switch (option->type) { - case IORESOURCE_IO: - ret = pnp_assign_port(dev, &option->u.port, nport++); - break; - case IORESOURCE_MEM: - ret = pnp_assign_mem(dev, &option->u.mem, nmem++); - break; - case IORESOURCE_IRQ: - ret = pnp_assign_irq(dev, &option->u.irq, nirq++); - break; - case IORESOURCE_DMA: - ret = pnp_assign_dma(dev, &option->u.dma, ndma++); - break; - default: - ret = -EINVAL; - break; + if (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 (ret < 0) - break; } + if (depnum) { + struct pnp_option *dep; + int i; + + dev_dbg(&dev->dev, "assigning dependent option %d\n", depnum); + for (i = 1, dep = dev->dependent; i < depnum; + i++, dep = dep->next) + if (!dep) + goto fail; + port = dep->port; + mem = dep->mem; + irq = dep->irq; + dma = dep->dma; + while (port) { + if (!pnp_assign_port(dev, port, nport)) + goto fail; + nport++; + port = port->next; + } + while (mem) { + if (!pnp_assign_mem(dev, mem, nmem)) + goto fail; + nmem++; + mem = mem->next; + } + while (irq) { + if (!pnp_assign_irq(dev, irq, nirq)) + goto fail; + nirq++; + irq = irq->next; + } + while (dma) { + pnp_assign_dma(dev, dma, ndma); + ndma++; + dma = dma->next; + } + } else if (dev->dependent) + goto fail; + + mutex_unlock(&pnp_res_mutex); + dbg_pnp_show_resources(dev, "after pnp_assign_resources"); + return 1; + +fail: + pnp_clean_resource_table(dev); mutex_unlock(&pnp_res_mutex); - 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; + dbg_pnp_show_resources(dev, "after pnp_assign_resources (failed)"); + return 0; } /** @@ -283,25 +431,29 @@ static int pnp_assign_resources(struct pnp_dev *dev, int set) */ int pnp_auto_config_dev(struct pnp_dev *dev) { - int i, ret; + struct pnp_option *dep; + int i = 1; if (!pnp_can_configure(dev)) { dev_dbg(&dev->dev, "configuration not supported\n"); return -ENODEV; } - 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) + if (!dev->dependent) { + if (pnp_assign_resources(dev, 0)) return 0; + } else { + dep = dev->dependent; + do { + if (pnp_assign_resources(dev, i)) + return 0; + dep = dep->next; + i++; + } while (dep); } dev_err(&dev->dev, "unable to assign resources\n"); - return ret; + return -EBUSY; } /** diff --git a/trunk/drivers/pnp/pnpacpi/core.c b/trunk/drivers/pnp/pnpacpi/core.c index c1b9ea34977b..50902773beaf 100644 --- a/trunk/drivers/pnp/pnpacpi/core.c +++ b/trunk/drivers/pnp/pnpacpi/core.c @@ -117,7 +117,9 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state) { int power_state; - power_state = acpi_pm_device_sleep_state(&dev->dev, NULL); + power_state = acpi_pm_device_sleep_state(&dev->dev, + device_may_wakeup(&dev->dev), + NULL); if (power_state < 0) power_state = (state.event == PM_EVENT_ON) ? ACPI_STATE_D0 : ACPI_STATE_D3; diff --git a/trunk/drivers/pnp/pnpacpi/rsparser.c b/trunk/drivers/pnp/pnpacpi/rsparser.c index d7e9f2152df0..46c791adb894 100644 --- a/trunk/drivers/pnp/pnpacpi/rsparser.c +++ b/trunk/drivers/pnp/pnpacpi/rsparser.c @@ -3,8 +3,6 @@ * * Copyright (c) 2004 Matthieu Castet * Copyright (c) 2004 Li Shaohua - * Copyright (C) 2008 Hewlett-Packard Development Company, L.P. - * Bjorn Helgaas * * 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 @@ -100,10 +98,8 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev, int irq, flags; int p, t; - if (!valid_IRQ(gsi)) { - pnp_add_irq_resource(dev, gsi, IORESOURCE_DISABLED); + if (!valid_IRQ(gsi)) return; - } /* * in IO-APIC mode, use overrided attribute. Two reasons: @@ -182,68 +178,13 @@ static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start, u64 end = start + len - 1; if (io_decode == ACPI_DECODE_16) - flags |= IORESOURCE_IO_16BIT_ADDR; + flags |= PNP_PORT_FLAG_16BITADDR; if (len == 0 || end >= 0x10003) flags |= IORESOURCE_DISABLED; pnp_add_io_resource(dev, start, end, flags); } -/* - * Device CSRs that do not appear in PCI config space should be described - * via ACPI. This would normally be done with Address Space Descriptors - * marked as "consumer-only," but old versions of Windows and Linux ignore - * the producer/consumer flag, so HP invented a vendor-defined resource to - * describe the location and size of CSR space. - */ -static struct acpi_vendor_uuid hp_ccsr_uuid = { - .subtype = 2, - .data = { 0xf9, 0xad, 0xe9, 0x69, 0x4f, 0x92, 0x5f, 0xab, 0xf6, 0x4a, - 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad }, -}; - -static int vendor_resource_matches(struct pnp_dev *dev, - struct acpi_resource_vendor_typed *vendor, - struct acpi_vendor_uuid *match, - int expected_len) -{ - int uuid_len = sizeof(vendor->uuid); - u8 uuid_subtype = vendor->uuid_subtype; - u8 *uuid = vendor->uuid; - int actual_len; - - /* byte_length includes uuid_subtype and uuid */ - actual_len = vendor->byte_length - uuid_len - 1; - - if (uuid_subtype == match->subtype && - uuid_len == sizeof(match->data) && - memcmp(uuid, match->data, uuid_len) == 0) { - if (expected_len && expected_len != actual_len) { - dev_err(&dev->dev, "wrong vendor descriptor size; " - "expected %d, found %d bytes\n", - expected_len, actual_len); - return 0; - } - - return 1; - } - - return 0; -} - -static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev, - struct acpi_resource_vendor_typed *vendor) -{ - if (vendor_resource_matches(dev, vendor, &hp_ccsr_uuid, 16)) { - u64 start, length; - - memcpy(&start, vendor->byte_data, sizeof(start)); - memcpy(&length, vendor->byte_data + 8, sizeof(length)); - - pnp_add_mem_resource(dev, start, start + length - 1, 0); - } -} - static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev, u64 start, u64 len, int write_protect) @@ -294,7 +235,6 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, struct acpi_resource_dma *dma; struct acpi_resource_io *io; struct acpi_resource_fixed_io *fixed_io; - struct acpi_resource_vendor_typed *vendor_typed; struct acpi_resource_memory24 *memory24; struct acpi_resource_memory32 *memory32; struct acpi_resource_fixed_memory32 *fixed_memory32; @@ -308,39 +248,24 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, * _CRS, but some firmware violates this, so parse them all. */ irq = &res->data.irq; - 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; - } + for (i = 0; i < irq->interrupt_count; i++) { + pnpacpi_parse_allocated_irqresource(dev, + irq->interrupts[i], + irq->triggering, + irq->polarity, + irq->sharable); } break; case ACPI_RESOURCE_TYPE_DMA: dma = &res->data.dma; - if (dma->channel_count > 0 && dma->channels[0] != (u8) -1) + if (dma->channel_count > 0) { flags = dma_flags(dma->type, dma->bus_master, dma->transfer); - else - flags = IORESOURCE_DISABLED; - pnp_add_dma_resource(dev, dma->channels[0], flags); + if (dma->channels[0] == (u8) -1) + flags |= IORESOURCE_DISABLED; + pnp_add_dma_resource(dev, dma->channels[0], flags); + } break; case ACPI_RESOURCE_TYPE_IO: @@ -364,8 +289,6 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, break; case ACPI_RESOURCE_TYPE_VENDOR: - vendor_typed = &res->data.vendor_typed; - pnpacpi_parse_allocated_vendor(dev, vendor_typed); break; case ACPI_RESOURCE_TYPE_END_TAG: @@ -408,29 +331,12 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, if (extended_irq->producer_consumer == ACPI_PRODUCER) return AE_OK; - 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; - } + 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); } break; @@ -467,147 +373,179 @@ int pnpacpi_parse_allocated_resource(struct pnp_dev *dev) } static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev, - unsigned int option_flags, + struct pnp_option *option, struct acpi_resource_dma *p) { int i; - unsigned char map = 0, flags; + struct pnp_dma *dma; if (p->channel_count == 0) return; + dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL); + if (!dma) + return; for (i = 0; i < p->channel_count; i++) - map |= 1 << p->channels[i]; + dma->map |= 1 << p->channels[i]; + + dma->flags = dma_flags(p->type, p->bus_master, p->transfer); - flags = dma_flags(p->type, p->bus_master, p->transfer); - pnp_register_dma_resource(dev, option_flags, map, flags); + pnp_register_dma_resource(dev, option, dma); } static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev, - unsigned int option_flags, + struct pnp_option *option, struct acpi_resource_irq *p) { int i; - pnp_irq_mask_t map; - unsigned char flags; + struct pnp_irq *irq; if (p->interrupt_count == 0) return; + irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL); + if (!irq) + return; - bitmap_zero(map.bits, PNP_IRQ_NR); for (i = 0; i < p->interrupt_count; i++) if (p->interrupts[i]) - __set_bit(p->interrupts[i], map.bits); + __set_bit(p->interrupts[i], irq->map); + irq->flags = irq_flags(p->triggering, p->polarity, p->sharable); - flags = irq_flags(p->triggering, p->polarity, p->sharable); - pnp_register_irq_resource(dev, option_flags, &map, flags); + pnp_register_irq_resource(dev, option, irq); } static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev, - unsigned int option_flags, + struct pnp_option *option, struct acpi_resource_extended_irq *p) { int i; - pnp_irq_mask_t map; - unsigned char flags; + struct pnp_irq *irq; if (p->interrupt_count == 0) return; + irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL); + if (!irq) + return; - bitmap_zero(map.bits, PNP_IRQ_NR); - for (i = 0; i < p->interrupt_count; i++) { - if (p->interrupts[i]) { - 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); - } - } + 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); - flags = irq_flags(p->triggering, p->polarity, p->sharable); - pnp_register_irq_resource(dev, option_flags, &map, flags); + pnp_register_irq_resource(dev, option, irq); } static __init void pnpacpi_parse_port_option(struct pnp_dev *dev, - unsigned int option_flags, + struct pnp_option *option, struct acpi_resource_io *io) { - unsigned char flags = 0; + struct pnp_port *port; if (io->address_length == 0) return; - - 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); + 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); } static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev, - unsigned int option_flags, + struct pnp_option *option, struct acpi_resource_fixed_io *io) { + struct pnp_port *port; + if (io->address_length == 0) return; - - pnp_register_port_resource(dev, option_flags, io->address, io->address, - 0, io->address_length, IORESOURCE_IO_FIXED); + 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); } static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev, - unsigned int option_flags, + struct pnp_option *option, struct acpi_resource_memory24 *p) { - unsigned char flags = 0; + struct pnp_mem *mem; if (p->address_length == 0) return; + mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); + if (!mem) + return; + mem->min = p->minimum; + mem->max = p->maximum; + mem->align = p->alignment; + mem->size = p->address_length; + + mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? + IORESOURCE_MEM_WRITEABLE : 0; - 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); + pnp_register_mem_resource(dev, option, mem); } static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev, - unsigned int option_flags, + struct pnp_option *option, struct acpi_resource_memory32 *p) { - unsigned char flags = 0; + struct pnp_mem *mem; if (p->address_length == 0) return; + mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); + if (!mem) + return; + mem->min = p->minimum; + mem->max = p->maximum; + mem->align = p->alignment; + mem->size = p->address_length; + + mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? + IORESOURCE_MEM_WRITEABLE : 0; - 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); + pnp_register_mem_resource(dev, option, mem); } static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev, - unsigned int option_flags, + struct pnp_option *option, struct acpi_resource_fixed_memory32 *p) { - unsigned char flags = 0; + struct pnp_mem *mem; if (p->address_length == 0) return; + mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); + if (!mem) + return; + mem->min = mem->max = p->address; + mem->size = p->address_length; + mem->align = 0; + + mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? + IORESOURCE_MEM_WRITEABLE : 0; - 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); + pnp_register_mem_resource(dev, option, mem); } static __init void pnpacpi_parse_address_option(struct pnp_dev *dev, - unsigned int option_flags, + struct pnp_option *option, struct acpi_resource *r) { struct acpi_resource_address64 addr, *p = &addr; acpi_status status; - unsigned char flags = 0; + struct pnp_mem *mem; + struct pnp_port *port; status = acpi_resource_to_address64(r, p); if (!ACPI_SUCCESS(status)) { @@ -620,37 +558,49 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev, return; if (p->resource_type == ACPI_MEMORY_RANGE) { - 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); + 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); + } } struct acpipnp_parse_option_s { + struct pnp_option *option; + struct pnp_option *option_independent; struct pnp_dev *dev; - unsigned int option_flags; }; static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, void *data) { - int priority; + int priority = 0; struct acpipnp_parse_option_s *parse_data = data; struct pnp_dev *dev = parse_data->dev; - unsigned int option_flags = parse_data->option_flags; + struct pnp_option *option = parse_data->option; switch (res->type) { case ACPI_RESOURCE_TYPE_IRQ: - pnpacpi_parse_irq_option(dev, option_flags, &res->data.irq); + pnpacpi_parse_irq_option(dev, option, &res->data.irq); break; case ACPI_RESOURCE_TYPE_DMA: - pnpacpi_parse_dma_option(dev, option_flags, &res->data.dma); + pnpacpi_parse_dma_option(dev, option, &res->data.dma); break; case ACPI_RESOURCE_TYPE_START_DEPENDENT: @@ -670,19 +620,31 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, priority = PNP_RES_PRIORITY_INVALID; break; } - parse_data->option_flags = pnp_new_dependent_set(dev, priority); + /* TBD: Consider performance/robustness bits */ + option = pnp_register_dependent_option(dev, priority); + if (!option) + return AE_ERROR; + parse_data->option = option; break; case ACPI_RESOURCE_TYPE_END_DEPENDENT: - parse_data->option_flags = 0; + /*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"); break; case ACPI_RESOURCE_TYPE_IO: - pnpacpi_parse_port_option(dev, option_flags, &res->data.io); + pnpacpi_parse_port_option(dev, option, &res->data.io); break; case ACPI_RESOURCE_TYPE_FIXED_IO: - pnpacpi_parse_fixed_port_option(dev, option_flags, + pnpacpi_parse_fixed_port_option(dev, option, &res->data.fixed_io); break; @@ -691,31 +653,29 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, break; case ACPI_RESOURCE_TYPE_MEMORY24: - pnpacpi_parse_mem24_option(dev, option_flags, - &res->data.memory24); + pnpacpi_parse_mem24_option(dev, option, &res->data.memory24); break; case ACPI_RESOURCE_TYPE_MEMORY32: - pnpacpi_parse_mem32_option(dev, option_flags, - &res->data.memory32); + pnpacpi_parse_mem32_option(dev, option, &res->data.memory32); break; case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: - pnpacpi_parse_fixed_mem32_option(dev, option_flags, + pnpacpi_parse_fixed_mem32_option(dev, option, &res->data.fixed_memory32); break; case ACPI_RESOURCE_TYPE_ADDRESS16: case ACPI_RESOURCE_TYPE_ADDRESS32: case ACPI_RESOURCE_TYPE_ADDRESS64: - pnpacpi_parse_address_option(dev, option_flags, res); + pnpacpi_parse_address_option(dev, option, res); break; case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: - pnpacpi_parse_ext_irq_option(dev, option_flags, + pnpacpi_parse_ext_irq_option(dev, option, &res->data.extended_irq); break; @@ -739,9 +699,12 @@ int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev) dev_dbg(&dev->dev, "parse resource options\n"); - parse_data.dev = dev; - parse_data.option_flags = 0; + 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; status = acpi_walk_resources(handle, METHOD_NAME__PRS, pnpacpi_option_resource, &parse_data); @@ -843,13 +806,6 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev, struct acpi_resource_irq *irq = &resource->data.irq; int triggering, polarity, shareable; - if (!pnp_resource_enabled(p)) { - irq->interrupt_count = 0; - dev_dbg(&dev->dev, " encode irq (%s)\n", - p ? "disabled" : "missing"); - return; - } - decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable); irq->triggering = triggering; irq->polarity = polarity; @@ -872,13 +828,6 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev, struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq; int triggering, polarity, shareable; - if (!pnp_resource_enabled(p)) { - extended_irq->interrupt_count = 0; - dev_dbg(&dev->dev, " encode extended irq (%s)\n", - p ? "disabled" : "missing"); - return; - } - decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable); extended_irq->producer_consumer = ACPI_CONSUMER; extended_irq->triggering = triggering; @@ -899,13 +848,6 @@ static void pnpacpi_encode_dma(struct pnp_dev *dev, { struct acpi_resource_dma *dma = &resource->data.dma; - if (!pnp_resource_enabled(p)) { - dma->channel_count = 0; - dev_dbg(&dev->dev, " encode dma (%s)\n", - p ? "disabled" : "missing"); - return; - } - /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ switch (p->flags & IORESOURCE_DMA_SPEED_MASK) { case IORESOURCE_DMA_TYPEA: @@ -947,21 +889,17 @@ static void pnpacpi_encode_io(struct pnp_dev *dev, { struct acpi_resource_io *io = &resource->data.io; - 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); + /* 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); } static void pnpacpi_encode_fixed_io(struct pnp_dev *dev, @@ -970,16 +908,11 @@ static void pnpacpi_encode_fixed_io(struct pnp_dev *dev, { struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io; - 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; - } + fixed_io->address = p->start; + fixed_io->address_length = p->end - p->start + 1; - dev_dbg(&dev->dev, " encode fixed_io %#x-%#x\n", fixed_io->address, - fixed_io->address + fixed_io->address_length - 1); + dev_dbg(&dev->dev, " encode fixed_io %#llx-%#llx\n", + (unsigned long long) p->start, (unsigned long long) p->end); } static void pnpacpi_encode_mem24(struct pnp_dev *dev, @@ -988,22 +921,17 @@ static void pnpacpi_encode_mem24(struct pnp_dev *dev, { struct acpi_resource_memory24 *memory24 = &resource->data.memory24; - 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, + /* 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, memory24->write_protect); } @@ -1013,21 +941,16 @@ static void pnpacpi_encode_mem32(struct pnp_dev *dev, { struct acpi_resource_memory32 *memory32 = &resource->data.memory32; - 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; - } + 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; - dev_dbg(&dev->dev, " encode mem32 %#x-%#x write_protect %#x\n", - memory32->minimum, - memory32->minimum + memory32->address_length - 1, + dev_dbg(&dev->dev, " encode mem32 %#llx-%#llx write_protect %#x\n", + (unsigned long long) p->start, (unsigned long long) p->end, memory32->write_protect); } @@ -1037,20 +960,15 @@ static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev, { struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32; - 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; - } + 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; - dev_dbg(&dev->dev, " encode fixed_mem32 %#x-%#x write_protect %#x\n", - fixed_memory32->address, - fixed_memory32->address + fixed_memory32->address_length - 1, + dev_dbg(&dev->dev, " encode fixed_mem32 %#llx-%#llx " + "write_protect %#x\n", + (unsigned long long) p->start, (unsigned long long) p->end, fixed_memory32->write_protect); } diff --git a/trunk/drivers/pnp/pnpbios/rsparser.c b/trunk/drivers/pnp/pnpbios/rsparser.c index ca567671379e..5ff9a4c0447e 100644 --- a/trunk/drivers/pnp/pnpbios/rsparser.c +++ b/trunk/drivers/pnp/pnpbios/rsparser.c @@ -216,116 +216,137 @@ static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev, static __init void pnpbios_parse_mem_option(struct pnp_dev *dev, unsigned char *p, int size, - unsigned int option_flags) + struct pnp_option *option) { - 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); + 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); } static __init void pnpbios_parse_mem32_option(struct pnp_dev *dev, unsigned char *p, int size, - unsigned int option_flags) + struct pnp_option *option) { - 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); + 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); } static __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev, unsigned char *p, int size, - unsigned int option_flags) + struct pnp_option *option) { - 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); + 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); } static __init void pnpbios_parse_irq_option(struct pnp_dev *dev, unsigned char *p, int size, - unsigned int option_flags) + struct pnp_option *option) { + struct pnp_irq *irq; unsigned long bits; - pnp_irq_mask_t map; - unsigned char flags = IORESOURCE_IRQ_HIGHEDGE; + irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL); + if (!irq) + return; bits = (p[2] << 8) | p[1]; - - bitmap_zero(map.bits, PNP_IRQ_NR); - bitmap_copy(map.bits, &bits, 16); - + bitmap_copy(irq->map, &bits, 16); if (size > 2) - flags = p[3]; - - pnp_register_irq_resource(dev, option_flags, &map, flags); + irq->flags = p[3]; + else + irq->flags = IORESOURCE_IRQ_HIGHEDGE; + pnp_register_irq_resource(dev, option, irq); } static __init void pnpbios_parse_dma_option(struct pnp_dev *dev, unsigned char *p, int size, - unsigned int option_flags) + struct pnp_option *option) { - pnp_register_dma_resource(dev, option_flags, p[1], p[2]); + 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); } static __init void pnpbios_parse_port_option(struct pnp_dev *dev, unsigned char *p, int size, - unsigned int option_flags) + struct pnp_option *option) { - 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); + 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); } static __init void pnpbios_parse_fixed_port_option(struct pnp_dev *dev, unsigned char *p, int size, - unsigned int option_flags) + struct pnp_option *option) { - 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); + 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); } static __init unsigned char * pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, - struct pnp_dev *dev) + struct pnp_dev *dev) { unsigned int len, tag; - int priority; - unsigned int option_flags; + int priority = 0; + struct pnp_option *option, *option_independent; if (!p) return NULL; dev_dbg(&dev->dev, "parse resource options\n"); - option_flags = 0; + + option_independent = option = pnp_register_independent_option(dev); + if (!option) + return NULL; + while ((char *)p < (char *)end) { /* determine the type of tag */ @@ -342,38 +363,37 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, case LARGE_TAG_MEM: if (len != 9) goto len_err; - pnpbios_parse_mem_option(dev, p, len, option_flags); + pnpbios_parse_mem_option(dev, p, len, option); break; case LARGE_TAG_MEM32: if (len != 17) goto len_err; - pnpbios_parse_mem32_option(dev, p, len, option_flags); + pnpbios_parse_mem32_option(dev, p, len, option); break; case LARGE_TAG_FIXEDMEM32: if (len != 9) goto len_err; - pnpbios_parse_fixed_mem32_option(dev, p, len, - option_flags); + pnpbios_parse_fixed_mem32_option(dev, p, len, option); break; case SMALL_TAG_IRQ: if (len < 2 || len > 3) goto len_err; - pnpbios_parse_irq_option(dev, p, len, option_flags); + pnpbios_parse_irq_option(dev, p, len, option); break; case SMALL_TAG_DMA: if (len != 2) goto len_err; - pnpbios_parse_dma_option(dev, p, len, option_flags); + pnpbios_parse_dma_option(dev, p, len, option); break; case SMALL_TAG_PORT: if (len != 7) goto len_err; - pnpbios_parse_port_option(dev, p, len, option_flags); + pnpbios_parse_port_option(dev, p, len, option); break; case SMALL_TAG_VENDOR: @@ -383,23 +403,28 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, case SMALL_TAG_FIXEDPORT: if (len != 3) goto len_err; - pnpbios_parse_fixed_port_option(dev, p, len, - option_flags); + pnpbios_parse_fixed_port_option(dev, p, len, option); break; case SMALL_TAG_STARTDEP: if (len > 1) goto len_err; - priority = PNP_RES_PRIORITY_ACCEPTABLE; + priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE; if (len > 0) - priority = p[1]; - option_flags = pnp_new_dependent_set(dev, priority); + priority = 0x100 | p[1]; + option = pnp_register_dependent_option(dev, priority); + if (!option) + return NULL; break; case SMALL_TAG_ENDDEP: if (len != 0) goto len_err; - option_flags = 0; + 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"); break; case SMALL_TAG_END: @@ -501,16 +526,8 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p, static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p, struct resource *res) { - unsigned long base; - unsigned long len; - - if (pnp_resource_enabled(res)) { - base = res->start; - len = res->end - res->start + 1; - } else { - base = 0; - len = 0; - } + unsigned long base = res->start; + unsigned long len = res->end - res->start + 1; p[4] = (base >> 8) & 0xff; p[5] = ((base >> 8) >> 8) & 0xff; @@ -519,22 +536,15 @@ static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p, p[10] = (len >> 8) & 0xff; p[11] = ((len >> 8) >> 8) & 0xff; - dev_dbg(&dev->dev, " encode mem %#lx-%#lx\n", base, base + len - 1); + dev_dbg(&dev->dev, " encode mem %#llx-%#llx\n", + (unsigned long long) res->start, (unsigned long long) res->end); } static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p, struct resource *res) { - 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; - } + unsigned long base = res->start; + unsigned long len = res->end - res->start + 1; p[4] = base & 0xff; p[5] = (base >> 8) & 0xff; @@ -549,22 +559,15 @@ static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p, p[18] = (len >> 16) & 0xff; p[19] = (len >> 24) & 0xff; - dev_dbg(&dev->dev, " encode mem32 %#lx-%#lx\n", base, base + len - 1); + dev_dbg(&dev->dev, " encode mem32 %#llx-%#llx\n", + (unsigned long long) res->start, (unsigned long long) res->end); } static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p, struct resource *res) { - 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; - } + unsigned long base = res->start; + unsigned long len = res->end - res->start + 1; p[4] = base & 0xff; p[5] = (base >> 8) & 0xff; @@ -575,54 +578,40 @@ static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p, p[10] = (len >> 16) & 0xff; p[11] = (len >> 24) & 0xff; - dev_dbg(&dev->dev, " encode fixed_mem32 %#lx-%#lx\n", base, - base + len - 1); + dev_dbg(&dev->dev, " encode fixed_mem32 %#llx-%#llx\n", + (unsigned long long) res->start, (unsigned long long) res->end); } static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p, struct resource *res) { - unsigned long map; - - if (pnp_resource_enabled(res)) - map = 1 << res->start; - else - map = 0; + unsigned long map = 0; + map = 1 << res->start; p[1] = map & 0xff; p[2] = (map >> 8) & 0xff; - dev_dbg(&dev->dev, " encode irq mask %#lx\n", map); + dev_dbg(&dev->dev, " encode irq %llu\n", + (unsigned long long)res->start); } static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p, struct resource *res) { - unsigned long map; - - if (pnp_resource_enabled(res)) - map = 1 << res->start; - else - map = 0; + unsigned long map = 0; + map = 1 << res->start; p[1] = map & 0xff; - dev_dbg(&dev->dev, " encode dma mask %#lx\n", map); + dev_dbg(&dev->dev, " encode dma %llu\n", + (unsigned long long)res->start); } static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p, struct resource *res) { - 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; - } + unsigned long base = res->start; + unsigned long len = res->end - res->start + 1; p[2] = base & 0xff; p[3] = (base >> 8) & 0xff; @@ -630,7 +619,8 @@ static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p, p[5] = (base >> 8) & 0xff; p[7] = len & 0xff; - dev_dbg(&dev->dev, " encode io %#lx-%#lx\n", base, base + len - 1); + dev_dbg(&dev->dev, " encode io %#llx-%#llx\n", + (unsigned long long) res->start, (unsigned long long) res->end); } static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p, @@ -639,20 +629,12 @@ static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p, unsigned long base = res->start; unsigned long len = res->end - res->start + 1; - if (pnp_resource_enabled(res)) { - base = res->start; - len = res->end - res->start + 1; - } else { - base = 0; - len = 0; - } - p[1] = base & 0xff; p[2] = (base >> 8) & 0xff; p[3] = len & 0xff; - dev_dbg(&dev->dev, " encode fixed_io %#lx-%#lx\n", base, - base + len - 1); + dev_dbg(&dev->dev, " encode fixed_io %#llx-%#llx\n", + (unsigned long long) res->start, (unsigned long long) res->end); } static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev diff --git a/trunk/drivers/pnp/quirks.c b/trunk/drivers/pnp/quirks.c index 55f55ed72dc7..1ff3bb585ab2 100644 --- a/trunk/drivers/pnp/quirks.c +++ b/trunk/drivers/pnp/quirks.c @@ -5,8 +5,6 @@ * when building up the resource structure for the first time. * * Copyright (c) 2000 Peter Denison - * Copyright (C) 2008 Hewlett-Packard Development Company, L.P. - * Bjorn Helgaas * * Heavily based on PCI quirks handling which is * @@ -22,207 +20,203 @@ #include #include "base.h" -static void quirk_awe32_add_ports(struct pnp_dev *dev, - struct pnp_option *option, - unsigned int offset) -{ - struct pnp_option *new_option; - - new_option = kmalloc(sizeof(struct pnp_option), GFP_KERNEL); - if (!new_option) { - dev_err(&dev->dev, "couldn't add ioport region to option set " - "%d\n", pnp_option_set(option)); - return; - } - - *new_option = *option; - new_option->u.port.min += offset; - new_option->u.port.max += offset; - list_add(&new_option->list, &option->list); - - dev_info(&dev->dev, "added ioport region %#llx-%#llx to set %d\n", - (unsigned long long) new_option->u.port.min, - (unsigned long long) new_option->u.port.max, - pnp_option_set(option)); -} - static void quirk_awe32_resources(struct pnp_dev *dev) { - struct pnp_option *option; - unsigned int set = ~0; + struct pnp_port *port, *port2, *port3; + struct pnp_option *res = dev->dependent; /* - * Add two extra ioport regions (at offset 0x400 and 0x800 from the - * one given) to every dependent option set. + * 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. */ - 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); + 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; } + port = res->port; + memcpy(port2, port, sizeof(struct pnp_port)); + memcpy(port3, port, sizeof(struct pnp_port)); + port->next = port2; + port2->next = port3; + port2->min += 0x400; + port2->max += 0x400; + port3->min += 0x800; + port3->max += 0x800; + dev_info(&dev->dev, + "AWE32 quirk - added ioports 0x%lx and 0x%lx\n", + (unsigned long)port2->min, + (unsigned long)port3->min); } } static void quirk_cmi8330_resources(struct pnp_dev *dev) { - struct pnp_option *option; - struct pnp_irq *irq; - struct pnp_dma *dma; + struct pnp_option *res = dev->dependent; + unsigned long tmp; - list_for_each_entry(option, &dev->options, list) { - if (!pnp_option_is_dependent(option)) - continue; + for (; res; res = res->next) { - if (option->type == IORESOURCE_IRQ) { - irq = &option->u.irq; - bitmap_zero(irq->map.bits, PNP_IRQ_NR); - __set_bit(5, irq->map.bits); - __set_bit(7, irq->map.bits); - __set_bit(10, irq->map.bits); - dev_info(&dev->dev, "set possible IRQs in " - "option set %d to 5, 7, 10\n", - pnp_option_set(option)); - } else if (option->type == IORESOURCE_DMA) { - dma = &option->u.dma; - if ((dma->flags & IORESOURCE_DMA_TYPE_MASK) == - IORESOURCE_DMA_8BIT && - dma->map != 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; - } + struct pnp_irq *irq; + struct pnp_dma *dma; + + for (irq = res->irq; irq; irq = irq->next) { // Valid irqs are 5, 7, 10 + tmp = 0x04A0; + bitmap_copy(irq->map, &tmp, 16); // 0000 0100 1010 0000 } + + for (dma = res->dma; dma; dma = dma->next) // Valid 8bit dma channels are 1,3 + if ((dma->flags & IORESOURCE_DMA_TYPE_MASK) == + IORESOURCE_DMA_8BIT) + dma->map = 0x000A; } + dev_info(&dev->dev, "CMI8330 quirk - forced possible IRQs to 5, 7, 10 " + "and DMA channels to 1, 3\n"); } static void quirk_sb16audio_resources(struct pnp_dev *dev) { - struct pnp_option *option; - unsigned int prev_option_flags = ~0, n = 0; struct pnp_port *port; + struct pnp_option *res = dev->dependent; + int changed = 0; /* - * The default range on the OPL port for these devices is 0x388-0x388. + * The default range on the mpu port for these devices is 0x388-0x388. * Here we increase that range so that two such cards can be * auto-configured. */ - list_for_each_entry(option, &dev->options, list) { - if (prev_option_flags != option->flags) { - prev_option_flags = option->flags; - n = 0; - } - 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); - } - } + 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 (changed) + dev_info(&dev->dev, "SB audio device quirk - increased port range\n"); } -static struct pnp_option *pnp_clone_dependent_set(struct pnp_dev *dev, - unsigned int set) +static struct pnp_option *quirk_isapnp_mpu_options(struct pnp_dev *dev) { - struct pnp_option *tail = NULL, *first_new_option = NULL; - struct pnp_option *option, *new_option; - unsigned int flags; + struct pnp_option *head = NULL; + struct pnp_option *prev = NULL; + struct pnp_option *res; - 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; - } + /* + * Build a functional IRQ-less variant of each MPU option. + */ - 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; - } + for (res = dev->dependent; res; res = res->next) { + struct pnp_option *curr; + struct pnp_port *port; + struct pnp_port *copy; + + port = res->port; + if (!port || !res->irq) + continue; + + copy = pnp_alloc(sizeof *copy); + if (!copy) + break; - *new_option = *option; - new_option->flags = flags; - if (!first_new_option) - first_new_option = new_option; + copy->min = port->min; + copy->max = port->max; + copy->align = port->align; + copy->size = port->size; + copy->flags = port->flags; - list_add(&new_option->list, &tail->list); - tail = new_option; + curr = pnp_build_option(PNP_RES_PRIORITY_FUNCTIONAL); + if (!curr) { + kfree(copy); + break; } + curr->port = copy; + + if (prev) + prev->next = curr; + else + head = curr; + prev = curr; } + if (head) + dev_info(&dev->dev, "adding IRQ-less MPU options\n"); - return first_new_option; + return head; } - -static void quirk_add_irq_optional_dependent_sets(struct pnp_dev *dev) +static void quirk_ad1815_mpu_resources(struct pnp_dev *dev) { - struct pnp_option *new_option; - unsigned int num_sets, i, set; + struct pnp_option *res; struct pnp_irq *irq; - num_sets = dev->num_dependent_sets; - for (i = 0; i < num_sets; i++) { - new_option = pnp_clone_dependent_set(dev, i); - if (!new_option) - return; + /* + * Distribute the independent IRQ over the dependent options + */ - 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); - } + res = dev->independent; + if (!res) + return; - dev_info(&dev->dev, "added dependent option set %d (same as " - "set %d except IRQ optional)\n", set, i); + irq = res->irq; + if (!irq || irq->next) + return; + + res = dev->dependent; + if (!res) + return; + + while (1) { + struct pnp_irq *copy; + + copy = pnp_alloc(sizeof *copy); + if (!copy) + break; + + memcpy(copy->map, irq->map, sizeof copy->map); + copy->flags = irq->flags; + + copy->next = res->irq; /* Yes, this is NULL */ + res->irq = copy; + + if (!res->next) + break; + res = res->next; } + kfree(irq); + + res->next = quirk_isapnp_mpu_options(dev); + + res = dev->independent; + res->irq = NULL; } -static void quirk_ad1815_mpu_resources(struct pnp_dev *dev) +static void quirk_isapnp_mpu_resources(struct pnp_dev *dev) { - 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; - } - } + struct pnp_option *res; - if (independent_irqs != 1) + res = dev->dependent; + if (!res) return; - irq->flags |= IORESOURCE_IRQ_OPTIONAL; - dev_info(&dev->dev, "made independent IRQ optional\n"); + while (res->next) + res = res->next; + + res->next = quirk_isapnp_mpu_options(dev); } #include @@ -254,7 +248,8 @@ static void quirk_system_pci_resources(struct pnp_dev *dev) for (j = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, j)); j++) { - if (res->start == 0 && res->end == 0) + if (res->flags & IORESOURCE_UNSET || + (res->start == 0 && res->end == 0)) continue; pnp_start = res->start; @@ -317,10 +312,10 @@ static struct pnp_fixup pnp_fixups[] = { {"CTL0043", quirk_sb16audio_resources}, {"CTL0044", quirk_sb16audio_resources}, {"CTL0045", quirk_sb16audio_resources}, - /* Add IRQ-optional MPU options */ + /* Add IRQ-less MPU options */ {"ADS7151", quirk_ad1815_mpu_resources}, - {"ADS7181", quirk_add_irq_optional_dependent_sets}, - {"AZT0002", quirk_add_irq_optional_dependent_sets}, + {"ADS7181", quirk_isapnp_mpu_resources}, + {"AZT0002", quirk_isapnp_mpu_resources}, /* PnP resources that might overlap PCI BARs */ {"PNP0c01", quirk_system_pci_resources}, {"PNP0c02", quirk_system_pci_resources}, diff --git a/trunk/drivers/pnp/resource.c b/trunk/drivers/pnp/resource.c index 4cfe3a1efdfb..390b50096e30 100644 --- a/trunk/drivers/pnp/resource.c +++ b/trunk/drivers/pnp/resource.c @@ -3,8 +3,6 @@ * * based on isapnp.c resource management (c) Jaroslav Kysela * Copyright 2003 Adam Belay - * Copyright (C) 2008 Hewlett-Packard Development Company, L.P. - * Bjorn Helgaas */ #include @@ -30,121 +28,201 @@ static int pnp_reserve_mem[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some * option registration */ -struct pnp_option *pnp_build_option(struct pnp_dev *dev, unsigned long type, - unsigned int option_flags) +struct pnp_option *pnp_build_option(int priority) { - struct pnp_option *option; + struct pnp_option *option = pnp_alloc(sizeof(struct pnp_option)); - option = kzalloc(sizeof(struct pnp_option), GFP_KERNEL); if (!option) return NULL; - option->flags = option_flags; - option->type = type; + option->priority = priority & 0xff; + /* make sure the priority is valid */ + if (option->priority > PNP_RES_PRIORITY_FUNCTIONAL) + option->priority = PNP_RES_PRIORITY_INVALID; - list_add_tail(&option->list, &dev->options); return option; } -int pnp_register_irq_resource(struct pnp_dev *dev, unsigned int option_flags, - pnp_irq_mask_t *map, unsigned char flags) +struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev) { struct pnp_option *option; - struct pnp_irq *irq; - option = pnp_build_option(dev, IORESOURCE_IRQ, option_flags); - if (!option) - return -ENOMEM; + 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; + + dev_dbg(&dev->dev, "new independent option\n"); + return option; +} + +struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev, + int priority) +{ + struct pnp_option *option; - irq = &option->u.irq; - irq->map = *map; - irq->flags = flags; + option = pnp_build_option(priority); + + if (dev->dependent) { + struct pnp_option *parent = dev->dependent; + while (parent->next) + parent = parent->next; + parent->next = option; + } else + dev->dependent = option; + + dev_dbg(&dev->dev, "new dependent option (priority %#x)\n", priority); + return option; +} + +int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option, + struct pnp_irq *data) +{ + struct pnp_irq *ptr; +#ifdef DEBUG + char buf[PNP_IRQ_NR]; /* hex-encoded, so this is overkill but safe */ +#endif + + ptr = option->irq; + while (ptr && ptr->next) + ptr = ptr->next; + if (ptr) + ptr->next = data; + else + option->irq = data; #ifdef CONFIG_PCI { int i; for (i = 0; i < 16; i++) - if (test_bit(i, irq->map.bits)) + if (test_bit(i, data->map)) pcibios_penalize_isa_irq(i, 0); } #endif - dbg_pnp_show_option(dev, option); +#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 return 0; } -int pnp_register_dma_resource(struct pnp_dev *dev, unsigned int option_flags, - unsigned char map, unsigned char flags) +int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option, + struct pnp_dma *data) { - struct pnp_option *option; - struct pnp_dma *dma; - - option = pnp_build_option(dev, IORESOURCE_DMA, option_flags); - if (!option) - return -ENOMEM; + 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; +} - dma = &option->u.dma; - dma->map = map; - dma->flags = flags; +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; +} - dbg_pnp_show_option(dev, option); +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); return 0; } -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) +static void pnp_free_port(struct pnp_port *port) { - struct pnp_option *option; - struct pnp_port *port; + struct pnp_port *next; - option = pnp_build_option(dev, IORESOURCE_IO, option_flags); - if (!option) - return -ENOMEM; + while (port) { + next = port->next; + kfree(port); + port = next; + } +} - port = &option->u.port; - port->min = min; - port->max = max; - port->align = align; - port->size = size; - port->flags = flags; +static void pnp_free_irq(struct pnp_irq *irq) +{ + struct pnp_irq *next; - dbg_pnp_show_option(dev, option); - return 0; + while (irq) { + next = irq->next; + kfree(irq); + irq = next; + } } -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 void pnp_free_dma(struct pnp_dma *dma) { - struct pnp_option *option; - struct pnp_mem *mem; + struct pnp_dma *next; - option = pnp_build_option(dev, IORESOURCE_MEM, option_flags); - if (!option) - return -ENOMEM; + while (dma) { + next = dma->next; + kfree(dma); + dma = next; + } +} - mem = &option->u.mem; - mem->min = min; - mem->max = max; - mem->align = align; - mem->size = size; - mem->flags = flags; +static void pnp_free_mem(struct pnp_mem *mem) +{ + struct pnp_mem *next; - dbg_pnp_show_option(dev, option); - return 0; + while (mem) { + next = mem->next; + kfree(mem); + mem = next; + } } -void pnp_free_options(struct pnp_dev *dev) +void pnp_free_option(struct pnp_option *option) { - struct pnp_option *option, *tmp; - - list_for_each_entry_safe(option, tmp, &dev->options, list) { - list_del(&option->list); + 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); kfree(option); + option = next; } } @@ -159,7 +237,7 @@ void pnp_free_options(struct pnp_dev *dev) !((*(enda) < *(startb)) || (*(endb) < *(starta))) #define cannot_compare(flags) \ -((flags) & IORESOURCE_DISABLED) +((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED)) int pnp_check_port(struct pnp_dev *dev, struct resource *res) { @@ -286,61 +364,6 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id) return IRQ_HANDLED; } -#ifdef CONFIG_PCI -static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci, - unsigned int irq) -{ - u32 class; - u8 progif; - - if (pci->irq == irq) { - dev_dbg(&pnp->dev, "device %s using irq %d\n", - pci_name(pci), irq); - return 1; - } - - /* - * See pci_setup_device() and ata_pci_sff_activate_host() for - * similar IDE legacy detection. - */ - pci_read_config_dword(pci, PCI_CLASS_REVISION, &class); - class >>= 8; /* discard revision ID */ - progif = class & 0xff; - class >>= 8; - - if (class == PCI_CLASS_STORAGE_IDE) { - /* - * Unless both channels are native-PCI mode only, - * treat the compatibility IRQs as busy. - */ - if ((progif & 0x5) != 0x5) - if (pci_get_legacy_ide_irq(pci, 0) == irq || - pci_get_legacy_ide_irq(pci, 1) == irq) { - dev_dbg(&pnp->dev, "legacy IDE device %s " - "using irq %d\n", pci_name(pci), irq); - return 1; - } - } - - return 0; -} -#endif - -static int pci_uses_irq(struct pnp_dev *pnp, unsigned int irq) -{ -#ifdef CONFIG_PCI - struct pci_dev *pci = NULL; - - for_each_pci_dev(pci) { - if (pci_dev_uses_irq(pnp, pci, irq)) { - pci_dev_put(pci); - return 1; - } - } -#endif - return 0; -} - int pnp_check_irq(struct pnp_dev *dev, struct resource *res) { int i; @@ -372,9 +395,18 @@ 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 */ - if (pci_uses_irq(dev, *irq)) - return 0; + { + struct pci_dev *pci = NULL; + for_each_pci_dev(pci) { + if (pci->irq == *irq) { + pci_dev_put(pci); + return 0; + } + } + } +#endif /* check if the resource is already in use, skip if the * device is active because it itself may be in use */ @@ -467,37 +499,81 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res) #endif } -int pnp_resource_type(struct resource *res) +struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev, + unsigned int type, unsigned int num) { - return res->flags & (IORESOURCE_IO | IORESOURCE_MEM | - IORESOURCE_IRQ | IORESOURCE_DMA); + 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; } struct resource *pnp_get_resource(struct pnp_dev *dev, unsigned int type, unsigned int num) { struct pnp_resource *pnp_res; - struct resource *res; - list_for_each_entry(pnp_res, &dev->resources, list) { - res = &pnp_res->res; - if (pnp_resource_type(res) == type && num-- == 0) - return res; - } + pnp_res = pnp_get_pnp_resource(dev, type, num); + if (pnp_res) + return &pnp_res->res; + return NULL; } EXPORT_SYMBOL(pnp_get_resource); -static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev) +static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev, int type) { struct pnp_resource *pnp_res; + int i; - 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; + 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; } struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, @@ -505,10 +581,15 @@ struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, { struct pnp_resource *pnp_res; struct resource *res; + static unsigned char warned; - pnp_res = pnp_new_resource(dev); + pnp_res = pnp_new_resource(dev, IORESOURCE_IRQ); if (!pnp_res) { - dev_err(&dev->dev, "can't add resource for IRQ %d\n", irq); + if (!warned) { + dev_err(&dev->dev, "can't add resource for IRQ %d\n", + irq); + warned = 1; + } return NULL; } @@ -526,10 +607,15 @@ struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma, { struct pnp_resource *pnp_res; struct resource *res; + static unsigned char warned; - pnp_res = pnp_new_resource(dev); + pnp_res = pnp_new_resource(dev, IORESOURCE_DMA); if (!pnp_res) { - dev_err(&dev->dev, "can't add resource for DMA %d\n", dma); + if (!warned) { + dev_err(&dev->dev, "can't add resource for DMA %d\n", + dma); + warned = 1; + } return NULL; } @@ -548,12 +634,16 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev, { struct pnp_resource *pnp_res; struct resource *res; + static unsigned char warned; - pnp_res = pnp_new_resource(dev); + pnp_res = pnp_new_resource(dev, IORESOURCE_IO); if (!pnp_res) { - dev_err(&dev->dev, "can't add resource for IO %#llx-%#llx\n", - (unsigned long long) start, - (unsigned long long) end); + 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; + } return NULL; } @@ -573,12 +663,16 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev, { struct pnp_resource *pnp_res; struct resource *res; + static unsigned char warned; - pnp_res = pnp_new_resource(dev); + pnp_res = pnp_new_resource(dev, IORESOURCE_MEM); if (!pnp_res) { - dev_err(&dev->dev, "can't add resource for MEM %#llx-%#llx\n", - (unsigned long long) start, - (unsigned long long) end); + 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; + } return NULL; } @@ -592,52 +686,6 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev, return pnp_res; } -/* - * Determine whether the specified resource is a possible configuration - * for this device. - */ -int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start, - resource_size_t size) -{ - struct pnp_option *option; - struct pnp_port *port; - struct pnp_mem *mem; - struct pnp_irq *irq; - struct pnp_dma *dma; - - list_for_each_entry(option, &dev->options, list) { - if (option->type != type) - continue; - - switch (option->type) { - case IORESOURCE_IO: - port = &option->u.port; - if (port->min == start && port->size == size) - return 1; - break; - case IORESOURCE_MEM: - mem = &option->u.mem; - if (mem->min == start && mem->size == size) - return 1; - break; - case IORESOURCE_IRQ: - irq = &option->u.irq; - if (start < PNP_IRQ_NR && - test_bit(start, irq->map.bits)) - return 1; - break; - case IORESOURCE_DMA: - dma = &option->u.dma; - if (dma->map & (1 << start)) - return 1; - break; - } - } - - return 0; -} -EXPORT_SYMBOL(pnp_possible_config); - /* format is: pnp_reserve_irq=irq1[,irq2] .... */ static int __init pnp_setup_reserve_irq(char *str) { diff --git a/trunk/drivers/pnp/support.c b/trunk/drivers/pnp/support.c index bbf78ef4ba02..95b076c18c07 100644 --- a/trunk/drivers/pnp/support.c +++ b/trunk/drivers/pnp/support.c @@ -2,8 +2,6 @@ * support.c - standard functions for the use of pnp protocol drivers * * Copyright 2003 Adam Belay - * Copyright (C) 2008 Hewlett-Packard Development Company, L.P. - * Bjorn Helgaas */ #include @@ -18,10 +16,6 @@ */ int pnp_is_active(struct pnp_dev *dev) { - /* - * I don't think this is very reliable because pnp_disable_dev() - * only clears out auto-assigned resources. - */ if (!pnp_port_start(dev, 0) && pnp_port_len(dev, 0) <= 1 && !pnp_mem_start(dev, 0) && pnp_mem_len(dev, 0) <= 1 && pnp_irq(dev, 0) == -1 && pnp_dma(dev, 0) == -1) @@ -58,154 +52,39 @@ void pnp_eisa_id_to_string(u32 id, char *str) str[7] = '\0'; } -char *pnp_resource_type_name(struct resource *res) -{ - switch (pnp_resource_type(res)) { - case IORESOURCE_IO: - return "io"; - case IORESOURCE_MEM: - return "mem"; - case IORESOURCE_IRQ: - return "irq"; - case IORESOURCE_DMA: - return "dma"; - } - return NULL; -} - void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc) { #ifdef DEBUG - char buf[128]; - int len = 0; - struct pnp_resource *pnp_res; struct resource *res; + int i; - if (list_empty(&dev->resources)) { - dev_dbg(&dev->dev, "%s: no current resources\n", desc); - return; - } - - 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)); + dev_dbg(&dev->dev, "current resources: %s\n", desc); - 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_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); } -#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_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); } - 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, - " "); - 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, - " "); - 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; + for (i = 0; i < PNP_MAX_PORT; i++) { + res = pnp_get_resource(dev, IORESOURCE_IO, i); + if (res && !(res->flags & IORESOURCE_UNSET)) + dev_dbg(&dev->dev, " io %#llx-%#llx flags %#lx\n", + (unsigned long long) res->start, + (unsigned long long) res->end, res->flags); + } + for (i = 0; i < PNP_MAX_MEM; i++) { + res = pnp_get_resource(dev, IORESOURCE_MEM, i); + if (res && !(res->flags & IORESOURCE_UNSET)) + dev_dbg(&dev->dev, " mem %#llx-%#llx flags %#lx\n", + (unsigned long long) res->start, + (unsigned long long) res->end, res->flags); } - dev_dbg(&dev->dev, "%s\n", buf); #endif } diff --git a/trunk/drivers/pnp/system.c b/trunk/drivers/pnp/system.c index 764f3a310685..cf4e07b01d48 100644 --- a/trunk/drivers/pnp/system.c +++ b/trunk/drivers/pnp/system.c @@ -60,7 +60,7 @@ static void reserve_resources_of_dev(struct pnp_dev *dev) int i; for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) { - if (res->flags & IORESOURCE_DISABLED) + if (res->flags & IORESOURCE_UNSET) continue; if (res->start == 0) continue; /* disabled */ @@ -81,7 +81,7 @@ static void reserve_resources_of_dev(struct pnp_dev *dev) } for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) { - if (res->flags & IORESOURCE_DISABLED) + if (res->flags & (IORESOURCE_UNSET | IORESOURCE_DISABLED)) continue; reserve_range(dev, res->start, res->end, 0); diff --git a/trunk/drivers/serial/8250_pnp.c b/trunk/drivers/serial/8250_pnp.c index 638b68649e79..97c68d021d28 100644 --- a/trunk/drivers/serial/8250_pnp.c +++ b/trunk/drivers/serial/8250_pnp.c @@ -383,14 +383,21 @@ static int __devinit check_name(char *name) return 0; } -static int __devinit check_resources(struct pnp_dev *dev) +static int __devinit check_resources(struct pnp_option *option) { - resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8}; - int i; + struct pnp_option *tmp; + if (!option) + return 0; - for (i = 0; i < ARRAY_SIZE(base); i++) { - if (pnp_possible_config(dev, IORESOURCE_IO, base[i], 8)) - return 1; + 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; } return 0; @@ -413,7 +420,10 @@ static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags) (dev->card && check_name(dev->card->name)))) return -ENODEV; - if (check_resources(dev)) + if (check_resources(dev->independent)) + return 0; + + if (check_resources(dev->dependent)) return 0; return -ENODEV; diff --git a/trunk/drivers/w1/masters/ds2482.c b/trunk/drivers/w1/masters/ds2482.c index df52cb355f7d..0fd5820d5c61 100644 --- a/trunk/drivers/w1/masters/ds2482.c +++ b/trunk/drivers/w1/masters/ds2482.c @@ -94,31 +94,21 @@ static const u8 ds2482_chan_rd[8] = #define DS2482_REG_STS_1WB 0x01 -static int ds2482_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int ds2482_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info); -static int ds2482_remove(struct i2c_client *client); +static int ds2482_attach_adapter(struct i2c_adapter *adapter); +static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind); +static int ds2482_detach_client(struct i2c_client *client); /** * Driver data (common to all clients) */ -static const struct i2c_device_id ds2482_id[] = { - { "ds2482", 0 }, - { } -}; - static struct i2c_driver ds2482_driver = { .driver = { .owner = THIS_MODULE, .name = "ds2482", }, - .probe = ds2482_probe, - .remove = ds2482_remove, - .id_table = ds2482_id, - .detect = ds2482_detect, - .address_data = &addr_data, + .attach_adapter = ds2482_attach_adapter, + .detach_client = ds2482_detach_client, }; /* @@ -134,7 +124,7 @@ struct ds2482_w1_chan { }; struct ds2482_data { - struct i2c_client *client; + struct i2c_client client; struct mutex access_lock; /* 1-wire interface(s) */ @@ -157,7 +147,7 @@ struct ds2482_data { static inline int ds2482_select_register(struct ds2482_data *pdev, u8 read_ptr) { if (pdev->read_prt != read_ptr) { - if (i2c_smbus_write_byte_data(pdev->client, + if (i2c_smbus_write_byte_data(&pdev->client, DS2482_CMD_SET_READ_PTR, read_ptr) < 0) return -1; @@ -177,7 +167,7 @@ static inline int ds2482_select_register(struct ds2482_data *pdev, u8 read_ptr) */ static inline int ds2482_send_cmd(struct ds2482_data *pdev, u8 cmd) { - if (i2c_smbus_write_byte(pdev->client, cmd) < 0) + if (i2c_smbus_write_byte(&pdev->client, cmd) < 0) return -1; pdev->read_prt = DS2482_PTR_CODE_STATUS; @@ -197,7 +187,7 @@ static inline int ds2482_send_cmd(struct ds2482_data *pdev, u8 cmd) static inline int ds2482_send_cmd_data(struct ds2482_data *pdev, u8 cmd, u8 byte) { - if (i2c_smbus_write_byte_data(pdev->client, cmd, byte) < 0) + if (i2c_smbus_write_byte_data(&pdev->client, cmd, byte) < 0) return -1; /* all cmds leave in STATUS, except CONFIG */ @@ -226,7 +216,7 @@ static int ds2482_wait_1wire_idle(struct ds2482_data *pdev) if (!ds2482_select_register(pdev, DS2482_PTR_CODE_STATUS)) { do { - temp = i2c_smbus_read_byte(pdev->client); + temp = i2c_smbus_read_byte(&pdev->client); } while ((temp >= 0) && (temp & DS2482_REG_STS_1WB) && (++retries < DS2482_WAIT_IDLE_TIMEOUT)); } @@ -248,13 +238,13 @@ static int ds2482_wait_1wire_idle(struct ds2482_data *pdev) */ static int ds2482_set_channel(struct ds2482_data *pdev, u8 channel) { - if (i2c_smbus_write_byte_data(pdev->client, DS2482_CMD_CHANNEL_SELECT, + if (i2c_smbus_write_byte_data(&pdev->client, DS2482_CMD_CHANNEL_SELECT, ds2482_chan_wr[channel]) < 0) return -1; pdev->read_prt = DS2482_PTR_CODE_CHANNEL; pdev->channel = -1; - if (i2c_smbus_read_byte(pdev->client) == ds2482_chan_rd[channel]) { + if (i2c_smbus_read_byte(&pdev->client) == ds2482_chan_rd[channel]) { pdev->channel = channel; return 0; } @@ -378,7 +368,7 @@ static u8 ds2482_w1_read_byte(void *data) ds2482_select_register(pdev, DS2482_PTR_CODE_DATA); /* Read the data byte */ - result = i2c_smbus_read_byte(pdev->client); + result = i2c_smbus_read_byte(&pdev->client); mutex_unlock(&pdev->access_lock); @@ -425,38 +415,47 @@ static u8 ds2482_w1_reset_bus(void *data) } -static int ds2482_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) +/** + * Called to see if the device exists on an i2c bus. + */ +static int ds2482_attach_adapter(struct i2c_adapter *adapter) { - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_BYTE_DATA | - I2C_FUNC_SMBUS_BYTE)) - return -ENODEV; - - strlcpy(info->type, "ds2482", I2C_NAME_SIZE); - - return 0; + return i2c_probe(adapter, &addr_data, ds2482_detect); } -static int ds2482_probe(struct i2c_client *client, - const struct i2c_device_id *id) + +/* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. + */ +static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind) { struct ds2482_data *data; - int err = -ENODEV; + struct i2c_client *new_client; + int err = 0; int temp1; int idx; + if (!i2c_check_functionality(adapter, + I2C_FUNC_SMBUS_WRITE_BYTE_DATA | + I2C_FUNC_SMBUS_BYTE)) + goto exit; + if (!(data = kzalloc(sizeof(struct ds2482_data), GFP_KERNEL))) { err = -ENOMEM; goto exit; } - data->client = client; - i2c_set_clientdata(client, data); + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->driver = &ds2482_driver; + new_client->adapter = adapter; /* Reset the device (sets the read_ptr to status) */ if (ds2482_send_cmd(data, DS2482_CMD_RESET) < 0) { - dev_warn(&client->dev, "DS2482 reset failed.\n"); + dev_dbg(&adapter->dev, "DS2482 reset failed at 0x%02x.\n", + address); goto exit_free; } @@ -464,10 +463,10 @@ static int ds2482_probe(struct i2c_client *client, ndelay(525); /* Read the status byte - only reset bit and line should be set */ - temp1 = i2c_smbus_read_byte(client); + temp1 = i2c_smbus_read_byte(new_client); if (temp1 != (DS2482_REG_STS_LL | DS2482_REG_STS_RST)) { - dev_warn(&client->dev, "DS2482 reset status " - "0x%02X - not a DS2482\n", temp1); + dev_dbg(&adapter->dev, "DS2482 (0x%02x) reset status " + "0x%02X - not a DS2482\n", address, temp1); goto exit_free; } @@ -479,8 +478,16 @@ static int ds2482_probe(struct i2c_client *client, /* Set all config items to 0 (off) */ ds2482_send_cmd_data(data, DS2482_CMD_WRITE_CONFIG, 0xF0); + /* We can fill in the remaining client fields */ + snprintf(new_client->name, sizeof(new_client->name), "ds2482-%d00", + data->w1_count); + mutex_init(&data->access_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) + goto exit_free; + /* Register 1-wire interface(s) */ for (idx = 0; idx < data->w1_count; idx++) { data->w1_ch[idx].pdev = data; @@ -504,6 +511,8 @@ static int ds2482_probe(struct i2c_client *client, return 0; exit_w1_remove: + i2c_detach_client(new_client); + for (idx = 0; idx < data->w1_count; idx++) { if (data->w1_ch[idx].pdev != NULL) w1_remove_master_device(&data->w1_ch[idx].w1_bm); @@ -514,10 +523,10 @@ static int ds2482_probe(struct i2c_client *client, return err; } -static int ds2482_remove(struct i2c_client *client) +static int ds2482_detach_client(struct i2c_client *client) { struct ds2482_data *data = i2c_get_clientdata(client); - int idx; + int err, idx; /* Unregister the 1-wire bridge(s) */ for (idx = 0; idx < data->w1_count; idx++) { @@ -525,6 +534,13 @@ static int ds2482_remove(struct i2c_client *client) w1_remove_master_device(&data->w1_ch[idx].w1_bm); } + /* Detach the i2c device */ + if ((err = i2c_detach_client(client))) { + dev_err(&client->dev, + "Deregistration failed, client not detached.\n"); + return err; + } + /* Free the memory */ kfree(data); return 0; diff --git a/trunk/firmware/.gitignore b/trunk/firmware/.gitignore deleted file mode 100644 index d9c69017bc9a..000000000000 --- a/trunk/firmware/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -*.gen.S -*.fw -*.bin -*.csp -*.dsp -ihex2fw diff --git a/trunk/firmware/Makefile b/trunk/firmware/Makefile index 9fe86041f86e..e4f2fb3d1917 100644 --- a/trunk/firmware/Makefile +++ b/trunk/firmware/Makefile @@ -56,7 +56,7 @@ fw-shipped-$(CONFIG_USB_SERIAL_KEYSPAN_USA28X) += keyspan/usa28x.fw fw-shipped-$(CONFIG_USB_SERIAL_KEYSPAN_USA49W) += keyspan/usa49w.fw fw-shipped-$(CONFIG_USB_SERIAL_KEYSPAN_USA49WLC) += keyspan/usa49wlc.fw else -fw-shipped- += keyspan/mpr.fw keyspan/usa18x.fw keyspan/usa19.fw \ +fw-shipped- := keyspan/mpr.fw keyspan/usa18x.fw keyspan/usa19.fw \ keyspan/usa19qi.fw keyspan/usa19qw.fw keyspan/usa19w.fw \ keyspan/usa28.fw keyspan/usa28xa.fw keyspan/usa28xb.fw \ keyspan/usa28x.fw keyspan/usa49w.fw keyspan/usa49wlc.fw diff --git a/trunk/fs/Kconfig b/trunk/fs/Kconfig index 84ab76a206a0..313b2e06ded5 100644 --- a/trunk/fs/Kconfig +++ b/trunk/fs/Kconfig @@ -1544,6 +1544,10 @@ config UFS_FS The recently released UFS2 variant (used in FreeBSD 5.x) is READ-ONLY supported. + If you only intend to mount files from some other Unix over the + network using NFS, you don't need the UFS file system support (but + you need NFS file system support obviously). + Note that this option is generally not needed for floppies, since a good portable way to transport files and directories between unixes (and even other operating systems) is given by the tar program ("man @@ -1583,7 +1587,6 @@ menuconfig NETWORK_FILESYSTEMS Say Y here to get to see options for network filesystems and filesystem-related networking code, such as NFS daemon and RPCSEC security modules. - This option alone does not add any kernel code. If you say N, all options in this submenu will be skipped and @@ -1592,92 +1595,76 @@ menuconfig NETWORK_FILESYSTEMS if NETWORK_FILESYSTEMS config NFS_FS - tristate "NFS client support" + tristate "NFS file system support" depends on INET select LOCKD select SUNRPC select NFS_ACL_SUPPORT if NFS_V3_ACL help - Choose Y here if you want to access files residing on other - computers using Sun's Network File System protocol. To compile - this file system support as a module, choose M here: the module - will be called nfs. + If you are connected to some other (usually local) Unix computer + (using SLIP, PLIP, PPP or Ethernet) and want to mount files residing + on that computer (the NFS server) using the Network File Sharing + protocol, say Y. "Mounting files" means that the client can access + the files with usual UNIX commands as if they were sitting on the + client's hard disk. For this to work, the server must run the + programs nfsd and mountd (but does not need to have NFS file system + support enabled in its kernel). NFS is explained in the Network + Administrator's Guide, available from + , on its man page: "man + nfs", and in the NFS-HOWTO. - To mount file systems exported by NFS servers, you also need to - install the user space mount.nfs command which can be found in - the Linux nfs-utils package, available from http://linux-nfs.org/. - Information about using the mount command is available in the - mount(8) man page. More detail about the Linux NFS client - implementation is available via the nfs(5) man page. + A superior but less widely used alternative to NFS is provided by + the Coda file system; see "Coda file system support" below. - Below you can choose which versions of the NFS protocol are - available in the kernel to mount NFS servers. Support for NFS - version 2 (RFC 1094) is always available when NFS_FS is selected. + If you say Y here, you should have said Y to TCP/IP networking also. + This option would enlarge your kernel by about 27 KB. - To configure a system which mounts its root file system via NFS - at boot time, say Y here, select "Kernel level IP - autoconfiguration" in the NETWORK menu, and select "Root file - system on NFS" below. You cannot compile this file system as a - module in this case. + To compile this file system support as a module, choose M here: the + module will be called nfs. - If unsure, say N. + If you are configuring a diskless machine which will mount its root + file system over NFS at boot time, say Y here and to "Kernel + level IP autoconfiguration" above and to "Root file system on NFS" + below. You cannot compile this driver as a module in this case. + There are two packages designed for booting diskless machines over + the net: netboot, available from + , and Etherboot, + available from . + + If you don't know what all this is about, say N. config NFS_V3 - bool "NFS client support for NFS version 3" + bool "Provide NFSv3 client support" depends on NFS_FS help - This option enables support for version 3 of the NFS protocol - (RFC 1813) in the kernel's NFS client. + Say Y here if you want your NFS client to be able to speak version + 3 of the NFS protocol. If unsure, say Y. config NFS_V3_ACL - bool "NFS client support for the NFSv3 ACL protocol extension" + bool "Provide client support for the NFSv3 ACL protocol extension" depends on NFS_V3 help - Some NFS servers support an auxiliary NFSv3 ACL protocol that - Sun added to Solaris but never became an official part of the - NFS version 3 protocol. This protocol extension allows - applications on NFS clients to manipulate POSIX Access Control - Lists on files residing on NFS servers. NFS servers enforce - ACLs on local files whether this protocol is available or not. - - Choose Y here if your NFS server supports the Solaris NFSv3 ACL - protocol extension and you want your NFS client to allow - applications to access and modify ACLs on files on the server. - - Most NFS servers don't support the Solaris NFSv3 ACL protocol - extension. You can choose N here or specify the "noacl" mount - option to prevent your NFS client from trying to use the NFSv3 - ACL protocol. + Implement the NFSv3 ACL protocol extension for manipulating POSIX + Access Control Lists. The server should also be compiled with + the NFSv3 ACL protocol extension; see the CONFIG_NFSD_V3_ACL option. If unsure, say N. config NFS_V4 - bool "NFS client support for NFS version 4 (EXPERIMENTAL)" + bool "Provide NFSv4 client support (EXPERIMENTAL)" depends on NFS_FS && EXPERIMENTAL select RPCSEC_GSS_KRB5 help - This option enables support for version 4 of the NFS protocol - (RFC 3530) in the kernel's NFS client. + Say Y here if you want your NFS client to be able to speak the newer + version 4 of the NFS protocol. - To mount NFS servers using NFSv4, you also need to install user - space programs which can be found in the Linux nfs-utils package, - available from http://linux-nfs.org/. + Note: Requires auxiliary userspace daemons which may be found on + http://www.citi.umich.edu/projects/nfsv4/ If unsure, say N. -config ROOT_NFS - bool "Root file system on NFS" - depends on NFS_FS=y && IP_PNP - help - If you want your system to mount its root file system via NFS, - choose Y here. This is common practice for managing systems - without local permanent storage. For details, read - . - - Most people say N here. - config NFSD tristate "NFS server support" depends on INET @@ -1759,6 +1746,20 @@ config NFSD_V4 If unsure, say N. +config ROOT_NFS + bool "Root file system on NFS" + depends on NFS_FS=y && IP_PNP + help + If you want your Linux box to mount its whole root file system (the + one containing the directory /) from some other computer over the + net via NFS (presumably because your box doesn't have a hard disk), + say Y. Read for + details. It is likely that in this case, you also want to say Y to + "Kernel level IP autoconfiguration" so that your box can discover + its network address at boot time. + + Most people say N here. + config LOCKD tristate @@ -1799,6 +1800,27 @@ config SUNRPC_XPRT_RDMA If unsure, say N. +config SUNRPC_BIND34 + bool "Support for rpcbind versions 3 & 4 (EXPERIMENTAL)" + depends on SUNRPC && EXPERIMENTAL + default n + help + RPC requests over IPv6 networks require support for larger + addresses when performing an RPC bind. Sun added support for + IPv6 addressing by creating two new versions of the rpcbind + protocol (RFC 1833). + + This option enables support in the kernel RPC client for + querying rpcbind servers via versions 3 and 4 of the rpcbind + protocol. The kernel automatically falls back to version 2 + if a remote rpcbind service does not support versions 3 or 4. + By themselves, these new versions do not provide support for + RPC over IPv6, but the new protocol versions are necessary to + support it. + + If unsure, say N to get traditional behavior (version 2 rpcbind + requests only). + config RPCSEC_GSS_KRB5 tristate "Secure RPC: Kerberos V mechanism (EXPERIMENTAL)" depends on SUNRPC && EXPERIMENTAL diff --git a/trunk/fs/compat_ioctl.c b/trunk/fs/compat_ioctl.c index c54eaab71a19..97dba0d92348 100644 --- a/trunk/fs/compat_ioctl.c +++ b/trunk/fs/compat_ioctl.c @@ -69,11 +69,9 @@ #include #include -#ifdef CONFIG_BLOCK #include #include #include -#endif #include #include @@ -2026,7 +2024,6 @@ COMPATIBLE_IOCTL(GIO_UNISCRNMAP) COMPATIBLE_IOCTL(PIO_UNISCRNMAP) COMPATIBLE_IOCTL(PIO_FONTRESET) COMPATIBLE_IOCTL(PIO_UNIMAPCLR) -#ifdef CONFIG_BLOCK /* Big S */ COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN) COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK) @@ -2036,7 +2033,6 @@ COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER) COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND) COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST) COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI) -#endif /* Big T */ COMPATIBLE_IOCTL(TUNSETNOCSUM) COMPATIBLE_IOCTL(TUNSETDEBUG) @@ -2107,7 +2103,6 @@ COMPATIBLE_IOCTL(SIOCGIFVLAN) COMPATIBLE_IOCTL(SIOCSIFVLAN) COMPATIBLE_IOCTL(SIOCBRADDBR) COMPATIBLE_IOCTL(SIOCBRDELBR) -#ifdef CONFIG_BLOCK /* SG stuff */ COMPATIBLE_IOCTL(SG_SET_TIMEOUT) COMPATIBLE_IOCTL(SG_GET_TIMEOUT) @@ -2132,7 +2127,6 @@ COMPATIBLE_IOCTL(SG_SCSI_RESET) COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE) COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN) COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN) -#endif /* PPP stuff */ COMPATIBLE_IOCTL(PPPIOCGFLAGS) COMPATIBLE_IOCTL(PPPIOCSFLAGS) diff --git a/trunk/fs/lockd/clntproc.c b/trunk/fs/lockd/clntproc.c index 1f6dc518505c..5df517b81f3f 100644 --- a/trunk/fs/lockd/clntproc.c +++ b/trunk/fs/lockd/clntproc.c @@ -224,9 +224,7 @@ void nlm_release_call(struct nlm_rqst *call) static void nlmclnt_rpc_release(void *data) { - lock_kernel(); nlm_release_call(data); - unlock_kernel(); } static int nlm_wait_on_grace(wait_queue_head_t *queue) @@ -432,7 +430,7 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl) * Report the conflicting lock back to the application. */ fl->fl_start = req->a_res.lock.fl.fl_start; - fl->fl_end = req->a_res.lock.fl.fl_end; + fl->fl_end = req->a_res.lock.fl.fl_start; fl->fl_type = req->a_res.lock.fl.fl_type; fl->fl_pid = 0; break; @@ -712,9 +710,7 @@ static void nlmclnt_unlock_callback(struct rpc_task *task, void *data) die: return; retry_rebind: - lock_kernel(); nlm_rebind_host(req->a_host); - unlock_kernel(); retry_unlock: rpc_restart_call(task); } @@ -792,9 +788,7 @@ static void nlmclnt_cancel_callback(struct rpc_task *task, void *data) /* Don't ever retry more than 3 times */ if (req->a_retries++ >= NLMCLNT_MAX_RETRIES) goto die; - lock_kernel(); nlm_rebind_host(req->a_host); - unlock_kernel(); rpc_restart_call(task); rpc_delay(task, 30 * HZ); } diff --git a/trunk/fs/lockd/svc4proc.c b/trunk/fs/lockd/svc4proc.c index 2e27176ff42f..385437e3387d 100644 --- a/trunk/fs/lockd/svc4proc.c +++ b/trunk/fs/lockd/svc4proc.c @@ -248,9 +248,7 @@ static void nlm4svc_callback_exit(struct rpc_task *task, void *data) static void nlm4svc_callback_release(void *data) { - lock_kernel(); nlm_release_call(data); - unlock_kernel(); } static const struct rpc_call_ops nlm4svc_callback_ops = { diff --git a/trunk/fs/lockd/svclock.c b/trunk/fs/lockd/svclock.c index 56a08ab9a4cb..81aca859bfde 100644 --- a/trunk/fs/lockd/svclock.c +++ b/trunk/fs/lockd/svclock.c @@ -795,7 +795,6 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data) dprintk("lockd: GRANT_MSG RPC callback\n"); - lock_kernel(); /* if the block is not on a list at this point then it has * been invalidated. Don't try to requeue it. * @@ -805,7 +804,7 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data) * for nlm_blocked? */ if (list_empty(&block->b_list)) - goto out; + return; /* Technically, we should down the file semaphore here. Since we * move the block towards the head of the queue only, no harm @@ -819,17 +818,13 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data) } nlmsvc_insert_block(block, timeout); svc_wake_up(block->b_daemon); -out: - unlock_kernel(); } static void nlmsvc_grant_release(void *data) { struct nlm_rqst *call = data; - lock_kernel(); nlmsvc_release_block(call->a_block); - unlock_kernel(); } static const struct rpc_call_ops nlmsvc_grant_ops = { diff --git a/trunk/fs/lockd/svcproc.c b/trunk/fs/lockd/svcproc.c index ce6952b50a75..88379cc6e0b1 100644 --- a/trunk/fs/lockd/svcproc.c +++ b/trunk/fs/lockd/svcproc.c @@ -278,9 +278,7 @@ static void nlmsvc_callback_exit(struct rpc_task *task, void *data) static void nlmsvc_callback_release(void *data) { - lock_kernel(); nlm_release_call(data); - unlock_kernel(); } static const struct rpc_call_ops nlmsvc_callback_ops = { diff --git a/trunk/fs/nfs/callback.c b/trunk/fs/nfs/callback.c index f447f4b4476c..c1e7c8300629 100644 --- a/trunk/fs/nfs/callback.c +++ b/trunk/fs/nfs/callback.c @@ -27,7 +27,7 @@ struct nfs_callback_data { unsigned int users; - struct svc_rqst *rqst; + struct svc_serv *serv; struct task_struct *task; }; @@ -91,17 +91,21 @@ nfs_callback_svc(void *vrqstp) svc_process(rqstp); } unlock_kernel(); + nfs_callback_info.task = NULL; + svc_exit_thread(rqstp); return 0; } /* - * Bring up the callback thread if it is not already up. + * Bring up the server process if it is not already up. */ int nfs_callback_up(void) { struct svc_serv *serv = NULL; + struct svc_rqst *rqstp; int ret = 0; + lock_kernel(); mutex_lock(&nfs_callback_mutex); if (nfs_callback_info.users++ || nfs_callback_info.task != NULL) goto out; @@ -117,23 +121,22 @@ int nfs_callback_up(void) nfs_callback_tcpport = ret; dprintk("Callback port = 0x%x\n", nfs_callback_tcpport); - nfs_callback_info.rqst = svc_prepare_thread(serv, &serv->sv_pools[0]); - if (IS_ERR(nfs_callback_info.rqst)) { - ret = PTR_ERR(nfs_callback_info.rqst); - nfs_callback_info.rqst = NULL; + rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]); + if (IS_ERR(rqstp)) { + ret = PTR_ERR(rqstp); goto out_err; } svc_sock_update_bufs(serv); + nfs_callback_info.serv = serv; - nfs_callback_info.task = kthread_run(nfs_callback_svc, - nfs_callback_info.rqst, + nfs_callback_info.task = kthread_run(nfs_callback_svc, rqstp, "nfsv4-svc"); if (IS_ERR(nfs_callback_info.task)) { ret = PTR_ERR(nfs_callback_info.task); - svc_exit_thread(nfs_callback_info.rqst); - nfs_callback_info.rqst = NULL; + nfs_callback_info.serv = NULL; nfs_callback_info.task = NULL; + svc_exit_thread(rqstp); goto out_err; } out: @@ -146,6 +149,7 @@ int nfs_callback_up(void) if (serv) svc_destroy(serv); mutex_unlock(&nfs_callback_mutex); + unlock_kernel(); return ret; out_err: dprintk("Couldn't create callback socket or server thread; err = %d\n", @@ -155,19 +159,17 @@ int nfs_callback_up(void) } /* - * Kill the callback thread if it's no longer being used. + * Kill the server process if it is not already down. */ void nfs_callback_down(void) { + lock_kernel(); mutex_lock(&nfs_callback_mutex); nfs_callback_info.users--; - if (nfs_callback_info.users == 0 && nfs_callback_info.task != NULL) { + if (nfs_callback_info.users == 0 && nfs_callback_info.task != NULL) kthread_stop(nfs_callback_info.task); - svc_exit_thread(nfs_callback_info.rqst); - nfs_callback_info.rqst = NULL; - nfs_callback_info.task = NULL; - } mutex_unlock(&nfs_callback_mutex); + unlock_kernel(); } static int nfs_callback_authenticate(struct svc_rqst *rqstp) diff --git a/trunk/fs/nfs/client.c b/trunk/fs/nfs/client.c index 5ee23e7058b3..f2a092ca69b5 100644 --- a/trunk/fs/nfs/client.c +++ b/trunk/fs/nfs/client.c @@ -431,14 +431,14 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, { to->to_initval = timeo * HZ / 10; to->to_retries = retrans; + if (!to->to_retries) + to->to_retries = 2; switch (proto) { case XPRT_TRANSPORT_TCP: case XPRT_TRANSPORT_RDMA: - if (to->to_retries == 0) - to->to_retries = NFS_DEF_TCP_RETRANS; if (to->to_initval == 0) - to->to_initval = NFS_DEF_TCP_TIMEO * HZ / 10; + to->to_initval = 60 * HZ; if (to->to_initval > NFS_MAX_TCP_TIMEOUT) to->to_initval = NFS_MAX_TCP_TIMEOUT; to->to_increment = to->to_initval; @@ -450,17 +450,14 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, to->to_exponential = 0; break; case XPRT_TRANSPORT_UDP: - if (to->to_retries == 0) - to->to_retries = NFS_DEF_UDP_RETRANS; + default: if (!to->to_initval) - to->to_initval = NFS_DEF_UDP_TIMEO * HZ / 10; + to->to_initval = 11 * HZ / 10; if (to->to_initval > NFS_MAX_UDP_TIMEOUT) to->to_initval = NFS_MAX_UDP_TIMEOUT; to->to_maxval = NFS_MAX_UDP_TIMEOUT; to->to_exponential = 1; break; - default: - BUG(); } } diff --git a/trunk/fs/nfs/dir.c b/trunk/fs/nfs/dir.c index 28a238dab23a..982a2064fe4c 100644 --- a/trunk/fs/nfs/dir.c +++ b/trunk/fs/nfs/dir.c @@ -133,14 +133,13 @@ nfs_opendir(struct inode *inode, struct file *filp) { int res; - dfprintk(FILE, "NFS: open dir(%s/%s)\n", - filp->f_path.dentry->d_parent->d_name.name, - filp->f_path.dentry->d_name.name); - - nfs_inc_stats(inode, NFSIOS_VFSOPEN); + dfprintk(VFS, "NFS: opendir(%s/%ld)\n", + inode->i_sb->s_id, inode->i_ino); + lock_kernel(); /* Call generic open code in order to cache credentials */ res = nfs_open(inode, filp); + unlock_kernel(); return res; } @@ -529,11 +528,13 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) struct nfs_fattr fattr; long res; - dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", + dfprintk(VFS, "NFS: readdir(%s/%s) starting at cookie %Lu\n", dentry->d_parent->d_name.name, dentry->d_name.name, (long long)filp->f_pos); nfs_inc_stats(inode, NFSIOS_VFSGETDENTS); + lock_kernel(); + /* * filp->f_pos points to the dirent entry number. * *desc->dir_cookie has the cookie for the next entry. We have @@ -591,9 +592,10 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) } out: nfs_unblock_sillyrename(dentry); + unlock_kernel(); if (res > 0) res = 0; - dfprintk(FILE, "NFS: readdir(%s/%s) returns %ld\n", + dfprintk(VFS, "NFS: readdir(%s/%s) returns %ld\n", dentry->d_parent->d_name.name, dentry->d_name.name, res); return res; @@ -601,15 +603,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) { - struct dentry *dentry = filp->f_path.dentry; - struct inode *inode = dentry->d_inode; - - dfprintk(FILE, "NFS: llseek dir(%s/%s, %lld, %d)\n", - dentry->d_parent->d_name.name, - dentry->d_name.name, - offset, origin); - - mutex_lock(&inode->i_mutex); + mutex_lock(&filp->f_path.dentry->d_inode->i_mutex); switch (origin) { case 1: offset += filp->f_pos; @@ -625,7 +619,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) nfs_file_open_context(filp)->dir_cookie = 0; } out: - mutex_unlock(&inode->i_mutex); + mutex_unlock(&filp->f_path.dentry->d_inode->i_mutex); return offset; } @@ -635,11 +629,10 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) */ static int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync) { - dfprintk(FILE, "NFS: fsync dir(%s/%s) datasync %d\n", + dfprintk(VFS, "NFS: fsync_dir(%s/%s) datasync %d\n", dentry->d_parent->d_name.name, dentry->d_name.name, datasync); - nfs_inc_stats(dentry->d_inode, NFSIOS_VFSFSYNC); return 0; } @@ -774,6 +767,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) struct nfs_fattr fattr; parent = dget_parent(dentry); + lock_kernel(); dir = parent->d_inode; nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE); inode = dentry->d_inode; @@ -811,6 +805,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); out_valid: + unlock_kernel(); dput(parent); dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is valid\n", __func__, dentry->d_parent->d_name.name, @@ -829,6 +824,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) shrink_dcache_parent(dentry); } d_drop(dentry); + unlock_kernel(); dput(parent); dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n", __func__, dentry->d_parent->d_name.name, @@ -862,14 +858,6 @@ static int nfs_dentry_delete(struct dentry *dentry) } -static void nfs_drop_nlink(struct inode *inode) -{ - spin_lock(&inode->i_lock); - if (inode->i_nlink > 0) - drop_nlink(inode); - spin_unlock(&inode->i_lock); -} - /* * Called when the dentry loses inode. * We use it to clean up silly-renamed files. @@ -881,8 +869,10 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA; if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { + lock_kernel(); drop_nlink(inode); nfs_complete_unlink(dentry, inode); + unlock_kernel(); } iput(inode); } @@ -913,6 +903,8 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru res = ERR_PTR(-ENOMEM); dentry->d_op = NFS_PROTO(dir)->dentry_ops; + lock_kernel(); + /* * If we're doing an exclusive create, optimize away the lookup * but don't hash the dentry. @@ -920,7 +912,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru if (nfs_is_exclusive_create(dir, nd)) { d_instantiate(dentry, NULL); res = NULL; - goto out; + goto out_unlock; } parent = dentry->d_parent; @@ -948,6 +940,8 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); out_unblock_sillyrename: nfs_unblock_sillyrename(parent); +out_unlock: + unlock_kernel(); out: return res; } @@ -1005,7 +999,9 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry } /* Open the file on the server */ + lock_kernel(); res = nfs4_atomic_open(dir, dentry, nd); + unlock_kernel(); if (IS_ERR(res)) { error = PTR_ERR(res); switch (error) { @@ -1067,7 +1063,9 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) * operations that change the directory. We therefore save the * change attribute *before* we do the RPC call. */ + lock_kernel(); ret = nfs4_open_revalidate(dir, dentry, openflags, nd); + unlock_kernel(); out: dput(parent); if (!ret) @@ -1220,11 +1218,14 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode, if ((nd->flags & LOOKUP_CREATE) != 0) open_flags = nd->intent.open.flags; + lock_kernel(); error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd); if (error != 0) goto out_err; + unlock_kernel(); return 0; out_err: + unlock_kernel(); d_drop(dentry); return error; } @@ -1247,11 +1248,14 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) attr.ia_mode = mode; attr.ia_valid = ATTR_MODE; + lock_kernel(); status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev); if (status != 0) goto out_err; + unlock_kernel(); return 0; out_err: + unlock_kernel(); d_drop(dentry); return status; } @@ -1270,12 +1274,15 @@ static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) attr.ia_valid = ATTR_MODE; attr.ia_mode = mode | S_IFDIR; + lock_kernel(); error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr); if (error != 0) goto out_err; + unlock_kernel(); return 0; out_err: d_drop(dentry); + unlock_kernel(); return error; } @@ -1292,12 +1299,14 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry) dfprintk(VFS, "NFS: rmdir(%s/%ld), %s\n", dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); + lock_kernel(); error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name); /* Ensure the VFS deletes this inode */ if (error == 0 && dentry->d_inode != NULL) clear_nlink(dentry->d_inode); else if (error == -ENOENT) nfs_dentry_handle_enoent(dentry); + unlock_kernel(); return error; } @@ -1399,7 +1408,7 @@ static int nfs_safe_remove(struct dentry *dentry) error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); /* The VFS may want to delete this inode */ if (error == 0) - nfs_drop_nlink(inode); + drop_nlink(inode); nfs_mark_for_revalidate(inode); } else error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); @@ -1422,6 +1431,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) dfprintk(VFS, "NFS: unlink(%s/%ld, %s)\n", dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); + lock_kernel(); spin_lock(&dcache_lock); spin_lock(&dentry->d_lock); if (atomic_read(&dentry->d_count) > 1) { @@ -1430,6 +1440,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) /* Start asynchronous writeout of the inode */ write_inode_now(dentry->d_inode, 0); error = nfs_sillyrename(dir, dentry); + unlock_kernel(); return error; } if (!d_unhashed(dentry)) { @@ -1443,6 +1454,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); } else if (need_rehash) d_rehash(dentry); + unlock_kernel(); return error; } @@ -1479,9 +1491,13 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym attr.ia_mode = S_IFLNK | S_IRWXUGO; attr.ia_valid = ATTR_MODE; + lock_kernel(); + page = alloc_page(GFP_HIGHUSER); - if (!page) + if (!page) { + unlock_kernel(); return -ENOMEM; + } kaddr = kmap_atomic(page, KM_USER0); memcpy(kaddr, symname, pathlen); @@ -1496,6 +1512,7 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym dentry->d_name.name, symname, error); d_drop(dentry); __free_page(page); + unlock_kernel(); return error; } @@ -1513,6 +1530,7 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym } else __free_page(page); + unlock_kernel(); return 0; } @@ -1526,12 +1544,14 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) old_dentry->d_parent->d_name.name, old_dentry->d_name.name, dentry->d_parent->d_name.name, dentry->d_name.name); + lock_kernel(); d_drop(dentry); error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); if (error == 0) { atomic_inc(&inode->i_count); d_add(dentry, inode); } + unlock_kernel(); return error; } @@ -1571,6 +1591,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, * To prevent any new references to the target during the rename, * we unhash the dentry and free the inode in advance. */ + lock_kernel(); if (!d_unhashed(new_dentry)) { d_drop(new_dentry); rehash = new_dentry; @@ -1614,7 +1635,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, /* dentry still busy? */ goto out; } else - nfs_drop_nlink(new_inode); + drop_nlink(new_inode); go_ahead: /* @@ -1648,6 +1669,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, /* new dentry created? */ if (dentry) dput(dentry); + unlock_kernel(); return error; } @@ -1940,6 +1962,8 @@ int nfs_permission(struct inode *inode, int mask, struct nameidata *nd) } force_lookup: + lock_kernel(); + if (!NFS_PROTO(inode)->access) goto out_notsup; @@ -1949,6 +1973,7 @@ int nfs_permission(struct inode *inode, int mask, struct nameidata *nd) put_rpccred(cred); } else res = PTR_ERR(cred); + unlock_kernel(); out: dfprintk(VFS, "NFS: permission(%s/%ld), mask=0x%x, res=%d\n", inode->i_sb->s_id, inode->i_ino, mask, res); @@ -1957,6 +1982,7 @@ int nfs_permission(struct inode *inode, int mask, struct nameidata *nd) res = nfs_revalidate_inode(NFS_SERVER(inode), inode); if (res == 0) res = generic_permission(inode, mask, NULL); + unlock_kernel(); goto out; } diff --git a/trunk/fs/nfs/direct.c b/trunk/fs/nfs/direct.c index 08f6b040d289..4757a2b326a1 100644 --- a/trunk/fs/nfs/direct.c +++ b/trunk/fs/nfs/direct.c @@ -890,7 +890,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, count = iov_length(iov, nr_segs); nfs_add_stats(mapping->host, NFSIOS_DIRECTREADBYTES, count); - dfprintk(FILE, "NFS: direct read(%s/%s, %zd@%Ld)\n", + dprintk("nfs: direct read(%s/%s, %zd@%Ld)\n", file->f_path.dentry->d_parent->d_name.name, file->f_path.dentry->d_name.name, count, (long long) pos); @@ -947,7 +947,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, count = iov_length(iov, nr_segs); nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, count); - dfprintk(FILE, "NFS: direct write(%s/%s, %zd@%Ld)\n", + dfprintk(VFS, "nfs: direct write(%s/%s, %zd@%Ld)\n", file->f_path.dentry->d_parent->d_name.name, file->f_path.dentry->d_name.name, count, (long long) pos); diff --git a/trunk/fs/nfs/file.c b/trunk/fs/nfs/file.c index 78460657f5cb..4e98a56a1777 100644 --- a/trunk/fs/nfs/file.c +++ b/trunk/fs/nfs/file.c @@ -50,7 +50,7 @@ static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov, static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov, unsigned long nr_segs, loff_t pos); static int nfs_file_flush(struct file *, fl_owner_t id); -static int nfs_file_fsync(struct file *, struct dentry *dentry, int datasync); +static int nfs_fsync(struct file *, struct dentry *dentry, int datasync); static int nfs_check_flags(int flags); static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); @@ -72,7 +72,7 @@ const struct file_operations nfs_file_operations = { .open = nfs_file_open, .flush = nfs_file_flush, .release = nfs_file_release, - .fsync = nfs_file_fsync, + .fsync = nfs_fsync, .lock = nfs_lock, .flock = nfs_flock, .splice_read = nfs_file_splice_read, @@ -119,33 +119,25 @@ nfs_file_open(struct inode *inode, struct file *filp) { int res; - dprintk("NFS: open file(%s/%s)\n", - filp->f_path.dentry->d_parent->d_name.name, - filp->f_path.dentry->d_name.name); - res = nfs_check_flags(filp->f_flags); if (res) return res; nfs_inc_stats(inode, NFSIOS_VFSOPEN); - res = nfs_open(inode, filp); + lock_kernel(); + res = NFS_PROTO(inode)->file_open(inode, filp); + unlock_kernel(); return res; } static int nfs_file_release(struct inode *inode, struct file *filp) { - struct dentry *dentry = filp->f_path.dentry; - - dprintk("NFS: release(%s/%s)\n", - dentry->d_parent->d_name.name, - dentry->d_name.name); - /* Ensure that dirty pages are flushed out with the right creds */ if (filp->f_mode & FMODE_WRITE) - nfs_wb_all(dentry->d_inode); + nfs_wb_all(filp->f_path.dentry->d_inode); nfs_inc_stats(inode, NFSIOS_VFSRELEASE); - return nfs_release(inode, filp); + return NFS_PROTO(inode)->file_release(inode, filp); } /** @@ -179,12 +171,6 @@ static int nfs_revalidate_file_size(struct inode *inode, struct file *filp) static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) { loff_t loff; - - dprintk("NFS: llseek file(%s/%s, %lld, %d)\n", - filp->f_path.dentry->d_parent->d_name.name, - filp->f_path.dentry->d_name.name, - offset, origin); - /* origin == SEEK_END => we must revalidate the cached file length */ if (origin == SEEK_END) { struct inode *inode = filp->f_mapping->host; @@ -199,7 +185,7 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) } /* - * Helper for nfs_file_flush() and nfs_file_fsync() + * Helper for nfs_file_flush() and nfs_fsync() * * Notice that it clears the NFS_CONTEXT_ERROR_WRITE before synching to * disk, but it retrieves and clears ctx->error after synching, despite @@ -225,18 +211,16 @@ static int nfs_do_fsync(struct nfs_open_context *ctx, struct inode *inode) /* * Flush all dirty pages, and check for write errors. + * */ static int nfs_file_flush(struct file *file, fl_owner_t id) { struct nfs_open_context *ctx = nfs_file_open_context(file); - struct dentry *dentry = file->f_path.dentry; - struct inode *inode = dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int status; - dprintk("NFS: flush(%s/%s)\n", - dentry->d_parent->d_name.name, - dentry->d_name.name); + dfprintk(VFS, "nfs: flush(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino); if ((file->f_mode & FMODE_WRITE) == 0) return 0; @@ -261,7 +245,7 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov, if (iocb->ki_filp->f_flags & O_DIRECT) return nfs_file_direct_read(iocb, iov, nr_segs, pos); - dprintk("NFS: read(%s/%s, %lu@%lu)\n", + dfprintk(VFS, "nfs: read(%s/%s, %lu@%lu)\n", dentry->d_parent->d_name.name, dentry->d_name.name, (unsigned long) count, (unsigned long) pos); @@ -281,7 +265,7 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos, struct inode *inode = dentry->d_inode; ssize_t res; - dprintk("NFS: splice_read(%s/%s, %lu@%Lu)\n", + dfprintk(VFS, "nfs: splice_read(%s/%s, %lu@%Lu)\n", dentry->d_parent->d_name.name, dentry->d_name.name, (unsigned long) count, (unsigned long long) *ppos); @@ -298,7 +282,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) struct inode *inode = dentry->d_inode; int status; - dprintk("NFS: mmap(%s/%s)\n", + dfprintk(VFS, "nfs: mmap(%s/%s)\n", dentry->d_parent->d_name.name, dentry->d_name.name); status = nfs_revalidate_mapping(inode, file->f_mapping); @@ -316,14 +300,12 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) * whether any write errors occurred for this process. */ static int -nfs_file_fsync(struct file *file, struct dentry *dentry, int datasync) +nfs_fsync(struct file *file, struct dentry *dentry, int datasync) { struct nfs_open_context *ctx = nfs_file_open_context(file); struct inode *inode = dentry->d_inode; - dprintk("NFS: fsync file(%s/%s) datasync %d\n", - dentry->d_parent->d_name.name, dentry->d_name.name, - datasync); + dfprintk(VFS, "nfs: fsync(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino); nfs_inc_stats(inode, NFSIOS_VFSFSYNC); return nfs_do_fsync(ctx, inode); @@ -346,11 +328,6 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping, struct page *page; index = pos >> PAGE_CACHE_SHIFT; - dfprintk(PAGECACHE, "NFS: write_begin(%s/%s(%ld), %u@%lld)\n", - file->f_path.dentry->d_parent->d_name.name, - file->f_path.dentry->d_name.name, - mapping->host->i_ino, len, (long long) pos); - page = __grab_cache_page(mapping, index); if (!page) return -ENOMEM; @@ -371,32 +348,9 @@ static int nfs_write_end(struct file *file, struct address_space *mapping, unsigned offset = pos & (PAGE_CACHE_SIZE - 1); int status; - dfprintk(PAGECACHE, "NFS: write_end(%s/%s(%ld), %u@%lld)\n", - file->f_path.dentry->d_parent->d_name.name, - file->f_path.dentry->d_name.name, - mapping->host->i_ino, len, (long long) pos); - - /* - * Zero any uninitialised parts of the page, and then mark the page - * as up to date if it turns out that we're extending the file. - */ - if (!PageUptodate(page)) { - unsigned pglen = nfs_page_length(page); - unsigned end = offset + len; - - if (pglen == 0) { - zero_user_segments(page, 0, offset, - end, PAGE_CACHE_SIZE); - SetPageUptodate(page); - } else if (end >= pglen) { - zero_user_segment(page, end, PAGE_CACHE_SIZE); - if (offset == 0) - SetPageUptodate(page); - } else - zero_user_segment(page, pglen, PAGE_CACHE_SIZE); - } - + lock_kernel(); status = nfs_updatepage(file, page, offset, copied); + unlock_kernel(); unlock_page(page); page_cache_release(page); @@ -408,8 +362,6 @@ static int nfs_write_end(struct file *file, struct address_space *mapping, static void nfs_invalidate_page(struct page *page, unsigned long offset) { - dfprintk(PAGECACHE, "NFS: invalidate_page(%p, %lu)\n", page, offset); - if (offset != 0) return; /* Cancel any unstarted writes on this page */ @@ -418,20 +370,13 @@ static void nfs_invalidate_page(struct page *page, unsigned long offset) static int nfs_release_page(struct page *page, gfp_t gfp) { - dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); - /* If PagePrivate() is set, then the page is not freeable */ return 0; } static int nfs_launder_page(struct page *page) { - struct inode *inode = page->mapping->host; - - dfprintk(PAGECACHE, "NFS: launder_page(%ld, %llu)\n", - inode->i_ino, (long long)page_offset(page)); - - return nfs_wb_page(inode, page); + return nfs_wb_page(page->mapping->host, page); } const struct address_space_operations nfs_file_aops = { @@ -451,19 +396,13 @@ const struct address_space_operations nfs_file_aops = { static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page) { struct file *filp = vma->vm_file; - struct dentry *dentry = filp->f_path.dentry; unsigned pagelen; int ret = -EINVAL; struct address_space *mapping; - dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n", - dentry->d_parent->d_name.name, dentry->d_name.name, - filp->f_mapping->host->i_ino, - (long long)page_offset(page)); - lock_page(page); mapping = page->mapping; - if (mapping != dentry->d_inode->i_mapping) + if (mapping != vma->vm_file->f_path.dentry->d_inode->i_mapping) goto out_unlock; ret = 0; @@ -511,9 +450,9 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, if (iocb->ki_filp->f_flags & O_DIRECT) return nfs_file_direct_write(iocb, iov, nr_segs, pos); - dprintk("NFS: write(%s/%s, %lu@%Ld)\n", + dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%Ld)\n", dentry->d_parent->d_name.name, dentry->d_name.name, - (unsigned long) count, (long long) pos); + inode->i_ino, (unsigned long) count, (long long) pos); result = -EBUSY; if (IS_SWAPFILE(inode)) @@ -647,8 +586,7 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) * This makes locking act as a cache coherency point. */ nfs_sync_mapping(filp->f_mapping); - if (!nfs_have_delegation(inode, FMODE_READ)) - nfs_zap_caches(inode); + nfs_zap_caches(inode); out: return status; } @@ -658,35 +596,23 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) */ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) { - struct inode *inode = filp->f_mapping->host; - int ret = -ENOLCK; + struct inode * inode = filp->f_mapping->host; - dprintk("NFS: lock(%s/%s, t=%x, fl=%x, r=%lld:%lld)\n", - filp->f_path.dentry->d_parent->d_name.name, - filp->f_path.dentry->d_name.name, + dprintk("NFS: nfs_lock(f=%s/%ld, t=%x, fl=%x, r=%Ld:%Ld)\n", + inode->i_sb->s_id, inode->i_ino, fl->fl_type, fl->fl_flags, (long long)fl->fl_start, (long long)fl->fl_end); - nfs_inc_stats(inode, NFSIOS_VFSLOCK); /* No mandatory locks over NFS */ if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) - goto out_err; - - if (NFS_PROTO(inode)->lock_check_bounds != NULL) { - ret = NFS_PROTO(inode)->lock_check_bounds(fl); - if (ret < 0) - goto out_err; - } + return -ENOLCK; if (IS_GETLK(cmd)) - ret = do_getlk(filp, cmd, fl); - else if (fl->fl_type == F_UNLCK) - ret = do_unlk(filp, cmd, fl); - else - ret = do_setlk(filp, cmd, fl); -out_err: - return ret; + return do_getlk(filp, cmd, fl); + if (fl->fl_type == F_UNLCK) + return do_unlk(filp, cmd, fl); + return do_setlk(filp, cmd, fl); } /* @@ -694,9 +620,9 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) */ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) { - dprintk("NFS: flock(%s/%s, t=%x, fl=%x)\n", - filp->f_path.dentry->d_parent->d_name.name, - filp->f_path.dentry->d_name.name, + dprintk("NFS: nfs_flock(f=%s/%ld, t=%x, fl=%x)\n", + filp->f_path.dentry->d_inode->i_sb->s_id, + filp->f_path.dentry->d_inode->i_ino, fl->fl_type, fl->fl_flags); /* @@ -719,15 +645,12 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) return do_setlk(filp, cmd, fl); } -/* - * There is no protocol support for leases, so we have no way to implement - * them correctly in the face of opens by other clients. - */ static int nfs_setlease(struct file *file, long arg, struct file_lock **fl) { - dprintk("NFS: setlease(%s/%s, arg=%ld)\n", - file->f_path.dentry->d_parent->d_name.name, - file->f_path.dentry->d_name.name, arg); - + /* + * There is no protocol support for leases, so we have no way + * to implement them correctly in the face of opens by other + * clients. + */ return -EINVAL; } diff --git a/trunk/fs/nfs/inode.c b/trunk/fs/nfs/inode.c index df23f987da6b..596c5d8e86f4 100644 --- a/trunk/fs/nfs/inode.c +++ b/trunk/fs/nfs/inode.c @@ -57,6 +57,8 @@ static int enable_ino64 = NFS_64_BIT_INODE_NUMBERS_ENABLED; static void nfs_invalidate_inode(struct inode *); static int nfs_update_inode(struct inode *, struct nfs_fattr *); +static void nfs_zap_acl_cache(struct inode *); + static struct kmem_cache * nfs_inode_cachep; static inline unsigned long @@ -165,7 +167,7 @@ void nfs_zap_mapping(struct inode *inode, struct address_space *mapping) } } -void nfs_zap_acl_cache(struct inode *inode) +static void nfs_zap_acl_cache(struct inode *inode) { void (*clear_acl_cache)(struct inode *); @@ -345,7 +347,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) goto out; } -#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE) +#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET) int nfs_setattr(struct dentry *dentry, struct iattr *attr) @@ -367,9 +369,10 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) /* Optimization: if the end result is no change, don't RPC */ attr->ia_valid &= NFS_VALID_ATTRS; - if ((attr->ia_valid & ~ATTR_FILE) == 0) + if (attr->ia_valid == 0) return 0; + lock_kernel(); /* Write all dirty data */ if (S_ISREG(inode->i_mode)) { filemap_write_and_wait(inode->i_mapping); @@ -383,65 +386,10 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); if (error == 0) nfs_refresh_inode(inode, &fattr); + unlock_kernel(); return error; } -/** - * nfs_vmtruncate - unmap mappings "freed" by truncate() syscall - * @inode: inode of the file used - * @offset: file offset to start truncating - * - * This is a copy of the common vmtruncate, but with the locking - * corrected to take into account the fact that NFS requires - * inode->i_size to be updated under the inode->i_lock. - */ -static int nfs_vmtruncate(struct inode * inode, loff_t offset) -{ - if (i_size_read(inode) < offset) { - unsigned long limit; - - limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit != RLIM_INFINITY && offset > limit) - goto out_sig; - if (offset > inode->i_sb->s_maxbytes) - goto out_big; - spin_lock(&inode->i_lock); - i_size_write(inode, offset); - spin_unlock(&inode->i_lock); - } else { - struct address_space *mapping = inode->i_mapping; - - /* - * truncation of in-use swapfiles is disallowed - it would - * cause subsequent swapout to scribble on the now-freed - * blocks. - */ - if (IS_SWAPFILE(inode)) - return -ETXTBSY; - spin_lock(&inode->i_lock); - i_size_write(inode, offset); - spin_unlock(&inode->i_lock); - - /* - * unmap_mapping_range is called twice, first simply for - * efficiency so that truncate_inode_pages does fewer - * single-page unmaps. However after this first call, and - * before truncate_inode_pages finishes, it is possible for - * private pages to be COWed, which remain after - * truncate_inode_pages finishes, hence the second - * unmap_mapping_range call must be made for correctness. - */ - unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); - truncate_inode_pages(mapping, offset); - unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); - } - return 0; -out_sig: - send_sig(SIGXFSZ, current, 0); -out_big: - return -EFBIG; -} - /** * nfs_setattr_update_inode - Update inode metadata after a setattr call. * @inode: pointer to struct inode @@ -468,7 +416,8 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) } if ((attr->ia_valid & ATTR_SIZE) != 0) { nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC); - nfs_vmtruncate(inode, attr->ia_size); + inode->i_size = attr->ia_size; + vmtruncate(inode, attr->ia_size); } } @@ -698,6 +647,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) inode->i_sb->s_id, (long long)NFS_FILEID(inode)); nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); + lock_kernel(); if (is_bad_inode(inode)) goto out_nowait; if (NFS_STALE(inode)) @@ -746,6 +696,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) nfs_wake_up_inode(inode); out_nowait: + unlock_kernel(); return status; } @@ -880,9 +831,9 @@ static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) if (S_ISDIR(inode->i_mode)) nfsi->cache_validity |= NFS_INO_INVALID_DATA; } - if (i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size) && + if (inode->i_size == nfs_size_to_loff_t(fattr->pre_size) && nfsi->npages == 0) - i_size_write(inode, nfs_size_to_loff_t(fattr->size)); + inode->i_size = nfs_size_to_loff_t(fattr->size); } } @@ -1023,7 +974,7 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa (fattr->valid & NFS_ATTR_WCC) == 0) { memcpy(&fattr->pre_ctime, &inode->i_ctime, sizeof(fattr->pre_ctime)); memcpy(&fattr->pre_mtime, &inode->i_mtime, sizeof(fattr->pre_mtime)); - fattr->pre_size = i_size_read(inode); + fattr->pre_size = inode->i_size; fattr->valid |= NFS_ATTR_WCC; } return nfs_post_op_update_inode(inode, fattr); @@ -1108,7 +1059,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) /* Do we perhaps have any outstanding writes, or has * the file grown beyond our last write? */ if (nfsi->npages == 0 || new_isize > cur_isize) { - i_size_write(inode, new_isize); + inode->i_size = new_isize; invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; } dprintk("NFS: isize change on server for file %s/%ld\n", diff --git a/trunk/fs/nfs/internal.h b/trunk/fs/nfs/internal.h index 24241fcbb98d..04ae867dddba 100644 --- a/trunk/fs/nfs/internal.h +++ b/trunk/fs/nfs/internal.h @@ -150,7 +150,6 @@ extern void nfs_clear_inode(struct inode *); #ifdef CONFIG_NFS_V4 extern void nfs4_clear_inode(struct inode *); #endif -void nfs_zap_acl_cache(struct inode *inode); /* super.c */ extern struct file_system_type nfs_xdev_fs_type; diff --git a/trunk/fs/nfs/iostat.h b/trunk/fs/nfs/iostat.h index a36952810032..6350ecbde589 100644 --- a/trunk/fs/nfs/iostat.h +++ b/trunk/fs/nfs/iostat.h @@ -5,41 +5,135 @@ * * Copyright (C) 2005, 2006 Chuck Lever * + * NFS client per-mount statistics provide information about the health of + * the NFS client and the health of each NFS mount point. Generally these + * are not for detailed problem diagnosis, but simply to indicate that there + * is a problem. + * + * These counters are not meant to be human-readable, but are meant to be + * integrated into system monitoring tools such as "sar" and "iostat". As + * such, the counters are sampled by the tools over time, and are never + * zeroed after a file system is mounted. Moving averages can be computed + * by the tools by taking the difference between two instantaneous samples + * and dividing that by the time between the samples. */ #ifndef _NFS_IOSTAT #define _NFS_IOSTAT +#define NFS_IOSTAT_VERS "1.0" + +/* + * NFS byte counters + * + * 1. SERVER - the number of payload bytes read from or written to the + * server by the NFS client via an NFS READ or WRITE request. + * + * 2. NORMAL - the number of bytes read or written by applications via + * the read(2) and write(2) system call interfaces. + * + * 3. DIRECT - the number of bytes read or written from files opened + * with the O_DIRECT flag. + * + * These counters give a view of the data throughput into and out of the NFS + * client. Comparing the number of bytes requested by an application with the + * number of bytes the client requests from the server can provide an + * indication of client efficiency (per-op, cache hits, etc). + * + * These counters can also help characterize which access methods are in + * use. DIRECT by itself shows whether there is any O_DIRECT traffic. + * NORMAL + DIRECT shows how much data is going through the system call + * interface. A large amount of SERVER traffic without much NORMAL or + * DIRECT traffic shows that applications are using mapped files. + * + * NFS page counters + * + * These count the number of pages read or written via nfs_readpage(), + * nfs_readpages(), or their write equivalents. + */ +enum nfs_stat_bytecounters { + NFSIOS_NORMALREADBYTES = 0, + NFSIOS_NORMALWRITTENBYTES, + NFSIOS_DIRECTREADBYTES, + NFSIOS_DIRECTWRITTENBYTES, + NFSIOS_SERVERREADBYTES, + NFSIOS_SERVERWRITTENBYTES, + NFSIOS_READPAGES, + NFSIOS_WRITEPAGES, + __NFSIOS_BYTESMAX, +}; + +/* + * NFS event counters + * + * These counters provide a low-overhead way of monitoring client activity + * without enabling NFS trace debugging. The counters show the rate at + * which VFS requests are made, and how often the client invalidates its + * data and attribute caches. This allows system administrators to monitor + * such things as how close-to-open is working, and answer questions such + * as "why are there so many GETATTR requests on the wire?" + * + * They also count anamolous events such as short reads and writes, silly + * renames due to close-after-delete, and operations that change the size + * of a file (such operations can often be the source of data corruption + * if applications aren't using file locking properly). + */ +enum nfs_stat_eventcounters { + NFSIOS_INODEREVALIDATE = 0, + NFSIOS_DENTRYREVALIDATE, + NFSIOS_DATAINVALIDATE, + NFSIOS_ATTRINVALIDATE, + NFSIOS_VFSOPEN, + NFSIOS_VFSLOOKUP, + NFSIOS_VFSACCESS, + NFSIOS_VFSUPDATEPAGE, + NFSIOS_VFSREADPAGE, + NFSIOS_VFSREADPAGES, + NFSIOS_VFSWRITEPAGE, + NFSIOS_VFSWRITEPAGES, + NFSIOS_VFSGETDENTS, + NFSIOS_VFSSETATTR, + NFSIOS_VFSFLUSH, + NFSIOS_VFSFSYNC, + NFSIOS_VFSLOCK, + NFSIOS_VFSRELEASE, + NFSIOS_CONGESTIONWAIT, + NFSIOS_SETATTRTRUNC, + NFSIOS_EXTENDWRITE, + NFSIOS_SILLYRENAME, + NFSIOS_SHORTREAD, + NFSIOS_SHORTWRITE, + NFSIOS_DELAY, + __NFSIOS_COUNTSMAX, +}; + +#ifdef __KERNEL__ + #include #include -#include struct nfs_iostats { unsigned long long bytes[__NFSIOS_BYTESMAX]; unsigned long events[__NFSIOS_COUNTSMAX]; } ____cacheline_aligned; -static inline void nfs_inc_server_stats(const struct nfs_server *server, - enum nfs_stat_eventcounters stat) +static inline void nfs_inc_server_stats(struct nfs_server *server, enum nfs_stat_eventcounters stat) { struct nfs_iostats *iostats; int cpu; cpu = get_cpu(); iostats = per_cpu_ptr(server->io_stats, cpu); - iostats->events[stat]++; + iostats->events[stat] ++; put_cpu_no_resched(); } -static inline void nfs_inc_stats(const struct inode *inode, - enum nfs_stat_eventcounters stat) +static inline void nfs_inc_stats(struct inode *inode, enum nfs_stat_eventcounters stat) { nfs_inc_server_stats(NFS_SERVER(inode), stat); } -static inline void nfs_add_server_stats(const struct nfs_server *server, - enum nfs_stat_bytecounters stat, - unsigned long addend) +static inline void nfs_add_server_stats(struct nfs_server *server, enum nfs_stat_bytecounters stat, unsigned long addend) { struct nfs_iostats *iostats; int cpu; @@ -50,9 +144,7 @@ static inline void nfs_add_server_stats(const struct nfs_server *server, put_cpu_no_resched(); } -static inline void nfs_add_stats(const struct inode *inode, - enum nfs_stat_bytecounters stat, - unsigned long addend) +static inline void nfs_add_stats(struct inode *inode, enum nfs_stat_bytecounters stat, unsigned long addend) { nfs_add_server_stats(NFS_SERVER(inode), stat, addend); } @@ -68,4 +160,5 @@ static inline void nfs_free_iostats(struct nfs_iostats *stats) free_percpu(stats); } -#endif /* _NFS_IOSTAT */ +#endif +#endif diff --git a/trunk/fs/nfs/nfs3acl.c b/trunk/fs/nfs/nfs3acl.c index 423842f51ac9..9b7362565c0c 100644 --- a/trunk/fs/nfs/nfs3acl.c +++ b/trunk/fs/nfs/nfs3acl.c @@ -5,8 +5,6 @@ #include #include -#include "internal.h" - #define NFSDBG_FACILITY NFSDBG_PROC ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size) @@ -207,8 +205,6 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type) status = nfs_revalidate_inode(server, inode); if (status < 0) return ERR_PTR(status); - if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL) - nfs_zap_acl_cache(inode); acl = nfs3_get_cached_acl(inode, type); if (acl != ERR_PTR(-EAGAIN)) return acl; @@ -323,8 +319,9 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, dprintk("NFS call setacl\n"); msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_SETACL]; status = rpc_call_sync(server->client_acl, &msg, 0); - nfs_access_zap_cache(inode); - nfs_zap_acl_cache(inode); + spin_lock(&inode->i_lock); + NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS; + spin_unlock(&inode->i_lock); dprintk("NFS reply setacl: %d\n", status); /* pages may have been allocated at the xdr layer. */ diff --git a/trunk/fs/nfs/nfs3proc.c b/trunk/fs/nfs/nfs3proc.c index 1e750e4574a9..c3523ad03ed1 100644 --- a/trunk/fs/nfs/nfs3proc.c +++ b/trunk/fs/nfs/nfs3proc.c @@ -129,8 +129,6 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, int status; dprintk("NFS call setattr\n"); - if (sattr->ia_valid & ATTR_FILE) - msg.rpc_cred = nfs_file_cred(sattr->ia_file); nfs_fattr_init(fattr); status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); if (status == 0) @@ -250,53 +248,6 @@ static int nfs3_proc_readlink(struct inode *inode, struct page *page, return status; } -struct nfs3_createdata { - struct rpc_message msg; - union { - struct nfs3_createargs create; - struct nfs3_mkdirargs mkdir; - struct nfs3_symlinkargs symlink; - struct nfs3_mknodargs mknod; - } arg; - struct nfs3_diropres res; - struct nfs_fh fh; - struct nfs_fattr fattr; - struct nfs_fattr dir_attr; -}; - -static struct nfs3_createdata *nfs3_alloc_createdata(void) -{ - struct nfs3_createdata *data; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (data != NULL) { - data->msg.rpc_argp = &data->arg; - data->msg.rpc_resp = &data->res; - data->res.fh = &data->fh; - data->res.fattr = &data->fattr; - data->res.dir_attr = &data->dir_attr; - nfs_fattr_init(data->res.fattr); - nfs_fattr_init(data->res.dir_attr); - } - return data; -} - -static int nfs3_do_create(struct inode *dir, struct dentry *dentry, struct nfs3_createdata *data) -{ - int status; - - status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0); - nfs_post_op_update_inode(dir, data->res.dir_attr); - if (status == 0) - status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); - return status; -} - -static void nfs3_free_createdata(struct nfs3_createdata *data) -{ - kfree(data); -} - /* * Create a regular file. * For now, we don't implement O_EXCL. @@ -305,60 +256,70 @@ static int nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, int flags, struct nameidata *nd) { - struct nfs3_createdata *data; + struct nfs_fh fhandle; + struct nfs_fattr fattr; + struct nfs_fattr dir_attr; + struct nfs3_createargs arg = { + .fh = NFS_FH(dir), + .name = dentry->d_name.name, + .len = dentry->d_name.len, + .sattr = sattr, + }; + struct nfs3_diropres res = { + .dir_attr = &dir_attr, + .fh = &fhandle, + .fattr = &fattr + }; + struct rpc_message msg = { + .rpc_proc = &nfs3_procedures[NFS3PROC_CREATE], + .rpc_argp = &arg, + .rpc_resp = &res, + }; mode_t mode = sattr->ia_mode; - int status = -ENOMEM; + int status; dprintk("NFS call create %s\n", dentry->d_name.name); - - data = nfs3_alloc_createdata(); - if (data == NULL) - goto out; - - data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_CREATE]; - data->arg.create.fh = NFS_FH(dir); - data->arg.create.name = dentry->d_name.name; - data->arg.create.len = dentry->d_name.len; - data->arg.create.sattr = sattr; - - data->arg.create.createmode = NFS3_CREATE_UNCHECKED; + arg.createmode = NFS3_CREATE_UNCHECKED; if (flags & O_EXCL) { - data->arg.create.createmode = NFS3_CREATE_EXCLUSIVE; - data->arg.create.verifier[0] = jiffies; - data->arg.create.verifier[1] = current->pid; + arg.createmode = NFS3_CREATE_EXCLUSIVE; + arg.verifier[0] = jiffies; + arg.verifier[1] = current->pid; } sattr->ia_mode &= ~current->fs->umask; - for (;;) { - status = nfs3_do_create(dir, dentry, data); +again: + nfs_fattr_init(&dir_attr); + nfs_fattr_init(&fattr); + status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); + nfs_refresh_inode(dir, &dir_attr); - if (status != -ENOTSUPP) - break; - /* If the server doesn't support the exclusive creation - * semantics, try again with simple 'guarded' mode. */ - switch (data->arg.create.createmode) { + /* If the server doesn't support the exclusive creation semantics, + * try again with simple 'guarded' mode. */ + if (status == -ENOTSUPP) { + switch (arg.createmode) { case NFS3_CREATE_EXCLUSIVE: - data->arg.create.createmode = NFS3_CREATE_GUARDED; + arg.createmode = NFS3_CREATE_GUARDED; break; case NFS3_CREATE_GUARDED: - data->arg.create.createmode = NFS3_CREATE_UNCHECKED; + arg.createmode = NFS3_CREATE_UNCHECKED; break; case NFS3_CREATE_UNCHECKED: goto out; } - nfs_fattr_init(data->res.dir_attr); - nfs_fattr_init(data->res.fattr); + goto again; } + if (status == 0) + status = nfs_instantiate(dentry, &fhandle, &fattr); if (status != 0) goto out; /* When we created the file with exclusive semantics, make * sure we set the attributes afterwards. */ - if (data->arg.create.createmode == NFS3_CREATE_EXCLUSIVE) { + if (arg.createmode == NFS3_CREATE_EXCLUSIVE) { dprintk("NFS call setattr (post-create)\n"); if (!(sattr->ia_valid & ATTR_ATIME_SET)) @@ -369,15 +330,14 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, /* Note: we could use a guarded setattr here, but I'm * not sure this buys us anything (and I'd have * to revamp the NFSv3 XDR code) */ - status = nfs3_proc_setattr(dentry, data->res.fattr, sattr); - nfs_post_op_update_inode(dentry->d_inode, data->res.fattr); + status = nfs3_proc_setattr(dentry, &fattr, sattr); + nfs_post_op_update_inode(dentry->d_inode, &fattr); dprintk("NFS reply setattr (post-create): %d\n", status); - if (status != 0) - goto out; } + if (status != 0) + goto out; status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode); out: - nfs3_free_createdata(data); dprintk("NFS reply create: %d\n", status); return status; } @@ -492,28 +452,40 @@ static int nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, unsigned int len, struct iattr *sattr) { - struct nfs3_createdata *data; - int status = -ENOMEM; + struct nfs_fh fhandle; + struct nfs_fattr fattr, dir_attr; + struct nfs3_symlinkargs arg = { + .fromfh = NFS_FH(dir), + .fromname = dentry->d_name.name, + .fromlen = dentry->d_name.len, + .pages = &page, + .pathlen = len, + .sattr = sattr + }; + struct nfs3_diropres res = { + .dir_attr = &dir_attr, + .fh = &fhandle, + .fattr = &fattr + }; + struct rpc_message msg = { + .rpc_proc = &nfs3_procedures[NFS3PROC_SYMLINK], + .rpc_argp = &arg, + .rpc_resp = &res, + }; + int status; if (len > NFS3_MAXPATHLEN) return -ENAMETOOLONG; dprintk("NFS call symlink %s\n", dentry->d_name.name); - data = nfs3_alloc_createdata(); - if (data == NULL) + nfs_fattr_init(&dir_attr); + nfs_fattr_init(&fattr); + status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); + nfs_post_op_update_inode(dir, &dir_attr); + if (status != 0) goto out; - data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_SYMLINK]; - data->arg.symlink.fromfh = NFS_FH(dir); - data->arg.symlink.fromname = dentry->d_name.name; - data->arg.symlink.fromlen = dentry->d_name.len; - data->arg.symlink.pages = &page; - data->arg.symlink.pathlen = len; - data->arg.symlink.sattr = sattr; - - status = nfs3_do_create(dir, dentry, data); - - nfs3_free_createdata(data); + status = nfs_instantiate(dentry, &fhandle, &fattr); out: dprintk("NFS reply symlink: %d\n", status); return status; @@ -522,31 +494,42 @@ nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, static int nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) { - struct nfs3_createdata *data; + struct nfs_fh fhandle; + struct nfs_fattr fattr, dir_attr; + struct nfs3_mkdirargs arg = { + .fh = NFS_FH(dir), + .name = dentry->d_name.name, + .len = dentry->d_name.len, + .sattr = sattr + }; + struct nfs3_diropres res = { + .dir_attr = &dir_attr, + .fh = &fhandle, + .fattr = &fattr + }; + struct rpc_message msg = { + .rpc_proc = &nfs3_procedures[NFS3PROC_MKDIR], + .rpc_argp = &arg, + .rpc_resp = &res, + }; int mode = sattr->ia_mode; - int status = -ENOMEM; + int status; dprintk("NFS call mkdir %s\n", dentry->d_name.name); sattr->ia_mode &= ~current->fs->umask; - data = nfs3_alloc_createdata(); - if (data == NULL) + nfs_fattr_init(&dir_attr); + nfs_fattr_init(&fattr); + status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); + nfs_post_op_update_inode(dir, &dir_attr); + if (status != 0) goto out; - - data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKDIR]; - data->arg.mkdir.fh = NFS_FH(dir); - data->arg.mkdir.name = dentry->d_name.name; - data->arg.mkdir.len = dentry->d_name.len; - data->arg.mkdir.sattr = sattr; - - status = nfs3_do_create(dir, dentry, data); + status = nfs_instantiate(dentry, &fhandle, &fattr); if (status != 0) goto out; - status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode); out: - nfs3_free_createdata(data); dprintk("NFS reply mkdir: %d\n", status); return status; } @@ -632,50 +615,52 @@ static int nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, dev_t rdev) { - struct nfs3_createdata *data; + struct nfs_fh fh; + struct nfs_fattr fattr, dir_attr; + struct nfs3_mknodargs arg = { + .fh = NFS_FH(dir), + .name = dentry->d_name.name, + .len = dentry->d_name.len, + .sattr = sattr, + .rdev = rdev + }; + struct nfs3_diropres res = { + .dir_attr = &dir_attr, + .fh = &fh, + .fattr = &fattr + }; + struct rpc_message msg = { + .rpc_proc = &nfs3_procedures[NFS3PROC_MKNOD], + .rpc_argp = &arg, + .rpc_resp = &res, + }; mode_t mode = sattr->ia_mode; - int status = -ENOMEM; + int status; + + switch (sattr->ia_mode & S_IFMT) { + case S_IFBLK: arg.type = NF3BLK; break; + case S_IFCHR: arg.type = NF3CHR; break; + case S_IFIFO: arg.type = NF3FIFO; break; + case S_IFSOCK: arg.type = NF3SOCK; break; + default: return -EINVAL; + } dprintk("NFS call mknod %s %u:%u\n", dentry->d_name.name, MAJOR(rdev), MINOR(rdev)); sattr->ia_mode &= ~current->fs->umask; - data = nfs3_alloc_createdata(); - if (data == NULL) - goto out; - - data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKNOD]; - data->arg.mknod.fh = NFS_FH(dir); - data->arg.mknod.name = dentry->d_name.name; - data->arg.mknod.len = dentry->d_name.len; - data->arg.mknod.sattr = sattr; - data->arg.mknod.rdev = rdev; - - switch (sattr->ia_mode & S_IFMT) { - case S_IFBLK: - data->arg.mknod.type = NF3BLK; - break; - case S_IFCHR: - data->arg.mknod.type = NF3CHR; - break; - case S_IFIFO: - data->arg.mknod.type = NF3FIFO; - break; - case S_IFSOCK: - data->arg.mknod.type = NF3SOCK; - break; - default: - status = -EINVAL; + nfs_fattr_init(&dir_attr); + nfs_fattr_init(&fattr); + status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); + nfs_post_op_update_inode(dir, &dir_attr); + if (status != 0) goto out; - } - - status = nfs3_do_create(dir, dentry, data); + status = nfs_instantiate(dentry, &fh, &fattr); if (status != 0) goto out; status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode); out: - nfs3_free_createdata(data); dprintk("NFS reply mknod: %d\n", status); return status; } @@ -816,6 +801,8 @@ const struct nfs_rpc_ops nfs_v3_clientops = { .write_done = nfs3_write_done, .commit_setup = nfs3_proc_commit_setup, .commit_done = nfs3_commit_done, + .file_open = nfs_open, + .file_release = nfs_release, .lock = nfs3_proc_lock, .clear_acl_cache = nfs3_forget_cached_acls, }; diff --git a/trunk/fs/nfs/nfs4proc.c b/trunk/fs/nfs/nfs4proc.c index c910413eaeca..1293e0acd82b 100644 --- a/trunk/fs/nfs/nfs4proc.c +++ b/trunk/fs/nfs/nfs4proc.c @@ -451,7 +451,9 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) /* Save the delegation */ memcpy(stateid.data, delegation->stateid.data, sizeof(stateid.data)); rcu_read_unlock(); + lock_kernel(); ret = nfs_may_open(state->inode, state->owner->so_cred, open_mode); + unlock_kernel(); if (ret != 0) goto out; ret = -EAGAIN; @@ -1137,9 +1139,8 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, int return res; } -static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, - struct nfs_fattr *fattr, struct iattr *sattr, - struct nfs4_state *state) +static int _nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr, + struct iattr *sattr, struct nfs4_state *state) { struct nfs_server *server = NFS_SERVER(inode); struct nfs_setattrargs arg = { @@ -1153,10 +1154,9 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, .server = server, }; struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETATTR], - .rpc_argp = &arg, - .rpc_resp = &res, - .rpc_cred = cred, + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETATTR], + .rpc_argp = &arg, + .rpc_resp = &res, }; unsigned long timestamp = jiffies; int status; @@ -1166,6 +1166,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, if (nfs4_copy_delegation_stateid(&arg.stateid, inode)) { /* Use that stateid */ } else if (state != NULL) { + msg.rpc_cred = state->owner->so_cred; nfs4_copy_stateid(&arg.stateid, state, current->files); } else memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); @@ -1176,16 +1177,15 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, return status; } -static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, - struct nfs_fattr *fattr, struct iattr *sattr, - struct nfs4_state *state) +static int nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr, + struct iattr *sattr, struct nfs4_state *state) { struct nfs_server *server = NFS_SERVER(inode); struct nfs4_exception exception = { }; int err; do { err = nfs4_handle_exception(server, - _nfs4_do_setattr(inode, cred, fattr, sattr, state), + _nfs4_do_setattr(inode, fattr, sattr, state), &exception); } while (exception.retry); return err; @@ -1647,25 +1647,29 @@ static int nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, struct iattr *sattr) { + struct rpc_cred *cred; struct inode *inode = dentry->d_inode; - struct rpc_cred *cred = NULL; + struct nfs_open_context *ctx; struct nfs4_state *state = NULL; int status; nfs_fattr_init(fattr); - /* Search for an existing open(O_WRITE) file */ - if (sattr->ia_valid & ATTR_FILE) { - struct nfs_open_context *ctx; + cred = rpc_lookup_cred(); + if (IS_ERR(cred)) + return PTR_ERR(cred); - ctx = nfs_file_open_context(sattr->ia_file); - cred = ctx->cred; + /* Search for an existing open(O_WRITE) file */ + ctx = nfs_find_open_context(inode, cred, FMODE_WRITE); + if (ctx != NULL) state = ctx->state; - } - status = nfs4_do_setattr(inode, cred, fattr, sattr, state); + status = nfs4_do_setattr(inode, fattr, sattr, state); if (status == 0) nfs_setattr_update_inode(inode, sattr); + if (ctx != NULL) + put_nfs_open_context(ctx); + put_rpccred(cred); return status; } @@ -1893,16 +1897,17 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, goto out; } state = nfs4_do_open(dir, &path, flags, sattr, cred); + put_rpccred(cred); d_drop(dentry); if (IS_ERR(state)) { status = PTR_ERR(state); - goto out_putcred; + goto out; } d_add(dentry, igrab(state->inode)); nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); if (flags & O_EXCL) { struct nfs_fattr fattr; - status = nfs4_do_setattr(state->inode, cred, &fattr, sattr, state); + status = nfs4_do_setattr(state->inode, &fattr, sattr, state); if (status == 0) nfs_setattr_update_inode(state->inode, sattr); nfs_post_op_update_inode(state->inode, &fattr); @@ -1911,8 +1916,6 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, status = nfs4_intent_set_file(nd, &path, state); else nfs4_close_sync(&path, state, flags); -out_putcred: - put_rpccred(cred); out: return status; } @@ -2076,81 +2079,47 @@ static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *n return err; } -struct nfs4_createdata { - struct rpc_message msg; - struct nfs4_create_arg arg; - struct nfs4_create_res res; - struct nfs_fh fh; - struct nfs_fattr fattr; - struct nfs_fattr dir_fattr; -}; - -static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, - struct qstr *name, struct iattr *sattr, u32 ftype) -{ - struct nfs4_createdata *data; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (data != NULL) { - struct nfs_server *server = NFS_SERVER(dir); - - data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE]; - data->msg.rpc_argp = &data->arg; - data->msg.rpc_resp = &data->res; - data->arg.dir_fh = NFS_FH(dir); - data->arg.server = server; - data->arg.name = name; - data->arg.attrs = sattr; - data->arg.ftype = ftype; - data->arg.bitmask = server->attr_bitmask; - data->res.server = server; - data->res.fh = &data->fh; - data->res.fattr = &data->fattr; - data->res.dir_fattr = &data->dir_fattr; - nfs_fattr_init(data->res.fattr); - nfs_fattr_init(data->res.dir_fattr); - } - return data; -} - -static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data) -{ - int status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0); - if (status == 0) { - update_changeattr(dir, &data->res.dir_cinfo); - nfs_post_op_update_inode(dir, data->res.dir_fattr); - status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); - } - return status; -} - -static void nfs4_free_createdata(struct nfs4_createdata *data) -{ - kfree(data); -} - static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, unsigned int len, struct iattr *sattr) { - struct nfs4_createdata *data; - int status = -ENAMETOOLONG; + struct nfs_server *server = NFS_SERVER(dir); + struct nfs_fh fhandle; + struct nfs_fattr fattr, dir_fattr; + struct nfs4_create_arg arg = { + .dir_fh = NFS_FH(dir), + .server = server, + .name = &dentry->d_name, + .attrs = sattr, + .ftype = NF4LNK, + .bitmask = server->attr_bitmask, + }; + struct nfs4_create_res res = { + .server = server, + .fh = &fhandle, + .fattr = &fattr, + .dir_fattr = &dir_fattr, + }; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK], + .rpc_argp = &arg, + .rpc_resp = &res, + }; + int status; if (len > NFS4_MAXPATHLEN) - goto out; + return -ENAMETOOLONG; - status = -ENOMEM; - data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4LNK); - if (data == NULL) - goto out; - - data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK]; - data->arg.u.symlink.pages = &page; - data->arg.u.symlink.len = len; + arg.u.symlink.pages = &page; + arg.u.symlink.len = len; + nfs_fattr_init(&fattr); + nfs_fattr_init(&dir_fattr); - status = nfs4_do_create(dir, dentry, data); - - nfs4_free_createdata(data); -out: + status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); + if (!status) { + update_changeattr(dir, &res.dir_cinfo); + nfs_post_op_update_inode(dir, res.dir_fattr); + status = nfs_instantiate(dentry, &fhandle, &fattr); + } return status; } @@ -2171,17 +2140,39 @@ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) { - struct nfs4_createdata *data; - int status = -ENOMEM; - - data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4DIR); - if (data == NULL) - goto out; - - status = nfs4_do_create(dir, dentry, data); + struct nfs_server *server = NFS_SERVER(dir); + struct nfs_fh fhandle; + struct nfs_fattr fattr, dir_fattr; + struct nfs4_create_arg arg = { + .dir_fh = NFS_FH(dir), + .server = server, + .name = &dentry->d_name, + .attrs = sattr, + .ftype = NF4DIR, + .bitmask = server->attr_bitmask, + }; + struct nfs4_create_res res = { + .server = server, + .fh = &fhandle, + .fattr = &fattr, + .dir_fattr = &dir_fattr, + }; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], + .rpc_argp = &arg, + .rpc_resp = &res, + }; + int status; - nfs4_free_createdata(data); -out: + nfs_fattr_init(&fattr); + nfs_fattr_init(&dir_fattr); + + status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); + if (!status) { + update_changeattr(dir, &res.dir_cinfo); + nfs_post_op_update_inode(dir, res.dir_fattr); + status = nfs_instantiate(dentry, &fhandle, &fattr); + } return status; } @@ -2251,34 +2242,56 @@ static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, dev_t rdev) { - struct nfs4_createdata *data; - int mode = sattr->ia_mode; - int status = -ENOMEM; + struct nfs_server *server = NFS_SERVER(dir); + struct nfs_fh fh; + struct nfs_fattr fattr, dir_fattr; + struct nfs4_create_arg arg = { + .dir_fh = NFS_FH(dir), + .server = server, + .name = &dentry->d_name, + .attrs = sattr, + .bitmask = server->attr_bitmask, + }; + struct nfs4_create_res res = { + .server = server, + .fh = &fh, + .fattr = &fattr, + .dir_fattr = &dir_fattr, + }; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], + .rpc_argp = &arg, + .rpc_resp = &res, + }; + int status; + int mode = sattr->ia_mode; + + nfs_fattr_init(&fattr); + nfs_fattr_init(&dir_fattr); BUG_ON(!(sattr->ia_valid & ATTR_MODE)); BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode)); - - data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4SOCK); - if (data == NULL) - goto out; - if (S_ISFIFO(mode)) - data->arg.ftype = NF4FIFO; + arg.ftype = NF4FIFO; else if (S_ISBLK(mode)) { - data->arg.ftype = NF4BLK; - data->arg.u.device.specdata1 = MAJOR(rdev); - data->arg.u.device.specdata2 = MINOR(rdev); + arg.ftype = NF4BLK; + arg.u.device.specdata1 = MAJOR(rdev); + arg.u.device.specdata2 = MINOR(rdev); } else if (S_ISCHR(mode)) { - data->arg.ftype = NF4CHR; - data->arg.u.device.specdata1 = MAJOR(rdev); - data->arg.u.device.specdata2 = MINOR(rdev); + arg.ftype = NF4CHR; + arg.u.device.specdata1 = MAJOR(rdev); + arg.u.device.specdata2 = MINOR(rdev); } + else + arg.ftype = NF4SOCK; - status = nfs4_do_create(dir, dentry, data); - - nfs4_free_createdata(data); -out: + status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); + if (status == 0) { + update_changeattr(dir, &res.dir_cinfo); + nfs_post_op_update_inode(dir, res.dir_fattr); + status = nfs_instantiate(dentry, &fh, &fattr); + } return status; } @@ -2693,8 +2706,6 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen) ret = nfs_revalidate_inode(server, inode); if (ret < 0) return ret; - if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL) - nfs_zap_acl_cache(inode); ret = nfs4_read_cached_acl(inode, buf, buflen); if (ret != -ENOENT) return ret; @@ -2722,8 +2733,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl nfs_inode_return_delegation(inode); buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); - nfs_access_zap_cache(inode); - nfs_zap_acl_cache(inode); + nfs_zap_caches(inode); return ret; } @@ -2757,7 +2767,8 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server) task->tk_status = 0; return -EAGAIN; case -NFS4ERR_DELAY: - nfs_inc_server_stats(server, NFSIOS_DELAY); + nfs_inc_server_stats((struct nfs_server *) server, + NFSIOS_DELAY); case -NFS4ERR_GRACE: rpc_delay(task, NFS4_POLL_RETRY_MAX); task->tk_status = 0; @@ -2922,7 +2933,7 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cre int nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cred *cred) { - long timeout = 0; + long timeout; int err; do { err = _nfs4_proc_setclientid_confirm(clp, cred); @@ -3714,6 +3725,8 @@ const struct nfs_rpc_ops nfs_v4_clientops = { .write_done = nfs4_write_done, .commit_setup = nfs4_proc_commit_setup, .commit_done = nfs4_commit_done, + .file_open = nfs_open, + .file_release = nfs_release, .lock = nfs4_proc_lock, .clear_acl_cache = nfs4_zap_acl_attr, }; diff --git a/trunk/fs/nfs/nfs4state.c b/trunk/fs/nfs/nfs4state.c index 401ef8b28f97..856a8934f610 100644 --- a/trunk/fs/nfs/nfs4state.c +++ b/trunk/fs/nfs/nfs4state.c @@ -940,6 +940,7 @@ static int reclaimer(void *ptr) allow_signal(SIGKILL); /* Ensure exclusive access to NFSv4 state */ + lock_kernel(); down_write(&clp->cl_sem); /* Are there any NFS mounts out there? */ if (list_empty(&clp->cl_superblocks)) @@ -999,6 +1000,7 @@ static int reclaimer(void *ptr) nfs_delegation_reap_unclaimed(clp); out: up_write(&clp->cl_sem); + unlock_kernel(); if (status == -NFS4ERR_CB_PATH_DOWN) nfs_handle_cb_pathdown(clp); nfs4_clear_recover_bit(clp); diff --git a/trunk/fs/nfs/nfsroot.c b/trunk/fs/nfs/nfsroot.c index 46763d1cd397..531379d36823 100644 --- a/trunk/fs/nfs/nfsroot.c +++ b/trunk/fs/nfs/nfsroot.c @@ -1,4 +1,6 @@ /* + * $Id: nfsroot.c,v 1.45 1998/03/07 10:44:46 mj Exp $ + * * Copyright (C) 1995, 1996 Gero Kuhlmann * * Allow an NFS filesystem to be mounted as root. The way this works is: @@ -295,10 +297,10 @@ static int __init root_nfs_name(char *name) nfs_data.flags = NFS_MOUNT_NONLM; /* No lockd in nfs root yet */ nfs_data.rsize = NFS_DEF_FILE_IO_SIZE; nfs_data.wsize = NFS_DEF_FILE_IO_SIZE; - nfs_data.acregmin = NFS_DEF_ACREGMIN; - nfs_data.acregmax = NFS_DEF_ACREGMAX; - nfs_data.acdirmin = NFS_DEF_ACDIRMIN; - nfs_data.acdirmax = NFS_DEF_ACDIRMAX; + nfs_data.acregmin = 3; + nfs_data.acregmax = 60; + nfs_data.acdirmin = 30; + nfs_data.acdirmax = 60; strcpy(buf, NFS_ROOT); /* Process options received from the remote server */ diff --git a/trunk/fs/nfs/proc.c b/trunk/fs/nfs/proc.c index 4dbb84df1b68..03599bfe81cf 100644 --- a/trunk/fs/nfs/proc.c +++ b/trunk/fs/nfs/proc.c @@ -129,8 +129,6 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, sattr->ia_mode &= S_IALLUGO; dprintk("NFS call setattr\n"); - if (sattr->ia_valid & ATTR_FILE) - msg.rpc_cred = nfs_file_cred(sattr->ia_file); nfs_fattr_init(fattr); status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); if (status == 0) @@ -600,29 +598,6 @@ nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl) return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl); } -/* Helper functions for NFS lock bounds checking */ -#define NFS_LOCK32_OFFSET_MAX ((__s32)0x7fffffffUL) -static int nfs_lock_check_bounds(const struct file_lock *fl) -{ - __s32 start, end; - - start = (__s32)fl->fl_start; - if ((loff_t)start != fl->fl_start) - goto out_einval; - - if (fl->fl_end != OFFSET_MAX) { - end = (__s32)fl->fl_end; - if ((loff_t)end != fl->fl_end) - goto out_einval; - } else - end = NFS_LOCK32_OFFSET_MAX; - - if (start < 0 || start > end) - goto out_einval; - return 0; -out_einval: - return -EINVAL; -} const struct nfs_rpc_ops nfs_v2_clientops = { .version = 2, /* protocol version */ @@ -655,6 +630,7 @@ const struct nfs_rpc_ops nfs_v2_clientops = { .write_setup = nfs_proc_write_setup, .write_done = nfs_write_done, .commit_setup = nfs_proc_commit_setup, + .file_open = nfs_open, + .file_release = nfs_release, .lock = nfs_proc_lock, - .lock_check_bounds = nfs_lock_check_bounds, }; diff --git a/trunk/fs/nfs/super.c b/trunk/fs/nfs/super.c index 1b94e3650f5c..614efeed5437 100644 --- a/trunk/fs/nfs/super.c +++ b/trunk/fs/nfs/super.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include @@ -66,6 +65,7 @@ enum { /* Mount options that take no arguments */ Opt_soft, Opt_hard, + Opt_intr, Opt_nointr, Opt_posix, Opt_noposix, Opt_cto, Opt_nocto, Opt_ac, Opt_noac, @@ -92,8 +92,8 @@ enum { Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost, Opt_addr, Opt_mountaddr, Opt_clientaddr, - /* Special mount options */ - Opt_userspace, Opt_deprecated, Opt_sloppy, + /* Mount options that are ignored */ + Opt_userspace, Opt_deprecated, Opt_err }; @@ -101,14 +101,10 @@ enum { static match_table_t nfs_mount_option_tokens = { { Opt_userspace, "bg" }, { Opt_userspace, "fg" }, - { Opt_userspace, "retry=%s" }, - - { Opt_sloppy, "sloppy" }, - { Opt_soft, "soft" }, { Opt_hard, "hard" }, - { Opt_deprecated, "intr" }, - { Opt_deprecated, "nointr" }, + { Opt_intr, "intr" }, + { Opt_nointr, "nointr" }, { Opt_posix, "posix" }, { Opt_noposix, "noposix" }, { Opt_cto, "cto" }, @@ -140,6 +136,7 @@ static match_table_t nfs_mount_option_tokens = { { Opt_acdirmin, "acdirmin=%u" }, { Opt_acdirmax, "acdirmax=%u" }, { Opt_actimeo, "actimeo=%u" }, + { Opt_userspace, "retry=%u" }, { Opt_namelen, "namlen=%u" }, { Opt_mountport, "mountport=%u" }, { Opt_mountvers, "mountvers=%u" }, @@ -210,7 +207,6 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); static void nfs_kill_super(struct super_block *); static void nfs_put_super(struct super_block *); -static int nfs_remount(struct super_block *sb, int *flags, char *raw_data); static struct file_system_type nfs_fs_type = { .owner = THIS_MODULE, @@ -238,7 +234,6 @@ static const struct super_operations nfs_sops = { .umount_begin = nfs_umount_begin, .show_options = nfs_show_options, .show_stats = nfs_show_stats, - .remount_fs = nfs_remount, }; #ifdef CONFIG_NFS_V4 @@ -283,7 +278,6 @@ static const struct super_operations nfs4_sops = { .umount_begin = nfs_umount_begin, .show_options = nfs_show_options, .show_stats = nfs_show_stats, - .remount_fs = nfs_remount, }; #endif @@ -374,6 +368,8 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) }; int error; + lock_kernel(); + error = server->nfs_client->rpc_ops->statfs(server, fh, &res); if (error < 0) goto out_err; @@ -405,10 +401,12 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_namelen = server->namelen; + unlock_kernel(); return 0; out_err: dprintk("%s: statfs error = %d\n", __func__, -error); + unlock_kernel(); return error; } @@ -516,13 +514,13 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, if (nfss->bsize != 0) seq_printf(m, ",bsize=%u", nfss->bsize); seq_printf(m, ",namlen=%u", nfss->namelen); - if (nfss->acregmin != NFS_DEF_ACREGMIN*HZ || showdefaults) + if (nfss->acregmin != 3*HZ || showdefaults) seq_printf(m, ",acregmin=%u", nfss->acregmin/HZ); - if (nfss->acregmax != NFS_DEF_ACREGMAX*HZ || showdefaults) + if (nfss->acregmax != 60*HZ || showdefaults) seq_printf(m, ",acregmax=%u", nfss->acregmax/HZ); - if (nfss->acdirmin != NFS_DEF_ACDIRMIN*HZ || showdefaults) + if (nfss->acdirmin != 30*HZ || showdefaults) seq_printf(m, ",acdirmin=%u", nfss->acdirmin/HZ); - if (nfss->acdirmax != NFS_DEF_ACDIRMAX*HZ || showdefaults) + if (nfss->acdirmax != 60*HZ || showdefaults) seq_printf(m, ",acdirmax=%u", nfss->acdirmax/HZ); for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) { if (nfss->flags & nfs_infop->flag) @@ -704,233 +702,49 @@ static int nfs_verify_server_address(struct sockaddr *addr) return 0; } -static void nfs_parse_ipv4_address(char *string, size_t str_len, - struct sockaddr *sap, size_t *addr_len) -{ - struct sockaddr_in *sin = (struct sockaddr_in *)sap; - u8 *addr = (u8 *)&sin->sin_addr.s_addr; - - if (str_len <= INET_ADDRSTRLEN) { - dfprintk(MOUNT, "NFS: parsing IPv4 address %*s\n", - (int)str_len, string); - - sin->sin_family = AF_INET; - *addr_len = sizeof(*sin); - if (in4_pton(string, str_len, addr, '\0', NULL)) - return; - } - - sap->sa_family = AF_UNSPEC; - *addr_len = 0; -} - -#define IPV6_SCOPE_DELIMITER '%' - -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -static void nfs_parse_ipv6_scope_id(const char *string, const size_t str_len, - const char *delim, - struct sockaddr_in6 *sin6) -{ - char *p; - size_t len; - - if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)) - return ; - if (*delim != IPV6_SCOPE_DELIMITER) - return; - - len = (string + str_len) - delim - 1; - p = kstrndup(delim + 1, len, GFP_KERNEL); - if (p) { - unsigned long scope_id = 0; - struct net_device *dev; - - dev = dev_get_by_name(&init_net, p); - if (dev != NULL) { - scope_id = dev->ifindex; - dev_put(dev); - } else { - /* scope_id is set to zero on error */ - strict_strtoul(p, 10, &scope_id); - } - - kfree(p); - sin6->sin6_scope_id = scope_id; - dfprintk(MOUNT, "NFS: IPv6 scope ID = %lu\n", scope_id); - } -} - -static void nfs_parse_ipv6_address(char *string, size_t str_len, - struct sockaddr *sap, size_t *addr_len) -{ - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; - u8 *addr = (u8 *)&sin6->sin6_addr.in6_u; - const char *delim; - - if (str_len <= INET6_ADDRSTRLEN) { - dfprintk(MOUNT, "NFS: parsing IPv6 address %*s\n", - (int)str_len, string); - - sin6->sin6_family = AF_INET6; - *addr_len = sizeof(*sin6); - if (in6_pton(string, str_len, addr, IPV6_SCOPE_DELIMITER, &delim)) { - nfs_parse_ipv6_scope_id(string, str_len, delim, sin6); - return; - } - } - - sap->sa_family = AF_UNSPEC; - *addr_len = 0; -} -#else -static void nfs_parse_ipv6_address(char *string, size_t str_len, - struct sockaddr *sap, size_t *addr_len) -{ - sap->sa_family = AF_UNSPEC; - *addr_len = 0; -} -#endif - -/* - * Construct a sockaddr based on the contents of a string that contains - * an IP address in presentation format. - * - * If there is a problem constructing the new sockaddr, set the address - * family to AF_UNSPEC. - */ -static void nfs_parse_ip_address(char *string, size_t str_len, - struct sockaddr *sap, size_t *addr_len) -{ - unsigned int i, colons; - - colons = 0; - for (i = 0; i < str_len; i++) - if (string[i] == ':') - colons++; - - if (colons >= 2) - nfs_parse_ipv6_address(string, str_len, sap, addr_len); - else - nfs_parse_ipv4_address(string, str_len, sap, addr_len); -} - /* - * Sanity check the NFS transport protocol. + * Parse string addresses passed in via a mount option, + * and construct a sockaddr based on the result. * + * If address parsing fails, set the sockaddr's address + * family to AF_UNSPEC to force nfs_verify_server_address() + * to punt the mount. */ -static void nfs_validate_transport_protocol(struct nfs_parsed_mount_data *mnt) -{ - switch (mnt->nfs_server.protocol) { - case XPRT_TRANSPORT_UDP: - case XPRT_TRANSPORT_TCP: - case XPRT_TRANSPORT_RDMA: - break; - default: - mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP; - } -} - -/* - * For text based NFSv2/v3 mounts, the mount protocol transport default - * settings should depend upon the specified NFS transport. - */ -static void nfs_set_mount_transport_protocol(struct nfs_parsed_mount_data *mnt) +static void nfs_parse_server_address(char *value, + struct sockaddr *sap, + size_t *len) { - nfs_validate_transport_protocol(mnt); + if (strchr(value, ':')) { + struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap; + u8 *addr = (u8 *)&ap->sin6_addr.in6_u; - if (mnt->mount_server.protocol == XPRT_TRANSPORT_UDP || - mnt->mount_server.protocol == XPRT_TRANSPORT_TCP) + ap->sin6_family = AF_INET6; + *len = sizeof(*ap); + if (in6_pton(value, -1, addr, '\0', NULL)) return; - switch (mnt->nfs_server.protocol) { - case XPRT_TRANSPORT_UDP: - mnt->mount_server.protocol = XPRT_TRANSPORT_UDP; - break; - case XPRT_TRANSPORT_TCP: - case XPRT_TRANSPORT_RDMA: - mnt->mount_server.protocol = XPRT_TRANSPORT_TCP; - } -} - -/* - * Parse the value of the 'sec=' option. - * - * The flavor_len setting is for v4 mounts. - */ -static int nfs_parse_security_flavors(char *value, - struct nfs_parsed_mount_data *mnt) -{ - substring_t args[MAX_OPT_ARGS]; - - dfprintk(MOUNT, "NFS: parsing sec=%s option\n", value); + } else { + struct sockaddr_in *ap = (struct sockaddr_in *)sap; + u8 *addr = (u8 *)&ap->sin_addr.s_addr; - switch (match_token(value, nfs_secflavor_tokens, args)) { - case Opt_sec_none: - mnt->auth_flavor_len = 0; - mnt->auth_flavors[0] = RPC_AUTH_NULL; - break; - case Opt_sec_sys: - mnt->auth_flavor_len = 0; - mnt->auth_flavors[0] = RPC_AUTH_UNIX; - break; - case Opt_sec_krb5: - mnt->auth_flavor_len = 1; - mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5; - break; - case Opt_sec_krb5i: - mnt->auth_flavor_len = 1; - mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5I; - break; - case Opt_sec_krb5p: - mnt->auth_flavor_len = 1; - mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5P; - break; - case Opt_sec_lkey: - mnt->auth_flavor_len = 1; - mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEY; - break; - case Opt_sec_lkeyi: - mnt->auth_flavor_len = 1; - mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEYI; - break; - case Opt_sec_lkeyp: - mnt->auth_flavor_len = 1; - mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEYP; - break; - case Opt_sec_spkm: - mnt->auth_flavor_len = 1; - mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKM; - break; - case Opt_sec_spkmi: - mnt->auth_flavor_len = 1; - mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKMI; - break; - case Opt_sec_spkmp: - mnt->auth_flavor_len = 1; - mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKMP; - break; - default: - return 0; + ap->sin_family = AF_INET; + *len = sizeof(*ap); + if (in4_pton(value, -1, addr, '\0', NULL)) + return; } - return 1; -} - -static void nfs_parse_invalid_value(const char *option) -{ - dfprintk(MOUNT, "NFS: bad value specified for %s option\n", option); + sap->sa_family = AF_UNSPEC; + *len = 0; } /* * Error-check and convert a string of mount options from user space into - * a data structure. The whole mount string is processed; bad options are - * skipped as they are encountered. If there were no errors, return 1; - * otherwise return 0 (zero). + * a data structure */ static int nfs_parse_mount_options(char *raw, struct nfs_parsed_mount_data *mnt) { char *p, *string, *secdata; - int rc, sloppy = 0, errors = 0; + int rc; if (!raw) { dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); @@ -963,16 +777,15 @@ static int nfs_parse_mount_options(char *raw, token = match_token(p, nfs_mount_option_tokens, args); switch (token) { - - /* - * boolean options: foo/nofoo - */ case Opt_soft: mnt->flags |= NFS_MOUNT_SOFT; break; case Opt_hard: mnt->flags &= ~NFS_MOUNT_SOFT; break; + case Opt_intr: + case Opt_nointr: + break; case Opt_posix: mnt->flags |= NFS_MOUNT_POSIX; break; @@ -1006,14 +819,20 @@ static int nfs_parse_mount_options(char *raw, case Opt_udp: mnt->flags &= ~NFS_MOUNT_TCP; mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; + mnt->timeo = 7; + mnt->retrans = 5; break; case Opt_tcp: mnt->flags |= NFS_MOUNT_TCP; mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP; + mnt->timeo = 600; + mnt->retrans = 2; break; case Opt_rdma: mnt->flags |= NFS_MOUNT_TCP; /* for side protocols */ mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA; + mnt->timeo = 600; + mnt->retrans = 2; break; case Opt_acl: mnt->flags &= ~NFS_MOUNT_NOACL; @@ -1034,144 +853,165 @@ static int nfs_parse_mount_options(char *raw, mnt->flags |= NFS_MOUNT_UNSHARED; break; - /* - * options that take numeric values - */ case Opt_port: - if (match_int(args, &option) || - option < 0 || option > USHORT_MAX) { - errors++; - nfs_parse_invalid_value("port"); - } else - mnt->nfs_server.port = option; + if (match_int(args, &option)) + return 0; + if (option < 0 || option > 65535) + return 0; + mnt->nfs_server.port = option; break; case Opt_rsize: - if (match_int(args, &option) || option < 0) { - errors++; - nfs_parse_invalid_value("rsize"); - } else - mnt->rsize = option; + if (match_int(args, &mnt->rsize)) + return 0; break; case Opt_wsize: - if (match_int(args, &option) || option < 0) { - errors++; - nfs_parse_invalid_value("wsize"); - } else - mnt->wsize = option; + if (match_int(args, &mnt->wsize)) + return 0; break; case Opt_bsize: - if (match_int(args, &option) || option < 0) { - errors++; - nfs_parse_invalid_value("bsize"); - } else - mnt->bsize = option; + if (match_int(args, &option)) + return 0; + if (option < 0) + return 0; + mnt->bsize = option; break; case Opt_timeo: - if (match_int(args, &option) || option <= 0) { - errors++; - nfs_parse_invalid_value("timeo"); - } else - mnt->timeo = option; + if (match_int(args, &mnt->timeo)) + return 0; break; case Opt_retrans: - if (match_int(args, &option) || option <= 0) { - errors++; - nfs_parse_invalid_value("retrans"); - } else - mnt->retrans = option; + if (match_int(args, &mnt->retrans)) + return 0; break; case Opt_acregmin: - if (match_int(args, &option) || option < 0) { - errors++; - nfs_parse_invalid_value("acregmin"); - } else - mnt->acregmin = option; + if (match_int(args, &mnt->acregmin)) + return 0; break; case Opt_acregmax: - if (match_int(args, &option) || option < 0) { - errors++; - nfs_parse_invalid_value("acregmax"); - } else - mnt->acregmax = option; + if (match_int(args, &mnt->acregmax)) + return 0; break; case Opt_acdirmin: - if (match_int(args, &option) || option < 0) { - errors++; - nfs_parse_invalid_value("acdirmin"); - } else - mnt->acdirmin = option; + if (match_int(args, &mnt->acdirmin)) + return 0; break; case Opt_acdirmax: - if (match_int(args, &option) || option < 0) { - errors++; - nfs_parse_invalid_value("acdirmax"); - } else - mnt->acdirmax = option; + if (match_int(args, &mnt->acdirmax)) + return 0; break; case Opt_actimeo: - if (match_int(args, &option) || option < 0) { - errors++; - nfs_parse_invalid_value("actimeo"); - } else - mnt->acregmin = mnt->acregmax = - mnt->acdirmin = mnt->acdirmax = option; + if (match_int(args, &option)) + return 0; + if (option < 0) + return 0; + mnt->acregmin = + mnt->acregmax = + mnt->acdirmin = + mnt->acdirmax = option; break; case Opt_namelen: - if (match_int(args, &option) || option < 0) { - errors++; - nfs_parse_invalid_value("namlen"); - } else - mnt->namlen = option; + if (match_int(args, &mnt->namlen)) + return 0; break; case Opt_mountport: - if (match_int(args, &option) || - option < 0 || option > USHORT_MAX) { - errors++; - nfs_parse_invalid_value("mountport"); - } else - mnt->mount_server.port = option; + if (match_int(args, &option)) + return 0; + if (option < 0 || option > 65535) + return 0; + mnt->mount_server.port = option; break; case Opt_mountvers: - if (match_int(args, &option) || - option < NFS_MNT_VERSION || - option > NFS_MNT3_VERSION) { - errors++; - nfs_parse_invalid_value("mountvers"); - } else - mnt->mount_server.version = option; + if (match_int(args, &option)) + return 0; + if (option < 0) + return 0; + mnt->mount_server.version = option; break; case Opt_nfsvers: - if (match_int(args, &option)) { - errors++; - nfs_parse_invalid_value("nfsvers"); - break; - } + if (match_int(args, &option)) + return 0; switch (option) { - case NFS2_VERSION: + case 2: mnt->flags &= ~NFS_MOUNT_VER3; break; - case NFS3_VERSION: + case 3: mnt->flags |= NFS_MOUNT_VER3; break; default: - errors++; - nfs_parse_invalid_value("nfsvers"); + goto out_unrec_vers; } break; - /* - * options that take text values - */ case Opt_sec: string = match_strdup(args); if (string == NULL) goto out_nomem; - rc = nfs_parse_security_flavors(string, mnt); + token = match_token(string, nfs_secflavor_tokens, args); kfree(string); - if (!rc) { - errors++; - dfprintk(MOUNT, "NFS: unrecognized " - "security flavor\n"); + + /* + * The flags setting is for v2/v3. The flavor_len + * setting is for v4. v2/v3 also need to know the + * difference between NULL and UNIX. + */ + switch (token) { + case Opt_sec_none: + mnt->flags &= ~NFS_MOUNT_SECFLAVOUR; + mnt->auth_flavor_len = 0; + mnt->auth_flavors[0] = RPC_AUTH_NULL; + break; + case Opt_sec_sys: + mnt->flags &= ~NFS_MOUNT_SECFLAVOUR; + mnt->auth_flavor_len = 0; + mnt->auth_flavors[0] = RPC_AUTH_UNIX; + break; + case Opt_sec_krb5: + mnt->flags |= NFS_MOUNT_SECFLAVOUR; + mnt->auth_flavor_len = 1; + mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5; + break; + case Opt_sec_krb5i: + mnt->flags |= NFS_MOUNT_SECFLAVOUR; + mnt->auth_flavor_len = 1; + mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5I; + break; + case Opt_sec_krb5p: + mnt->flags |= NFS_MOUNT_SECFLAVOUR; + mnt->auth_flavor_len = 1; + mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5P; + break; + case Opt_sec_lkey: + mnt->flags |= NFS_MOUNT_SECFLAVOUR; + mnt->auth_flavor_len = 1; + mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEY; + break; + case Opt_sec_lkeyi: + mnt->flags |= NFS_MOUNT_SECFLAVOUR; + mnt->auth_flavor_len = 1; + mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEYI; + break; + case Opt_sec_lkeyp: + mnt->flags |= NFS_MOUNT_SECFLAVOUR; + mnt->auth_flavor_len = 1; + mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEYP; + break; + case Opt_sec_spkm: + mnt->flags |= NFS_MOUNT_SECFLAVOUR; + mnt->auth_flavor_len = 1; + mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKM; + break; + case Opt_sec_spkmi: + mnt->flags |= NFS_MOUNT_SECFLAVOUR; + mnt->auth_flavor_len = 1; + mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKMI; + break; + case Opt_sec_spkmp: + mnt->flags |= NFS_MOUNT_SECFLAVOUR; + mnt->auth_flavor_len = 1; + mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKMP; + break; + default: + goto out_unrec_sec; } break; case Opt_proto: @@ -1186,20 +1026,24 @@ static int nfs_parse_mount_options(char *raw, case Opt_xprt_udp: mnt->flags &= ~NFS_MOUNT_TCP; mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; + mnt->timeo = 7; + mnt->retrans = 5; break; case Opt_xprt_tcp: mnt->flags |= NFS_MOUNT_TCP; mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP; + mnt->timeo = 600; + mnt->retrans = 2; break; case Opt_xprt_rdma: /* vector side protocols to TCP */ mnt->flags |= NFS_MOUNT_TCP; mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA; + mnt->timeo = 600; + mnt->retrans = 2; break; default: - errors++; - dfprintk(MOUNT, "NFS: unrecognized " - "transport protocol\n"); + goto out_unrec_xprt; } break; case Opt_mountproto: @@ -1219,19 +1063,16 @@ static int nfs_parse_mount_options(char *raw, break; case Opt_xprt_rdma: /* not used for side protocols */ default: - errors++; - dfprintk(MOUNT, "NFS: unrecognized " - "transport protocol\n"); + goto out_unrec_xprt; } break; case Opt_addr: string = match_strdup(args); if (string == NULL) goto out_nomem; - nfs_parse_ip_address(string, strlen(string), - (struct sockaddr *) - &mnt->nfs_server.address, - &mnt->nfs_server.addrlen); + nfs_parse_server_address(string, (struct sockaddr *) + &mnt->nfs_server.address, + &mnt->nfs_server.addrlen); kfree(string); break; case Opt_clientaddr: @@ -1252,33 +1093,24 @@ static int nfs_parse_mount_options(char *raw, string = match_strdup(args); if (string == NULL) goto out_nomem; - nfs_parse_ip_address(string, strlen(string), - (struct sockaddr *) - &mnt->mount_server.address, - &mnt->mount_server.addrlen); + nfs_parse_server_address(string, (struct sockaddr *) + &mnt->mount_server.address, + &mnt->mount_server.addrlen); kfree(string); break; - /* - * Special options - */ - case Opt_sloppy: - sloppy = 1; - dfprintk(MOUNT, "NFS: relaxing parsing rules\n"); - break; case Opt_userspace: case Opt_deprecated: - dfprintk(MOUNT, "NFS: ignoring mount option " - "'%s'\n", p); break; default: - errors++; - dfprintk(MOUNT, "NFS: unrecognized mount option " - "'%s'\n", p); + goto out_unknown; } } + nfs_set_port((struct sockaddr *)&mnt->nfs_server.address, + mnt->nfs_server.port); + return 1; out_nomem: @@ -1288,6 +1120,21 @@ static int nfs_parse_mount_options(char *raw, free_secdata(secdata); printk(KERN_INFO "NFS: security options invalid: %d\n", rc); return 0; +out_unrec_vers: + printk(KERN_INFO "NFS: unrecognized NFS version number\n"); + return 0; + +out_unrec_xprt: + printk(KERN_INFO "NFS: unrecognized transport protocol\n"); + return 0; + +out_unrec_sec: + printk(KERN_INFO "NFS: unrecognized security flavor\n"); + return 0; + +out_unknown: + printk(KERN_INFO "NFS: unknown mount option: %s\n", p); + return 0; } /* @@ -1341,146 +1188,11 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args, if (status == 0) return 0; - dfprintk(MOUNT, "NFS: unable to mount server %s, error %d\n", + dfprintk(MOUNT, "NFS: unable to mount server %s, error %d", hostname, status); return status; } -static int nfs_parse_simple_hostname(const char *dev_name, - char **hostname, size_t maxnamlen, - char **export_path, size_t maxpathlen) -{ - size_t len; - char *colon, *comma; - - colon = strchr(dev_name, ':'); - if (colon == NULL) - goto out_bad_devname; - - len = colon - dev_name; - if (len > maxnamlen) - goto out_hostname; - - /* N.B. caller will free nfs_server.hostname in all cases */ - *hostname = kstrndup(dev_name, len, GFP_KERNEL); - if (!*hostname) - goto out_nomem; - - /* kill possible hostname list: not supported */ - comma = strchr(*hostname, ','); - if (comma != NULL) { - if (comma == *hostname) - goto out_bad_devname; - *comma = '\0'; - } - - colon++; - len = strlen(colon); - if (len > maxpathlen) - goto out_path; - *export_path = kstrndup(colon, len, GFP_KERNEL); - if (!*export_path) - goto out_nomem; - - dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", *export_path); - return 0; - -out_bad_devname: - dfprintk(MOUNT, "NFS: device name not in host:path format\n"); - return -EINVAL; - -out_nomem: - dfprintk(MOUNT, "NFS: not enough memory to parse device name\n"); - return -ENOMEM; - -out_hostname: - dfprintk(MOUNT, "NFS: server hostname too long\n"); - return -ENAMETOOLONG; - -out_path: - dfprintk(MOUNT, "NFS: export pathname too long\n"); - return -ENAMETOOLONG; -} - -/* - * Hostname has square brackets around it because it contains one or - * more colons. We look for the first closing square bracket, and a - * colon must follow it. - */ -static int nfs_parse_protected_hostname(const char *dev_name, - char **hostname, size_t maxnamlen, - char **export_path, size_t maxpathlen) -{ - size_t len; - char *start, *end; - - start = (char *)(dev_name + 1); - - end = strchr(start, ']'); - if (end == NULL) - goto out_bad_devname; - if (*(end + 1) != ':') - goto out_bad_devname; - - len = end - start; - if (len > maxnamlen) - goto out_hostname; - - /* N.B. caller will free nfs_server.hostname in all cases */ - *hostname = kstrndup(start, len, GFP_KERNEL); - if (*hostname == NULL) - goto out_nomem; - - end += 2; - len = strlen(end); - if (len > maxpathlen) - goto out_path; - *export_path = kstrndup(end, len, GFP_KERNEL); - if (!*export_path) - goto out_nomem; - - return 0; - -out_bad_devname: - dfprintk(MOUNT, "NFS: device name not in host:path format\n"); - return -EINVAL; - -out_nomem: - dfprintk(MOUNT, "NFS: not enough memory to parse device name\n"); - return -ENOMEM; - -out_hostname: - dfprintk(MOUNT, "NFS: server hostname too long\n"); - return -ENAMETOOLONG; - -out_path: - dfprintk(MOUNT, "NFS: export pathname too long\n"); - return -ENAMETOOLONG; -} - -/* - * Split "dev_name" into "hostname:export_path". - * - * The leftmost colon demarks the split between the server's hostname - * and the export path. If the hostname starts with a left square - * bracket, then it may contain colons. - * - * Note: caller frees hostname and export path, even on error. - */ -static int nfs_parse_devname(const char *dev_name, - char **hostname, size_t maxnamlen, - char **export_path, size_t maxpathlen) -{ - if (*dev_name == '[') - return nfs_parse_protected_hostname(dev_name, - hostname, maxnamlen, - export_path, maxpathlen); - - return nfs_parse_simple_hostname(dev_name, - hostname, maxnamlen, - export_path, maxpathlen); -} - /* * Validate the NFS2/NFS3 mount data * - fills in the mount root filehandle @@ -1510,14 +1222,16 @@ static int nfs_validate_mount_data(void *options, args->flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP); args->rsize = NFS_MAX_FILE_IO_SIZE; args->wsize = NFS_MAX_FILE_IO_SIZE; - args->acregmin = NFS_DEF_ACREGMIN; - args->acregmax = NFS_DEF_ACREGMAX; - args->acdirmin = NFS_DEF_ACDIRMIN; - args->acdirmax = NFS_DEF_ACDIRMAX; + args->timeo = 600; + args->retrans = 2; + args->acregmin = 3; + args->acregmax = 60; + args->acdirmin = 30; + args->acdirmax = 60; args->mount_server.port = 0; /* autobind unless user sets port */ + args->mount_server.protocol = XPRT_TRANSPORT_UDP; args->nfs_server.port = 0; /* autobind unless user sets port */ args->nfs_server.protocol = XPRT_TRANSPORT_TCP; - args->auth_flavors[0] = RPC_AUTH_UNIX; switch (data->version) { case 1: @@ -1575,9 +1289,7 @@ static int nfs_validate_mount_data(void *options, args->nfs_server.hostname = kstrdup(data->hostname, GFP_KERNEL); args->namlen = data->namlen; args->bsize = data->bsize; - - if (data->flags & NFS_MOUNT_SECFLAVOUR) - args->auth_flavors[0] = data->pseudoflavor; + args->auth_flavors[0] = data->pseudoflavor; if (!args->nfs_server.hostname) goto out_nomem; @@ -1609,6 +1321,8 @@ static int nfs_validate_mount_data(void *options, break; default: { + unsigned int len; + char *c; int status; if (nfs_parse_mount_options((char *)options, args) == 0) @@ -1618,22 +1332,21 @@ static int nfs_validate_mount_data(void *options, &args->nfs_server.address)) goto out_no_address; - nfs_set_port((struct sockaddr *)&args->nfs_server.address, - args->nfs_server.port); - - nfs_set_mount_transport_protocol(args); - - status = nfs_parse_devname(dev_name, - &args->nfs_server.hostname, - PAGE_SIZE, - &args->nfs_server.export_path, - NFS_MAXPATHLEN); - if (!status) - status = nfs_try_mount(args, mntfh); + c = strchr(dev_name, ':'); + if (c == NULL) + return -EINVAL; + len = c - dev_name; + /* N.B. caller will free nfs_server.hostname in all cases */ + args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL); + if (!args->nfs_server.hostname) + goto out_nomem; - kfree(args->nfs_server.export_path); - args->nfs_server.export_path = NULL; + c++; + if (strlen(c) > NFS_MAXPATHLEN) + return -ENAMETOOLONG; + args->nfs_server.export_path = c; + status = nfs_try_mount(args, mntfh); if (status) return status; @@ -1641,6 +1354,9 @@ static int nfs_validate_mount_data(void *options, } } + if (!(args->flags & NFS_MOUNT_SECFLAVOUR)) + args->auth_flavors[0] = RPC_AUTH_UNIX; + #ifndef CONFIG_NFS_V3 if (args->flags & NFS_MOUNT_VER3) goto out_v3_not_compiled; @@ -1680,80 +1396,6 @@ static int nfs_validate_mount_data(void *options, return -EINVAL; } -static int -nfs_compare_remount_data(struct nfs_server *nfss, - struct nfs_parsed_mount_data *data) -{ - if (data->flags != nfss->flags || - data->rsize != nfss->rsize || - data->wsize != nfss->wsize || - data->retrans != nfss->client->cl_timeout->to_retries || - data->auth_flavors[0] != nfss->client->cl_auth->au_flavor || - data->acregmin != nfss->acregmin / HZ || - data->acregmax != nfss->acregmax / HZ || - data->acdirmin != nfss->acdirmin / HZ || - data->acdirmax != nfss->acdirmax / HZ || - data->timeo != (10U * nfss->client->cl_timeout->to_initval / HZ) || - data->nfs_server.addrlen != nfss->nfs_client->cl_addrlen || - memcmp(&data->nfs_server.address, &nfss->nfs_client->cl_addr, - data->nfs_server.addrlen) != 0) - return -EINVAL; - - return 0; -} - -static int -nfs_remount(struct super_block *sb, int *flags, char *raw_data) -{ - int error; - struct nfs_server *nfss = sb->s_fs_info; - struct nfs_parsed_mount_data *data; - struct nfs_mount_data *options = (struct nfs_mount_data *)raw_data; - struct nfs4_mount_data *options4 = (struct nfs4_mount_data *)raw_data; - u32 nfsvers = nfss->nfs_client->rpc_ops->version; - - /* - * Userspace mount programs that send binary options generally send - * them populated with default values. We have no way to know which - * ones were explicitly specified. Fall back to legacy behavior and - * just return success. - */ - if ((nfsvers == 4 && options4->version == 1) || - (nfsvers <= 3 && options->version >= 1 && - options->version <= 6)) - return 0; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - /* fill out struct with values from existing mount */ - data->flags = nfss->flags; - data->rsize = nfss->rsize; - data->wsize = nfss->wsize; - data->retrans = nfss->client->cl_timeout->to_retries; - data->auth_flavors[0] = nfss->client->cl_auth->au_flavor; - data->acregmin = nfss->acregmin / HZ; - data->acregmax = nfss->acregmax / HZ; - data->acdirmin = nfss->acdirmin / HZ; - data->acdirmax = nfss->acdirmax / HZ; - data->timeo = 10U * nfss->client->cl_timeout->to_initval / HZ; - data->nfs_server.addrlen = nfss->nfs_client->cl_addrlen; - memcpy(&data->nfs_server.address, &nfss->nfs_client->cl_addr, - data->nfs_server.addrlen); - - /* overwrite those values with any that were specified */ - error = nfs_parse_mount_options((char *)options, data); - if (error < 0) - goto out; - - /* compare new mount options with old ones */ - error = nfs_compare_remount_data(nfss, data); -out: - kfree(data); - return error; -} - /* * Initialise the common bits of the superblock */ @@ -2169,13 +1811,14 @@ static int nfs4_validate_mount_data(void *options, args->rsize = NFS_MAX_FILE_IO_SIZE; args->wsize = NFS_MAX_FILE_IO_SIZE; - args->acregmin = NFS_DEF_ACREGMIN; - args->acregmax = NFS_DEF_ACREGMAX; - args->acdirmin = NFS_DEF_ACDIRMIN; - args->acdirmax = NFS_DEF_ACDIRMAX; + args->timeo = 600; + args->retrans = 2; + args->acregmin = 3; + args->acregmax = 60; + args->acdirmin = 30; + args->acdirmax = 60; args->nfs_server.port = NFS_PORT; /* 2049 unless user set port= */ - args->auth_flavors[0] = RPC_AUTH_UNIX; - args->auth_flavor_len = 0; + args->nfs_server.protocol = XPRT_TRANSPORT_TCP; switch (data->version) { case 1: @@ -2191,13 +1834,18 @@ static int nfs4_validate_mount_data(void *options, &args->nfs_server.address)) goto out_no_address; - if (data->auth_flavourlen) { - if (data->auth_flavourlen > 1) - goto out_inval_auth; + switch (data->auth_flavourlen) { + case 0: + args->auth_flavors[0] = RPC_AUTH_UNIX; + break; + case 1: if (copy_from_user(&args->auth_flavors[0], data->auth_flavours, sizeof(args->auth_flavors[0]))) return -EFAULT; + break; + default: + goto out_inval_auth; } c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN); @@ -2231,11 +1879,10 @@ static int nfs4_validate_mount_data(void *options, args->acdirmin = data->acdirmin; args->acdirmax = data->acdirmax; args->nfs_server.protocol = data->proto; - nfs_validate_transport_protocol(args); break; default: { - int status; + unsigned int len; if (nfs_parse_mount_options((char *)options, args) == 0) return -EINVAL; @@ -2244,25 +1891,44 @@ static int nfs4_validate_mount_data(void *options, &args->nfs_server.address)) return -EINVAL; - nfs_set_port((struct sockaddr *)&args->nfs_server.address, - args->nfs_server.port); + switch (args->auth_flavor_len) { + case 0: + args->auth_flavors[0] = RPC_AUTH_UNIX; + break; + case 1: + break; + default: + goto out_inval_auth; + } - nfs_validate_transport_protocol(args); + /* + * Split "dev_name" into "hostname:mntpath". + */ + c = strchr(dev_name, ':'); + if (c == NULL) + return -EINVAL; + /* while calculating len, pretend ':' is '\0' */ + len = c - dev_name; + if (len > NFS4_MAXNAMLEN) + return -ENAMETOOLONG; + /* N.B. caller will free nfs_server.hostname in all cases */ + args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL); + if (!args->nfs_server.hostname) + goto out_nomem; - if (args->auth_flavor_len > 1) - goto out_inval_auth; + c++; /* step over the ':' */ + len = strlen(c); + if (len > NFS4_MAXPATHLEN) + return -ENAMETOOLONG; + args->nfs_server.export_path = kstrndup(c, len, GFP_KERNEL); + if (!args->nfs_server.export_path) + goto out_nomem; + + dprintk("NFS: MNTPATH: '%s'\n", args->nfs_server.export_path); if (args->client_address == NULL) goto out_no_client_address; - status = nfs_parse_devname(dev_name, - &args->nfs_server.hostname, - NFS4_MAXNAMLEN, - &args->nfs_server.export_path, - NFS4_MAXPATHLEN); - if (status < 0) - return status; - break; } } @@ -2278,6 +1944,10 @@ static int nfs4_validate_mount_data(void *options, data->auth_flavourlen); return -EINVAL; +out_nomem: + dfprintk(MOUNT, "NFS4: not enough memory to handle mount options\n"); + return -ENOMEM; + out_no_address: dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n"); return -EINVAL; diff --git a/trunk/fs/nfs/write.c b/trunk/fs/nfs/write.c index 3229e217c773..f333848fd3be 100644 --- a/trunk/fs/nfs/write.c +++ b/trunk/fs/nfs/write.c @@ -34,6 +34,9 @@ /* * Local function declarations */ +static struct nfs_page * nfs_update_request(struct nfs_open_context*, + struct page *, + unsigned int, unsigned int); static void nfs_pageio_init_write(struct nfs_pageio_descriptor *desc, struct inode *inode, int ioflags); static void nfs_redirty_request(struct nfs_page *req); @@ -133,21 +136,16 @@ static struct nfs_page *nfs_page_find_request(struct page *page) static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int count) { struct inode *inode = page->mapping->host; - loff_t end, i_size; - pgoff_t end_index; + loff_t end, i_size = i_size_read(inode); + pgoff_t end_index = (i_size - 1) >> PAGE_CACHE_SHIFT; - spin_lock(&inode->i_lock); - i_size = i_size_read(inode); - end_index = (i_size - 1) >> PAGE_CACHE_SHIFT; if (i_size > 0 && page->index < end_index) - goto out; + return; end = ((loff_t)page->index << PAGE_CACHE_SHIFT) + ((loff_t)offset+count); if (i_size >= end) - goto out; - i_size_write(inode, end); + return; nfs_inc_stats(inode, NFSIOS_EXTENDWRITE); -out: - spin_unlock(&inode->i_lock); + i_size_write(inode, end); } /* A writeback failed: mark the page as bad, and invalidate the page cache */ @@ -171,6 +169,29 @@ static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int SetPageUptodate(page); } +static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page, + unsigned int offset, unsigned int count) +{ + struct nfs_page *req; + int ret; + + for (;;) { + req = nfs_update_request(ctx, page, offset, count); + if (!IS_ERR(req)) + break; + ret = PTR_ERR(req); + if (ret != -EBUSY) + return ret; + ret = nfs_wb_page(page->mapping->host, page); + if (ret != 0) + return ret; + } + /* Update file length */ + nfs_grow_file(page, offset, count); + nfs_clear_page_tag_locked(req); + return 0; +} + static int wb_priority(struct writeback_control *wbc) { if (wbc->for_reclaim) @@ -247,9 +268,12 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, return ret; spin_lock(&inode->i_lock); } - if (test_bit(PG_CLEAN, &req->wb_flags)) { + if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) { + /* This request is marked for commit */ spin_unlock(&inode->i_lock); - BUG(); + nfs_clear_page_tag_locked(req); + nfs_pageio_complete(pgio); + return 0; } if (nfs_set_page_writeback(page) != 0) { spin_unlock(&inode->i_lock); @@ -331,19 +355,11 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) /* * Insert a write request into an inode */ -static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) +static void nfs_inode_add_request(struct inode *inode, struct nfs_page *req) { struct nfs_inode *nfsi = NFS_I(inode); int error; - error = radix_tree_preload(GFP_NOFS); - if (error != 0) - goto out; - - /* Lock the request! */ - nfs_lock_request_dontget(req); - - spin_lock(&inode->i_lock); error = radix_tree_insert(&nfsi->nfs_page_tree, req->wb_index, req); BUG_ON(error); if (!nfsi->npages) { @@ -357,10 +373,6 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) kref_get(&req->wb_kref); radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED); - spin_unlock(&inode->i_lock); - radix_tree_preload_end(); -out: - return error; } /* @@ -393,6 +405,19 @@ nfs_mark_request_dirty(struct nfs_page *req) __set_page_dirty_nobuffers(req->wb_page); } +/* + * Check if a request is dirty + */ +static inline int +nfs_dirty_request(struct nfs_page *req) +{ + struct page *page = req->wb_page; + + if (page == NULL || test_bit(PG_NEED_COMMIT, &req->wb_flags)) + return 0; + return !PageWriteback(page); +} + #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) /* * Add a request to the inode's commit list. @@ -405,7 +430,7 @@ nfs_mark_request_commit(struct nfs_page *req) spin_lock(&inode->i_lock); nfsi->ncommit++; - set_bit(PG_CLEAN, &(req)->wb_flags); + set_bit(PG_NEED_COMMIT, &(req)->wb_flags); radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_COMMIT); @@ -415,19 +440,6 @@ nfs_mark_request_commit(struct nfs_page *req) __mark_inode_dirty(inode, I_DIRTY_DATASYNC); } -static int -nfs_clear_request_commit(struct nfs_page *req) -{ - struct page *page = req->wb_page; - - if (test_and_clear_bit(PG_CLEAN, &(req)->wb_flags)) { - dec_zone_page_state(page, NR_UNSTABLE_NFS); - dec_bdi_stat(page->mapping->backing_dev_info, BDI_RECLAIMABLE); - return 1; - } - return 0; -} - static inline int nfs_write_need_commit(struct nfs_write_data *data) { @@ -437,7 +449,7 @@ int nfs_write_need_commit(struct nfs_write_data *data) static inline int nfs_reschedule_unstable_write(struct nfs_page *req) { - if (test_and_clear_bit(PG_NEED_COMMIT, &req->wb_flags)) { + if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) { nfs_mark_request_commit(req); return 1; } @@ -453,12 +465,6 @@ nfs_mark_request_commit(struct nfs_page *req) { } -static inline int -nfs_clear_request_commit(struct nfs_page *req) -{ - return 0; -} - static inline int nfs_write_need_commit(struct nfs_write_data *data) { @@ -516,8 +522,11 @@ static void nfs_cancel_commit_list(struct list_head *head) while(!list_empty(head)) { req = nfs_list_entry(head->next); + dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); + dec_bdi_stat(req->wb_page->mapping->backing_dev_info, + BDI_RECLAIMABLE); nfs_list_remove_request(req); - nfs_clear_request_commit(req); + clear_bit(PG_NEED_COMMIT, &(req)->wb_flags); nfs_inode_remove_request(req); nfs_unlock_request(req); } @@ -555,122 +564,108 @@ static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst, pg #endif /* - * Search for an existing write request, and attempt to update - * it to reflect a new dirty region on a given page. + * Try to update any existing write request, or create one if there is none. + * In order to match, the request's credentials must match those of + * the calling process. * - * If the attempt fails, then the existing request is flushed out - * to disk. + * Note: Should always be called with the Page Lock held! */ -static struct nfs_page *nfs_try_to_update_request(struct inode *inode, - struct page *page, - unsigned int offset, - unsigned int bytes) +static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx, + struct page *page, unsigned int offset, unsigned int bytes) { - struct nfs_page *req; - unsigned int rqend; - unsigned int end; - int error; - - if (!PagePrivate(page)) - return NULL; + struct address_space *mapping = page->mapping; + struct inode *inode = mapping->host; + struct nfs_page *req, *new = NULL; + pgoff_t rqend, end; end = offset + bytes; - spin_lock(&inode->i_lock); for (;;) { - req = nfs_page_find_request_locked(page); - if (req == NULL) - goto out_unlock; - - rqend = req->wb_offset + req->wb_bytes; - /* - * Tell the caller to flush out the request if - * the offsets are non-contiguous. - * Note: nfs_flush_incompatible() will already - * have flushed out requests having wrong owners. + /* Loop over all inode entries and see if we find + * A request for the page we wish to update */ - if (offset > rqend - || end < req->wb_offset) - goto out_flushme; + if (new) { + if (radix_tree_preload(GFP_NOFS)) { + nfs_release_request(new); + return ERR_PTR(-ENOMEM); + } + } - if (nfs_set_page_tag_locked(req)) + spin_lock(&inode->i_lock); + req = nfs_page_find_request_locked(page); + if (req) { + if (!nfs_set_page_tag_locked(req)) { + int error; + + spin_unlock(&inode->i_lock); + error = nfs_wait_on_request(req); + nfs_release_request(req); + if (error < 0) { + if (new) { + radix_tree_preload_end(); + nfs_release_request(new); + } + return ERR_PTR(error); + } + continue; + } + spin_unlock(&inode->i_lock); + if (new) { + radix_tree_preload_end(); + nfs_release_request(new); + } break; + } - /* The request is locked, so wait and then retry */ + if (new) { + nfs_lock_request_dontget(new); + nfs_inode_add_request(inode, new); + spin_unlock(&inode->i_lock); + radix_tree_preload_end(); + req = new; + goto zero_page; + } spin_unlock(&inode->i_lock); - error = nfs_wait_on_request(req); - nfs_release_request(req); - if (error != 0) - goto out_err; - spin_lock(&inode->i_lock); + + new = nfs_create_request(ctx, inode, page, offset, bytes); + if (IS_ERR(new)) + return new; } - if (nfs_clear_request_commit(req)) - radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree, - req->wb_index, NFS_PAGE_TAG_COMMIT); + /* We have a request for our page. + * If the creds don't match, or the + * page addresses don't match, + * tell the caller to wait on the conflicting + * request. + */ + rqend = req->wb_offset + req->wb_bytes; + if (req->wb_context != ctx + || req->wb_page != page + || !nfs_dirty_request(req) + || offset > rqend || end < req->wb_offset) { + nfs_clear_page_tag_locked(req); + return ERR_PTR(-EBUSY); + } /* Okay, the request matches. Update the region */ if (offset < req->wb_offset) { req->wb_offset = offset; req->wb_pgbase = offset; + req->wb_bytes = max(end, rqend) - req->wb_offset; + goto zero_page; } + if (end > rqend) req->wb_bytes = end - req->wb_offset; - else - req->wb_bytes = rqend - req->wb_offset; -out_unlock: - spin_unlock(&inode->i_lock); - return req; -out_flushme: - spin_unlock(&inode->i_lock); - nfs_release_request(req); - error = nfs_wb_page(inode, page); -out_err: - return ERR_PTR(error); -} -/* - * Try to update an existing write request, or create one if there is none. - * - * Note: Should always be called with the Page Lock held to prevent races - * if we have to add a new request. Also assumes that the caller has - * already called nfs_flush_incompatible() if necessary. - */ -static struct nfs_page * nfs_setup_write_request(struct nfs_open_context* ctx, - struct page *page, unsigned int offset, unsigned int bytes) -{ - struct inode *inode = page->mapping->host; - struct nfs_page *req; - int error; - - req = nfs_try_to_update_request(inode, page, offset, bytes); - if (req != NULL) - goto out; - req = nfs_create_request(ctx, inode, page, offset, bytes); - if (IS_ERR(req)) - goto out; - error = nfs_inode_add_request(inode, req); - if (error != 0) { - nfs_release_request(req); - req = ERR_PTR(error); - } -out: return req; -} - -static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page, - unsigned int offset, unsigned int count) -{ - struct nfs_page *req; - - req = nfs_setup_write_request(ctx, page, offset, count); - if (IS_ERR(req)) - return PTR_ERR(req); - /* Update file length */ - nfs_grow_file(page, offset, count); - nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); - nfs_clear_page_tag_locked(req); - return 0; +zero_page: + /* If this page might potentially be marked as up to date, + * then we need to zero any uninitalised data. */ + if (req->wb_pgbase == 0 && req->wb_bytes != PAGE_CACHE_SIZE + && !PageUptodate(req->wb_page)) + zero_user_segment(req->wb_page, req->wb_bytes, PAGE_CACHE_SIZE); + return req; } int nfs_flush_incompatible(struct file *file, struct page *page) @@ -690,7 +685,8 @@ int nfs_flush_incompatible(struct file *file, struct page *page) req = nfs_page_find_request(page); if (req == NULL) return 0; - do_flush = req->wb_page != page || req->wb_context != ctx; + do_flush = req->wb_page != page || req->wb_context != ctx + || !nfs_dirty_request(req); nfs_release_request(req); if (!do_flush) return 0; @@ -725,10 +721,10 @@ int nfs_updatepage(struct file *file, struct page *page, nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE); - dprintk("NFS: nfs_updatepage(%s/%s %d@%lld)\n", + dprintk("NFS: nfs_updatepage(%s/%s %d@%Ld)\n", file->f_path.dentry->d_parent->d_name.name, file->f_path.dentry->d_name.name, count, - (long long)(page_offset(page) + offset)); + (long long)(page_offset(page) +offset)); /* If we're not using byte range locks, and we know the page * is up to date, it may be more efficient to extend the write @@ -748,7 +744,7 @@ int nfs_updatepage(struct file *file, struct page *page, else __set_page_dirty_nobuffers(page); - dprintk("NFS: nfs_updatepage returns %d (isize %lld)\n", + dprintk("NFS: nfs_updatepage returns %d (isize %Ld)\n", status, (long long)i_size_read(inode)); return status; } @@ -756,7 +752,12 @@ int nfs_updatepage(struct file *file, struct page *page, static void nfs_writepage_release(struct nfs_page *req) { - if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) { + if (PageError(req->wb_page)) { + nfs_end_page_writeback(req->wb_page); + nfs_inode_remove_request(req); + } else if (!nfs_reschedule_unstable_write(req)) { + /* Set the PG_uptodate flag */ + nfs_mark_uptodate(req->wb_page, req->wb_pgbase, req->wb_bytes); nfs_end_page_writeback(req->wb_page); nfs_inode_remove_request(req); } else @@ -833,7 +834,7 @@ static int nfs_write_rpcsetup(struct nfs_page *req, NFS_PROTO(inode)->write_setup(data, &msg); dprintk("NFS: %5u initiated write call " - "(req %s/%lld, %u bytes @ offset %llu)\n", + "(req %s/%Ld, %u bytes @ offset %Lu)\n", data->task.tk_pid, inode->i_sb->s_id, (long long)NFS_FILEID(inode), @@ -977,13 +978,13 @@ static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata) { struct nfs_write_data *data = calldata; + struct nfs_page *req = data->req; - dprintk("NFS: %5u write(%s/%lld %d@%lld)", - task->tk_pid, - data->req->wb_context->path.dentry->d_inode->i_sb->s_id, - (long long) - NFS_FILEID(data->req->wb_context->path.dentry->d_inode), - data->req->wb_bytes, (long long)req_offset(data->req)); + dprintk("NFS: write (%s/%Ld %d@%Ld)", + req->wb_context->path.dentry->d_inode->i_sb->s_id, + (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode), + req->wb_bytes, + (long long)req_offset(req)); nfs_writeback_done(task, data); } @@ -1057,8 +1058,7 @@ static void nfs_writeback_release_full(void *calldata) nfs_list_remove_request(req); - dprintk("NFS: %5u write (%s/%lld %d@%lld)", - data->task.tk_pid, + dprintk("NFS: write (%s/%Ld %d@%Ld)", req->wb_context->path.dentry->d_inode->i_sb->s_id, (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode), req->wb_bytes, @@ -1078,6 +1078,8 @@ static void nfs_writeback_release_full(void *calldata) dprintk(" marked for commit\n"); goto next; } + /* Set the PG_uptodate flag? */ + nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); dprintk(" OK\n"); remove_request: nfs_end_page_writeback(page); @@ -1131,7 +1133,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) static unsigned long complain; if (time_before(complain, jiffies)) { - dprintk("NFS: faulty NFS server %s:" + dprintk("NFS: faulty NFS server %s:" " (committed = %d) != (stable = %d)\n", NFS_SERVER(data->inode)->nfs_client->cl_hostname, resp->verf->committed, argp->stable); @@ -1295,9 +1297,12 @@ static void nfs_commit_release(void *calldata) while (!list_empty(&data->pages)) { req = nfs_list_entry(data->pages.next); nfs_list_remove_request(req); - nfs_clear_request_commit(req); + clear_bit(PG_NEED_COMMIT, &(req)->wb_flags); + dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); + dec_bdi_stat(req->wb_page->mapping->backing_dev_info, + BDI_RECLAIMABLE); - dprintk("NFS: commit (%s/%lld %d@%lld)", + dprintk("NFS: commit (%s/%Ld %d@%Ld)", req->wb_context->path.dentry->d_inode->i_sb->s_id, (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode), req->wb_bytes, @@ -1313,6 +1318,9 @@ static void nfs_commit_release(void *calldata) * returned by the server against all stored verfs. */ if (!memcmp(req->wb_verf.verifier, data->verf.verifier, sizeof(data->verf.verifier))) { /* We have a match */ + /* Set the PG_uptodate flag */ + nfs_mark_uptodate(req->wb_page, req->wb_pgbase, + req->wb_bytes); nfs_inode_remove_request(req); dprintk(" OK\n"); goto next; @@ -1471,7 +1479,7 @@ int nfs_wb_page_cancel(struct inode *inode, struct page *page) req = nfs_page_find_request(page); if (req == NULL) goto out; - if (test_bit(PG_CLEAN, &req->wb_flags)) { + if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) { nfs_release_request(req); break; } diff --git a/trunk/fs/nfsd/nfs4callback.c b/trunk/fs/nfsd/nfs4callback.c index 702fa577aa6e..4d4760e687c3 100644 --- a/trunk/fs/nfsd/nfs4callback.c +++ b/trunk/fs/nfsd/nfs4callback.c @@ -381,7 +381,7 @@ static int do_probe_callback(void *data) .program = &cb_program, .version = nfs_cb_version[1]->number, .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */ - .flags = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET), + .flags = (RPC_CLNT_CREATE_NOPING), }; struct rpc_message msg = { .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], diff --git a/trunk/include/acpi/acconfig.h b/trunk/include/acpi/acconfig.h index 4eb75a88795a..28fe8bae1037 100644 --- a/trunk/include/acpi/acconfig.h +++ b/trunk/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20080609 +#define ACPI_CA_VERSION 0x20080321 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, diff --git a/trunk/include/acpi/acdisasm.h b/trunk/include/acpi/acdisasm.h index f53faca8ec80..788f88782012 100644 --- a/trunk/include/acpi/acdisasm.h +++ b/trunk/include/acpi/acdisasm.h @@ -162,7 +162,6 @@ extern struct acpi_dmtable_info acpi_dm_table_info_dmar_hdr[]; extern struct acpi_dmtable_info acpi_dm_table_info_dmar_scope[]; extern struct acpi_dmtable_info acpi_dm_table_info_dmar0[]; extern struct acpi_dmtable_info acpi_dm_table_info_dmar1[]; -extern struct acpi_dmtable_info acpi_dm_table_info_dmar2[]; extern struct acpi_dmtable_info acpi_dm_table_info_ecdt[]; extern struct acpi_dmtable_info acpi_dm_table_info_einj[]; extern struct acpi_dmtable_info acpi_dm_table_info_einj0[]; diff --git a/trunk/include/acpi/acdispat.h b/trunk/include/acpi/acdispat.h index 21a73a105d0a..910f018d92c7 100644 --- a/trunk/include/acpi/acdispat.h +++ b/trunk/include/acpi/acdispat.h @@ -221,7 +221,7 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state); * dsinit */ acpi_status -acpi_ds_initialize_objects(u32 table_index, +acpi_ds_initialize_objects(acpi_native_uint table_index, struct acpi_namespace_node *start_node); /* diff --git a/trunk/include/acpi/acexcep.h b/trunk/include/acpi/acexcep.h index e5a890ffeb02..1f591171bf31 100644 --- a/trunk/include/acpi/acexcep.h +++ b/trunk/include/acpi/acexcep.h @@ -108,9 +108,8 @@ #define AE_BAD_HEX_CONSTANT (acpi_status) (0x0007 | AE_CODE_PROGRAMMER) #define AE_BAD_OCTAL_CONSTANT (acpi_status) (0x0008 | AE_CODE_PROGRAMMER) #define AE_BAD_DECIMAL_CONSTANT (acpi_status) (0x0009 | AE_CODE_PROGRAMMER) -#define AE_MISSING_ARGUMENTS (acpi_status) (0x000A | AE_CODE_PROGRAMMER) -#define AE_CODE_PGM_MAX 0x000A +#define AE_CODE_PGM_MAX 0x0009 /* * Acpi table exceptions @@ -226,7 +225,6 @@ char const *acpi_gbl_exception_names_env[] = { }; char const *acpi_gbl_exception_names_pgm[] = { - NULL, "AE_BAD_PARAMETER", "AE_BAD_CHARACTER", "AE_BAD_PATHNAME", @@ -235,12 +233,10 @@ char const *acpi_gbl_exception_names_pgm[] = { "AE_ALIGNMENT", "AE_BAD_HEX_CONSTANT", "AE_BAD_OCTAL_CONSTANT", - "AE_BAD_DECIMAL_CONSTANT", - "AE_MISSING_ARGUMENTS" + "AE_BAD_DECIMAL_CONSTANT" }; char const *acpi_gbl_exception_names_tbl[] = { - NULL, "AE_BAD_SIGNATURE", "AE_BAD_HEADER", "AE_BAD_CHECKSUM", @@ -250,7 +246,6 @@ char const *acpi_gbl_exception_names_tbl[] = { }; char const *acpi_gbl_exception_names_aml[] = { - NULL, "AE_AML_ERROR", "AE_AML_PARSE", "AE_AML_BAD_OPCODE", @@ -288,7 +283,6 @@ char const *acpi_gbl_exception_names_aml[] = { }; char const *acpi_gbl_exception_names_ctrl[] = { - NULL, "AE_CTRL_RETURN_VALUE", "AE_CTRL_PENDING", "AE_CTRL_TERMINATE", diff --git a/trunk/include/acpi/acglobal.h b/trunk/include/acpi/acglobal.h index 15dda46b70d1..74ad971241db 100644 --- a/trunk/include/acpi/acglobal.h +++ b/trunk/include/acpi/acglobal.h @@ -140,7 +140,7 @@ ACPI_EXTERN u32 acpi_gbl_trace_flags; */ ACPI_EXTERN struct acpi_internal_rsdt acpi_gbl_root_table_list; ACPI_EXTERN struct acpi_table_fadt acpi_gbl_FADT; -extern u8 acpi_gbl_permanent_mmap; +extern acpi_native_uint acpi_gbl_permanent_mmap; /* These addresses are calculated from FADT address values */ diff --git a/trunk/include/acpi/achware.h b/trunk/include/acpi/achware.h index 97a72b193276..d4fb9bbc903c 100644 --- a/trunk/include/acpi/achware.h +++ b/trunk/include/acpi/achware.h @@ -87,8 +87,6 @@ acpi_status acpi_hw_clear_acpi_status(void); /* * hwgpe - GPE support */ -acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info); - acpi_status acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info *gpe_event_info); @@ -102,9 +100,11 @@ acpi_status acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, struct acpi_gpe_block_info *gpe_block); +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info, acpi_event_status * event_status); +#endif /* ACPI_FUTURE_USAGE */ acpi_status acpi_hw_disable_all_gpes(void); diff --git a/trunk/include/acpi/acinterp.h b/trunk/include/acpi/acinterp.h index e8db7a3143a5..e249ce5d3300 100644 --- a/trunk/include/acpi/acinterp.h +++ b/trunk/include/acpi/acinterp.h @@ -366,7 +366,10 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth); void acpi_ex_dump_operands(union acpi_operand_object **operands, - const char *opcode_name, u32 num_opcodes); + acpi_interpreter_mode interpreter_mode, + char *ident, + u32 num_levels, + char *note, char *module_name, u32 line_number); #ifdef ACPI_FUTURE_USAGE void diff --git a/trunk/include/acpi/aclocal.h b/trunk/include/acpi/aclocal.h index b221c8583ddd..c5cdc32ac2f8 100644 --- a/trunk/include/acpi/aclocal.h +++ b/trunk/include/acpi/aclocal.h @@ -98,8 +98,8 @@ union acpi_parse_object; static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = { "ACPI_MTX_Interpreter", - "ACPI_MTX_Namespace", "ACPI_MTX_Tables", + "ACPI_MTX_Namespace", "ACPI_MTX_Events", "ACPI_MTX_Caches", "ACPI_MTX_Memory", @@ -282,8 +282,8 @@ struct acpi_predefined_names { /* Info structure used to convert external<->internal namestrings */ struct acpi_namestring_info { - const char *external_name; - const char *next_external_char; + char *external_name; + char *next_external_char; char *internal_name; u32 length; u32 num_segments; diff --git a/trunk/include/acpi/acmacros.h b/trunk/include/acpi/acmacros.h index 57ab9e9d7593..fb41a3b802fc 100644 --- a/trunk/include/acpi/acmacros.h +++ b/trunk/include/acpi/acmacros.h @@ -80,12 +80,12 @@ */ #define ACPI_CAST_PTR(t, p) ((t *) (acpi_uintptr_t) (p)) #define ACPI_CAST_INDIRECT_PTR(t, p) ((t **) (acpi_uintptr_t) (p)) -#define ACPI_ADD_PTR(t, a, b) ACPI_CAST_PTR (t, (ACPI_CAST_PTR (u8,(a)) + (acpi_size)(b))) -#define ACPI_PTR_DIFF(a, b) (acpi_size) (ACPI_CAST_PTR (u8,(a)) - ACPI_CAST_PTR (u8,(b))) +#define ACPI_ADD_PTR(t,a,b) ACPI_CAST_PTR (t, (ACPI_CAST_PTR (u8,(a)) + (acpi_native_uint)(b))) +#define ACPI_PTR_DIFF(a,b) (acpi_native_uint) (ACPI_CAST_PTR (u8,(a)) - ACPI_CAST_PTR (u8,(b))) /* Pointer/Integer type conversions */ -#define ACPI_TO_POINTER(i) ACPI_ADD_PTR (void, (void *) NULL, (acpi_size) i) +#define ACPI_TO_POINTER(i) ACPI_ADD_PTR (void,(void *) NULL,(acpi_native_uint) i) #define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p,(void *) NULL) #define ACPI_OFFSET(d,f) (acpi_size) ACPI_PTR_DIFF (&(((d *)0)->f),(void *) NULL) #define ACPI_PHYSADDR_TO_PTR(i) ACPI_TO_POINTER(i) @@ -296,22 +296,22 @@ struct acpi_integer_overlay { /* * Rounding macros (Power of two boundaries only) */ -#define ACPI_ROUND_DOWN(value, boundary) (((acpi_size)(value)) & \ - (~(((acpi_size) boundary)-1))) +#define ACPI_ROUND_DOWN(value,boundary) (((acpi_native_uint)(value)) & \ + (~(((acpi_native_uint) boundary)-1))) -#define ACPI_ROUND_UP(value, boundary) ((((acpi_size)(value)) + \ - (((acpi_size) boundary)-1)) & \ - (~(((acpi_size) boundary)-1))) +#define ACPI_ROUND_UP(value,boundary) ((((acpi_native_uint)(value)) + \ + (((acpi_native_uint) boundary)-1)) & \ + (~(((acpi_native_uint) boundary)-1))) -/* Note: sizeof(acpi_size) evaluates to either 4 or 8 (32- vs 64-bit mode) */ +/* Note: sizeof(acpi_native_uint) evaluates to either 2, 4, or 8 */ #define ACPI_ROUND_DOWN_TO_32BIT(a) ACPI_ROUND_DOWN(a,4) #define ACPI_ROUND_DOWN_TO_64BIT(a) ACPI_ROUND_DOWN(a,8) -#define ACPI_ROUND_DOWN_TO_NATIVE_WORD(a) ACPI_ROUND_DOWN(a,sizeof(acpi_size)) +#define ACPI_ROUND_DOWN_TO_NATIVE_WORD(a) ACPI_ROUND_DOWN(a,sizeof(acpi_native_uint)) #define ACPI_ROUND_UP_TO_32BIT(a) ACPI_ROUND_UP(a,4) #define ACPI_ROUND_UP_TO_64BIT(a) ACPI_ROUND_UP(a,8) -#define ACPI_ROUND_UP_TO_NATIVE_WORD(a) ACPI_ROUND_UP(a,sizeof(acpi_size)) +#define ACPI_ROUND_UP_TO_NATIVE_WORD(a) ACPI_ROUND_UP(a,sizeof(acpi_native_uint)) #define ACPI_ROUND_BITS_UP_TO_BYTES(a) ACPI_DIV_8((a) + 7) #define ACPI_ROUND_BITS_DOWN_TO_BYTES(a) ACPI_DIV_8((a)) @@ -322,7 +322,7 @@ struct acpi_integer_overlay { #define ACPI_ROUND_UP_TO(value,boundary) (((value) + ((boundary)-1)) / (boundary)) -#define ACPI_IS_MISALIGNED(value) (((acpi_size)value) & (sizeof(acpi_size)-1)) +#define ACPI_IS_MISALIGNED(value) (((acpi_native_uint)value) & (sizeof(acpi_native_uint)-1)) /* * Bitmask creation @@ -414,7 +414,7 @@ struct acpi_integer_overlay { * error messages. The __FILE__ macro is not very useful for this, because it * often includes the entire pathname to the module */ -#define ACPI_MODULE_NAME(name) static const char ACPI_UNUSED_VAR _acpi_module_name[] = name; +#define ACPI_MODULE_NAME(name) static char ACPI_UNUSED_VAR *_acpi_module_name = name; #else #define ACPI_MODULE_NAME(name) #endif @@ -467,17 +467,19 @@ struct acpi_integer_overlay { /* * If ACPI_GET_FUNCTION_NAME was not defined in the compiler-dependent header, * define it now. This is the case where there the compiler does not support - * a __FUNCTION__ macro or equivalent. + * a __FUNCTION__ macro or equivalent. We save the function name on the + * local stack. */ #ifndef ACPI_GET_FUNCTION_NAME #define ACPI_GET_FUNCTION_NAME _acpi_function_name /* * The Name parameter should be the procedure name as a quoted string. - * The function name is also used by the function exit macros below. + * This is declared as a local string ("MyFunctionName") so that it can + * be also used by the function exit macros below. * Note: (const char) is used to be compatible with the debug interfaces * and macros such as __FUNCTION__. */ -#define ACPI_FUNCTION_NAME(name) static const char _acpi_function_name[] = #name; +#define ACPI_FUNCTION_NAME(name) const char *_acpi_function_name = #name; #else /* Compiler supports __FUNCTION__ (or equivalent) -- Ignore this macro */ @@ -597,7 +599,7 @@ struct acpi_integer_overlay { /* Stack and buffer dumping */ #define ACPI_DUMP_STACK_ENTRY(a) acpi_ex_dump_operand((a),0) -#define ACPI_DUMP_OPERANDS(a,b,c) acpi_ex_dump_operands(a,b,c) +#define ACPI_DUMP_OPERANDS(a,b,c,d,e) acpi_ex_dump_operands(a,b,c,d,e,_acpi_module_name,__LINE__) #define ACPI_DUMP_ENTRY(a,b) acpi_ns_dump_entry (a,b) #define ACPI_DUMP_PATHNAME(a,b,c,d) acpi_ns_dump_pathname(a,b,c,d) @@ -633,7 +635,7 @@ struct acpi_integer_overlay { #define ACPI_FUNCTION_VALUE_EXIT(s) do { } while(0) #define ACPI_FUNCTION_ENTRY() do { } while(0) #define ACPI_DUMP_STACK_ENTRY(a) do { } while(0) -#define ACPI_DUMP_OPERANDS(a,b,c) do { } while(0) +#define ACPI_DUMP_OPERANDS(a,b,c,d,e) do { } while(0) #define ACPI_DUMP_ENTRY(a,b) do { } while(0) #define ACPI_DUMP_TABLES(a,b) do { } while(0) #define ACPI_DUMP_PATHNAME(a,b,c,d) do { } while(0) diff --git a/trunk/include/acpi/acnamesp.h b/trunk/include/acpi/acnamesp.h index 9ed70a050580..713b30903fe5 100644 --- a/trunk/include/acpi/acnamesp.h +++ b/trunk/include/acpi/acnamesp.h @@ -86,7 +86,8 @@ acpi_status acpi_ns_initialize_devices(void); acpi_status acpi_ns_load_namespace(void); acpi_status -acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node); +acpi_ns_load_table(acpi_native_uint table_index, + struct acpi_namespace_node *node); /* * nswalk - walk the namespace @@ -107,11 +108,12 @@ struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, struct * nsparse - table parsing */ acpi_status -acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node); +acpi_ns_parse_table(acpi_native_uint table_index, + struct acpi_namespace_node *start_node); acpi_status -acpi_ns_one_complete_parse(u32 pass_number, - u32 table_index, +acpi_ns_one_complete_parse(acpi_native_uint pass_number, + acpi_native_uint table_index, struct acpi_namespace_node *start_node); /* @@ -199,7 +201,7 @@ acpi_ns_pattern_match(struct acpi_namespace_node *obj_node, char *search_for); acpi_status acpi_ns_get_node(struct acpi_namespace_node *prefix_node, - const char *external_pathname, + char *external_pathname, u32 flags, struct acpi_namespace_node **out_node); acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node); @@ -263,30 +265,28 @@ acpi_object_type acpi_ns_get_type(struct acpi_namespace_node *node); u32 acpi_ns_local(acpi_object_type type); void -acpi_ns_report_error(const char *module_name, +acpi_ns_report_error(char *module_name, u32 line_number, - const char *internal_name, acpi_status lookup_status); + char *internal_name, acpi_status lookup_status); void -acpi_ns_report_method_error(const char *module_name, +acpi_ns_report_method_error(char *module_name, u32 line_number, - const char *message, + char *message, struct acpi_namespace_node *node, - const char *path, acpi_status lookup_status); + char *path, acpi_status lookup_status); -void -acpi_ns_print_node_pathname(struct acpi_namespace_node *node, const char *msg); +void acpi_ns_print_node_pathname(struct acpi_namespace_node *node, char *msg); acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info); void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info); -acpi_status -acpi_ns_internalize_name(const char *dotted_name, char **converted_name); +acpi_status acpi_ns_internalize_name(char *dotted_name, char **converted_name); acpi_status acpi_ns_externalize_name(u32 internal_name_length, - const char *internal_name, + char *internal_name, u32 * converted_name_length, char **converted_name); struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle); diff --git a/trunk/include/acpi/acpi_bus.h b/trunk/include/acpi/acpi_bus.h index db90a74f8714..2f1c68c7a727 100644 --- a/trunk/include/acpi/acpi_bus.h +++ b/trunk/include/acpi/acpi_bus.h @@ -376,9 +376,9 @@ acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) #ifdef CONFIG_PM_SLEEP -int acpi_pm_device_sleep_state(struct device *, int *); +int acpi_pm_device_sleep_state(struct device *, int, int *); #else /* !CONFIG_PM_SLEEP */ -static inline int acpi_pm_device_sleep_state(struct device *d, int *p) +static inline int acpi_pm_device_sleep_state(struct device *d, int w, int *p) { if (p) *p = ACPI_STATE_D0; diff --git a/trunk/include/acpi/acpiosxf.h b/trunk/include/acpi/acpiosxf.h index 3f93a6b4e17f..d4a560d2deb6 100644 --- a/trunk/include/acpi/acpiosxf.h +++ b/trunk/include/acpi/acpiosxf.h @@ -144,7 +144,7 @@ void acpi_os_release_mutex(acpi_mutex handle); void *acpi_os_allocate(acpi_size size); void __iomem *acpi_os_map_memory(acpi_physical_address where, - acpi_size length); + acpi_native_uint length); void acpi_os_unmap_memory(void __iomem * logical_address, acpi_size size); diff --git a/trunk/include/acpi/acpixf.h b/trunk/include/acpi/acpixf.h index 94d94e126e9f..2c3806e6546f 100644 --- a/trunk/include/acpi/acpixf.h +++ b/trunk/include/acpi/acpixf.h @@ -98,7 +98,7 @@ void acpi_free(void *address); */ acpi_status acpi_reallocate_root_table(void); -acpi_status acpi_find_root_pointer(acpi_size *rsdp_address); +acpi_status acpi_find_root_pointer(acpi_native_uint * rsdp_address); acpi_status acpi_load_tables(void); @@ -108,15 +108,15 @@ acpi_status acpi_unload_table_id(acpi_owner_id id); acpi_status acpi_get_table_header(acpi_string signature, - u32 instance, + acpi_native_uint instance, struct acpi_table_header *out_table_header); acpi_status acpi_get_table(acpi_string signature, - u32 instance, struct acpi_table_header **out_table); + acpi_native_uint instance, struct acpi_table_header **out_table); acpi_status -acpi_get_table_by_index(u32 table_index, +acpi_get_table_by_index(acpi_native_uint table_index, struct acpi_table_header **out_table); acpi_status @@ -248,7 +248,9 @@ acpi_status acpi_disable_event(u32 event, u32 flags); acpi_status acpi_clear_event(u32 event); +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status); +#endif /* ACPI_FUTURE_USAGE */ acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type); @@ -258,10 +260,12 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags); acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags); +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_get_gpe_status(acpi_handle gpe_device, u32 gpe_number, u32 flags, acpi_event_status * event_status); +#endif /* ACPI_FUTURE_USAGE */ acpi_status acpi_install_gpe_block(acpi_handle gpe_device, diff --git a/trunk/include/acpi/acstruct.h b/trunk/include/acpi/acstruct.h index 7980a26bad35..a907c67d651e 100644 --- a/trunk/include/acpi/acstruct.h +++ b/trunk/include/acpi/acstruct.h @@ -108,6 +108,7 @@ struct acpi_walk_state { union acpi_operand_object **caller_return_desc; union acpi_generic_state *control_state; /* List of control states (nested IFs) */ struct acpi_namespace_node *deferred_node; /* Used when executing deferred opcodes */ + struct acpi_gpe_event_info *gpe_event_info; /* Info for GPE (_Lxx/_Exx methods only */ union acpi_operand_object *implicit_return_obj; struct acpi_namespace_node *method_call_node; /* Called method Node */ union acpi_parse_object *method_call_op; /* method_call Op if running a method */ @@ -142,7 +143,7 @@ struct acpi_init_walk_info { u16 package_init; u16 object_count; acpi_owner_id owner_id; - u32 table_index; + acpi_native_uint table_index; }; struct acpi_get_devices_info { @@ -188,12 +189,17 @@ struct acpi_evaluate_info { union acpi_operand_object **parameters; struct acpi_namespace_node *resolved_node; union acpi_operand_object *return_object; - u8 param_count; u8 pass_number; + u8 parameter_type; u8 return_object_type; u8 flags; }; +/* Types for parameter_type above */ + +#define ACPI_PARAM_ARGS 0 +#define ACPI_PARAM_GPE 1 + /* Values for Flags above */ #define ACPI_IGNORE_RETURN_VALUE 1 diff --git a/trunk/include/acpi/actables.h b/trunk/include/acpi/actables.h index 0cbe1b9ab522..4b36a55b0b3b 100644 --- a/trunk/include/acpi/actables.h +++ b/trunk/include/acpi/actables.h @@ -49,7 +49,7 @@ acpi_status acpi_allocate_root_table(u32 initial_table_count); /* * tbfadt - FADT parse/convert/validate */ -void acpi_tb_parse_fadt(u32 table_index, u8 flags); +void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags); void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length); @@ -58,7 +58,8 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length); */ acpi_status acpi_tb_find_table(char *signature, - char *oem_id, char *oem_table_id, u32 *table_index); + char *oem_id, + char *oem_table_id, acpi_native_uint * table_index); /* * tbinstal - Table removal and deletion @@ -68,28 +69,30 @@ acpi_status acpi_tb_resize_root_table_list(void); acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc); acpi_status -acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index); +acpi_tb_add_table(struct acpi_table_desc *table_desc, + acpi_native_uint * table_index); acpi_status acpi_tb_store_table(acpi_physical_address address, struct acpi_table_header *table, - u32 length, u8 flags, u32 *table_index); + u32 length, u8 flags, acpi_native_uint * table_index); void acpi_tb_delete_table(struct acpi_table_desc *table_desc); void acpi_tb_terminate(void); -void acpi_tb_delete_namespace_by_owner(u32 table_index); +void acpi_tb_delete_namespace_by_owner(acpi_native_uint table_index); -acpi_status acpi_tb_allocate_owner_id(u32 table_index); +acpi_status acpi_tb_allocate_owner_id(acpi_native_uint table_index); -acpi_status acpi_tb_release_owner_id(u32 table_index); +acpi_status acpi_tb_release_owner_id(acpi_native_uint table_index); -acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id); +acpi_status +acpi_tb_get_owner_id(acpi_native_uint table_index, acpi_owner_id * owner_id); -u8 acpi_tb_is_table_loaded(u32 table_index); +u8 acpi_tb_is_table_loaded(acpi_native_uint table_index); -void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded); +void acpi_tb_set_table_loaded_flag(acpi_native_uint table_index, u8 is_loaded); /* * tbutils - table manager utilities @@ -100,14 +103,14 @@ void acpi_tb_print_table_header(acpi_physical_address address, struct acpi_table_header *header); -u8 acpi_tb_checksum(u8 *buffer, u32 length); +u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length); acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length); void acpi_tb_install_table(acpi_physical_address address, - u8 flags, char *signature, u32 table_index); + u8 flags, char *signature, acpi_native_uint table_index); acpi_status acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags); diff --git a/trunk/include/acpi/actbl1.h b/trunk/include/acpi/actbl1.h index d38f9be2f6ee..9af239bd1153 100644 --- a/trunk/include/acpi/actbl1.h +++ b/trunk/include/acpi/actbl1.h @@ -300,7 +300,6 @@ struct acpi_table_dbgp { /******************************************************************************* * * DMAR - DMA Remapping table - * From "Intel Virtualization Technology for Directed I/O", Sept. 2007 * ******************************************************************************/ @@ -311,10 +310,6 @@ struct acpi_table_dmar { u8 reserved[10]; }; -/* Flags */ - -#define ACPI_DMAR_INTR_REMAP (1) - /* DMAR subtable header */ struct acpi_dmar_header { @@ -387,20 +382,6 @@ struct acpi_dmar_reserved_memory { #define ACPI_DMAR_ALLOW_ALL (1) - -/* 2: Root Port ATS Capability Reporting Structure */ - -struct acpi_dmar_atsr { - struct acpi_dmar_header header; - u8 flags; - u8 reserved; - u16 segment; -}; - -/* Flags */ - -#define ACPI_DMAR_ALL_PORTS (1) - /******************************************************************************* * * ECDT - Embedded Controller Boot Resources Table @@ -1175,9 +1156,9 @@ struct acpi_srat_mem_affinity { u16 reserved; /* Reserved, must be zero */ u64 base_address; u64 length; - u32 reserved1; + u32 memory_type; /* See acpi_address_range_id */ u32 flags; - u64 reserved2; /* Reserved, must be zero */ + u64 reserved1; /* Reserved, must be zero */ }; /* Flags */ diff --git a/trunk/include/acpi/actypes.h b/trunk/include/acpi/actypes.h index 4ea4f40bf894..dfea2d440488 100644 --- a/trunk/include/acpi/actypes.h +++ b/trunk/include/acpi/actypes.h @@ -110,10 +110,10 @@ * usually used for memory allocation, efficient loop counters, and array * indexes. The types are similar to the size_t type in the C library and are * required because there is no C type that consistently represents the native - * data width. ACPI_SIZE is needed because there is no guarantee that a - * kernel-level C library is present. + * data width. * * ACPI_SIZE 16/32/64-bit unsigned value + * ACPI_NATIVE_UINT 16/32/64-bit unsigned value * ACPI_NATIVE_INT 16/32/64-bit signed value * */ @@ -147,9 +147,9 @@ typedef int INT32; /*! [End] no source code translation !*/ +typedef u64 acpi_native_uint; typedef s64 acpi_native_int; -typedef u64 acpi_size; typedef u64 acpi_io_address; typedef u64 acpi_physical_address; @@ -186,9 +186,9 @@ typedef int INT32; /*! [End] no source code translation !*/ +typedef u32 acpi_native_uint; typedef s32 acpi_native_int; -typedef u32 acpi_size; typedef u32 acpi_io_address; typedef u32 acpi_physical_address; @@ -202,6 +202,10 @@ typedef u32 acpi_physical_address; #error unknown ACPI_MACHINE_WIDTH #endif +/* Variable-width type, used instead of clib size_t */ + +typedef acpi_native_uint acpi_size; + /******************************************************************************* * * OS-dependent and compiler-dependent types @@ -215,7 +219,7 @@ typedef u32 acpi_physical_address; /* Value returned by acpi_os_get_thread_id */ #ifndef acpi_thread_id -#define acpi_thread_id acpi_size +#define acpi_thread_id acpi_native_uint #endif /* Object returned from acpi_os_create_lock */ @@ -227,7 +231,7 @@ typedef u32 acpi_physical_address; /* Flags for acpi_os_acquire_lock/acpi_os_release_lock */ #ifndef acpi_cpu_flags -#define acpi_cpu_flags acpi_size +#define acpi_cpu_flags acpi_native_uint #endif /* Object returned from acpi_os_create_cache */ diff --git a/trunk/include/acpi/acutils.h b/trunk/include/acpi/acutils.h index 69f8888771ff..b42cadf07302 100644 --- a/trunk/include/acpi/acutils.h +++ b/trunk/include/acpi/acutils.h @@ -172,7 +172,7 @@ char *acpi_ut_strstr(char *string1, char *string2); void *acpi_ut_memcpy(void *dest, const void *src, acpi_size count); -void *acpi_ut_memset(void *dest, u8 value, acpi_size count); +void *acpi_ut_memset(void *dest, acpi_native_uint value, acpi_size count); int acpi_ut_to_upper(int c); @@ -245,45 +245,41 @@ void acpi_ut_track_stack_ptr(void); void acpi_ut_trace(u32 line_number, - const char *function_name, - const char *module_name, u32 component_id); + const char *function_name, char *module_name, u32 component_id); void acpi_ut_trace_ptr(u32 line_number, const char *function_name, - const char *module_name, u32 component_id, void *pointer); + char *module_name, u32 component_id, void *pointer); void acpi_ut_trace_u32(u32 line_number, const char *function_name, - const char *module_name, u32 component_id, u32 integer); + char *module_name, u32 component_id, u32 integer); void acpi_ut_trace_str(u32 line_number, const char *function_name, - const char *module_name, u32 component_id, char *string); + char *module_name, u32 component_id, char *string); void acpi_ut_exit(u32 line_number, - const char *function_name, - const char *module_name, u32 component_id); + const char *function_name, char *module_name, u32 component_id); void acpi_ut_status_exit(u32 line_number, const char *function_name, - const char *module_name, - u32 component_id, acpi_status status); + char *module_name, u32 component_id, acpi_status status); void acpi_ut_value_exit(u32 line_number, const char *function_name, - const char *module_name, - u32 component_id, acpi_integer value); + char *module_name, u32 component_id, acpi_integer value); void acpi_ut_ptr_exit(u32 line_number, const char *function_name, - const char *module_name, u32 component_id, u8 *ptr); + char *module_name, u32 component_id, u8 * ptr); void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id); @@ -301,35 +297,33 @@ void ACPI_INTERNAL_VAR_XFACE acpi_ut_debug_print(u32 requested_debug_level, u32 line_number, const char *function_name, - const char *module_name, - u32 component_id, - const char *format, ...) ACPI_PRINTF_LIKE(6); + char *module_name, + u32 component_id, char *format, ...) ACPI_PRINTF_LIKE(6); void ACPI_INTERNAL_VAR_XFACE acpi_ut_debug_print_raw(u32 requested_debug_level, u32 line_number, const char *function_name, - const char *module_name, + char *module_name, u32 component_id, - const char *format, ...) ACPI_PRINTF_LIKE(6); + char *format, ...) ACPI_PRINTF_LIKE(6); void ACPI_INTERNAL_VAR_XFACE -acpi_ut_error(const char *module_name, - u32 line_number, const char *format, ...) ACPI_PRINTF_LIKE(3); +acpi_ut_error(char *module_name, + u32 line_number, char *format, ...) ACPI_PRINTF_LIKE(3); void ACPI_INTERNAL_VAR_XFACE -acpi_ut_exception(const char *module_name, +acpi_ut_exception(char *module_name, u32 line_number, - acpi_status status, - const char *format, ...) ACPI_PRINTF_LIKE(4); + acpi_status status, char *format, ...) ACPI_PRINTF_LIKE(4); void ACPI_INTERNAL_VAR_XFACE -acpi_ut_warning(const char *module_name, - u32 line_number, const char *format, ...) ACPI_PRINTF_LIKE(3); +acpi_ut_warning(char *module_name, + u32 line_number, char *format, ...) ACPI_PRINTF_LIKE(3); void ACPI_INTERNAL_VAR_XFACE -acpi_ut_info(const char *module_name, - u32 line_number, const char *format, ...) ACPI_PRINTF_LIKE(3); +acpi_ut_info(char *module_name, + u32 line_number, char *format, ...) ACPI_PRINTF_LIKE(3); /* * utdelete - Object deletion and reference counts @@ -382,14 +376,13 @@ acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest); /* * utobject - internal object create/delete/cache routines */ -union acpi_operand_object *acpi_ut_create_internal_object_dbg(const char - *module_name, +union acpi_operand_object *acpi_ut_create_internal_object_dbg(char *module_name, u32 line_number, u32 component_id, acpi_object_type type); -void *acpi_ut_allocate_object_desc_dbg(const char *module_name, +void *acpi_ut_allocate_object_desc_dbg(char *module_name, u32 line_number, u32 component_id); #define acpi_ut_create_internal_object(t) acpi_ut_create_internal_object_dbg (_acpi_module_name,__LINE__,_COMPONENT,t) @@ -483,7 +476,7 @@ u8 acpi_ut_valid_acpi_name(u32 name); acpi_name acpi_ut_repair_name(char *name); -u8 acpi_ut_valid_acpi_char(char character, u32 position); +u8 acpi_ut_valid_acpi_char(char character, acpi_native_uint position); acpi_status acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer); @@ -550,29 +543,26 @@ acpi_status acpi_ut_initialize_buffer(struct acpi_buffer *buffer, acpi_size required_length); -void *acpi_ut_allocate(acpi_size size, - u32 component, const char *module, u32 line); +void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line); void *acpi_ut_allocate_zeroed(acpi_size size, - u32 component, const char *module, u32 line); + u32 component, char *module, u32 line); #ifdef ACPI_DBG_TRACK_ALLOCATIONS void *acpi_ut_allocate_and_track(acpi_size size, - u32 component, const char *module, u32 line); + u32 component, char *module, u32 line); void *acpi_ut_allocate_zeroed_and_track(acpi_size size, - u32 component, - const char *module, u32 line); + u32 component, char *module, u32 line); void -acpi_ut_free_and_track(void *address, - u32 component, const char *module, u32 line); +acpi_ut_free_and_track(void *address, u32 component, char *module, u32 line); #ifdef ACPI_FUTURE_USAGE void acpi_ut_dump_allocation_info(void); #endif /* ACPI_FUTURE_USAGE */ -void acpi_ut_dump_allocations(u32 component, const char *module); +void acpi_ut_dump_allocations(u32 component, char *module); acpi_status acpi_ut_create_list(char *list_name, diff --git a/trunk/include/acpi/processor.h b/trunk/include/acpi/processor.h index 3795590e152a..06ebb6ef72aa 100644 --- a/trunk/include/acpi/processor.h +++ b/trunk/include/acpi/processor.h @@ -255,7 +255,7 @@ extern void acpi_processor_unregister_performance(struct int acpi_processor_notify_smm(struct module *calling_module); /* for communication between multiple parts of the processor kernel module */ -DECLARE_PER_CPU(struct acpi_processor *, processors); +extern struct acpi_processor *processors[NR_CPUS]; extern struct acpi_processor_errata errata; void arch_acpi_processor_init_pdc(struct acpi_processor *pr); diff --git a/trunk/include/acpi/reboot.h b/trunk/include/acpi/reboot.h index 0419184ce886..8857f57e0b78 100644 --- a/trunk/include/acpi/reboot.h +++ b/trunk/include/acpi/reboot.h @@ -1,11 +1,9 @@ -#ifndef __ACPI_REBOOT_H -#define __ACPI_REBOOT_H - -#ifdef CONFIG_ACPI -extern void acpi_reboot(void); -#else -static inline void acpi_reboot(void) { } -#endif +/* + * Dummy placeholder to make the EFI patches apply to the x86 tree. + * Andrew/Len, please just kill this file if you encounter it. + */ +#ifndef acpi_reboot +# define acpi_reboot() do { } while (0) #endif diff --git a/trunk/include/asm-ia64/processor.h b/trunk/include/asm-ia64/processor.h index f88fa054d01d..6aff126fc07e 100644 --- a/trunk/include/asm-ia64/processor.h +++ b/trunk/include/asm-ia64/processor.h @@ -763,8 +763,6 @@ prefetchw (const void *x) #define spin_lock_prefetch(x) prefetchw(x) extern unsigned long boot_option_idle_override; -extern unsigned long idle_halt; -extern unsigned long idle_nomwait; #endif /* !__ASSEMBLY__ */ diff --git a/trunk/include/asm-x86/processor.h b/trunk/include/asm-x86/processor.h index 55402d2ab938..7f7382704592 100644 --- a/trunk/include/asm-x86/processor.h +++ b/trunk/include/asm-x86/processor.h @@ -727,8 +727,6 @@ extern int force_mwait; extern void select_idle_routine(const struct cpuinfo_x86 *c); extern unsigned long boot_option_idle_override; -extern unsigned long idle_halt; -extern unsigned long idle_nomwait; extern void enable_sep_cpu(void); extern int sysenter_setup(void); diff --git a/trunk/include/linux/blkdev.h b/trunk/include/linux/blkdev.h index 88d68081a0f1..32a441b05fd5 100644 --- a/trunk/include/linux/blkdev.h +++ b/trunk/include/linux/blkdev.h @@ -985,9 +985,6 @@ static inline int bdev_integrity_enabled(struct block_device *bdev, int rw) static inline int blk_integrity_rq(struct request *rq) { - if (rq->bio == NULL) - return 0; - return bio_integrity(rq->bio); } diff --git a/trunk/include/linux/freezer.h b/trunk/include/linux/freezer.h index deddeedf3257..08934995c7ab 100644 --- a/trunk/include/linux/freezer.h +++ b/trunk/include/linux/freezer.h @@ -127,15 +127,6 @@ static inline void set_freezable(void) current->flags &= ~PF_NOFREEZE; } -/* - * Tell the freezer that the current task should be frozen by it and that it - * should send a fake signal to the task to freeze it. - */ -static inline void set_freezable_with_signal(void) -{ - current->flags &= ~(PF_NOFREEZE | PF_FREEZER_NOSIG); -} - /* * Freezer-friendly wrappers around wait_event_interruptible() and * wait_event_interruptible_timeout(), originally defined in @@ -183,7 +174,6 @@ static inline void freezer_do_not_count(void) {} static inline void freezer_count(void) {} static inline int freezer_should_skip(struct task_struct *p) { return 0; } static inline void set_freezable(void) {} -static inline void set_freezable_with_signal(void) {} #define wait_event_freezable(wq, condition) \ wait_event_interruptible(wq, condition) diff --git a/trunk/include/linux/inet.h b/trunk/include/linux/inet.h index 4cca05c9678e..1354080cf8cf 100644 --- a/trunk/include/linux/inet.h +++ b/trunk/include/linux/inet.h @@ -44,13 +44,6 @@ #include -/* - * These mimic similar macros defined in user-space for inet_ntop(3). - * See /usr/include/netinet/in.h . - */ -#define INET_ADDRSTRLEN (16) -#define INET6_ADDRSTRLEN (48) - extern __be32 in_aton(const char *str); extern int in4_pton(const char *src, int srclen, u8 *dst, int delim, const char **end); extern int in6_pton(const char *src, int srclen, u8 *dst, int delim, const char **end); diff --git a/trunk/include/linux/ioport.h b/trunk/include/linux/ioport.h index 2cd07cc29687..c6801bffe76d 100644 --- a/trunk/include/linux/ioport.h +++ b/trunk/include/linux/ioport.h @@ -59,7 +59,6 @@ struct resource_list { #define IORESOURCE_IRQ_HIGHLEVEL (1<<2) #define IORESOURCE_IRQ_LOWLEVEL (1<<3) #define IORESOURCE_IRQ_SHAREABLE (1<<4) -#define IORESOURCE_IRQ_OPTIONAL (1<<5) /* PnP DMA specific bits (IORESOURCE_BITS) */ #define IORESOURCE_DMA_TYPE_MASK (3<<0) @@ -89,10 +88,6 @@ struct resource_list { #define IORESOURCE_MEM_SHADOWABLE (1<<5) /* dup: IORESOURCE_SHADOWABLE */ #define IORESOURCE_MEM_EXPANSIONROM (1<<6) -/* PnP I/O specific bits (IORESOURCE_BITS) */ -#define IORESOURCE_IO_16BIT_ADDR (1<<0) -#define IORESOURCE_IO_FIXED (1<<1) - /* PCI ROM control bits (IORESOURCE_BITS) */ #define IORESOURCE_ROM_ENABLE (1<<0) /* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */ #define IORESOURCE_ROM_SHADOW (1<<1) /* ROM is copy at C000:0 */ diff --git a/trunk/include/linux/nfs_fs.h b/trunk/include/linux/nfs_fs.h index 29d261918734..27d6a8d98cef 100644 --- a/trunk/include/linux/nfs_fs.h +++ b/trunk/include/linux/nfs_fs.h @@ -12,19 +12,9 @@ #include /* Default timeout values */ -#define NFS_DEF_UDP_TIMEO (11) -#define NFS_DEF_UDP_RETRANS (3) -#define NFS_DEF_TCP_TIMEO (600) -#define NFS_DEF_TCP_RETRANS (2) - #define NFS_MAX_UDP_TIMEOUT (60*HZ) #define NFS_MAX_TCP_TIMEOUT (600*HZ) -#define NFS_DEF_ACREGMIN (3) -#define NFS_DEF_ACREGMAX (60) -#define NFS_DEF_ACDIRMIN (30) -#define NFS_DEF_ACDIRMAX (60) - /* * When flushing a cluster of dirty pages, there can be different * strategies: diff --git a/trunk/include/linux/nfs_iostat.h b/trunk/include/linux/nfs_iostat.h deleted file mode 100644 index 1cb9a3fed2b3..000000000000 --- a/trunk/include/linux/nfs_iostat.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * User-space visible declarations for NFS client per-mount - * point statistics - * - * Copyright (C) 2005, 2006 Chuck Lever - * - * NFS client per-mount statistics provide information about the - * health of the NFS client and the health of each NFS mount point. - * Generally these are not for detailed problem diagnosis, but - * simply to indicate that there is a problem. - * - * These counters are not meant to be human-readable, but are meant - * to be integrated into system monitoring tools such as "sar" and - * "iostat". As such, the counters are sampled by the tools over - * time, and are never zeroed after a file system is mounted. - * Moving averages can be computed by the tools by taking the - * difference between two instantaneous samples and dividing that - * by the time between the samples. - */ - -#ifndef _LINUX_NFS_IOSTAT -#define _LINUX_NFS_IOSTAT - -#define NFS_IOSTAT_VERS "1.0" - -/* - * NFS byte counters - * - * 1. SERVER - the number of payload bytes read from or written - * to the server by the NFS client via an NFS READ or WRITE - * request. - * - * 2. NORMAL - the number of bytes read or written by applications - * via the read(2) and write(2) system call interfaces. - * - * 3. DIRECT - the number of bytes read or written from files - * opened with the O_DIRECT flag. - * - * These counters give a view of the data throughput into and out - * of the NFS client. Comparing the number of bytes requested by - * an application with the number of bytes the client requests from - * the server can provide an indication of client efficiency - * (per-op, cache hits, etc). - * - * These counters can also help characterize which access methods - * are in use. DIRECT by itself shows whether there is any O_DIRECT - * traffic. NORMAL + DIRECT shows how much data is going through - * the system call interface. A large amount of SERVER traffic - * without much NORMAL or DIRECT traffic shows that applications - * are using mapped files. - * - * NFS page counters - * - * These count the number of pages read or written via nfs_readpage(), - * nfs_readpages(), or their write equivalents. - * - * NB: When adding new byte counters, please include the measured - * units in the name of each byte counter to help users of this - * interface determine what exactly is being counted. - */ -enum nfs_stat_bytecounters { - NFSIOS_NORMALREADBYTES = 0, - NFSIOS_NORMALWRITTENBYTES, - NFSIOS_DIRECTREADBYTES, - NFSIOS_DIRECTWRITTENBYTES, - NFSIOS_SERVERREADBYTES, - NFSIOS_SERVERWRITTENBYTES, - NFSIOS_READPAGES, - NFSIOS_WRITEPAGES, - __NFSIOS_BYTESMAX, -}; - -/* - * NFS event counters - * - * These counters provide a low-overhead way of monitoring client - * activity without enabling NFS trace debugging. The counters - * show the rate at which VFS requests are made, and how often the - * client invalidates its data and attribute caches. This allows - * system administrators to monitor such things as how close-to-open - * is working, and answer questions such as "why are there so many - * GETATTR requests on the wire?" - * - * They also count anamolous events such as short reads and writes, - * silly renames due to close-after-delete, and operations that - * change the size of a file (such operations can often be the - * source of data corruption if applications aren't using file - * locking properly). - */ -enum nfs_stat_eventcounters { - NFSIOS_INODEREVALIDATE = 0, - NFSIOS_DENTRYREVALIDATE, - NFSIOS_DATAINVALIDATE, - NFSIOS_ATTRINVALIDATE, - NFSIOS_VFSOPEN, - NFSIOS_VFSLOOKUP, - NFSIOS_VFSACCESS, - NFSIOS_VFSUPDATEPAGE, - NFSIOS_VFSREADPAGE, - NFSIOS_VFSREADPAGES, - NFSIOS_VFSWRITEPAGE, - NFSIOS_VFSWRITEPAGES, - NFSIOS_VFSGETDENTS, - NFSIOS_VFSSETATTR, - NFSIOS_VFSFLUSH, - NFSIOS_VFSFSYNC, - NFSIOS_VFSLOCK, - NFSIOS_VFSRELEASE, - NFSIOS_CONGESTIONWAIT, - NFSIOS_SETATTRTRUNC, - NFSIOS_EXTENDWRITE, - NFSIOS_SILLYRENAME, - NFSIOS_SHORTREAD, - NFSIOS_SHORTWRITE, - NFSIOS_DELAY, - __NFSIOS_COUNTSMAX, -}; - -#endif /* _LINUX_NFS_IOSTAT */ diff --git a/trunk/include/linux/nfs_page.h b/trunk/include/linux/nfs_page.h index 3c60685d972b..a1676e19e491 100644 --- a/trunk/include/linux/nfs_page.h +++ b/trunk/include/linux/nfs_page.h @@ -27,12 +27,9 @@ /* * Valid flags for a dirty buffer */ -enum { - PG_BUSY = 0, - PG_CLEAN, - PG_NEED_COMMIT, - PG_NEED_RESCHED, -}; +#define PG_BUSY 0 +#define PG_NEED_COMMIT 1 +#define PG_NEED_RESCHED 2 struct nfs_inode; struct nfs_page { diff --git a/trunk/include/linux/nfs_xdr.h b/trunk/include/linux/nfs_xdr.h index 8c77c11224d1..24263bb8e0be 100644 --- a/trunk/include/linux/nfs_xdr.h +++ b/trunk/include/linux/nfs_xdr.h @@ -829,8 +829,9 @@ struct nfs_rpc_ops { int (*write_done) (struct rpc_task *, struct nfs_write_data *); void (*commit_setup) (struct nfs_write_data *, struct rpc_message *); int (*commit_done) (struct rpc_task *, struct nfs_write_data *); + int (*file_open) (struct inode *, struct file *); + int (*file_release) (struct inode *, struct file *); int (*lock)(struct file *, int, struct file_lock *); - int (*lock_check_bounds)(const struct file_lock *); void (*clear_acl_cache)(struct inode *); }; diff --git a/trunk/include/linux/pnp.h b/trunk/include/linux/pnp.h index 1ce54b63085d..63b128d512fb 100644 --- a/trunk/include/linux/pnp.h +++ b/trunk/include/linux/pnp.h @@ -1,8 +1,6 @@ /* * Linux Plug and Play Support * Copyright by Adam Belay - * Copyright (C) 2008 Hewlett-Packard Development Company, L.P. - * Bjorn Helgaas */ #ifndef _LINUX_PNP_H @@ -17,6 +15,7 @@ struct pnp_protocol; struct pnp_dev; +struct pnp_resource_table; /* * Resource Management @@ -25,14 +24,7 @@ struct resource *pnp_get_resource(struct pnp_dev *, unsigned int, unsigned int); static inline int pnp_resource_valid(struct resource *res) { - if (res) - return 1; - return 0; -} - -static inline int pnp_resource_enabled(struct resource *res) -{ - if (res && !(res->flags & IORESOURCE_DISABLED)) + if (res && !(res->flags & IORESOURCE_UNSET)) return 1; return 0; } @@ -48,31 +40,19 @@ static inline resource_size_t pnp_resource_len(struct resource *res) static inline resource_size_t pnp_port_start(struct pnp_dev *dev, unsigned int bar) { - struct resource *res = pnp_get_resource(dev, IORESOURCE_IO, bar); - - if (pnp_resource_valid(res)) - return res->start; - return 0; + return pnp_get_resource(dev, IORESOURCE_IO, bar)->start; } static inline resource_size_t pnp_port_end(struct pnp_dev *dev, unsigned int bar) { - struct resource *res = pnp_get_resource(dev, IORESOURCE_IO, bar); - - if (pnp_resource_valid(res)) - return res->end; - return 0; + return pnp_get_resource(dev, IORESOURCE_IO, bar)->end; } static inline unsigned long pnp_port_flags(struct pnp_dev *dev, unsigned int bar) { - struct resource *res = pnp_get_resource(dev, IORESOURCE_IO, bar); - - if (pnp_resource_valid(res)) - return res->flags; - return IORESOURCE_IO | IORESOURCE_AUTO; + return pnp_get_resource(dev, IORESOURCE_IO, bar)->flags; } static inline int pnp_port_valid(struct pnp_dev *dev, unsigned int bar) @@ -83,41 +63,25 @@ static inline int pnp_port_valid(struct pnp_dev *dev, unsigned int bar) static inline resource_size_t pnp_port_len(struct pnp_dev *dev, unsigned int bar) { - struct resource *res = pnp_get_resource(dev, IORESOURCE_IO, bar); - - if (pnp_resource_valid(res)) - return pnp_resource_len(res); - return 0; + return pnp_resource_len(pnp_get_resource(dev, IORESOURCE_IO, bar)); } static inline resource_size_t pnp_mem_start(struct pnp_dev *dev, unsigned int bar) { - struct resource *res = pnp_get_resource(dev, IORESOURCE_MEM, bar); - - if (pnp_resource_valid(res)) - return res->start; - return 0; + return pnp_get_resource(dev, IORESOURCE_MEM, bar)->start; } static inline resource_size_t pnp_mem_end(struct pnp_dev *dev, unsigned int bar) { - struct resource *res = pnp_get_resource(dev, IORESOURCE_MEM, bar); - - if (pnp_resource_valid(res)) - return res->end; - return 0; + return pnp_get_resource(dev, IORESOURCE_MEM, bar)->end; } static inline unsigned long pnp_mem_flags(struct pnp_dev *dev, unsigned int bar) { - struct resource *res = pnp_get_resource(dev, IORESOURCE_MEM, bar); - - if (pnp_resource_valid(res)) - return res->flags; - return IORESOURCE_MEM | IORESOURCE_AUTO; + return pnp_get_resource(dev, IORESOURCE_MEM, bar)->flags; } static inline int pnp_mem_valid(struct pnp_dev *dev, unsigned int bar) @@ -128,30 +92,18 @@ static inline int pnp_mem_valid(struct pnp_dev *dev, unsigned int bar) static inline resource_size_t pnp_mem_len(struct pnp_dev *dev, unsigned int bar) { - struct resource *res = pnp_get_resource(dev, IORESOURCE_MEM, bar); - - if (pnp_resource_valid(res)) - return pnp_resource_len(res); - return 0; + return pnp_resource_len(pnp_get_resource(dev, IORESOURCE_MEM, bar)); } static inline resource_size_t pnp_irq(struct pnp_dev *dev, unsigned int bar) { - struct resource *res = pnp_get_resource(dev, IORESOURCE_IRQ, bar); - - if (pnp_resource_valid(res)) - return res->start; - return -1; + return pnp_get_resource(dev, IORESOURCE_IRQ, bar)->start; } static inline unsigned long pnp_irq_flags(struct pnp_dev *dev, unsigned int bar) { - struct resource *res = pnp_get_resource(dev, IORESOURCE_IRQ, bar); - - if (pnp_resource_valid(res)) - return res->flags; - return IORESOURCE_IRQ | IORESOURCE_AUTO; + return pnp_get_resource(dev, IORESOURCE_IRQ, bar)->flags; } static inline int pnp_irq_valid(struct pnp_dev *dev, unsigned int bar) @@ -162,20 +114,12 @@ static inline int pnp_irq_valid(struct pnp_dev *dev, unsigned int bar) static inline resource_size_t pnp_dma(struct pnp_dev *dev, unsigned int bar) { - struct resource *res = pnp_get_resource(dev, IORESOURCE_DMA, bar); - - if (pnp_resource_valid(res)) - return res->start; - return -1; + return pnp_get_resource(dev, IORESOURCE_DMA, bar)->start; } static inline unsigned long pnp_dma_flags(struct pnp_dev *dev, unsigned int bar) { - struct resource *res = pnp_get_resource(dev, IORESOURCE_DMA, bar); - - if (pnp_resource_valid(res)) - return res->flags; - return IORESOURCE_DMA | IORESOURCE_AUTO; + return pnp_get_resource(dev, IORESOURCE_DMA, bar)->flags; } static inline int pnp_dma_valid(struct pnp_dev *dev, unsigned int bar) @@ -184,6 +128,57 @@ static inline int pnp_dma_valid(struct pnp_dev *dev, unsigned int bar) } +#define PNP_PORT_FLAG_16BITADDR (1<<0) +#define PNP_PORT_FLAG_FIXED (1<<1) + +struct pnp_port { + unsigned short min; /* min base number */ + unsigned short max; /* max base number */ + unsigned char align; /* align boundary */ + unsigned char size; /* size of range */ + unsigned char flags; /* port flags */ + unsigned char pad; /* pad */ + struct pnp_port *next; /* next port */ +}; + +#define PNP_IRQ_NR 256 +struct pnp_irq { + DECLARE_BITMAP(map, PNP_IRQ_NR); /* bitmask for IRQ lines */ + unsigned char flags; /* IRQ flags */ + unsigned char pad; /* pad */ + struct pnp_irq *next; /* next IRQ */ +}; + +struct pnp_dma { + unsigned char map; /* bitmask for DMA channels */ + unsigned char flags; /* DMA flags */ + struct pnp_dma *next; /* next port */ +}; + +struct pnp_mem { + unsigned int min; /* min base number */ + unsigned int max; /* max base number */ + unsigned int align; /* align boundary */ + unsigned int size; /* size of range */ + unsigned char flags; /* memory flags */ + unsigned char pad; /* pad */ + struct pnp_mem *next; /* next memory resource */ +}; + +#define PNP_RES_PRIORITY_PREFERRED 0 +#define PNP_RES_PRIORITY_ACCEPTABLE 1 +#define PNP_RES_PRIORITY_FUNCTIONAL 2 +#define PNP_RES_PRIORITY_INVALID 65535 + +struct pnp_option { + unsigned short priority; /* priority */ + struct pnp_port *port; /* first port */ + struct pnp_irq *irq; /* first IRQ */ + struct pnp_dma *dma; /* first DMA */ + struct pnp_mem *mem; /* first memory resource */ + struct pnp_option *next; /* used to chain dependent resources */ +}; + /* * Device Management */ @@ -251,9 +246,9 @@ struct pnp_dev { int active; int capabilities; - unsigned int num_dependent_sets; - struct list_head resources; - struct list_head options; + struct pnp_option *independent; + struct pnp_option *dependent; + struct pnp_resource_table *res; char name[PNP_NAME_LEN]; /* contains a human-readable name */ int flags; /* used by protocols */ @@ -430,8 +425,6 @@ void pnp_unregister_card_driver(struct pnp_card_driver *drv); extern struct list_head pnp_cards; /* resource management */ -int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t base, - resource_size_t size); int pnp_auto_config_dev(struct pnp_dev *dev); int pnp_start_dev(struct pnp_dev *dev); int pnp_stop_dev(struct pnp_dev *dev); @@ -459,9 +452,6 @@ static inline int pnp_register_card_driver(struct pnp_card_driver *drv) { return static inline void pnp_unregister_card_driver(struct pnp_card_driver *drv) { } /* resource management */ -static inline int pnp_possible_config(struct pnp_dev *dev, int type, - resource_size_t base, - resource_size_t size) { return 0; } static inline int pnp_auto_config_dev(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_start_dev(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_stop_dev(struct pnp_dev *dev) { return -ENODEV; } diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index ba2f859c6e4f..21349173d148 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -1494,7 +1494,6 @@ static inline void put_task_struct(struct task_struct *t) #define PF_MEMPOLICY 0x10000000 /* Non-default NUMA mempolicy */ #define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */ #define PF_FREEZER_SKIP 0x40000000 /* Freezer should not count it as freezeable */ -#define PF_FREEZER_NOSIG 0x80000000 /* Freezer won't send signals to it */ /* * Only the _current_ task can read/write to tsk->flags, but other diff --git a/trunk/include/linux/sunrpc/clnt.h b/trunk/include/linux/sunrpc/clnt.h index e5bfe01ee305..6fff7f82ef12 100644 --- a/trunk/include/linux/sunrpc/clnt.h +++ b/trunk/include/linux/sunrpc/clnt.h @@ -42,8 +42,7 @@ struct rpc_clnt { unsigned int cl_softrtry : 1,/* soft timeouts */ cl_discrtry : 1,/* disconnect before retry */ - cl_autobind : 1,/* use getport() */ - cl_chatty : 1;/* be verbose */ + cl_autobind : 1;/* use getport() */ struct rpc_rtt * cl_rtt; /* RTO estimator data */ const struct rpc_timeout *cl_timeout; /* Timeout strategy */ @@ -115,7 +114,6 @@ struct rpc_create_args { #define RPC_CLNT_CREATE_NONPRIVPORT (1UL << 3) #define RPC_CLNT_CREATE_NOPING (1UL << 4) #define RPC_CLNT_CREATE_DISCRTRY (1UL << 5) -#define RPC_CLNT_CREATE_QUIET (1UL << 6) struct rpc_clnt *rpc_create(struct rpc_create_args *args); struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, @@ -125,9 +123,6 @@ void rpc_shutdown_client(struct rpc_clnt *); void rpc_release_client(struct rpc_clnt *); int rpcb_register(u32, u32, int, unsigned short, int *); -int rpcb_v4_register(const u32 program, const u32 version, - const struct sockaddr *address, - const char *netid, int *result); int rpcb_getport_sync(struct sockaddr_in *, u32, u32, int); void rpcb_getport_async(struct rpc_task *); diff --git a/trunk/include/linux/sunrpc/sched.h b/trunk/include/linux/sunrpc/sched.h index 64981a2f1cae..d1a5c8c1a0f1 100644 --- a/trunk/include/linux/sunrpc/sched.h +++ b/trunk/include/linux/sunrpc/sched.h @@ -135,6 +135,7 @@ struct rpc_task_setup { #define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER) #define RPC_DO_ROOTOVERRIDE(t) ((t)->tk_flags & RPC_TASK_ROOTCREDS) #define RPC_ASSASSINATED(t) ((t)->tk_flags & RPC_TASK_KILLED) +#define RPC_DO_CALLBACK(t) ((t)->tk_callback != NULL) #define RPC_IS_SOFT(t) ((t)->tk_flags & RPC_TASK_SOFT) #define RPC_TASK_RUNNING 0 diff --git a/trunk/kernel/cpu.c b/trunk/kernel/cpu.c index cfb1d43ab801..b11f06dc149a 100644 --- a/trunk/kernel/cpu.c +++ b/trunk/kernel/cpu.c @@ -299,7 +299,6 @@ int __ref cpu_down(unsigned int cpu) cpu_maps_update_done(); return err; } -EXPORT_SYMBOL(cpu_down); #endif /*CONFIG_HOTPLUG_CPU*/ /* Requires cpu_add_remove_lock to be held */ diff --git a/trunk/kernel/kthread.c b/trunk/kernel/kthread.c index ac3fb7326641..97747cdd37c9 100644 --- a/trunk/kernel/kthread.c +++ b/trunk/kernel/kthread.c @@ -235,7 +235,7 @@ int kthreadd(void *unused) set_user_nice(tsk, KTHREAD_NICE_LEVEL); set_cpus_allowed(tsk, CPU_MASK_ALL); - current->flags |= PF_NOFREEZE | PF_FREEZER_NOSIG; + current->flags |= PF_NOFREEZE; for (;;) { set_current_state(TASK_INTERRUPTIBLE); diff --git a/trunk/kernel/power/process.c b/trunk/kernel/power/process.c index 5fb87652f214..f1d0b345c9ba 100644 --- a/trunk/kernel/power/process.c +++ b/trunk/kernel/power/process.c @@ -19,6 +19,9 @@ */ #define TIMEOUT (20 * HZ) +#define FREEZER_KERNEL_THREADS 0 +#define FREEZER_USER_SPACE 1 + static inline int freezeable(struct task_struct * p) { if ((p == current) || @@ -81,53 +84,63 @@ static void fake_signal_wake_up(struct task_struct *p) spin_unlock_irqrestore(&p->sighand->siglock, flags); } -static inline bool should_send_signal(struct task_struct *p) +static int has_mm(struct task_struct *p) { - return !(p->flags & PF_FREEZER_NOSIG); + return (p->mm && !(p->flags & PF_BORROWED_MM)); } /** * freeze_task - send a freeze request to given task * @p: task to send the request to - * @sig_only: if set, the request will only be sent if the task has the - * PF_FREEZER_NOSIG flag unset - * Return value: 'false', if @sig_only is set and the task has - * PF_FREEZER_NOSIG set or the task is frozen, 'true', otherwise + * @with_mm_only: if set, the request will only be sent if the task has its + * own mm + * Return value: 0, if @with_mm_only is set and the task has no mm of its + * own or the task is frozen, 1, otherwise * - * The freeze request is sent by setting the tasks's TIF_FREEZE flag and + * The freeze request is sent by seting the tasks's TIF_FREEZE flag and * either sending a fake signal to it or waking it up, depending on whether - * or not it has PF_FREEZER_NOSIG set. If @sig_only is set and the task - * has PF_FREEZER_NOSIG set (ie. it is a typical kernel thread), its - * TIF_FREEZE flag will not be set. + * or not it has its own mm (ie. it is a user land task). If @with_mm_only + * is set and the task has no mm of its own (ie. it is a kernel thread), + * its TIF_FREEZE flag should not be set. + * + * The task_lock() is necessary to prevent races with exit_mm() or + * use_mm()/unuse_mm() from occuring. */ -static bool freeze_task(struct task_struct *p, bool sig_only) +static int freeze_task(struct task_struct *p, int with_mm_only) { - /* - * We first check if the task is freezing and next if it has already - * been frozen to avoid the race with frozen_process() which first marks - * the task as frozen and next clears its TIF_FREEZE. - */ - if (!freezing(p)) { - rmb(); - if (frozen(p)) - return false; - - if (!sig_only || should_send_signal(p)) - set_freeze_flag(p); - else - return false; - } + int ret = 1; - if (should_send_signal(p)) { - if (!signal_pending(p)) - fake_signal_wake_up(p); - } else if (sig_only) { - return false; + task_lock(p); + if (freezing(p)) { + if (has_mm(p)) { + if (!signal_pending(p)) + fake_signal_wake_up(p); + } else { + if (with_mm_only) + ret = 0; + else + wake_up_state(p, TASK_INTERRUPTIBLE); + } } else { - wake_up_state(p, TASK_INTERRUPTIBLE); + rmb(); + if (frozen(p)) { + ret = 0; + } else { + if (has_mm(p)) { + set_freeze_flag(p); + fake_signal_wake_up(p); + } else { + if (with_mm_only) { + ret = 0; + } else { + set_freeze_flag(p); + wake_up_state(p, TASK_INTERRUPTIBLE); + } + } + } } - - return true; + task_unlock(p); + return ret; } static void cancel_freezing(struct task_struct *p) @@ -143,7 +156,7 @@ static void cancel_freezing(struct task_struct *p) } } -static int try_to_freeze_tasks(bool sig_only) +static int try_to_freeze_tasks(int freeze_user_space) { struct task_struct *g, *p; unsigned long end_time; @@ -162,7 +175,7 @@ static int try_to_freeze_tasks(bool sig_only) if (frozen(p) || !freezeable(p)) continue; - if (!freeze_task(p, sig_only)) + if (!freeze_task(p, freeze_user_space)) continue; /* @@ -222,13 +235,13 @@ int freeze_processes(void) int error; printk("Freezing user space processes ... "); - error = try_to_freeze_tasks(true); + error = try_to_freeze_tasks(FREEZER_USER_SPACE); if (error) goto Exit; printk("done.\n"); printk("Freezing remaining freezable tasks ... "); - error = try_to_freeze_tasks(false); + error = try_to_freeze_tasks(FREEZER_KERNEL_THREADS); if (error) goto Exit; printk("done."); @@ -238,7 +251,7 @@ int freeze_processes(void) return error; } -static void thaw_tasks(bool nosig_only) +static void thaw_tasks(int thaw_user_space) { struct task_struct *g, *p; @@ -247,7 +260,7 @@ static void thaw_tasks(bool nosig_only) if (!freezeable(p)) continue; - if (nosig_only && should_send_signal(p)) + if (!p->mm == thaw_user_space) continue; thaw_process(p); @@ -258,8 +271,8 @@ static void thaw_tasks(bool nosig_only) void thaw_processes(void) { printk("Restarting tasks ... "); - thaw_tasks(true); - thaw_tasks(false); + thaw_tasks(FREEZER_KERNEL_THREADS); + thaw_tasks(FREEZER_USER_SPACE); schedule(); printk("done.\n"); } diff --git a/trunk/kernel/power/user.c b/trunk/kernel/power/user.c index a6332a313262..f5512cb3aa86 100644 --- a/trunk/kernel/power/user.c +++ b/trunk/kernel/power/user.c @@ -23,7 +23,6 @@ #include #include #include -#include #include @@ -70,22 +69,16 @@ static int snapshot_open(struct inode *inode, struct file *filp) struct snapshot_data *data; int error; - mutex_lock(&pm_mutex); - - if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { - error = -EBUSY; - goto Unlock; - } + if (!atomic_add_unless(&snapshot_device_available, -1, 0)) + return -EBUSY; if ((filp->f_flags & O_ACCMODE) == O_RDWR) { atomic_inc(&snapshot_device_available); - error = -ENOSYS; - goto Unlock; + return -ENOSYS; } if(create_basic_memory_bitmaps()) { atomic_inc(&snapshot_device_available); - error = -ENOMEM; - goto Unlock; + return -ENOMEM; } nonseekable_open(inode, filp); data = &snapshot_state; @@ -105,36 +98,33 @@ static int snapshot_open(struct inode *inode, struct file *filp) if (error) pm_notifier_call_chain(PM_POST_HIBERNATION); } - if (error) + if (error) { atomic_inc(&snapshot_device_available); + return error; + } data->frozen = 0; data->ready = 0; data->platform_support = 0; - Unlock: - mutex_unlock(&pm_mutex); - - return error; + return 0; } static int snapshot_release(struct inode *inode, struct file *filp) { struct snapshot_data *data; - mutex_lock(&pm_mutex); - swsusp_free(); free_basic_memory_bitmaps(); data = filp->private_data; free_all_swap_pages(data->swap); - if (data->frozen) + if (data->frozen) { + mutex_lock(&pm_mutex); thaw_processes(); + mutex_unlock(&pm_mutex); + } pm_notifier_call_chain(data->mode == O_WRONLY ? PM_POST_HIBERNATION : PM_POST_RESTORE); atomic_inc(&snapshot_device_available); - - mutex_unlock(&pm_mutex); - return 0; } @@ -144,13 +134,9 @@ static ssize_t snapshot_read(struct file *filp, char __user *buf, struct snapshot_data *data; ssize_t res; - mutex_lock(&pm_mutex); - data = filp->private_data; - if (!data->ready) { - res = -ENODATA; - goto Unlock; - } + if (!data->ready) + return -ENODATA; res = snapshot_read_next(&data->handle, count); if (res > 0) { if (copy_to_user(buf, data_of(data->handle), res)) @@ -158,10 +144,6 @@ static ssize_t snapshot_read(struct file *filp, char __user *buf, else *offp = data->handle.offset; } - - Unlock: - mutex_unlock(&pm_mutex); - return res; } @@ -171,8 +153,6 @@ static ssize_t snapshot_write(struct file *filp, const char __user *buf, struct snapshot_data *data; ssize_t res; - mutex_lock(&pm_mutex); - data = filp->private_data; res = snapshot_write_next(&data->handle, count); if (res > 0) { @@ -181,14 +161,11 @@ static ssize_t snapshot_write(struct file *filp, const char __user *buf, else *offp = data->handle.offset; } - - mutex_unlock(&pm_mutex); - return res; } -static long snapshot_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) +static int snapshot_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { int error = 0; struct snapshot_data *data; @@ -202,9 +179,6 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (!mutex_trylock(&pm_mutex)) - return -EBUSY; - data = filp->private_data; switch (cmd) { @@ -212,6 +186,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, case SNAPSHOT_FREEZE: if (data->frozen) break; + mutex_lock(&pm_mutex); printk("Syncing filesystems ... "); sys_sync(); printk("done.\n"); @@ -219,6 +194,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, error = freeze_processes(); if (error) thaw_processes(); + mutex_unlock(&pm_mutex); if (!error) data->frozen = 1; break; @@ -226,7 +202,9 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, case SNAPSHOT_UNFREEZE: if (!data->frozen || data->ready) break; + mutex_lock(&pm_mutex); thaw_processes(); + mutex_unlock(&pm_mutex); data->frozen = 0; break; @@ -329,11 +307,16 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, error = -EPERM; break; } + if (!mutex_trylock(&pm_mutex)) { + error = -EBUSY; + break; + } /* * Tasks are frozen and the notifiers have been called with * PM_HIBERNATION_PREPARE */ error = suspend_devices_and_enter(PM_SUSPEND_MEM); + mutex_unlock(&pm_mutex); break; case SNAPSHOT_PLATFORM_SUPPORT: @@ -407,8 +390,6 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, } - mutex_unlock(&pm_mutex); - return error; } @@ -418,7 +399,7 @@ static const struct file_operations snapshot_fops = { .read = snapshot_read, .write = snapshot_write, .llseek = no_llseek, - .unlocked_ioctl = snapshot_ioctl, + .ioctl = snapshot_ioctl, }; static struct miscdevice snapshot_device = { diff --git a/trunk/net/sunrpc/auth_gss/auth_gss.c b/trunk/net/sunrpc/auth_gss/auth_gss.c index 834a83199bdf..cc12d5f5d5da 100644 --- a/trunk/net/sunrpc/auth_gss/auth_gss.c +++ b/trunk/net/sunrpc/auth_gss/auth_gss.c @@ -63,11 +63,22 @@ static const struct rpc_credops gss_nullops; # define RPCDBG_FACILITY RPCDBG_AUTH #endif -#define GSS_CRED_SLACK 1024 +#define NFS_NGROUPS 16 + +#define GSS_CRED_SLACK 1024 /* XXX: unused */ /* length of a krb5 verifier (48), plus data added before arguments when * using integrity (two 4-byte integers): */ #define GSS_VERF_SLACK 100 +/* XXX this define must match the gssd define +* as it is passed to gssd to signal the use of +* machine creds should be part of the shared rpc interface */ + +#define CA_RUN_AS_MACHINE 0x00000200 + +/* dump the buffer in `emacs-hexl' style */ +#define isprint(c) ((c > 0x1f) && (c < 0x7f)) + struct gss_auth { struct kref kref; struct rpc_auth rpc_auth; @@ -135,7 +146,7 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *dest) q = (const void *)((const char *)p + len); if (unlikely(q > end || q < p)) return ERR_PTR(-EFAULT); - dest->data = kmemdup(p, len, GFP_NOFS); + dest->data = kmemdup(p, len, GFP_KERNEL); if (unlikely(dest->data == NULL)) return ERR_PTR(-ENOMEM); dest->len = len; @@ -160,7 +171,7 @@ gss_alloc_context(void) { struct gss_cl_ctx *ctx; - ctx = kzalloc(sizeof(*ctx), GFP_NOFS); + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (ctx != NULL) { ctx->gc_proc = RPC_GSS_PROC_DATA; ctx->gc_seq = 1; /* NetApp 6.4R1 doesn't accept seq. no. 0 */ @@ -261,7 +272,7 @@ __gss_find_upcall(struct rpc_inode *rpci, uid_t uid) return NULL; } -/* Try to add an upcall to the pipefs queue. +/* Try to add a upcall to the pipefs queue. * If an upcall owned by our uid already exists, then we return a reference * to that upcall instead of adding the new upcall. */ @@ -330,7 +341,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid) { struct gss_upcall_msg *gss_msg; - gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS); + gss_msg = kzalloc(sizeof(*gss_msg), GFP_KERNEL); if (gss_msg != NULL) { INIT_LIST_HEAD(&gss_msg->list); rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); @@ -482,6 +493,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) { const void *p, *end; void *buf; + struct rpc_clnt *clnt; struct gss_upcall_msg *gss_msg; struct inode *inode = filp->f_path.dentry->d_inode; struct gss_cl_ctx *ctx; @@ -491,10 +503,11 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) if (mlen > MSG_BUF_MAXSIZE) goto out; err = -ENOMEM; - buf = kmalloc(mlen, GFP_NOFS); + buf = kmalloc(mlen, GFP_KERNEL); if (!buf) goto out; + clnt = RPC_I(inode)->private; err = -EFAULT; if (copy_from_user(buf, src, mlen)) goto err; @@ -793,7 +806,7 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) dprintk("RPC: gss_create_cred for uid %d, flavor %d\n", acred->uid, auth->au_flavor); - if (!(cred = kzalloc(sizeof(*cred), GFP_NOFS))) + if (!(cred = kzalloc(sizeof(*cred), GFP_KERNEL))) goto out_err; rpcauth_init_cred(&cred->gc_base, acred, auth, &gss_credops); diff --git a/trunk/net/sunrpc/auth_gss/gss_krb5_mech.c b/trunk/net/sunrpc/auth_gss/gss_krb5_mech.c index ef45eba22485..60c3dba545d7 100644 --- a/trunk/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/trunk/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -70,7 +70,7 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res) q = (const void *)((const char *)p + len); if (unlikely(q > end || q < p)) return ERR_PTR(-EFAULT); - res->data = kmemdup(p, len, GFP_NOFS); + res->data = kmemdup(p, len, GFP_KERNEL); if (unlikely(res->data == NULL)) return ERR_PTR(-ENOMEM); res->len = len; @@ -131,7 +131,7 @@ gss_import_sec_context_kerberos(const void *p, struct krb5_ctx *ctx; int tmp; - if (!(ctx = kzalloc(sizeof(*ctx), GFP_NOFS))) + if (!(ctx = kzalloc(sizeof(*ctx), GFP_KERNEL))) goto out_err; p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate)); diff --git a/trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c b/trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c index 035e1dd6af1b..5deb4b6e4514 100644 --- a/trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c +++ b/trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c @@ -76,7 +76,7 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res) q = (const void *)((const char *)p + len); if (unlikely(q > end || q < p)) return ERR_PTR(-EFAULT); - res->data = kmemdup(p, len, GFP_NOFS); + res->data = kmemdup(p, len, GFP_KERNEL); if (unlikely(res->data == NULL)) return ERR_PTR(-ENOMEM); return q; @@ -90,7 +90,7 @@ gss_import_sec_context_spkm3(const void *p, size_t len, struct spkm3_ctx *ctx; int version; - if (!(ctx = kzalloc(sizeof(*ctx), GFP_NOFS))) + if (!(ctx = kzalloc(sizeof(*ctx), GFP_KERNEL))) goto out_err; p = simple_get_bytes(p, end, &version, sizeof(version)); diff --git a/trunk/net/sunrpc/auth_gss/gss_spkm3_token.c b/trunk/net/sunrpc/auth_gss/gss_spkm3_token.c index 3308157436d2..6cdd241ad267 100644 --- a/trunk/net/sunrpc/auth_gss/gss_spkm3_token.c +++ b/trunk/net/sunrpc/auth_gss/gss_spkm3_token.c @@ -90,7 +90,7 @@ asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits) int decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen, int explen) { - if (!(out->data = kzalloc(explen,GFP_NOFS))) + if (!(out->data = kzalloc(explen,GFP_KERNEL))) return 0; out->len = explen; memcpy(out->data, in, enclen); diff --git a/trunk/net/sunrpc/auth_unix.c b/trunk/net/sunrpc/auth_unix.c index 46b2647c5bd2..44920b90bdc4 100644 --- a/trunk/net/sunrpc/auth_unix.c +++ b/trunk/net/sunrpc/auth_unix.c @@ -66,7 +66,7 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) dprintk("RPC: allocating UNIX cred for uid %d gid %d\n", acred->uid, acred->gid); - if (!(cred = kmalloc(sizeof(*cred), GFP_NOFS))) + if (!(cred = kmalloc(sizeof(*cred), GFP_KERNEL))) return ERR_PTR(-ENOMEM); rpcauth_init_cred(&cred->uc_base, acred, auth, &unix_credops); diff --git a/trunk/net/sunrpc/clnt.c b/trunk/net/sunrpc/clnt.c index 76739e928d0d..8945307556ec 100644 --- a/trunk/net/sunrpc/clnt.c +++ b/trunk/net/sunrpc/clnt.c @@ -25,7 +25,6 @@ #include #include -#include #include #include #include @@ -59,6 +58,7 @@ static void call_start(struct rpc_task *task); static void call_reserve(struct rpc_task *task); static void call_reserveresult(struct rpc_task *task); static void call_allocate(struct rpc_task *task); +static void call_encode(struct rpc_task *task); static void call_decode(struct rpc_task *task); static void call_bind(struct rpc_task *task); static void call_bind_status(struct rpc_task *task); @@ -70,9 +70,9 @@ static void call_refreshresult(struct rpc_task *task); static void call_timeout(struct rpc_task *task); static void call_connect(struct rpc_task *task); static void call_connect_status(struct rpc_task *task); +static __be32 * call_header(struct rpc_task *task); +static __be32 * call_verify(struct rpc_task *task); -static __be32 *rpc_encode_header(struct rpc_task *task); -static __be32 *rpc_verify_header(struct rpc_task *task); static int rpc_ping(struct rpc_clnt *clnt, int flags); static void rpc_register_client(struct rpc_clnt *clnt) @@ -324,8 +324,6 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) clnt->cl_autobind = 1; if (args->flags & RPC_CLNT_CREATE_DISCRTRY) clnt->cl_discrtry = 1; - if (!(args->flags & RPC_CLNT_CREATE_QUIET)) - clnt->cl_chatty = 1; return clnt; } @@ -692,21 +690,6 @@ rpc_restart_call(struct rpc_task *task) } EXPORT_SYMBOL_GPL(rpc_restart_call); -#ifdef RPC_DEBUG -static const char *rpc_proc_name(const struct rpc_task *task) -{ - const struct rpc_procinfo *proc = task->tk_msg.rpc_proc; - - if (proc) { - if (proc->p_name) - return proc->p_name; - else - return "NULL"; - } else - return "no proc"; -} -#endif - /* * 0. Initial state * @@ -718,9 +701,9 @@ call_start(struct rpc_task *task) { struct rpc_clnt *clnt = task->tk_client; - dprintk("RPC: %5u call_start %s%d proc %s (%s)\n", task->tk_pid, + dprintk("RPC: %5u call_start %s%d proc %d (%s)\n", task->tk_pid, clnt->cl_protname, clnt->cl_vers, - rpc_proc_name(task), + task->tk_msg.rpc_proc->p_proc, (RPC_IS_ASYNC(task) ? "async" : "sync")); /* Increment call count */ @@ -878,7 +861,7 @@ rpc_xdr_buf_init(struct xdr_buf *buf, void *start, size_t len) * 3. Encode arguments of an RPC call */ static void -rpc_xdr_encode(struct rpc_task *task) +call_encode(struct rpc_task *task) { struct rpc_rqst *req = task->tk_rqstp; kxdrproc_t encode; @@ -893,19 +876,23 @@ rpc_xdr_encode(struct rpc_task *task) (char *)req->rq_buffer + req->rq_callsize, req->rq_rcvsize); - p = rpc_encode_header(task); - if (p == NULL) { - printk(KERN_INFO "RPC: couldn't encode RPC header, exit EIO\n"); + /* Encode header and provided arguments */ + encode = task->tk_msg.rpc_proc->p_encode; + if (!(p = call_header(task))) { + printk(KERN_INFO "RPC: call_header failed, exit EIO\n"); rpc_exit(task, -EIO); return; } - - encode = task->tk_msg.rpc_proc->p_encode; if (encode == NULL) return; task->tk_status = rpcauth_wrap_req(task, encode, req, p, task->tk_msg.rpc_argp); + if (task->tk_status == -ENOMEM) { + /* XXX: Is this sane? */ + rpc_delay(task, 3*HZ); + task->tk_status = -EAGAIN; + } } /* @@ -942,9 +929,11 @@ call_bind_status(struct rpc_task *task) } switch (task->tk_status) { - case -ENOMEM: - dprintk("RPC: %5u rpcbind out of memory\n", task->tk_pid); - rpc_delay(task, HZ >> 2); + case -EAGAIN: + dprintk("RPC: %5u rpcbind waiting for another request " + "to finish\n", task->tk_pid); + /* avoid busy-waiting here -- could be a network outage. */ + rpc_delay(task, 5*HZ); goto retry_timeout; case -EACCES: dprintk("RPC: %5u remote rpcbind: RPC program/version " @@ -1057,16 +1046,10 @@ call_transmit(struct rpc_task *task) /* Encode here so that rpcsec_gss can use correct sequence number. */ if (rpc_task_need_encode(task)) { BUG_ON(task->tk_rqstp->rq_bytes_sent != 0); - rpc_xdr_encode(task); + call_encode(task); /* Did the encode result in an error condition? */ - if (task->tk_status != 0) { - /* Was the error nonfatal? */ - if (task->tk_status == -EAGAIN) - rpc_delay(task, HZ >> 4); - else - rpc_exit(task, task->tk_status); + if (task->tk_status != 0) return; - } } xprt_transmit(task); if (task->tk_status < 0) @@ -1149,8 +1132,7 @@ call_status(struct rpc_task *task) rpc_exit(task, status); break; default: - if (clnt->cl_chatty) - printk("%s: RPC call returned error %d\n", + printk("%s: RPC call returned error %d\n", clnt->cl_protname, -status); rpc_exit(task, status); } @@ -1175,8 +1157,7 @@ call_timeout(struct rpc_task *task) task->tk_timeouts++; if (RPC_IS_SOFT(task)) { - if (clnt->cl_chatty) - printk(KERN_NOTICE "%s: server %s not responding, timed out\n", + printk(KERN_NOTICE "%s: server %s not responding, timed out\n", clnt->cl_protname, clnt->cl_server); rpc_exit(task, -EIO); return; @@ -1184,8 +1165,7 @@ call_timeout(struct rpc_task *task) if (!(task->tk_flags & RPC_CALL_MAJORSEEN)) { task->tk_flags |= RPC_CALL_MAJORSEEN; - if (clnt->cl_chatty) - printk(KERN_NOTICE "%s: server %s not responding, still trying\n", + printk(KERN_NOTICE "%s: server %s not responding, still trying\n", clnt->cl_protname, clnt->cl_server); } rpc_force_rebind(clnt); @@ -1216,9 +1196,8 @@ call_decode(struct rpc_task *task) task->tk_pid, task->tk_status); if (task->tk_flags & RPC_CALL_MAJORSEEN) { - if (clnt->cl_chatty) - printk(KERN_NOTICE "%s: server %s OK\n", - clnt->cl_protname, clnt->cl_server); + printk(KERN_NOTICE "%s: server %s OK\n", + clnt->cl_protname, clnt->cl_server); task->tk_flags &= ~RPC_CALL_MAJORSEEN; } @@ -1245,7 +1224,8 @@ call_decode(struct rpc_task *task) goto out_retry; } - p = rpc_verify_header(task); + /* Verify the RPC header */ + p = call_verify(task); if (IS_ERR(p)) { if (p == ERR_PTR(-EAGAIN)) goto out_retry; @@ -1263,7 +1243,7 @@ call_decode(struct rpc_task *task) return; out_retry: task->tk_status = 0; - /* Note: rpc_verify_header() may have freed the RPC slot */ + /* Note: call_verify() may have freed the RPC slot */ if (task->tk_rqstp == req) { req->rq_received = req->rq_rcv_buf.len = 0; if (task->tk_client->cl_discrtry) @@ -1310,8 +1290,11 @@ call_refreshresult(struct rpc_task *task) return; } +/* + * Call header serialization + */ static __be32 * -rpc_encode_header(struct rpc_task *task) +call_header(struct rpc_task *task) { struct rpc_clnt *clnt = task->tk_client; struct rpc_rqst *req = task->tk_rqstp; @@ -1331,8 +1314,11 @@ rpc_encode_header(struct rpc_task *task) return p; } +/* + * Reply header verification + */ static __be32 * -rpc_verify_header(struct rpc_task *task) +call_verify(struct rpc_task *task) { struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0]; int len = task->tk_rqstp->rq_rcv_buf.len >> 2; @@ -1406,7 +1392,7 @@ rpc_verify_header(struct rpc_task *task) task->tk_action = call_bind; goto out_retry; case RPC_AUTH_TOOWEAK: - printk(KERN_NOTICE "RPC: server %s requires stronger " + printk(KERN_NOTICE "call_verify: server %s requires stronger " "authentication.\n", task->tk_client->cl_server); break; default: @@ -1445,10 +1431,10 @@ rpc_verify_header(struct rpc_task *task) error = -EPROTONOSUPPORT; goto out_err; case RPC_PROC_UNAVAIL: - dprintk("RPC: %5u %s: proc %s unsupported by program %u, " + dprintk("RPC: %5u %s: proc %p unsupported by program %u, " "version %u on server %s\n", task->tk_pid, __func__, - rpc_proc_name(task), + task->tk_msg.rpc_proc, task->tk_client->cl_prog, task->tk_client->cl_vers, task->tk_client->cl_server); @@ -1531,53 +1517,44 @@ struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int EXPORT_SYMBOL_GPL(rpc_call_null); #ifdef RPC_DEBUG -static void rpc_show_header(void) -{ - printk(KERN_INFO "-pid- flgs status -client- --rqstp- " - "-timeout ---ops--\n"); -} - -static void rpc_show_task(const struct rpc_clnt *clnt, - const struct rpc_task *task) -{ - const char *rpc_waitq = "none"; - char *p, action[KSYM_SYMBOL_LEN]; - - if (RPC_IS_QUEUED(task)) - rpc_waitq = rpc_qname(task->tk_waitqueue); - - /* map tk_action pointer to a function name; then trim off - * the "+0x0 [sunrpc]" */ - sprint_symbol(action, (unsigned long)task->tk_action); - p = strchr(action, '+'); - if (p) - *p = '\0'; - - printk(KERN_INFO "%5u %04x %6d %8p %8p %8ld %8p %sv%u %s a:%s q:%s\n", - task->tk_pid, task->tk_flags, task->tk_status, - clnt, task->tk_rqstp, task->tk_timeout, task->tk_ops, - clnt->cl_protname, clnt->cl_vers, rpc_proc_name(task), - action, rpc_waitq); -} - void rpc_show_tasks(void) { struct rpc_clnt *clnt; - struct rpc_task *task; - int header = 0; + struct rpc_task *t; spin_lock(&rpc_client_lock); + if (list_empty(&all_clients)) + goto out; + printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout " + "-rpcwait -action- ---ops--\n"); list_for_each_entry(clnt, &all_clients, cl_clients) { + if (list_empty(&clnt->cl_tasks)) + continue; spin_lock(&clnt->cl_lock); - list_for_each_entry(task, &clnt->cl_tasks, tk_task) { - if (!header) { - rpc_show_header(); - header++; - } - rpc_show_task(clnt, task); + list_for_each_entry(t, &clnt->cl_tasks, tk_task) { + const char *rpc_waitq = "none"; + int proc; + + if (t->tk_msg.rpc_proc) + proc = t->tk_msg.rpc_proc->p_proc; + else + proc = -1; + + if (RPC_IS_QUEUED(t)) + rpc_waitq = rpc_qname(t->tk_waitqueue); + + printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n", + t->tk_pid, proc, + t->tk_flags, t->tk_status, + t->tk_client, + (t->tk_client ? t->tk_client->cl_prog : 0), + t->tk_rqstp, t->tk_timeout, + rpc_waitq, + t->tk_action, t->tk_ops); } spin_unlock(&clnt->cl_lock); } +out: spin_unlock(&rpc_client_lock); } #endif diff --git a/trunk/net/sunrpc/rpcb_clnt.c b/trunk/net/sunrpc/rpcb_clnt.c index 24db2b4d12d3..e6fb21b19b86 100644 --- a/trunk/net/sunrpc/rpcb_clnt.c +++ b/trunk/net/sunrpc/rpcb_clnt.c @@ -32,10 +32,6 @@ #define RPCBIND_PROGRAM (100000u) #define RPCBIND_PORT (111u) -#define RPCBVERS_2 (2u) -#define RPCBVERS_3 (3u) -#define RPCBVERS_4 (4u) - enum { RPCBPROC_NULL, RPCBPROC_SET, @@ -68,7 +64,6 @@ enum { #define RPCB_MAXOWNERLEN sizeof(RPCB_OWNER_STRING) static void rpcb_getport_done(struct rpc_task *, void *); -static void rpcb_map_release(void *data); static struct rpc_program rpcb_program; struct rpcbind_args { @@ -81,73 +76,41 @@ struct rpcbind_args { const char * r_netid; const char * r_addr; const char * r_owner; - - int r_status; }; static struct rpc_procinfo rpcb_procedures2[]; static struct rpc_procinfo rpcb_procedures3[]; -static struct rpc_procinfo rpcb_procedures4[]; struct rpcb_info { - u32 rpc_vers; + int rpc_vers; struct rpc_procinfo * rpc_proc; }; static struct rpcb_info rpcb_next_version[]; static struct rpcb_info rpcb_next_version6[]; -static const struct rpc_call_ops rpcb_getport_ops = { - .rpc_call_done = rpcb_getport_done, - .rpc_release = rpcb_map_release, -}; - -static void rpcb_wake_rpcbind_waiters(struct rpc_xprt *xprt, int status) -{ - xprt_clear_binding(xprt); - rpc_wake_up_status(&xprt->binding, status); -} - static void rpcb_map_release(void *data) { struct rpcbind_args *map = data; - rpcb_wake_rpcbind_waiters(map->r_xprt, map->r_status); xprt_put(map->r_xprt); kfree(map); } -static const struct sockaddr_in rpcb_inaddr_loopback = { - .sin_family = AF_INET, - .sin_addr.s_addr = htonl(INADDR_LOOPBACK), - .sin_port = htons(RPCBIND_PORT), -}; - -static const struct sockaddr_in6 rpcb_in6addr_loopback = { - .sin6_family = AF_INET6, - .sin6_addr = IN6ADDR_LOOPBACK_INIT, - .sin6_port = htons(RPCBIND_PORT), +static const struct rpc_call_ops rpcb_getport_ops = { + .rpc_call_done = rpcb_getport_done, + .rpc_release = rpcb_map_release, }; -static struct rpc_clnt *rpcb_create_local(struct sockaddr *addr, - size_t addrlen, u32 version) +static void rpcb_wake_rpcbind_waiters(struct rpc_xprt *xprt, int status) { - struct rpc_create_args args = { - .protocol = XPRT_TRANSPORT_UDP, - .address = addr, - .addrsize = addrlen, - .servername = "localhost", - .program = &rpcb_program, - .version = version, - .authflavor = RPC_AUTH_UNIX, - .flags = RPC_CLNT_CREATE_NOPING, - }; - - return rpc_create(&args); + xprt_clear_binding(xprt); + rpc_wake_up_status(&xprt->binding, status); } static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, - size_t salen, int proto, u32 version) + size_t salen, int proto, u32 version, + int privileged) { struct rpc_create_args args = { .protocol = proto, @@ -157,8 +120,7 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, .program = &rpcb_program, .version = version, .authflavor = RPC_AUTH_UNIX, - .flags = (RPC_CLNT_CREATE_NOPING | - RPC_CLNT_CREATE_NONPRIVPORT), + .flags = RPC_CLNT_CREATE_NOPING, }; switch (srvaddr->sa_family) { @@ -172,72 +134,29 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, return NULL; } + if (!privileged) + args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; return rpc_create(&args); } -static int rpcb_register_call(struct sockaddr *addr, size_t addrlen, - u32 version, struct rpc_message *msg, - int *result) -{ - struct rpc_clnt *rpcb_clnt; - int error = 0; - - *result = 0; - - rpcb_clnt = rpcb_create_local(addr, addrlen, version); - if (!IS_ERR(rpcb_clnt)) { - error = rpc_call_sync(rpcb_clnt, msg, 0); - rpc_shutdown_client(rpcb_clnt); - } else - error = PTR_ERR(rpcb_clnt); - - if (error < 0) - printk(KERN_WARNING "RPC: failed to contact local rpcbind " - "server (errno %d).\n", -error); - dprintk("RPC: registration status %d/%d\n", error, *result); - - return error; -} - /** * rpcb_register - set or unset a port registration with the local rpcbind svc * @prog: RPC program number to bind * @vers: RPC version number to bind - * @prot: transport protocol to register + * @prot: transport protocol to use to make this request * @port: port value to register - * @okay: OUT: result code - * - * RPC services invoke this function to advertise their contact - * information via the system's rpcbind daemon. RPC services - * invoke this function once for each [program, version, transport] - * tuple they wish to advertise. - * - * Callers may also unregister RPC services that are no longer - * available by setting the passed-in port to zero. This removes - * all registered transports for [program, version] from the local - * rpcbind database. - * - * Returns zero if the registration request was dispatched - * successfully and a reply was received. The rpcbind daemon's - * boolean result code is stored in *okay. - * - * Returns an errno value and sets *result to zero if there was - * some problem that prevented the rpcbind request from being - * dispatched, or if the rpcbind daemon did not respond within - * the timeout. + * @okay: result code * - * This function uses rpcbind protocol version 2 to contact the - * local rpcbind daemon. + * port == 0 means unregister, port != 0 means register. * - * Registration works over both AF_INET and AF_INET6, and services - * registered via this function are advertised as available for any - * address. If the local rpcbind daemon is listening on AF_INET6, - * services registered via this function will be advertised on - * IN6ADDR_ANY (ie available for all AF_INET and AF_INET6 - * addresses). + * This routine supports only rpcbind version 2. */ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) { + struct sockaddr_in sin = { + .sin_family = AF_INET, + .sin_addr.s_addr = htonl(INADDR_LOOPBACK), + }; struct rpcbind_args map = { .r_prog = prog, .r_vers = vers, @@ -245,159 +164,32 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) .r_port = port, }; struct rpc_message msg = { + .rpc_proc = &rpcb_procedures2[port ? + RPCBPROC_SET : RPCBPROC_UNSET], .rpc_argp = &map, .rpc_resp = okay, }; + struct rpc_clnt *rpcb_clnt; + int error = 0; dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " "rpcbind\n", (port ? "" : "un"), prog, vers, prot, port); - msg.rpc_proc = &rpcb_procedures2[RPCBPROC_UNSET]; - if (port) - msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; - - return rpcb_register_call((struct sockaddr *)&rpcb_inaddr_loopback, - sizeof(rpcb_inaddr_loopback), - RPCBVERS_2, &msg, okay); -} - -/* - * Fill in AF_INET family-specific arguments to register - */ -static int rpcb_register_netid4(struct sockaddr_in *address_to_register, - struct rpc_message *msg) -{ - struct rpcbind_args *map = msg->rpc_argp; - unsigned short port = ntohs(address_to_register->sin_port); - char buf[32]; - - /* Construct AF_INET universal address */ - snprintf(buf, sizeof(buf), - NIPQUAD_FMT".%u.%u", - NIPQUAD(address_to_register->sin_addr.s_addr), - port >> 8, port & 0xff); - map->r_addr = buf; - - dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " - "local rpcbind\n", (port ? "" : "un"), - map->r_prog, map->r_vers, - map->r_addr, map->r_netid); - - msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; - if (port) - msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; - - return rpcb_register_call((struct sockaddr *)&rpcb_inaddr_loopback, - sizeof(rpcb_inaddr_loopback), - RPCBVERS_4, msg, msg->rpc_resp); -} - -/* - * Fill in AF_INET6 family-specific arguments to register - */ -static int rpcb_register_netid6(struct sockaddr_in6 *address_to_register, - struct rpc_message *msg) -{ - struct rpcbind_args *map = msg->rpc_argp; - unsigned short port = ntohs(address_to_register->sin6_port); - char buf[64]; - - /* Construct AF_INET6 universal address */ - snprintf(buf, sizeof(buf), - NIP6_FMT".%u.%u", - NIP6(address_to_register->sin6_addr), - port >> 8, port & 0xff); - map->r_addr = buf; - - dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " - "local rpcbind\n", (port ? "" : "un"), - map->r_prog, map->r_vers, - map->r_addr, map->r_netid); - - msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; - if (port) - msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; - - return rpcb_register_call((struct sockaddr *)&rpcb_in6addr_loopback, - sizeof(rpcb_in6addr_loopback), - RPCBVERS_4, msg, msg->rpc_resp); -} - -/** - * rpcb_v4_register - set or unset a port registration with the local rpcbind - * @program: RPC program number of service to (un)register - * @version: RPC version number of service to (un)register - * @address: address family, IP address, and port to (un)register - * @netid: netid of transport protocol to (un)register - * @result: result code from rpcbind RPC call - * - * RPC services invoke this function to advertise their contact - * information via the system's rpcbind daemon. RPC services - * invoke this function once for each [program, version, address, - * netid] tuple they wish to advertise. - * - * Callers may also unregister RPC services that are no longer - * available by setting the port number in the passed-in address - * to zero. Callers pass a netid of "" to unregister all - * transport netids associated with [program, version, address]. - * - * Returns zero if the registration request was dispatched - * successfully and a reply was received. The rpcbind daemon's - * result code is stored in *result. - * - * Returns an errno value and sets *result to zero if there was - * some problem that prevented the rpcbind request from being - * dispatched, or if the rpcbind daemon did not respond within - * the timeout. - * - * This function uses rpcbind protocol version 4 to contact the - * local rpcbind daemon. The local rpcbind daemon must support - * version 4 of the rpcbind protocol in order for these functions - * to register a service successfully. - * - * Supported netids include "udp" and "tcp" for UDP and TCP over - * IPv4, and "udp6" and "tcp6" for UDP and TCP over IPv6, - * respectively. - * - * The contents of @address determine the address family and the - * port to be registered. The usual practice is to pass INADDR_ANY - * as the raw address, but specifying a non-zero address is also - * supported by this API if the caller wishes to advertise an RPC - * service on a specific network interface. - * - * Note that passing in INADDR_ANY does not create the same service - * registration as IN6ADDR_ANY. The former advertises an RPC - * service on any IPv4 address, but not on IPv6. The latter - * advertises the service on all IPv4 and IPv6 addresses. - */ -int rpcb_v4_register(const u32 program, const u32 version, - const struct sockaddr *address, const char *netid, - int *result) -{ - struct rpcbind_args map = { - .r_prog = program, - .r_vers = version, - .r_netid = netid, - .r_owner = RPCB_OWNER_STRING, - }; - struct rpc_message msg = { - .rpc_argp = &map, - .rpc_resp = result, - }; + rpcb_clnt = rpcb_create("localhost", (struct sockaddr *) &sin, + sizeof(sin), XPRT_TRANSPORT_UDP, 2, 1); + if (IS_ERR(rpcb_clnt)) + return PTR_ERR(rpcb_clnt); - *result = 0; + error = rpc_call_sync(rpcb_clnt, &msg, 0); - switch (address->sa_family) { - case AF_INET: - return rpcb_register_netid4((struct sockaddr_in *)address, - &msg); - case AF_INET6: - return rpcb_register_netid6((struct sockaddr_in6 *)address, - &msg); - } + rpc_shutdown_client(rpcb_clnt); + if (error < 0) + printk(KERN_WARNING "RPC: failed to contact local rpcbind " + "server (errno %d).\n", -error); + dprintk("RPC: registration status %d/%d\n", error, *okay); - return -EAFNOSUPPORT; + return error; } /** @@ -435,7 +227,7 @@ int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot) __func__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot); rpcb_clnt = rpcb_create(NULL, (struct sockaddr *)sin, - sizeof(*sin), prot, RPCBVERS_2); + sizeof(*sin), prot, 2, 0); if (IS_ERR(rpcb_clnt)) return PTR_ERR(rpcb_clnt); @@ -497,16 +289,17 @@ void rpcb_getport_async(struct rpc_task *task) /* Autobind on cloned rpc clients is discouraged */ BUG_ON(clnt->cl_parent != clnt); - /* Put self on the wait queue to ensure we get notified if - * some other task is already attempting to bind the port */ - rpc_sleep_on(&xprt->binding, task, NULL); - if (xprt_test_and_set_binding(xprt)) { + status = -EAGAIN; /* tell caller to check again */ dprintk("RPC: %5u %s: waiting for another binder\n", task->tk_pid, __func__); - return; + goto bailout_nowake; } + /* Put self on queue before sending rpcbind request, in case + * rpcb_getport_done completes before we return from rpc_run_task */ + rpc_sleep_on(&xprt->binding, task, NULL); + /* Someone else may have bound if we slept */ if (xprt_bound(xprt)) { status = 0; @@ -545,7 +338,7 @@ void rpcb_getport_async(struct rpc_task *task) task->tk_pid, __func__, bind_version); rpcb_clnt = rpcb_create(clnt->cl_server, sap, salen, xprt->prot, - bind_version); + bind_version, 0); if (IS_ERR(rpcb_clnt)) { status = PTR_ERR(rpcb_clnt); dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n", @@ -568,15 +361,15 @@ void rpcb_getport_async(struct rpc_task *task) map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); map->r_addr = rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR); map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */ - map->r_status = -EIO; child = rpcb_call_async(rpcb_clnt, map, proc); rpc_release_client(rpcb_clnt); if (IS_ERR(child)) { + status = -EIO; /* rpcb_map_release() has freed the arguments */ dprintk("RPC: %5u %s: rpc_run_task failed\n", task->tk_pid, __func__); - return; + goto bailout_nofree; } rpc_put_task(child); @@ -585,6 +378,7 @@ void rpcb_getport_async(struct rpc_task *task) bailout_nofree: rpcb_wake_rpcbind_waiters(xprt, status); +bailout_nowake: task->tk_status = status; } EXPORT_SYMBOL_GPL(rpcb_getport_async); @@ -623,13 +417,9 @@ static void rpcb_getport_done(struct rpc_task *child, void *data) dprintk("RPC: %5u rpcb_getport_done(status %d, port %u)\n", child->tk_pid, status, map->r_port); - map->r_status = status; + rpcb_wake_rpcbind_waiters(xprt, status); } -/* - * XDR functions for rpcbind - */ - static int rpcb_encode_mapping(struct rpc_rqst *req, __be32 *p, struct rpcbind_args *rpcb) { @@ -648,7 +438,7 @@ static int rpcb_decode_getport(struct rpc_rqst *req, __be32 *p, unsigned short *portp) { *portp = (unsigned short) ntohl(*p++); - dprintk("RPC: rpcb_decode_getport result %u\n", + dprintk("RPC: rpcb_decode_getport result %u\n", *portp); return 0; } @@ -657,8 +447,8 @@ static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p, unsigned int *boolp) { *boolp = (unsigned int) ntohl(*p++); - dprintk("RPC: rpcb_decode_set: call %s\n", - (*boolp ? "succeeded" : "failed")); + dprintk("RPC: rpcb_decode_set result %u\n", + *boolp); return 0; } @@ -781,60 +571,52 @@ static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p, static struct rpc_procinfo rpcb_procedures2[] = { PROC(SET, mapping, set), PROC(UNSET, mapping, set), - PROC(GETPORT, mapping, getport), + PROC(GETADDR, mapping, getport), }; static struct rpc_procinfo rpcb_procedures3[] = { - PROC(SET, getaddr, set), - PROC(UNSET, getaddr, set), + PROC(SET, mapping, set), + PROC(UNSET, mapping, set), PROC(GETADDR, getaddr, getaddr), }; static struct rpc_procinfo rpcb_procedures4[] = { - PROC(SET, getaddr, set), - PROC(UNSET, getaddr, set), - PROC(GETADDR, getaddr, getaddr), + PROC(SET, mapping, set), + PROC(UNSET, mapping, set), PROC(GETVERSADDR, getaddr, getaddr), }; static struct rpcb_info rpcb_next_version[] = { - { - .rpc_vers = RPCBVERS_2, - .rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT], - }, - { - .rpc_proc = NULL, - }, +#ifdef CONFIG_SUNRPC_BIND34 + { 4, &rpcb_procedures4[RPCBPROC_GETVERSADDR] }, + { 3, &rpcb_procedures3[RPCBPROC_GETADDR] }, +#endif + { 2, &rpcb_procedures2[RPCBPROC_GETPORT] }, + { 0, NULL }, }; static struct rpcb_info rpcb_next_version6[] = { - { - .rpc_vers = RPCBVERS_4, - .rpc_proc = &rpcb_procedures4[RPCBPROC_GETADDR], - }, - { - .rpc_vers = RPCBVERS_3, - .rpc_proc = &rpcb_procedures3[RPCBPROC_GETADDR], - }, - { - .rpc_proc = NULL, - }, +#ifdef CONFIG_SUNRPC_BIND34 + { 4, &rpcb_procedures4[RPCBPROC_GETVERSADDR] }, + { 3, &rpcb_procedures3[RPCBPROC_GETADDR] }, +#endif + { 0, NULL }, }; static struct rpc_version rpcb_version2 = { - .number = RPCBVERS_2, + .number = 2, .nrprocs = RPCB_HIGHPROC_2, .procs = rpcb_procedures2 }; static struct rpc_version rpcb_version3 = { - .number = RPCBVERS_3, + .number = 3, .nrprocs = RPCB_HIGHPROC_3, .procs = rpcb_procedures3 }; static struct rpc_version rpcb_version4 = { - .number = RPCBVERS_4, + .number = 4, .nrprocs = RPCB_HIGHPROC_4, .procs = rpcb_procedures4 }; diff --git a/trunk/net/sunrpc/sched.c b/trunk/net/sunrpc/sched.c index 385f427bedad..6eab9bf94baf 100644 --- a/trunk/net/sunrpc/sched.c +++ b/trunk/net/sunrpc/sched.c @@ -576,7 +576,9 @@ EXPORT_SYMBOL_GPL(rpc_delay); */ static void rpc_prepare_task(struct rpc_task *task) { + lock_kernel(); task->tk_ops->rpc_call_prepare(task, task->tk_calldata); + unlock_kernel(); } /* @@ -586,7 +588,9 @@ void rpc_exit_task(struct rpc_task *task) { task->tk_action = NULL; if (task->tk_ops->rpc_call_done != NULL) { + lock_kernel(); task->tk_ops->rpc_call_done(task, task->tk_calldata); + unlock_kernel(); if (task->tk_action != NULL) { WARN_ON(RPC_ASSASSINATED(task)); /* Always release the RPC slot and buffer memory */ @@ -598,8 +602,11 @@ EXPORT_SYMBOL_GPL(rpc_exit_task); void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata) { - if (ops->rpc_release != NULL) + if (ops->rpc_release != NULL) { + lock_kernel(); ops->rpc_release(calldata); + unlock_kernel(); + } } /* @@ -619,15 +626,19 @@ static void __rpc_execute(struct rpc_task *task) /* * Execute any pending callback. */ - if (task->tk_callback) { + if (RPC_DO_CALLBACK(task)) { + /* Define a callback save pointer */ void (*save_callback)(struct rpc_task *); /* - * We set tk_callback to NULL before calling it, - * in case it sets the tk_callback field itself: + * If a callback exists, save it, reset it, + * call it. + * The save is needed to stop from resetting + * another callback set within the callback handler + * - Dave */ - save_callback = task->tk_callback; - task->tk_callback = NULL; + save_callback=task->tk_callback; + task->tk_callback=NULL; save_callback(task); } diff --git a/trunk/net/sunrpc/xprt.c b/trunk/net/sunrpc/xprt.c index 99a52aabe332..e1770f7ba0b3 100644 --- a/trunk/net/sunrpc/xprt.c +++ b/trunk/net/sunrpc/xprt.c @@ -690,7 +690,7 @@ static void xprt_connect_status(struct rpc_task *task) { struct rpc_xprt *xprt = task->tk_xprt; - if (task->tk_status == 0) { + if (task->tk_status >= 0) { xprt->stat.connect_count++; xprt->stat.connect_time += (long)jiffies - xprt->stat.connect_start; dprintk("RPC: %5u xprt_connect_status: connection established\n", @@ -699,6 +699,12 @@ static void xprt_connect_status(struct rpc_task *task) } switch (task->tk_status) { + case -ECONNREFUSED: + case -ECONNRESET: + dprintk("RPC: %5u xprt_connect_status: server %s refused " + "connection\n", task->tk_pid, + task->tk_client->cl_server); + break; case -ENOTCONN: dprintk("RPC: %5u xprt_connect_status: connection broken\n", task->tk_pid); @@ -872,7 +878,6 @@ void xprt_transmit(struct rpc_task *task) return; req->rq_connect_cookie = xprt->connect_cookie; - req->rq_xtime = jiffies; status = xprt->ops->send_request(task); if (status == 0) { dprintk("RPC: %5u xmit complete\n", task->tk_pid); diff --git a/trunk/net/sunrpc/xprtsock.c b/trunk/net/sunrpc/xprtsock.c index 4486c59c3aca..ddbe981ab516 100644 --- a/trunk/net/sunrpc/xprtsock.c +++ b/trunk/net/sunrpc/xprtsock.c @@ -579,6 +579,7 @@ static int xs_udp_send_request(struct rpc_task *task) req->rq_svec->iov_base, req->rq_svec->iov_len); + req->rq_xtime = jiffies; status = xs_sendpages(transport->sock, xs_addr(xprt), xprt->addrlen, xdr, @@ -670,6 +671,7 @@ static int xs_tcp_send_request(struct rpc_task *task) * to cope with writespace callbacks arriving _after_ we have * called sendmsg(). */ while (1) { + req->rq_xtime = jiffies; status = xs_sendpages(transport->sock, NULL, 0, xdr, req->rq_bytes_sent);