aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-07-17 23:57:20 +0200
committerIngo Molnar <mingo@elte.hu>2008-07-17 23:57:20 +0200
commit393d81aa026e19b6ede6f5f11955c97ee62e5df5 (patch)
treea1d9511e488e19d41089ff0a736f6ce52a81c6e5
parent93a0886e2368eafb9df5e2021fb185195cee88b2 (diff)
parent5b664cb235e97afbf34db9c4d77f08ebd725335e (diff)
downloadmrst-s0i3-test-393d81aa026e19b6ede6f5f11955c97ee62e5df5.tar.gz
mrst-s0i3-test-393d81aa026e19b6ede6f5f11955c97ee62e5df5.tar.xz
mrst-s0i3-test-393d81aa026e19b6ede6f5f11955c97ee62e5df5.zip
Merge branch 'linus' into xen-64bit
-rw-r--r--Documentation/ABI/testing/sysfs-firmware-acpi127
-rw-r--r--Documentation/filesystems/configfs/configfs.txt10
-rw-r--r--Documentation/filesystems/configfs/configfs_example.c14
-rw-r--r--Documentation/filesystems/ubifs.txt164
-rw-r--r--Documentation/i2c/chips/max68752
-rw-r--r--Documentation/i2c/chips/pca953910
-rw-r--r--Documentation/i2c/chips/pcf857412
-rw-r--r--Documentation/i2c/chips/pcf85759
-rw-r--r--Documentation/ioctl/hdio.txt7
-rw-r--r--Documentation/kernel-parameters.txt14
-rw-r--r--Documentation/laptops/acer-wmi.txt2
-rw-r--r--MAINTAINERS64
-rw-r--r--Makefile5
-rw-r--r--arch/avr32/boards/atngw100/setup.c7
-rw-r--r--arch/avr32/boards/atstk1000/atstk1002.c3
-rw-r--r--arch/avr32/mach-at32ap/at32ap700x.c30
-rw-r--r--arch/frv/mb93090-mb00/pci-frv.c30
-rw-r--r--arch/ia64/kernel/process.c4
-rw-r--r--arch/ia64/kvm/kvm-ia64.c4
-rw-r--r--arch/ia64/kvm/kvm_fw.c2
-rw-r--r--arch/m68knommu/kernel/comempci.c9
-rw-r--r--arch/mips/pmc-sierra/yosemite/ht.c36
-rw-r--r--arch/powerpc/platforms/82xx/ep8248e.c4
-rw-r--r--arch/s390/Kconfig2
-rw-r--r--arch/s390/kernel/stacktrace.c1
-rw-r--r--arch/sh/drivers/pci/pci.c32
-rw-r--r--arch/sparc64/kernel/pci.c2
-rw-r--r--arch/x86/kernel/Makefile3
-rw-r--r--arch/x86/kernel/acpi/processor.c6
-rw-r--r--arch/x86/kernel/acpi/sleep.c2
-rw-r--r--arch/x86/kernel/apm_32.c8
-rw-r--r--arch/x86/kernel/early-quirks.c26
-rw-r--r--arch/x86/kernel/numaq_32.c2
-rw-r--r--arch/x86/kernel/process.c28
-rw-r--r--arch/x86/kernel/setup.c5
-rw-r--r--arch/x86/mm/init_64.c2
-rw-r--r--arch/x86/mm/srat_32.c3
-rw-r--r--arch/x86/pci/common.c30
-rw-r--r--arch/x86/pci/early.c60
-rw-r--r--arch/x86/pci/irq.c120
-rw-r--r--arch/x86/pci/pci.h1
-rw-r--r--drivers/acpi/Kconfig9
-rw-r--r--drivers/acpi/Makefile3
-rw-r--r--drivers/acpi/bay.c3
-rw-r--r--drivers/acpi/bus.c24
-rw-r--r--drivers/acpi/dispatcher/dsinit.c2
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c1
-rw-r--r--drivers/acpi/dispatcher/dsopcode.c22
-rw-r--r--drivers/acpi/dispatcher/dswexec.c8
-rw-r--r--drivers/acpi/dispatcher/dswstate.c20
-rw-r--r--drivers/acpi/dock.c3
-rw-r--r--drivers/acpi/events/evevent.c6
-rw-r--r--drivers/acpi/events/evgpe.c36
-rw-r--r--drivers/acpi/events/evgpeblk.c18
-rw-r--r--drivers/acpi/events/evmisc.c4
-rw-r--r--drivers/acpi/events/evregion.c5
-rw-r--r--drivers/acpi/events/evrgnini.c2
-rw-r--r--drivers/acpi/events/evxfevnt.c18
-rw-r--r--drivers/acpi/executer/exconfig.c17
-rw-r--r--drivers/acpi/executer/exconvrt.c12
-rw-r--r--drivers/acpi/executer/excreate.c2
-rw-r--r--drivers/acpi/executer/exdump.c67
-rw-r--r--drivers/acpi/executer/exfldio.c9
-rw-r--r--drivers/acpi/executer/exmisc.c8
-rw-r--r--drivers/acpi/executer/exprep.c8
-rw-r--r--drivers/acpi/executer/exregion.c2
-rw-r--r--drivers/acpi/executer/exresop.c4
-rw-r--r--drivers/acpi/executer/exstore.c6
-rw-r--r--drivers/acpi/fan.c8
-rw-r--r--drivers/acpi/glue.c5
-rw-r--r--drivers/acpi/hardware/hwgpe.c52
-rw-r--r--drivers/acpi/namespace/nsdump.c6
-rw-r--r--drivers/acpi/namespace/nseval.c35
-rw-r--r--drivers/acpi/namespace/nsinit.c1
-rw-r--r--drivers/acpi/namespace/nsload.c3
-rw-r--r--drivers/acpi/namespace/nsparse.c15
-rw-r--r--drivers/acpi/namespace/nsutils.c50
-rw-r--r--drivers/acpi/namespace/nsxfeval.c3
-rw-r--r--drivers/acpi/numa.c4
-rw-r--r--drivers/acpi/parser/psargs.c4
-rw-r--r--drivers/acpi/parser/psxface.c4
-rw-r--r--drivers/acpi/pci_irq.c38
-rw-r--r--drivers/acpi/pci_slot.c368
-rw-r--r--drivers/acpi/power.c138
-rw-r--r--drivers/acpi/processor_core.c75
-rw-r--r--drivers/acpi/processor_idle.c34
-rw-r--r--drivers/acpi/processor_perflib.c18
-rw-r--r--drivers/acpi/processor_throttling.c38
-rw-r--r--drivers/acpi/reboot.c50
-rw-r--r--drivers/acpi/resources/rscalc.c4
-rw-r--r--drivers/acpi/resources/rscreate.c41
-rw-r--r--drivers/acpi/resources/rsmisc.c2
-rw-r--r--drivers/acpi/resources/rsutils.c13
-rw-r--r--drivers/acpi/scan.c104
-rw-r--r--drivers/acpi/sleep/main.c328
-rw-r--r--drivers/acpi/sleep/wakeup.c13
-rw-r--r--drivers/acpi/system.c169
-rw-r--r--drivers/acpi/tables/tbfadt.c23
-rw-r--r--drivers/acpi/tables/tbfind.c5
-rw-r--r--drivers/acpi/tables/tbinstal.c30
-rw-r--r--drivers/acpi/tables/tbutils.c15
-rw-r--r--drivers/acpi/tables/tbxface.c28
-rw-r--r--drivers/acpi/tables/tbxfroot.c4
-rw-r--r--drivers/acpi/utilities/utalloc.c5
-rw-r--r--drivers/acpi/utilities/utcopy.c4
-rw-r--r--drivers/acpi/utilities/utdebug.c54
-rw-r--r--drivers/acpi/utilities/utdelete.c2
-rw-r--r--drivers/acpi/utilities/uteval.c5
-rw-r--r--drivers/acpi/utilities/utmisc.c39
-rw-r--r--drivers/acpi/utilities/utmutex.c4
-rw-r--r--drivers/acpi/utilities/utobject.c9
-rw-r--r--drivers/acpi/video.c123
-rw-r--r--drivers/base/platform.c296
-rw-r--r--drivers/base/power/main.c675
-rw-r--r--drivers/base/power/power.h2
-rw-r--r--drivers/base/power/sysfs.c3
-rw-r--r--drivers/base/power/trace.c4
-rw-r--r--drivers/block/Kconfig12
-rw-r--r--drivers/block/Makefile1
-rw-r--r--drivers/block/hd.c (renamed from drivers/ide/legacy/hd.c)3
-rw-r--r--drivers/char/apm-emulation.c346
-rw-r--r--drivers/char/pcmcia/cm4000_cs.c2
-rw-r--r--drivers/hwmon/ad7418.c109
-rw-r--r--drivers/hwmon/adm1021.c105
-rw-r--r--drivers/hwmon/adm1025.c101
-rw-r--r--drivers/hwmon/adm1026.c109
-rw-r--r--drivers/hwmon/adm1029.c97
-rw-r--r--drivers/hwmon/adm1031.c96
-rw-r--r--drivers/hwmon/adm9240.c93
-rw-r--r--drivers/hwmon/ads7828.c89
-rw-r--r--drivers/hwmon/adt7470.c100
-rw-r--r--drivers/hwmon/adt7473.c102
-rw-r--r--drivers/hwmon/asb100.c207
-rw-r--r--drivers/hwmon/atxp1.c109
-rw-r--r--drivers/hwmon/ds1621.c99
-rw-r--r--drivers/hwmon/f75375s.c89
-rw-r--r--drivers/hwmon/fscher.c93
-rw-r--r--drivers/hwmon/fschmd.c112
-rw-r--r--drivers/hwmon/fscpos.c94
-rw-r--r--drivers/hwmon/gl518sm.c99
-rw-r--r--drivers/hwmon/gl520sm.c91
-rw-r--r--drivers/hwmon/lm63.c99
-rw-r--r--drivers/hwmon/lm77.c102
-rw-r--r--drivers/hwmon/lm80.c94
-rw-r--r--drivers/hwmon/lm83.c104
-rw-r--r--drivers/hwmon/lm87.c99
-rw-r--r--drivers/hwmon/lm90.c119
-rw-r--r--drivers/hwmon/lm92.c98
-rw-r--r--drivers/hwmon/lm93.c126
-rw-r--r--drivers/hwmon/max1619.c101
-rw-r--r--drivers/hwmon/max6650.c102
-rw-r--r--drivers/hwmon/smsc47m192.c102
-rw-r--r--drivers/hwmon/thmc50.c107
-rw-r--r--drivers/hwmon/w83791d.c205
-rw-r--r--drivers/hwmon/w83792d.c214
-rw-r--r--drivers/hwmon/w83793.c227
-rw-r--r--drivers/hwmon/w83l785ts.c117
-rw-r--r--drivers/hwmon/w83l786ng.c98
-rw-r--r--drivers/i2c/busses/i2c-amd756-s4882.c27
-rw-r--r--drivers/i2c/busses/i2c-nforce2-s4985.c31
-rw-r--r--drivers/i2c/chips/eeprom.c92
-rw-r--r--drivers/i2c/chips/max6875.c120
-rw-r--r--drivers/i2c/chips/pca9539.c109
-rw-r--r--drivers/i2c/chips/pcf8574.c108
-rw-r--r--drivers/i2c/chips/pcf8575.c96
-rw-r--r--drivers/i2c/chips/pcf8591.c94
-rw-r--r--drivers/i2c/i2c-core.c4
-rw-r--r--drivers/ide/Kconfig88
-rw-r--r--drivers/ide/Makefile10
-rw-r--r--drivers/ide/arm/Makefile1
-rw-r--r--drivers/ide/arm/bast-ide.c90
-rw-r--r--drivers/ide/arm/icside.c105
-rw-r--r--drivers/ide/arm/palm_bk3710.c3
-rw-r--r--drivers/ide/arm/rapide.c33
-rw-r--r--drivers/ide/h8300/ide-h8300.c19
-rw-r--r--drivers/ide/ide-cd.c160
-rw-r--r--drivers/ide/ide-disk.c1
-rw-r--r--drivers/ide/ide-floppy.c32
-rw-r--r--drivers/ide/ide-io.c72
-rw-r--r--drivers/ide/ide-iops.c24
-rw-r--r--drivers/ide/ide-lib.c151
-rw-r--r--drivers/ide/ide-pio-blacklist.c94
-rw-r--r--drivers/ide/ide-pnp.c4
-rw-r--r--drivers/ide/ide-probe.c21
-rw-r--r--drivers/ide/ide-tape.c1
-rw-r--r--drivers/ide/ide-taskfile.c33
-rw-r--r--drivers/ide/ide-timings.c (renamed from drivers/ide/ide-timing.h)204
-rw-r--r--drivers/ide/ide.c76
-rw-r--r--drivers/ide/legacy/ali14xx.c3
-rw-r--r--drivers/ide/legacy/buddha.c1
-rw-r--r--drivers/ide/legacy/falconide.c1
-rw-r--r--drivers/ide/legacy/gayle.c1
-rw-r--r--drivers/ide/legacy/ht6560b.c15
-rw-r--r--drivers/ide/legacy/ide-4drives.c25
-rw-r--r--drivers/ide/legacy/ide-cs.c11
-rw-r--r--drivers/ide/legacy/ide_platform.c9
-rw-r--r--drivers/ide/legacy/macide.c1
-rw-r--r--drivers/ide/legacy/q40ide.c1
-rw-r--r--drivers/ide/legacy/qd65xx.c19
-rw-r--r--drivers/ide/mips/au1xxx-ide.c13
-rw-r--r--drivers/ide/mips/swarm.c28
-rw-r--r--drivers/ide/pci/alim15x3.c6
-rw-r--r--drivers/ide/pci/amd74xx.c2
-rw-r--r--drivers/ide/pci/cmd640.c131
-rw-r--r--drivers/ide/pci/cmd64x.c6
-rw-r--r--drivers/ide/pci/cs5535.c6
-rw-r--r--drivers/ide/pci/cy82c693.c9
-rw-r--r--drivers/ide/pci/delkin_cb.c1
-rw-r--r--drivers/ide/pci/it821x.c6
-rw-r--r--drivers/ide/pci/scc_pata.c8
-rw-r--r--drivers/ide/pci/sgiioc4.c23
-rw-r--r--drivers/ide/pci/siimage.c3
-rw-r--r--drivers/ide/pci/sis5513.c3
-rw-r--r--drivers/ide/pci/sl82c105.c3
-rw-r--r--drivers/ide/pci/via82cxxx.c2
-rw-r--r--drivers/ide/ppc/Makefile1
-rw-r--r--drivers/ide/ppc/mpc8xx.c851
-rw-r--r--drivers/ide/ppc/pmac.c21
-rw-r--r--drivers/ide/setup-pci.c25
-rw-r--r--drivers/misc/Kconfig31
-rw-r--r--drivers/misc/Makefile5
-rw-r--r--drivers/misc/acer-wmi.c145
-rw-r--r--drivers/misc/compal-laptop.c404
-rw-r--r--drivers/misc/eeepc-laptop.c4
-rw-r--r--drivers/misc/fujitsu-laptop.c825
-rw-r--r--drivers/mmc/card/block.c60
-rw-r--r--drivers/mmc/card/mmc_test.c569
-rw-r--r--drivers/mmc/card/sdio_uart.c9
-rw-r--r--drivers/mmc/core/core.c41
-rw-r--r--drivers/mmc/core/mmc.c2
-rw-r--r--drivers/mmc/core/sd.c6
-rw-r--r--drivers/mmc/core/sdio_cis.c6
-rw-r--r--drivers/mmc/core/sdio_io.c167
-rw-r--r--drivers/mmc/host/Kconfig50
-rw-r--r--drivers/mmc/host/Makefile4
-rw-r--r--drivers/mmc/host/at91_mci.c257
-rw-r--r--drivers/mmc/host/atmel-mci-regs.h91
-rw-r--r--drivers/mmc/host/atmel-mci.c981
-rw-r--r--drivers/mmc/host/au1xmmc.c792
-rw-r--r--drivers/mmc/host/au1xmmc.h96
-rw-r--r--drivers/mmc/host/imxmmc.c9
-rw-r--r--drivers/mmc/host/mmc_spi.c33
-rw-r--r--drivers/mmc/host/mmci.c1
-rw-r--r--drivers/mmc/host/omap.c2
-rw-r--r--drivers/mmc/host/pxamci.c9
-rw-r--r--drivers/mmc/host/s3cmci.c1446
-rw-r--r--drivers/mmc/host/s3cmci.h70
-rw-r--r--drivers/mmc/host/sdhci-pci.c732
-rw-r--r--drivers/mmc/host/sdhci.c994
-rw-r--r--drivers/mmc/host/sdhci.h120
-rw-r--r--drivers/mmc/host/sdricoh_cs.c575
-rw-r--r--drivers/mmc/host/tifm_sd.c2
-rw-r--r--drivers/mmc/host/wbsd.c38
-rw-r--r--drivers/net/netconsole.c10
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c20
-rw-r--r--drivers/pci/Makefile2
-rw-r--r--drivers/pci/hotplug/acpi_pcihp.c85
-rw-r--r--drivers/pci/hotplug/acpiphp.h1
-rw-r--r--drivers/pci/hotplug/acpiphp_core.c25
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c23
-rw-r--r--drivers/pci/hotplug/acpiphp_ibm.c6
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_core.c2
-rw-r--r--drivers/pci/hotplug/cpqphp_core.c4
-rw-r--r--drivers/pci/hotplug/fakephp.c86
-rw-r--r--drivers/pci/hotplug/ibmphp_ebda.c3
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c284
-rw-r--r--drivers/pci/hotplug/pciehp.h16
-rw-r--r--drivers/pci/hotplug/pciehp_core.c127
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c318
-rw-r--r--drivers/pci/hotplug/rpadlpar_sysfs.c5
-rw-r--r--drivers/pci/hotplug/rpaphp_slot.c44
-rw-r--r--drivers/pci/hotplug/sgi_hotplug.c12
-rw-r--r--drivers/pci/hotplug/shpchp.h14
-rw-r--r--drivers/pci/hotplug/shpchp_core.c37
-rw-r--r--drivers/pci/hotplug/shpchp_hpc.c1
-rw-r--r--drivers/pci/intel-iommu.c1
-rw-r--r--drivers/pci/msi.c22
-rw-r--r--drivers/pci/pci-acpi.c277
-rw-r--r--drivers/pci/pci-driver.c388
-rw-r--r--drivers/pci/pci.c479
-rw-r--r--drivers/pci/pci.h48
-rw-r--r--drivers/pci/pcie/aer/aerdrv.c9
-rw-r--r--drivers/pci/pcie/aer/aerdrv_acpi.c8
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c24
-rw-r--r--drivers/pci/pcie/portdrv_bus.c1
-rw-r--r--drivers/pci/pcie/portdrv_core.c22
-rw-r--r--drivers/pci/pcie/portdrv_pci.c5
-rw-r--r--drivers/pci/probe.c38
-rw-r--r--drivers/pci/proc.c4
-rw-r--r--drivers/pci/quirks.c134
-rw-r--r--drivers/pci/setup-bus.c43
-rw-r--r--drivers/pci/setup-irq.c3
-rw-r--r--drivers/pci/setup-res.c70
-rw-r--r--drivers/pci/slot.c233
-rw-r--r--drivers/pcmcia/cistpl.c2
-rw-r--r--drivers/pnp/base.h148
-rw-r--r--drivers/pnp/core.c29
-rw-r--r--drivers/pnp/interface.c207
-rw-r--r--drivers/pnp/isapnp/core.c253
-rw-r--r--drivers/pnp/manager.c414
-rw-r--r--drivers/pnp/pnpacpi/core.c4
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c492
-rw-r--r--drivers/pnp/pnpbios/rsparser.c274
-rw-r--r--drivers/pnp/quirks.c307
-rw-r--r--drivers/pnp/resource.c454
-rw-r--r--drivers/pnp/support.c171
-rw-r--r--drivers/pnp/system.c4
-rw-r--r--drivers/s390/block/dasd_diag.c25
-rw-r--r--drivers/s390/block/dasd_eckd.c4
-rw-r--r--drivers/s390/block/dasd_fba.c7
-rw-r--r--drivers/s390/char/vmur.c10
-rw-r--r--drivers/s390/char/zcore.c101
-rw-r--r--drivers/s390/cio/Makefile2
-rw-r--r--drivers/s390/cio/chsc.c9
-rw-r--r--drivers/s390/cio/chsc.h2
-rw-r--r--drivers/s390/cio/qdio.c3929
-rw-r--r--drivers/s390/cio/qdio.h835
-rw-r--r--drivers/s390/cio/qdio_debug.c240
-rw-r--r--drivers/s390/cio/qdio_debug.h91
-rw-r--r--drivers/s390/cio/qdio_main.c1755
-rw-r--r--drivers/s390/cio/qdio_perf.c151
-rw-r--r--drivers/s390/cio/qdio_perf.h54
-rw-r--r--drivers/s390/cio/qdio_setup.c521
-rw-r--r--drivers/s390/cio/qdio_thinint.c380
-rw-r--r--drivers/s390/net/qeth_core.h12
-rw-r--r--drivers/s390/net/qeth_core_main.c87
-rw-r--r--drivers/s390/net/qeth_l2_main.c26
-rw-r--r--drivers/s390/net/qeth_l3_main.c25
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c12
-rw-r--r--drivers/s390/scsi/zfcp_dbf.h2
-rw-r--r--drivers/s390/scsi/zfcp_ext.h5
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c42
-rw-r--r--drivers/scsi/device_handler/scsi_dh_emc.c7
-rw-r--r--drivers/scsi/device_handler/scsi_dh_hp_sw.c7
-rw-r--r--drivers/scsi/device_handler/scsi_dh_rdac.c7
-rw-r--r--drivers/scsi/ide-scsi.c14
-rw-r--r--drivers/serial/8250_pnp.c24
-rw-r--r--drivers/w1/masters/ds2482.c104
-rw-r--r--firmware/.gitignore6
-rw-r--r--firmware/Makefile2
-rw-r--r--fs/Kconfig147
-rw-r--r--fs/Makefile1
-rw-r--r--fs/compat_ioctl.c6
-rw-r--r--fs/configfs/configfs_internal.h4
-rw-r--r--fs/configfs/dir.c147
-rw-r--r--fs/configfs/inode.c2
-rw-r--r--fs/configfs/symlink.c16
-rw-r--r--fs/dlm/config.c45
-rw-r--r--fs/fs-writeback.c22
-rw-r--r--fs/lockd/clntproc.c8
-rw-r--r--fs/lockd/svc4proc.c2
-rw-r--r--fs/lockd/svclock.c7
-rw-r--r--fs/lockd/svcproc.c2
-rw-r--r--fs/nfs/callback.c34
-rw-r--r--fs/nfs/client.c13
-rw-r--r--fs/nfs/dir.c88
-rw-r--r--fs/nfs/direct.c4
-rw-r--r--fs/nfs/file.c155
-rw-r--r--fs/nfs/inode.c79
-rw-r--r--fs/nfs/internal.h1
-rw-r--r--fs/nfs/iostat.h119
-rw-r--r--fs/nfs/nfs3acl.c9
-rw-r--r--fs/nfs/nfs3proc.c275
-rw-r--r--fs/nfs/nfs4proc.c265
-rw-r--r--fs/nfs/nfs4state.c2
-rw-r--r--fs/nfs/nfsroot.c10
-rw-r--r--fs/nfs/proc.c28
-rw-r--r--fs/nfs/super.c882
-rw-r--r--fs/nfs/write.c322
-rw-r--r--fs/nfsd/nfs4callback.c2
-rw-r--r--fs/ocfs2/aops.c13
-rw-r--r--fs/ocfs2/cluster/heartbeat.c17
-rw-r--r--fs/ocfs2/cluster/netdebug.c8
-rw-r--r--fs/ocfs2/cluster/nodemanager.c45
-rw-r--r--fs/ocfs2/dlmglue.c122
-rw-r--r--fs/ocfs2/file.c2
-rw-r--r--fs/ocfs2/journal.c2
-rw-r--r--fs/ocfs2/localalloc.c2
-rw-r--r--fs/ocfs2/ocfs2.h12
-rw-r--r--fs/ocfs2/ocfs2_fs.h2
-rw-r--r--fs/ocfs2/stack_user.c19
-rw-r--r--fs/ocfs2/super.c6
-rw-r--r--fs/ubifs/Kconfig72
-rw-r--r--fs/ubifs/Makefile9
-rw-r--r--fs/ubifs/budget.c731
-rw-r--r--fs/ubifs/commit.c677
-rw-r--r--fs/ubifs/compress.c253
-rw-r--r--fs/ubifs/debug.c2289
-rw-r--r--fs/ubifs/debug.h403
-rw-r--r--fs/ubifs/dir.c1240
-rw-r--r--fs/ubifs/file.c1275
-rw-r--r--fs/ubifs/find.c975
-rw-r--r--fs/ubifs/gc.c773
-rw-r--r--fs/ubifs/io.c914
-rw-r--r--fs/ubifs/ioctl.c204
-rw-r--r--fs/ubifs/journal.c1387
-rw-r--r--fs/ubifs/key.h533
-rw-r--r--fs/ubifs/log.c805
-rw-r--r--fs/ubifs/lprops.c1357
-rw-r--r--fs/ubifs/lpt.c2243
-rw-r--r--fs/ubifs/lpt_commit.c1648
-rw-r--r--fs/ubifs/master.c387
-rw-r--r--fs/ubifs/misc.h342
-rw-r--r--fs/ubifs/orphan.c958
-rw-r--r--fs/ubifs/recovery.c1519
-rw-r--r--fs/ubifs/replay.c1075
-rw-r--r--fs/ubifs/sb.c629
-rw-r--r--fs/ubifs/scan.c362
-rw-r--r--fs/ubifs/shrinker.c322
-rw-r--r--fs/ubifs/super.c1951
-rw-r--r--fs/ubifs/tnc.c2956
-rw-r--r--fs/ubifs/tnc_commit.c1103
-rw-r--r--fs/ubifs/tnc_misc.c494
-rw-r--r--fs/ubifs/ubifs-media.h745
-rw-r--r--fs/ubifs/ubifs.h1649
-rw-r--r--fs/ubifs/xattr.c581
-rw-r--r--include/acpi/acconfig.h2
-rw-r--r--include/acpi/acdisasm.h1
-rw-r--r--include/acpi/acdispat.h2
-rw-r--r--include/acpi/acexcep.h10
-rw-r--r--include/acpi/acglobal.h2
-rw-r--r--include/acpi/achware.h4
-rw-r--r--include/acpi/acinterp.h5
-rw-r--r--include/acpi/aclocal.h6
-rw-r--r--include/acpi/acmacros.h38
-rw-r--r--include/acpi/acnamesp.h30
-rw-r--r--include/acpi/acpi_bus.h12
-rw-r--r--include/acpi/acpi_drivers.h4
-rw-r--r--include/acpi/acpiosxf.h2
-rw-r--r--include/acpi/acpixf.h12
-rw-r--r--include/acpi/acstruct.h10
-rw-r--r--include/acpi/actables.h27
-rw-r--r--include/acpi/actbl1.h23
-rw-r--r--include/acpi/actypes.h16
-rw-r--r--include/acpi/acutils.h70
-rw-r--r--include/acpi/processor.h2
-rw-r--r--include/acpi/reboot.h14
-rw-r--r--include/asm-arm/arch-at91/at91_mci.h4
-rw-r--r--include/asm-arm/arch-s3c2410/regs-sdi.h20
-rw-r--r--include/asm-arm/plat-s3c24xx/mci.h15
-rw-r--r--include/asm-avr32/arch-at32ap/board.h6
-rw-r--r--include/asm-avr32/atmel-mci.h9
-rw-r--r--include/asm-generic/vmlinux.lds.h6
-rw-r--r--include/asm-ia64/processor.h2
-rw-r--r--include/asm-mips/mach-au1x00/au1100_mmc.h18
-rw-r--r--include/asm-s390/Kbuild2
-rw-r--r--include/asm-s390/chpid.h6
-rw-r--r--include/asm-s390/qdio.h646
-rw-r--r--include/asm-s390/schid.h3
-rw-r--r--include/asm-s390/setup.h2
-rw-r--r--include/asm-x86/e820.h3
-rw-r--r--include/asm-x86/pci-direct.h4
-rw-r--r--include/asm-x86/processor.h2
-rw-r--r--include/linux/acpi.h3
-rw-r--r--include/linux/blkdev.h3
-rw-r--r--include/linux/configfs.h4
-rw-r--r--include/linux/device.h9
-rw-r--r--include/linux/freezer.h10
-rw-r--r--include/linux/fs.h2
-rw-r--r--include/linux/ide.h74
-rw-r--r--include/linux/inet.h7
-rw-r--r--include/linux/init_task.h4
-rw-r--r--include/linux/ioport.h5
-rw-r--r--include/linux/mmc/core.h1
-rw-r--r--include/linux/mmc/host.h32
-rw-r--r--include/linux/mmc/mmc.h1
-rw-r--r--include/linux/mmc/sdio_func.h21
-rw-r--r--include/linux/nfs_fs.h10
-rw-r--r--include/linux/nfs_iostat.h119
-rw-r--r--include/linux/nfs_page.h9
-rw-r--r--include/linux/nfs_xdr.h3
-rw-r--r--include/linux/pci.h57
-rw-r--r--include/linux/pci_hotplug.h14
-rw-r--r--include/linux/pci_ids.h1
-rw-r--r--include/linux/pci_regs.h1
-rw-r--r--include/linux/platform_device.h1
-rw-r--r--include/linux/pm.h314
-rw-r--r--include/linux/pm_wakeup.h28
-rw-r--r--include/linux/pnp.h146
-rw-r--r--include/linux/sched.h27
-rw-r--r--include/linux/spi/mmc_spi.h9
-rw-r--r--include/linux/sunrpc/clnt.h7
-rw-r--r--include/linux/sunrpc/sched.h1
-rw-r--r--include/linux/suspend.h14
-rw-r--r--init/do_mounts.c3
-rw-r--r--kernel/Makefile3
-rw-r--r--kernel/cpu.c1
-rw-r--r--kernel/exit.c451
-rw-r--r--kernel/fork.c6
-rw-r--r--kernel/kthread.c2
-rw-r--r--kernel/power/disk.c50
-rw-r--r--kernel/power/main.c16
-rw-r--r--kernel/power/process.c97
-rw-r--r--kernel/power/user.c71
-rw-r--r--kernel/ptrace.c37
-rw-r--r--lib/Makefile14
-rw-r--r--lib/kobject.c1
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c27
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_mech.c4
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_mech.c4
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_token.c2
-rw-r--r--net/sunrpc/auth_unix.c2
-rw-r--r--net/sunrpc/clnt.c161
-rw-r--r--net/sunrpc/rpcb_clnt.c356
-rw-r--r--net/sunrpc/sched.c23
-rw-r--r--net/sunrpc/xprt.c9
-rw-r--r--net/sunrpc/xprtsock.c2
-rw-r--r--scripts/Makefile.fwinst25
508 files changed, 56964 insertions, 16739 deletions
diff --git a/Documentation/ABI/testing/sysfs-firmware-acpi b/Documentation/ABI/testing/sysfs-firmware-acpi
index 9470ed9afcc..f27be7d1a49 100644
--- a/Documentation/ABI/testing/sysfs-firmware-acpi
+++ b/Documentation/ABI/testing/sysfs-firmware-acpi
@@ -29,46 +29,46 @@ Description:
$ cd /sys/firmware/acpi/interrupts
$ grep . *
- error:0
- ff_gbl_lock:0
- ff_pmtimer:0
- ff_pwr_btn:0
- ff_rt_clk:0
- ff_slp_btn:0
- gpe00:0
- gpe01:0
- gpe02:0
- gpe03:0
- gpe04:0
- gpe05:0
- gpe06:0
- gpe07:0
- gpe08:0
- gpe09:174
- gpe0A:0
- gpe0B:0
- gpe0C:0
- gpe0D:0
- gpe0E:0
- gpe0F:0
- gpe10:0
- gpe11:60
- gpe12:0
- gpe13:0
- gpe14:0
- gpe15:0
- gpe16:0
- gpe17:0
- gpe18:0
- gpe19:7
- gpe1A:0
- gpe1B:0
- gpe1C:0
- gpe1D:0
- gpe1E:0
- gpe1F:0
- gpe_all:241
- sci:241
+ error: 0
+ ff_gbl_lock: 0 enable
+ ff_pmtimer: 0 invalid
+ ff_pwr_btn: 0 enable
+ ff_rt_clk: 2 disable
+ ff_slp_btn: 0 invalid
+ gpe00: 0 invalid
+ gpe01: 0 enable
+ gpe02: 108 enable
+ gpe03: 0 invalid
+ gpe04: 0 invalid
+ gpe05: 0 invalid
+ gpe06: 0 enable
+ gpe07: 0 enable
+ gpe08: 0 invalid
+ gpe09: 0 invalid
+ gpe0A: 0 invalid
+ gpe0B: 0 invalid
+ gpe0C: 0 invalid
+ gpe0D: 0 invalid
+ gpe0E: 0 invalid
+ gpe0F: 0 invalid
+ gpe10: 0 invalid
+ gpe11: 0 invalid
+ gpe12: 0 invalid
+ gpe13: 0 invalid
+ gpe14: 0 invalid
+ gpe15: 0 invalid
+ gpe16: 0 invalid
+ gpe17: 1084 enable
+ gpe18: 0 enable
+ gpe19: 0 invalid
+ gpe1A: 0 invalid
+ gpe1B: 0 invalid
+ gpe1C: 0 invalid
+ gpe1D: 0 invalid
+ gpe1E: 0 invalid
+ gpe1F: 0 invalid
+ gpe_all: 1192
+ sci: 1194
sci - The total number of times the ACPI SCI
has claimed an interrupt.
@@ -89,6 +89,13 @@ Description:
error - an interrupt that can't be accounted for above.
+ invalid: it's either a wakeup GPE or a GPE/Fixed Event that
+ doesn't have an event handler.
+
+ disable: the GPE/Fixed Event is valid but disabled.
+
+ enable: the GPE/Fixed Event is valid and enabled.
+
Root has permission to clear any of these counters. Eg.
# echo 0 > gpe11
@@ -97,3 +104,43 @@ Description:
None of these counters has an effect on the function
of the system, they are simply statistics.
+
+ Besides this, user can also write specific strings to these files
+ to enable/disable/clear ACPI interrupts in user space, which can be
+ used to debug some ACPI interrupt storm issues.
+
+ Note that only writting to VALID GPE/Fixed Event is allowed,
+ i.e. user can only change the status of runtime GPE and
+ Fixed Event with event handler installed.
+
+ Let's take power button fixed event for example, please kill acpid
+ and other user space applications so that the machine won't shutdown
+ when pressing the power button.
+ # cat ff_pwr_btn
+ 0
+ # press the power button for 3 times;
+ # cat ff_pwr_btn
+ 3
+ # echo disable > ff_pwr_btn
+ # cat ff_pwr_btn
+ disable
+ # press the power button for 3 times;
+ # cat ff_pwr_btn
+ disable
+ # echo enable > ff_pwr_btn
+ # cat ff_pwr_btn
+ 4
+ /*
+ * this is because the status bit is set even if the enable bit is cleared,
+ * and it triggers an ACPI fixed event when the enable bit is set again
+ */
+ # press the power button for 3 times;
+ # cat ff_pwr_btn
+ 7
+ # echo disable > ff_pwr_btn
+ # press the power button for 3 times;
+ # echo clear > ff_pwr_btn /* clear the status bit */
+ # echo disable > ff_pwr_btn
+ # cat ff_pwr_btn
+ 7
+
diff --git a/Documentation/filesystems/configfs/configfs.txt b/Documentation/filesystems/configfs/configfs.txt
index 44c97e6accb..15838d706ea 100644
--- a/Documentation/filesystems/configfs/configfs.txt
+++ b/Documentation/filesystems/configfs/configfs.txt
@@ -233,10 +233,12 @@ accomplished via the group operations specified on the group's
config_item_type.
struct configfs_group_operations {
- struct config_item *(*make_item)(struct config_group *group,
- const char *name);
- struct config_group *(*make_group)(struct config_group *group,
- const char *name);
+ int (*make_item)(struct config_group *group,
+ const char *name,
+ struct config_item **new_item);
+ int (*make_group)(struct config_group *group,
+ const char *name,
+ struct config_group **new_group);
int (*commit_item)(struct config_item *item);
void (*disconnect_notify)(struct config_group *group,
struct config_item *item);
diff --git a/Documentation/filesystems/configfs/configfs_example.c b/Documentation/filesystems/configfs/configfs_example.c
index 25151fd5c2c..0b422acd470 100644
--- a/Documentation/filesystems/configfs/configfs_example.c
+++ b/Documentation/filesystems/configfs/configfs_example.c
@@ -273,13 +273,13 @@ static inline struct simple_children *to_simple_children(struct config_item *ite
return item ? container_of(to_config_group(item), struct simple_children, group) : NULL;
}
-static struct config_item *simple_children_make_item(struct config_group *group, const char *name)
+static int simple_children_make_item(struct config_group *group, const char *name, struct config_item **new_item)
{
struct simple_child *simple_child;
simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL);
if (!simple_child)
- return NULL;
+ return -ENOMEM;
config_item_init_type_name(&simple_child->item, name,
@@ -287,7 +287,8 @@ static struct config_item *simple_children_make_item(struct config_group *group,
simple_child->storeme = 0;
- return &simple_child->item;
+ *new_item = &simple_child->item;
+ return 0;
}
static struct configfs_attribute simple_children_attr_description = {
@@ -359,20 +360,21 @@ static struct configfs_subsystem simple_children_subsys = {
* children of its own.
*/
-static struct config_group *group_children_make_group(struct config_group *group, const char *name)
+static int group_children_make_group(struct config_group *group, const char *name, struct config_group **new_group)
{
struct simple_children *simple_children;
simple_children = kzalloc(sizeof(struct simple_children),
GFP_KERNEL);
if (!simple_children)
- return NULL;
+ return -ENOMEM;
config_group_init_type_name(&simple_children->group, name,
&simple_children_type);
- return &simple_children->group;
+ *new_group = &simple_children->group;
+ return 0;
}
static struct configfs_attribute group_children_attr_description = {
diff --git a/Documentation/filesystems/ubifs.txt b/Documentation/filesystems/ubifs.txt
new file mode 100644
index 00000000000..540e9e7f59c
--- /dev/null
+++ b/Documentation/filesystems/ubifs.txt
@@ -0,0 +1,164 @@
+Introduction
+=============
+
+UBIFS file-system stands for UBI File System. UBI stands for "Unsorted
+Block Images". UBIFS is a flash file system, which means it is designed
+to work with flash devices. It is important to understand, that UBIFS
+is completely different to any traditional file-system in Linux, like
+Ext2, XFS, JFS, etc. UBIFS represents a separate class of file-systems
+which work with MTD devices, not block devices. The other Linux
+file-system of this class is JFFS2.
+
+To make it more clear, here is a small comparison of MTD devices and
+block devices.
+
+1 MTD devices represent flash devices and they consist of eraseblocks of
+ rather large size, typically about 128KiB. Block devices consist of
+ small blocks, typically 512 bytes.
+2 MTD devices support 3 main operations - read from some offset within an
+ eraseblock, write to some offset within an eraseblock, and erase a whole
+ eraseblock. Block devices support 2 main operations - read a whole
+ block and write a whole block.
+3 The whole eraseblock has to be erased before it becomes possible to
+ re-write its contents. Blocks may be just re-written.
+4 Eraseblocks become worn out after some number of erase cycles -
+ typically 100K-1G for SLC NAND and NOR flashes, and 1K-10K for MLC
+ NAND flashes. Blocks do not have the wear-out property.
+5 Eraseblocks may become bad (only on NAND flashes) and software should
+ deal with this. Blocks on hard drives typically do not become bad,
+ because hardware has mechanisms to substitute bad blocks, at least in
+ modern LBA disks.
+
+It should be quite obvious why UBIFS is very different to traditional
+file-systems.
+
+UBIFS works on top of UBI. UBI is a separate software layer which may be
+found in drivers/mtd/ubi. UBI is basically a volume management and
+wear-leveling layer. It provides so called UBI volumes which is a higher
+level abstraction than a MTD device. The programming model of UBI devices
+is very similar to MTD devices - they still consist of large eraseblocks,
+they have read/write/erase operations, but UBI devices are devoid of
+limitations like wear and bad blocks (items 4 and 5 in the above list).
+
+In a sense, UBIFS is a next generation of JFFS2 file-system, but it is
+very different and incompatible to JFFS2. The following are the main
+differences.
+
+* JFFS2 works on top of MTD devices, UBIFS depends on UBI and works on
+ top of UBI volumes.
+* JFFS2 does not have on-media index and has to build it while mounting,
+ which requires full media scan. UBIFS maintains the FS indexing
+ information on the flash media and does not require full media scan,
+ so it mounts many times faster than JFFS2.
+* JFFS2 is a write-through file-system, while UBIFS supports write-back,
+ which makes UBIFS much faster on writes.
+
+Similarly to JFFS2, UBIFS supports on-the-flight compression which makes
+it possible to fit quite a lot of data to the flash.
+
+Similarly to JFFS2, UBIFS is tolerant of unclean reboots and power-cuts.
+It does not need stuff like ckfs.ext2. UBIFS automatically replays its
+journal and recovers from crashes, ensuring that the on-flash data
+structures are consistent.
+
+UBIFS scales logarithmically (most of the data structures it uses are
+trees), so the mount time and memory consumption do not linearly depend
+on the flash size, like in case of JFFS2. This is because UBIFS
+maintains the FS index on the flash media. However, UBIFS depends on
+UBI, which scales linearly. So overall UBI/UBIFS stack scales linearly.
+Nevertheless, UBI/UBIFS scales considerably better than JFFS2.
+
+The authors of UBIFS believe, that it is possible to develop UBI2 which
+would scale logarithmically as well. UBI2 would support the same API as UBI,
+but it would be binary incompatible to UBI. So UBIFS would not need to be
+changed to use UBI2
+
+
+Mount options
+=============
+
+(*) == default.
+
+norm_unmount (*) commit on unmount; the journal is committed
+ when the file-system is unmounted so that the
+ next mount does not have to replay the journal
+ and it becomes very fast;
+fast_unmount do not commit on unmount; this option makes
+ unmount faster, but the next mount slower
+ because of the need to replay the journal.
+
+
+Quick usage instructions
+========================
+
+The UBI volume to mount is specified using "ubiX_Y" or "ubiX:NAME" syntax,
+where "X" is UBI device number, "Y" is UBI volume number, and "NAME" is
+UBI volume name.
+
+Mount volume 0 on UBI device 0 to /mnt/ubifs:
+$ mount -t ubifs ubi0_0 /mnt/ubifs
+
+Mount "rootfs" volume of UBI device 0 to /mnt/ubifs ("rootfs" is volume
+name):
+$ mount -t ubifs ubi0:rootfs /mnt/ubifs
+
+The following is an example of the kernel boot arguments to attach mtd0
+to UBI and mount volume "rootfs":
+ubi.mtd=0 root=ubi0:rootfs rootfstype=ubifs
+
+
+Module Parameters for Debugging
+===============================
+
+When UBIFS has been compiled with debugging enabled, there are 3 module
+parameters that are available to control aspects of testing and debugging.
+The parameters are unsigned integers where each bit controls an option.
+The parameters are:
+
+debug_msgs Selects which debug messages to display, as follows:
+
+ Message Type Flag value
+
+ General messages 1
+ Journal messages 2
+ Mount messages 4
+ Commit messages 8
+ LEB search messages 16
+ Budgeting messages 32
+ Garbage collection messages 64
+ Tree Node Cache (TNC) messages 128
+ LEB properties (lprops) messages 256
+ Input/output messages 512
+ Log messages 1024
+ Scan messages 2048
+ Recovery messages 4096
+
+debug_chks Selects extra checks that UBIFS can do while running:
+
+ Check Flag value
+
+ General checks 1
+ Check Tree Node Cache (TNC) 2
+ Check indexing tree size 4
+ Check orphan area 8
+ Check old indexing tree 16
+ Check LEB properties (lprops) 32
+ Check leaf nodes and inodes 64
+
+debug_tsts Selects a mode of testing, as follows:
+
+ Test mode Flag value
+
+ Force in-the-gaps method 2
+ Failure mode for recovery testing 4
+
+For example, set debug_msgs to 5 to display General messages and Mount
+messages.
+
+
+References
+==========
+
+UBIFS documentation and FAQ/HOWTO at the MTD web site:
+http://www.linux-mtd.infradead.org/doc/ubifs.html
+http://www.linux-mtd.infradead.org/faq/ubifs.html
diff --git a/Documentation/i2c/chips/max6875 b/Documentation/i2c/chips/max6875
index a0cd8af2f40..10ca43cd1a7 100644
--- a/Documentation/i2c/chips/max6875
+++ b/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 'max6875 subclient'.
+The even-address instance is called 'max6875', the odd one is 'dummy'.
Programming the chip using i2c-dev
diff --git a/Documentation/i2c/chips/pca9539 b/Documentation/i2c/chips/pca9539
index 1d81c530c4a..6aff890088b 100644
--- a/Documentation/i2c/chips/pca9539
+++ b/Documentation/i2c/chips/pca9539
@@ -7,7 +7,7 @@ drivers/gpio/pca9539.c instead.
Supported chips:
* Philips PCA9539
Prefix: 'pca9539'
- Addresses scanned: 0x74 - 0x77
+ Addresses scanned: none
Datasheet:
http://www.semiconductors.philips.com/acrobat/datasheets/PCA9539_2.pdf
@@ -23,6 +23,14 @@ 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/Documentation/i2c/chips/pcf8574 b/Documentation/i2c/chips/pcf8574
index 5c1ad1376b6..235815c075f 100644
--- a/Documentation/i2c/chips/pcf8574
+++ b/Documentation/i2c/chips/pcf8574
@@ -4,13 +4,13 @@ Kernel driver pcf8574
Supported chips:
* Philips PCF8574
Prefix: 'pcf8574'
- Addresses scanned: I2C 0x20 - 0x27
+ Addresses scanned: none
Datasheet: Publicly available at the Philips Semiconductors website
http://www.semiconductors.philips.com/pip/PCF8574P.html
* Philips PCF8574A
Prefix: 'pcf8574a'
- Addresses scanned: I2C 0x38 - 0x3f
+ Addresses scanned: none
Datasheet: Publicly available at the Philips Semiconductors website
http://www.semiconductors.philips.com/pip/PCF8574P.html
@@ -38,12 +38,10 @@ 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 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.
+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.
On detection (i.e. insmod, modprobe et al.), directories are being
created for each detected PCF8574(A):
diff --git a/Documentation/i2c/chips/pcf8575 b/Documentation/i2c/chips/pcf8575
index 25f5698a61c..40b268eb276 100644
--- a/Documentation/i2c/chips/pcf8575
+++ b/Documentation/i2c/chips/pcf8575
@@ -40,12 +40,9 @@ 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 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.
+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.
/sys interface
--------------
diff --git a/Documentation/ioctl/hdio.txt b/Documentation/ioctl/hdio.txt
index c19efdeace2..91a6ecbae0b 100644
--- a/Documentation/ioctl/hdio.txt
+++ b/Documentation/ioctl/hdio.txt
@@ -508,12 +508,13 @@ HDIO_DRIVE_RESET execute a device reset
error returns:
EACCES Access denied: requires CAP_SYS_ADMIN
+ ENXIO No such device: phy dead or ctl_addr == 0
+ EIO I/O error: reset timed out or hardware error
notes:
- Abort any current command, prevent anything else from being
- queued, execute a reset on the device, and issue BLKRRPART
- ioctl on the block device.
+ Execute a reset on the device as soon as the current IO
+ operation has completed.
Executes an ATAPI soft reset if applicable, otherwise
executes an ATA soft reset on the controller.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 312fe77764a..09ad7450647 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -147,10 +147,14 @@ and is between 256 and 4096 characters. It is defined in the file
default: 0
acpi_sleep= [HW,ACPI] Sleep options
- Format: { s3_bios, s3_mode, s3_beep }
+ Format: { s3_bios, s3_mode, s3_beep, old_ordering }
See Documentation/power/video.txt for s3_bios and s3_mode.
s3_beep is for debugging; it makes the PC's speaker beep
as soon as the kernel's real-mode entry point is called.
+ old_ordering causes the ACPI 1.0 ordering of the _PTS
+ control method, wrt putting devices into low power
+ states, to be enforced (the ACPI 2.0 ordering of _PTS is
+ used by default).
acpi_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode
Format: { level | edge | high | low }
@@ -818,7 +822,7 @@ and is between 256 and 4096 characters. It is defined in the file
See Documentation/ide/ide.txt.
idle= [X86]
- Format: idle=poll or idle=mwait
+ Format: idle=poll or idle=mwait, idle=halt, idle=nomwait
Poll forces a polling idle loop that can slightly improves the performance
of waking up a idle CPU, but will use a lot of power and make the system
run hot. Not recommended.
@@ -826,6 +830,9 @@ and is between 256 and 4096 characters. It is defined in the file
to not use it because it doesn't save as much power as a normal idle
loop use the MONITOR/MWAIT idle loop anyways. Performance should be the same
as idle=poll.
+ idle=halt. Halt is forced to be used for CPU idle.
+ In such case C2/C3 won't be used again.
+ idle=nomwait. Disable mwait for CPU C-states
ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem
Claim all unknown PCI IDE storage controllers.
@@ -1534,6 +1541,9 @@ and is between 256 and 4096 characters. It is defined in the file
Use with caution as certain devices share
address decoders between ROMs and other
resources.
+ norom [X86-32,X86_64] Do not assign address space to
+ expansion ROMs that do not already have
+ BIOS assigned address ranges.
irqmask=0xMMMM [X86-32] Set a bit mask of IRQs allowed to be
assigned automatically to PCI devices. You can
make the kernel exclude IRQs of your ISA cards
diff --git a/Documentation/laptops/acer-wmi.txt b/Documentation/laptops/acer-wmi.txt
index 79b7dbd2214..69b5dd4e5a5 100644
--- a/Documentation/laptops/acer-wmi.txt
+++ b/Documentation/laptops/acer-wmi.txt
@@ -174,8 +174,6 @@ The LED is exposed through the LED subsystem, and can be found in:
The mail LED is autodetected, so if you don't have one, the LED device won't
be registered.
-If you have a mail LED that is not green, please report this to me.
-
Backlight
*********
diff --git a/MAINTAINERS b/MAINTAINERS
index ee1c56a2075..93fd6b2efee 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -216,8 +216,8 @@ W: http://code.google.com/p/aceracpi
S: Maintained
ACPI
-P: Len Brown
-M: len.brown@intel.com
+P: Andi Kleen
+M: ak@linux.intel.com
M: lenb@kernel.org
L: linux-acpi@vger.kernel.org
W: http://www.lesswatts.org/projects/acpi/
@@ -239,8 +239,8 @@ W: http://www.lesswatts.org/projects/acpi/
S: Supported
ACPI FAN DRIVER
-P: Len Brown
-M: len.brown@intel.com
+P: Zhang Rui
+M: rui.zhang@intel.com
L: linux-acpi@vger.kernel.org
W: http://www.lesswatts.org/projects/acpi/
S: Supported
@@ -248,18 +248,18 @@ S: Supported
ACPI PCI HOTPLUG DRIVER
P: Kristen Carlson Accardi
M: kristen.c.accardi@intel.com
-L: pcihpd-discuss@lists.sourceforge.net
+L: linux-pci@vger.kernel.org
S: Supported
ACPI THERMAL DRIVER
-P: Len Brown
-M: len.brown@intel.com
+P: Zhang Rui
+M: rui.zhang@intel.com
L: linux-acpi@vger.kernel.org
W: http://www.lesswatts.org/projects/acpi/
S: Supported
ACPI VIDEO DRIVER
-P: Rui Zhang
+P: Zhang Rui
M: rui.zhang@intel.com
L: linux-acpi@vger.kernel.org
W: http://www.lesswatts.org/projects/acpi/
@@ -348,7 +348,9 @@ W: http://www.linux-usb.org/SpeedTouch/
S: Maintained
ALCHEMY AU1XX0 MMC DRIVER
-S: Orphan
+P: Manuel Lauss
+M: manuel.lauss@gmail.com
+S: Maintained
ALI1563 I2C DRIVER
P: Rudolf Marek
@@ -1143,23 +1145,28 @@ COMPACTPCI HOTPLUG CORE
P: Scott Murray
M: scottm@somanetworks.com
M: scott@spiteful.org
-L: pcihpd-discuss@lists.sourceforge.net
+L: linux-pci@vger.kernel.org
S: Supported
COMPACTPCI HOTPLUG ZIATECH ZT5550 DRIVER
P: Scott Murray
M: scottm@somanetworks.com
M: scott@spiteful.org
-L: pcihpd-discuss@lists.sourceforge.net
+L: linux-pci@vger.kernel.org
S: Supported
COMPACTPCI HOTPLUG GENERIC DRIVER
P: Scott Murray
M: scottm@somanetworks.com
M: scott@spiteful.org
-L: pcihpd-discuss@lists.sourceforge.net
+L: linux-pci@vger.kernel.org
S: Supported
+COMPAL LAPTOP SUPPORT
+P: Cezary Jackiewicz
+M: cezary.jackiewicz@gmail.com
+S: Maintained
+
COMPUTONE INTELLIPORT MULTIPORT CARD
P: Michael H. Warfield
M: mhw@wittsend.com
@@ -1787,6 +1794,12 @@ P: David Howells
M: dhowells@redhat.com
S: Maintained
+FUJITSU LAPTOP EXTRAS
+P: Jonathan Woithe
+M: jwoithe@physics.adelaide.edu.au
+L: linux-acpi@vger.kernel.org
+S: Maintained
+
FUSE: FILESYSTEM IN USERSPACE
P: Miklos Szeredi
M: miklos@szeredi.hu
@@ -2325,6 +2338,16 @@ L: linux-mtd@lists.infradead.org
W: http://www.linux-mtd.infradead.org/doc/jffs2.html
S: Maintained
+UBI FILE SYSTEM (UBIFS)
+P: Artem Bityutskiy
+M: dedekind@infradead.org
+P: Adrian Hunter
+M: ext-adrian.hunter@nokia.com
+L: linux-mtd@lists.infradead.org
+T: git git://git.infradead.org/~dedekind/ubifs-2.6.git
+W: http://www.linux-mtd.infradead.org/doc/ubifs.html
+S: Maintained
+
JFS FILESYSTEM
P: Dave Kleikamp
M: shaggy@austin.ibm.com
@@ -3196,7 +3219,7 @@ S: Supported
PCIE HOTPLUG DRIVER
P: Kristen Carlson Accardi
M: kristen.c.accardi@intel.com
-L: pcihpd-discuss@lists.sourceforge.net
+L: linux-pci@vger.kernel.org
S: Supported
PCMCIA SUBSYSTEM
@@ -3538,6 +3561,13 @@ L: linux-s390@vger.kernel.org
W: http://www.ibm.com/developerworks/linux/linux390/
S: Supported
+S3C24XX SD/MMC Driver
+P: Ben Dooks
+M: ben-linux@fluff.org
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+L: linux-kernel@vger.kernel.org
+S: Supported
+
SAA7146 VIDEO4LINUX-2 DRIVER
P: Michael Hunold
M: michael@mihu.de
@@ -3610,6 +3640,12 @@ P: Jim Cromie
M: jim.cromie@gmail.com
S: Maintained
+SDRICOH_CS MMC/SD HOST CONTROLLER INTERFACE DRIVER
+P: Sascha Sommer
+M: saschasommer@freenet.de
+L: sdricohcs-devel@lists.sourceforge.net (subscribers-only)
+S: Maintained
+
SECURITY CONTACT
P: Security Officers
M: security@kernel.org
@@ -3829,7 +3865,7 @@ S: Maintained
SHPC HOTPLUG DRIVER
P: Kristen Carlson Accardi
M: kristen.c.accardi@intel.com
-L: pcihpd-discuss@lists.sourceforge.net
+L: linux-pci@vger.kernel.org
S: Supported
SECURE DIGITAL HOST CONTROLLER INTERFACE DRIVER
diff --git a/Makefile b/Makefile
index 8a2a275be30..6192922de9c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,3 @@
-FRED=42
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 26
@@ -508,6 +507,8 @@ 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
@@ -516,8 +517,6 @@ 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/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c
index a51bb9fb3c8..c7fe94d03a1 100644
--- a/arch/avr32/boards/atngw100/setup.c
+++ b/arch/avr32/boards/atngw100/setup.c
@@ -19,6 +19,7 @@
#include <linux/leds.h>
#include <linux/spi/spi.h>
+#include <asm/atmel-mci.h>
#include <asm/io.h>
#include <asm/setup.h>
@@ -51,6 +52,11 @@ static struct spi_board_info spi0_board_info[] __initdata = {
},
};
+static struct mci_platform_data __initdata mci0_data = {
+ .detect_pin = GPIO_PIN_PC(25),
+ .wp_pin = GPIO_PIN_PE(0),
+};
+
/*
* The next two functions should go away as the boot loader is
* supposed to initialize the macb address registers with a valid
@@ -170,6 +176,7 @@ static int __init atngw100_init(void)
set_hw_addr(at32_add_device_eth(1, &eth_data[1]));
at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
+ at32_add_device_mci(0, &mci0_data);
at32_add_device_usba(0, NULL);
for (i = 0; i < ARRAY_SIZE(ngw_leds); i++) {
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c
index 86b363c1c25..e11659b732f 100644
--- a/arch/avr32/boards/atstk1000/atstk1002.c
+++ b/arch/avr32/boards/atstk1000/atstk1002.c
@@ -234,6 +234,9 @@ static int __init atstk1002_init(void)
#ifdef CONFIG_BOARD_ATSTK100X_SPI1
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
#endif
+#ifndef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
+ at32_add_device_mci(0, NULL);
+#endif
#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM
set_hw_addr(at32_add_device_eth(1, &eth_data[1]));
#else
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
index 07b21b121ee..021d5121718 100644
--- a/arch/avr32/mach-at32ap/at32ap700x.c
+++ b/arch/avr32/mach-at32ap/at32ap700x.c
@@ -14,6 +14,7 @@
#include <linux/spi/spi.h>
#include <linux/usb/atmel_usba_udc.h>
+#include <asm/atmel-mci.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -1278,20 +1279,32 @@ static struct clk atmel_mci0_pclk = {
.index = 9,
};
-struct platform_device *__init at32_add_device_mci(unsigned int id)
+struct platform_device *__init
+at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
{
- struct platform_device *pdev;
+ struct mci_platform_data _data;
+ struct platform_device *pdev;
+ struct dw_dma_slave *dws;
if (id != 0)
return NULL;
pdev = platform_device_alloc("atmel_mci", id);
if (!pdev)
- return NULL;
+ goto fail;
if (platform_device_add_resources(pdev, atmel_mci0_resource,
ARRAY_SIZE(atmel_mci0_resource)))
- goto err_add_resources;
+ goto fail;
+
+ if (!data) {
+ data = &_data;
+ memset(data, 0, sizeof(struct mci_platform_data));
+ }
+
+ if (platform_device_add_data(pdev, data,
+ sizeof(struct mci_platform_data)))
+ goto fail;
select_peripheral(PA(10), PERIPH_A, 0); /* CLK */
select_peripheral(PA(11), PERIPH_A, 0); /* CMD */
@@ -1300,12 +1313,19 @@ struct platform_device *__init at32_add_device_mci(unsigned int id)
select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */
select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */
+ if (data) {
+ if (data->detect_pin != GPIO_PIN_NONE)
+ at32_select_gpio(data->detect_pin, 0);
+ if (data->wp_pin != GPIO_PIN_NONE)
+ at32_select_gpio(data->wp_pin, 0);
+ }
+
atmel_mci0_pclk.dev = &pdev->dev;
platform_device_add(pdev);
return pdev;
-err_add_resources:
+fail:
platform_device_put(pdev);
return NULL;
}
diff --git a/arch/frv/mb93090-mb00/pci-frv.c b/arch/frv/mb93090-mb00/pci-frv.c
index 4f165c93be4..edae117fcc2 100644
--- a/arch/frv/mb93090-mb00/pci-frv.c
+++ b/arch/frv/mb93090-mb00/pci-frv.c
@@ -19,36 +19,6 @@
#include "pci-frv.h"
-#if 0
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
- struct resource *res, int resource)
-{
- u32 new, check;
- int reg;
-
- new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
- if (resource < 6) {
- reg = PCI_BASE_ADDRESS_0 + 4*resource;
- } else if (resource == PCI_ROM_RESOURCE) {
- res->flags |= IORESOURCE_ROM_ENABLE;
- new |= PCI_ROM_ADDRESS_ENABLE;
- reg = dev->rom_base_reg;
- } else {
- /* Somebody might have asked allocation of a non-standard resource */
- return;
- }
-
- pci_write_config_dword(dev, reg, new);
- pci_read_config_dword(dev, reg, &check);
- if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
- printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", pci_name(dev), resource,
- new, check);
- }
-}
-#endif
-
/*
* We need to avoid collisions with `mirrored' VGA ports
* and other strange ISA hardware, so we always want the
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index fabaf08d9a6..3ab8373103e 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -55,6 +55,10 @@ void (*ia64_mark_idle)(int);
unsigned long boot_option_idle_override = 0;
EXPORT_SYMBOL(boot_option_idle_override);
+unsigned long idle_halt;
+EXPORT_SYMBOL(idle_halt);
+unsigned long idle_nomwait;
+EXPORT_SYMBOL(idle_nomwait);
void
ia64_do_show_stack (struct unw_frame_info *info, void *arg)
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 318b8110062..68c978be9a5 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -395,7 +395,7 @@ static int handle_global_purge(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
if (kvm->vcpus[i]->cpu != -1) {
call_data.vcpu = kvm->vcpus[i];
smp_call_function_single(kvm->vcpus[i]->cpu,
- vcpu_global_purge, &call_data, 0, 1);
+ vcpu_global_purge, &call_data, 1);
} else
printk(KERN_WARNING"kvm: Uninit vcpu received ipi!\n");
@@ -1693,7 +1693,7 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
wake_up_interruptible(&vcpu->wq);
if (vcpu->guest_mode)
- smp_call_function_single(ipi_pcpu, vcpu_kick_intr, vcpu, 0, 0);
+ smp_call_function_single(ipi_pcpu, vcpu_kick_intr, vcpu, 0);
}
int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig)
diff --git a/arch/ia64/kvm/kvm_fw.c b/arch/ia64/kvm/kvm_fw.c
index 091f936c448..0c69d9ec92d 100644
--- a/arch/ia64/kvm/kvm_fw.c
+++ b/arch/ia64/kvm/kvm_fw.c
@@ -130,7 +130,7 @@ static struct ia64_pal_retval pal_cache_flush(struct kvm_vcpu *vcpu)
args.cache_type = gr29;
args.operation = gr30;
smp_call_function(remote_pal_cache_flush,
- (void *)&args, 1, 1);
+ (void *)&args, 1);
if (args.status != 0)
printk(KERN_ERR"pal_cache_flush error!,"
"status:0x%lx\n", args.status);
diff --git a/arch/m68knommu/kernel/comempci.c b/arch/m68knommu/kernel/comempci.c
index 6ee00effbad..0a68b5a85f8 100644
--- a/arch/m68knommu/kernel/comempci.c
+++ b/arch/m68knommu/kernel/comempci.c
@@ -375,15 +375,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
/*****************************************************************************/
-void pcibios_update_resource(struct pci_dev *dev, struct resource *root, struct resource *r, int resource)
-{
- printk(KERN_WARNING "%s(%d): no support for changing PCI resources...\n",
- __FILE__, __LINE__);
-}
-
-
-/*****************************************************************************/
-
/*
* Local routines to interrcept the standard I/O and vector handling
* code. Don't include this 'till now - initialization code above needs
diff --git a/arch/mips/pmc-sierra/yosemite/ht.c b/arch/mips/pmc-sierra/yosemite/ht.c
index 6380662bbf3..678388fd34b 100644
--- a/arch/mips/pmc-sierra/yosemite/ht.c
+++ b/arch/mips/pmc-sierra/yosemite/ht.c
@@ -345,42 +345,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
return pcibios_enable_resources(dev);
}
-
-
-void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
- struct resource *res, int resource)
-{
- u32 new, check;
- int reg;
-
- return;
-
- new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
- if (resource < 6) {
- reg = PCI_BASE_ADDRESS_0 + 4 * resource;
- } else if (resource == PCI_ROM_RESOURCE) {
- res->flags |= IORESOURCE_ROM_ENABLE;
- reg = dev->rom_base_reg;
- } else {
- /*
- * Somebody might have asked allocation of a non-standard
- * resource
- */
- return;
- }
-
- pci_write_config_dword(dev, reg, new);
- pci_read_config_dword(dev, reg, &check);
- if ((new ^ check) &
- ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
- PCI_BASE_ADDRESS_MEM_MASK)) {
- printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", pci_name(dev), resource,
- new, check);
- }
-}
-
-
void pcibios_align_resource(void *data, struct resource *res,
resource_size_t size, resource_size_t align)
{
diff --git a/arch/powerpc/platforms/82xx/ep8248e.c b/arch/powerpc/platforms/82xx/ep8248e.c
index d5770fdf7f0..373e993a5ed 100644
--- a/arch/powerpc/platforms/82xx/ep8248e.c
+++ b/arch/powerpc/platforms/82xx/ep8248e.c
@@ -59,6 +59,7 @@ 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)
@@ -164,6 +165,7 @@ static struct of_platform_driver ep8248e_mdio_driver = {
.probe = ep8248e_mdio_probe,
.remove = ep8248e_mdio_remove,
};
+#endif
struct cpm_pin {
int port, pin, flags;
@@ -296,7 +298,9 @@ 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/arch/s390/Kconfig b/arch/s390/Kconfig
index 5dc8f8028d5..eb530b4128b 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -289,7 +289,7 @@ config WARN_STACK_SIZE
int "Maximum frame size considered safe (128-2048)"
range 128 2048
depends on WARN_STACK
- default "256"
+ default "2048"
help
This allows you to specify the maximum frame size a function may
have without the compiler complaining about it.
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index 57571f10270..8841919ef7e 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -10,6 +10,7 @@
#include <linux/sched.h>
#include <linux/stacktrace.h>
#include <linux/kallsyms.h>
+#include <linux/module.h>
static unsigned long save_context_stack(struct stack_trace *trace,
unsigned long sp,
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index 08d2e732525..f57095a2617 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -76,38 +76,6 @@ void __devinit __weak pcibios_fixup_bus(struct pci_bus *bus)
pci_read_bridge_bases(bus);
}
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
- struct resource *res, int resource)
-{
- u32 new, check;
- int reg;
-
- new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
- if (resource < 6) {
- reg = PCI_BASE_ADDRESS_0 + 4*resource;
- } else if (resource == PCI_ROM_RESOURCE) {
- res->flags |= IORESOURCE_ROM_ENABLE;
- new |= PCI_ROM_ADDRESS_ENABLE;
- reg = dev->rom_base_reg;
- } else {
- /*
- * Somebody might have asked allocation of a non-standard
- * resource
- */
- return;
- }
-
- pci_write_config_dword(dev, reg, new);
- pci_read_config_dword(dev, reg, &check);
- if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ?
- PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
- printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", pci_name(dev), resource,
- new, check);
- }
-}
-
void pcibios_align_resource(void *data, struct resource *res,
resource_size_t size, resource_size_t align)
__attribute__ ((weak));
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index 112b09f16f3..d00a3656c28 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -408,7 +408,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
dev->class = class >> 8;
dev->revision = class & 0xff;
- sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
+ sprintf(dev->dev.bus_id, "%04x:%02x:%02x.%d", pci_domain_nr(bus),
dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
if (ofpci_verbose)
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 5112c84f542..da140611bb5 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -8,8 +8,7 @@ CPPFLAGS_vmlinux.lds += -U$(UTS_MACHINE)
ifdef CONFIG_FTRACE
# Do not profile debug utilities
-CFLAGS_REMOVE_tsc_64.o = -pg
-CFLAGS_REMOVE_tsc_32.o = -pg
+CFLAGS_REMOVE_tsc.o = -pg
CFLAGS_REMOVE_rtc.o = -pg
endif
diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c
index de2d2e4ebad..7c074eec39f 100644
--- a/arch/x86/kernel/acpi/processor.c
+++ b/arch/x86/kernel/acpi/processor.c
@@ -56,6 +56,12 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c)
if (cpu_has(c, X86_FEATURE_ACPI))
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/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index 793ad2045f5..868de3d5c39 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -158,6 +158,8 @@ static int __init acpi_sleep_setup(char *str)
acpi_realmode_flags |= 2;
if (strncmp(str, "s3_beep", 7) == 0)
acpi_realmode_flags |= 4;
+ if (strncmp(str, "old_ordering", 12) == 0)
+ acpi_old_suspend_ordering();
str = strchr(str, ',');
if (str != NULL)
str += strspn(str, ", \t");
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 75cb5da4ea0..bf9b441331e 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -1213,9 +1213,9 @@ static int suspend(int vetoable)
if (err != APM_SUCCESS)
apm_error("suspend", err);
err = (err == APM_SUCCESS) ? 0 : -EIO;
- device_power_up();
+ device_power_up(PMSG_RESUME);
local_irq_enable();
- device_resume();
+ device_resume(PMSG_RESUME);
queue_event(APM_NORMAL_RESUME, NULL);
spin_lock(&user_list_lock);
for (as = user_list; as != NULL; as = as->next) {
@@ -1240,7 +1240,7 @@ static void standby(void)
apm_error("standby", err);
local_irq_disable();
- device_power_up();
+ device_power_up(PMSG_RESUME);
local_irq_enable();
}
@@ -1326,7 +1326,7 @@ static void check_events(void)
ignore_bounce = 1;
if ((event != APM_NORMAL_RESUME)
|| (ignore_normal_resume == 0)) {
- device_resume();
+ device_resume(PMSG_RESUME);
queue_event(event, NULL);
}
ignore_normal_resume = 0;
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index a4665f37cfc..a0e11c0cc87 100644
--- a/arch/x86/kernel/early-quirks.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -120,7 +120,18 @@ static struct chipset early_qrk[] __initdata = {
{}
};
-static void __init check_dev_quirk(int num, int slot, int func)
+/**
+ * check_dev_quirk - apply early quirks to a given PCI device
+ * @num: bus number
+ * @slot: slot number
+ * @func: PCI function
+ *
+ * Check the vendor & device ID against the early quirks table.
+ *
+ * If the device is single function, let early_quirks() know so we don't
+ * poke at this device again.
+ */
+static int __init check_dev_quirk(int num, int slot, int func)
{
u16 class;
u16 vendor;
@@ -131,7 +142,7 @@ static void __init check_dev_quirk(int num, int slot, int func)
class = read_pci_config_16(num, slot, func, PCI_CLASS_DEVICE);
if (class == 0xffff)
- return;
+ return -1; /* no class, treat as single function */
vendor = read_pci_config_16(num, slot, func, PCI_VENDOR_ID);
@@ -154,7 +165,9 @@ static void __init check_dev_quirk(int num, int slot, int func)
type = read_pci_config_byte(num, slot, func,
PCI_HEADER_TYPE);
if (!(type & 0x80))
- return;
+ return -1;
+
+ return 0;
}
void __init early_quirks(void)
@@ -167,6 +180,9 @@ void __init early_quirks(void)
/* Poor man's PCI discovery */
for (num = 0; num < 32; num++)
for (slot = 0; slot < 32; slot++)
- for (func = 0; func < 8; func++)
- check_dev_quirk(num, slot, func);
+ for (func = 0; func < 8; func++) {
+ /* Only probe function 0 on single fn devices */
+ if (check_dev_quirk(num, slot, func))
+ break;
+ }
}
diff --git a/arch/x86/kernel/numaq_32.c b/arch/x86/kernel/numaq_32.c
index 5b20a5e7ac2..a23e8233b9a 100644
--- a/arch/x86/kernel/numaq_32.c
+++ b/arch/x86/kernel/numaq_32.c
@@ -96,7 +96,7 @@ int __init get_memcfg_numaq(void)
void __init numaq_tsc_disable(void)
{
if (!found_numaq)
- return -1;
+ return;
if (num_online_nodes() > 1) {
printk(KERN_DEBUG "NUMAQ: disabling TSC\n");
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 7dceea94723..4d629c62f4f 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -7,6 +7,12 @@
#include <linux/module.h>
#include <linux/pm.h>
#include <linux/clockchips.h>
+#include <asm/system.h>
+
+unsigned long idle_halt;
+EXPORT_SYMBOL(idle_halt);
+unsigned long idle_nomwait;
+EXPORT_SYMBOL(idle_nomwait);
struct kmem_cache *task_xstate_cachep;
@@ -325,7 +331,27 @@ static int __init idle_setup(char *str)
pm_idle = poll_idle;
} else if (!strcmp(str, "mwait"))
force_mwait = 1;
- else
+ else if (!strcmp(str, "halt")) {
+ /*
+ * When the boot option of idle=halt is added, halt is
+ * forced to be used for CPU idle. In such case CPU C2/C3
+ * won't be used again.
+ * To continue to load the CPU idle driver, don't touch
+ * the boot_option_idle_override.
+ */
+ pm_idle = default_idle;
+ idle_halt = 1;
+ return 0;
+ } else if (!strcmp(str, "nomwait")) {
+ /*
+ * If the boot option of "idle=nomwait" is added,
+ * it means that mwait will be disabled for CPU C2/C3
+ * states. In such case it won't touch the variable
+ * of boot_option_idle_override.
+ */
+ idle_nomwait = 1;
+ return 0;
+ } else
return -1;
boot_option_idle_override = 1;
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 2ed504b97d4..c9010f82141 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -684,6 +684,11 @@ void __init setup_arch(char **cmdline_p)
clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
}
+#ifdef CONFIG_PCI
+ if (pci_early_dump_regs)
+ early_dump_pci_devices();
+#endif
+
finish_e820_parsing();
#ifdef CONFIG_X86_32
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 27de2435e00..306049edd55 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -644,7 +644,7 @@ static unsigned long __init kernel_physical_mapping_init(unsigned long start,
unsigned long pud_phys;
pud_t *pud;
- next = start + PGDIR_SIZE;
+ next = (start + PGDIR_SIZE) & PGDIR_MASK;
if (next > end)
next = end;
diff --git a/arch/x86/mm/srat_32.c b/arch/x86/mm/srat_32.c
index f41d67f8f83..1eb2973a301 100644
--- a/arch/x86/mm/srat_32.c
+++ b/arch/x86/mm/srat_32.c
@@ -156,10 +156,9 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *memory_affinity)
num_memory_chunks++;
- printk(KERN_DEBUG "Memory range %08lx to %08lx (type %x)"
+ printk(KERN_DEBUG "Memory range %08lx to %08lx"
" in proximity domain %02x %s\n",
start_pfn, end_pfn,
- memory_affinity->memory_type,
pxm,
((memory_affinity->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) ?
"enabled and removable" : "enabled" ) );
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 20b9f59f95d..b67732bbb85 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -20,6 +20,7 @@
unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
PCI_PROBE_MMCONF;
+unsigned int pci_early_dump_regs;
static int pci_bf_sort;
int pci_routeirq;
int pcibios_last_bus = -1;
@@ -31,7 +32,7 @@ struct pci_raw_ops *raw_pci_ext_ops;
int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
int reg, int len, u32 *val)
{
- if (reg < 256 && raw_pci_ops)
+ if (domain == 0 && reg < 256 && raw_pci_ops)
return raw_pci_ops->read(domain, bus, devfn, reg, len, val);
if (raw_pci_ext_ops)
return raw_pci_ext_ops->read(domain, bus, devfn, reg, len, val);
@@ -41,7 +42,7 @@ int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
int reg, int len, u32 val)
{
- if (reg < 256 && raw_pci_ops)
+ if (domain == 0 && reg < 256 && raw_pci_ops)
return raw_pci_ops->write(domain, bus, devfn, reg, len, val);
if (raw_pci_ext_ops)
return raw_pci_ext_ops->write(domain, bus, devfn, reg, len, val);
@@ -121,6 +122,21 @@ void __init dmi_check_skip_isa_align(void)
dmi_check_system(can_skip_pciprobe_dmi_table);
}
+static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
+{
+ struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE];
+
+ if (pci_probe & PCI_NOASSIGN_ROMS) {
+ if (rom_r->parent)
+ return;
+ if (rom_r->start) {
+ /* we deal with BIOS assigned ROM later */
+ return;
+ }
+ rom_r->start = rom_r->end = rom_r->flags = 0;
+ }
+}
+
/*
* Called after each bus is probed, but before its children
* are examined.
@@ -128,7 +144,11 @@ void __init dmi_check_skip_isa_align(void)
void __devinit pcibios_fixup_bus(struct pci_bus *b)
{
+ struct pci_dev *dev;
+
pci_read_bridge_bases(b);
+ list_for_each_entry(dev, &b->devices, bus_list)
+ pcibios_fixup_device_resources(dev);
}
/*
@@ -481,12 +501,18 @@ char * __devinit pcibios_setup(char *str)
else if (!strcmp(str, "rom")) {
pci_probe |= PCI_ASSIGN_ROMS;
return NULL;
+ } else if (!strcmp(str, "norom")) {
+ pci_probe |= PCI_NOASSIGN_ROMS;
+ return NULL;
} else if (!strcmp(str, "assign-busses")) {
pci_probe |= PCI_ASSIGN_ALL_BUSSES;
return NULL;
} else if (!strcmp(str, "use_crs")) {
pci_probe |= PCI_USE__CRS;
return NULL;
+ } else if (!strcmp(str, "earlydump")) {
+ pci_early_dump_regs = 1;
+ return NULL;
} else if (!strcmp(str, "routeirq")) {
pci_routeirq = 1;
return NULL;
diff --git a/arch/x86/pci/early.c b/arch/x86/pci/early.c
index 42df4b6606d..858dbe3399f 100644
--- a/arch/x86/pci/early.c
+++ b/arch/x86/pci/early.c
@@ -49,7 +49,14 @@ void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val)
{
PDprintk("%x writing to %x: %x\n", slot, offset, val);
outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
- outb(val, 0xcfc);
+ outb(val, 0xcfc + (offset&3));
+}
+
+void write_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset, u16 val)
+{
+ PDprintk("%x writing to %x: %x\n", slot, offset, val);
+ outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
+ outw(val, 0xcfc + (offset&2));
}
int early_pci_allowed(void)
@@ -57,3 +64,54 @@ int early_pci_allowed(void)
return (pci_probe & (PCI_PROBE_CONF1|PCI_PROBE_NOEARLY)) ==
PCI_PROBE_CONF1;
}
+
+void early_dump_pci_device(u8 bus, u8 slot, u8 func)
+{
+ int i;
+ int j;
+ u32 val;
+
+ printk("PCI: %02x:%02x:%02x", bus, slot, func);
+
+ for (i = 0; i < 256; i += 4) {
+ if (!(i & 0x0f))
+ printk("\n%04x:",i);
+
+ val = read_pci_config(bus, slot, func, i);
+ for (j = 0; j < 4; j++) {
+ printk(" %02x", val & 0xff);
+ val >>= 8;
+ }
+ }
+ printk("\n");
+}
+
+void early_dump_pci_devices(void)
+{
+ unsigned bus, slot, func;
+
+ if (!early_pci_allowed())
+ return;
+
+ for (bus = 0; bus < 256; bus++) {
+ for (slot = 0; slot < 32; slot++) {
+ for (func = 0; func < 8; func++) {
+ u32 class;
+ u8 type;
+ class = read_pci_config(bus, slot, func,
+ PCI_CLASS_REVISION);
+ if (class == 0xffffffff)
+ break;
+
+ early_dump_pci_device(bus, slot, func);
+
+ /* No multi-function device? */
+ type = read_pci_config_byte(bus, slot, func,
+ PCI_HEADER_TYPE);
+ if (!(type & 0x80))
+ break;
+ }
+ }
+ }
+}
+
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index dc568c6b83f..6a06a2eb059 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -45,7 +45,8 @@ struct irq_router {
char *name;
u16 vendor, device;
int (*get)(struct pci_dev *router, struct pci_dev *dev, int pirq);
- int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new);
+ int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq,
+ int new);
};
struct irq_router_handler {
@@ -77,7 +78,8 @@ static inline struct irq_routing_table *pirq_check_routing_table(u8 *addr)
for (i = 0; i < rt->size; i++)
sum += addr[i];
if (!sum) {
- DBG(KERN_DEBUG "PCI: Interrupt Routing Table found at 0x%p\n", rt);
+ DBG(KERN_DEBUG "PCI: Interrupt Routing Table found at 0x%p\n",
+ rt);
return rt;
}
return NULL;
@@ -183,7 +185,8 @@ static unsigned int read_config_nybble(struct pci_dev *router, unsigned offset,
return (nr & 1) ? (x >> 4) : (x & 0xf);
}
-static void write_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr, unsigned int val)
+static void write_config_nybble(struct pci_dev *router, unsigned offset,
+ unsigned nr, unsigned int val)
{
u8 x;
unsigned reg = offset + (nr >> 1);
@@ -467,7 +470,8 @@ static int pirq_serverworks_get(struct pci_dev *router, struct pci_dev *dev, int
return inb(0xc01) & 0xf;
}
-static int pirq_serverworks_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+static int pirq_serverworks_set(struct pci_dev *router, struct pci_dev *dev,
+ int pirq, int irq)
{
outb(pirq, 0xc00);
outb(irq, 0xc01);
@@ -660,7 +664,8 @@ static __init int vlsi_router_probe(struct irq_router *r, struct pci_dev *router
}
-static __init int serverworks_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+static __init int serverworks_router_probe(struct irq_router *r,
+ struct pci_dev *router, u16 device)
{
switch (device) {
case PCI_DEVICE_ID_SERVERWORKS_OSB4:
@@ -827,10 +832,12 @@ static void __init pirq_find_router(struct irq_router *r)
for (h = pirq_routers; h->vendor; h++) {
/* First look for a router match */
- if (rt->rtr_vendor == h->vendor && h->probe(r, pirq_router_dev, rt->rtr_device))
+ if (rt->rtr_vendor == h->vendor &&
+ h->probe(r, pirq_router_dev, rt->rtr_device))
break;
/* Fall back to a device match */
- if (pirq_router_dev->vendor == h->vendor && h->probe(r, pirq_router_dev, pirq_router_dev->device))
+ if (pirq_router_dev->vendor == h->vendor &&
+ h->probe(r, pirq_router_dev, pirq_router_dev->device))
break;
}
printk(KERN_INFO "PCI: Using IRQ router %s [%04x/%04x] at %s\n",
@@ -845,11 +852,13 @@ static void __init pirq_find_router(struct irq_router *r)
static struct irq_info *pirq_get_info(struct pci_dev *dev)
{
struct irq_routing_table *rt = pirq_table;
- int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
+ int entries = (rt->size - sizeof(struct irq_routing_table)) /
+ sizeof(struct irq_info);
struct irq_info *info;
for (info = rt->slots; entries--; info++)
- if (info->bus == dev->bus->number && PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn))
+ if (info->bus == dev->bus->number &&
+ PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn))
return info;
return NULL;
}
@@ -890,7 +899,8 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
DBG(" -> not routed\n" KERN_DEBUG);
return 0;
}
- DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs);
+ DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask,
+ pirq_table->exclusive_irqs);
mask &= pcibios_irq_mask;
/* Work around broken HP Pavilion Notebooks which assign USB to
@@ -903,7 +913,8 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
}
/* same for Acer Travelmate 360, but with CB and irq 11 -> 10 */
- if (acer_tm360_irqrouting && dev->irq == 11 && dev->vendor == PCI_VENDOR_ID_O2) {
+ if (acer_tm360_irqrouting && dev->irq == 11 &&
+ dev->vendor == PCI_VENDOR_ID_O2) {
pirq = 0x68;
mask = 0x400;
dev->irq = r->get(pirq_router_dev, dev, pirq);
@@ -920,15 +931,16 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
newirq = 0;
else
printk("\n" KERN_WARNING
- "PCI: IRQ %i for device %s doesn't match PIRQ mask "
- "- try pci=usepirqmask\n" KERN_DEBUG, newirq,
- pci_name(dev));
+ "PCI: IRQ %i for device %s doesn't match PIRQ mask - try pci=usepirqmask\n"
+ KERN_DEBUG, newirq,
+ pci_name(dev));
}
if (!newirq && assign) {
for (i = 0; i < 16; i++) {
if (!(mask & (1 << i)))
continue;
- if (pirq_penalty[i] < pirq_penalty[newirq] && can_request_irq(i, IRQF_SHARED))
+ if (pirq_penalty[i] < pirq_penalty[newirq] &&
+ can_request_irq(i, IRQF_SHARED))
newirq = i;
}
}
@@ -944,7 +956,8 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
DBG(" -> got IRQ %d\n", irq);
msg = "Found";
eisa_set_level_irq(irq);
- } else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
+ } else if (newirq && r->set &&
+ (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
DBG(" -> assigning IRQ %d", newirq);
if (r->set(pirq_router_dev, dev, pirq, newirq)) {
eisa_set_level_irq(newirq);
@@ -962,7 +975,8 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
} else
return 0;
}
- printk(KERN_INFO "PCI: %s IRQ %d for device %s\n", msg, irq, pci_name(dev));
+ printk(KERN_INFO "PCI: %s IRQ %d for device %s\n", msg, irq,
+ pci_name(dev));
/* Update IRQ for all devices with the same pirq value */
while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) {
@@ -974,7 +988,10 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
if (!info)
continue;
if (info->irq[pin].link == pirq) {
- /* We refuse to override the dev->irq information. Give a warning! */
+ /*
+ * We refuse to override the dev->irq
+ * information. Give a warning!
+ */
if (dev2->irq && dev2->irq != irq && \
(!(pci_probe & PCI_USE_PIRQ_MASK) || \
((1 << dev2->irq) & mask))) {
@@ -987,7 +1004,9 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
dev2->irq = irq;
pirq_penalty[irq]++;
if (dev != dev2)
- printk(KERN_INFO "PCI: Sharing IRQ %d with %s\n", irq, pci_name(dev2));
+ printk(KERN_INFO
+ "PCI: Sharing IRQ %d with %s\n",
+ irq, pci_name(dev2));
}
}
return 1;
@@ -1001,15 +1020,21 @@ static void __init pcibios_fixup_irqs(void)
DBG(KERN_DEBUG "PCI: IRQ fixup\n");
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
/*
- * If the BIOS has set an out of range IRQ number, just ignore it.
- * Also keep track of which IRQ's are already in use.
+ * If the BIOS has set an out of range IRQ number, just
+ * ignore it. Also keep track of which IRQ's are
+ * already in use.
*/
if (dev->irq >= 16) {
- DBG(KERN_DEBUG "%s: ignoring bogus IRQ %d\n", pci_name(dev), dev->irq);
+ DBG(KERN_DEBUG "%s: ignoring bogus IRQ %d\n",
+ pci_name(dev), dev->irq);
dev->irq = 0;
}
- /* If the IRQ is already assigned to a PCI device, ignore its ISA use penalty */
- if (pirq_penalty[dev->irq] >= 100 && pirq_penalty[dev->irq] < 100000)
+ /*
+ * If the IRQ is already assigned to a PCI device,
+ * ignore its ISA use penalty
+ */
+ if (pirq_penalty[dev->irq] >= 100 &&
+ pirq_penalty[dev->irq] < 100000)
pirq_penalty[dev->irq] = 0;
pirq_penalty[dev->irq]++;
}
@@ -1025,8 +1050,13 @@ static void __init pcibios_fixup_irqs(void)
int irq;
if (pin) {
- pin--; /* interrupt pins are numbered starting from 1 */
- irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
+ /*
+ * interrupt pins are numbered starting
+ * from 1
+ */
+ pin--;
+ irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
+ PCI_SLOT(dev->devfn), pin);
/*
* Busses behind bridges are typically not listed in the MP-table.
* In this case we have to look up the IRQ based on the parent bus,
@@ -1067,7 +1097,8 @@ static int __init fix_broken_hp_bios_irq9(const struct dmi_system_id *d)
{
if (!broken_hp_bios_irq9) {
broken_hp_bios_irq9 = 1;
- printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
+ printk(KERN_INFO "%s detected - fixing broken IRQ routing\n",
+ d->ident);
}
return 0;
}
@@ -1080,7 +1111,8 @@ static int __init fix_acer_tm360_irqrouting(const struct dmi_system_id *d)
{
if (!acer_tm360_irqrouting) {
acer_tm360_irqrouting = 1;
- printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
+ printk(KERN_INFO "%s detected - fixing broken IRQ routing\n",
+ d->ident);
}
return 0;
}
@@ -1092,7 +1124,8 @@ static struct dmi_system_id __initdata pciirq_dmi_table[] = {
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
DMI_MATCH(DMI_BIOS_VERSION, "GE.M1.03"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"),
+ DMI_MATCH(DMI_PRODUCT_VERSION,
+ "HP Pavilion Notebook Model GE"),
DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"),
},
},
@@ -1131,7 +1164,10 @@ int __init pcibios_irq_init(void)
if (!(pirq_table->exclusive_irqs & (1 << i)))
pirq_penalty[i] += 100;
}
- /* If we're using the I/O APIC, avoid using the PCI IRQ routing table */
+ /*
+ * If we're using the I/O APIC, avoid using the PCI IRQ
+ * routing table
+ */
if (io_apic_assign_pci_irqs)
pirq_table = NULL;
}
@@ -1175,7 +1211,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
char *msg = "";
- pin--; /* interrupt pins are numbered starting from 1 */
+ pin--; /* interrupt pins are numbered starting from 1 */
if (io_apic_assign_pci_irqs) {
int irq;
@@ -1195,13 +1231,16 @@ static int pirq_enable_irq(struct pci_dev *dev)
irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
PCI_SLOT(bridge->devfn), pin);
if (irq >= 0)
- printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n",
- pci_name(bridge), 'A' + pin, irq);
+ printk(KERN_WARNING
+ "PCI: using PPB %s[%c] to get irq %d\n",
+ pci_name(bridge),
+ 'A' + pin, irq);
dev = bridge;
}
dev = temp_dev;
if (irq >= 0) {
- printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
+ printk(KERN_INFO
+ "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
pci_name(dev), 'A' + pin, irq);
dev->irq = irq;
return 0;
@@ -1212,12 +1251,17 @@ static int pirq_enable_irq(struct pci_dev *dev)
else
msg = " Please try using pci=biosirq.";
- /* With IDE legacy devices the IRQ lookup failure is not a problem.. */
- if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5))
+ /*
+ * With IDE legacy devices the IRQ lookup failure is not
+ * a problem..
+ */
+ if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE &&
+ !(dev->class & 0x5))
return 0;
- printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
- 'A' + pin, pci_name(dev), msg);
+ printk(KERN_WARNING
+ "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
+ 'A' + pin, pci_name(dev), msg);
}
return 0;
}
diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h
index b2270a55b0c..3e25deb821a 100644
--- a/arch/x86/pci/pci.h
+++ b/arch/x86/pci/pci.h
@@ -28,6 +28,7 @@
#define PCI_USE__CRS 0x10000
#define PCI_CHECK_ENABLE_AMD_MMCONF 0x20000
#define PCI_HAS_IO_ECS 0x40000
+#define PCI_NOASSIGN_ROMS 0x80000
extern unsigned int pci_probe;
extern unsigned long pirq_table_addr;
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index bba867391a8..735f5ea1747 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -336,6 +336,15 @@ config ACPI_EC
the battery and thermal drivers. If you are compiling for a
mobile system, say Y.
+config ACPI_PCI_SLOT
+ tristate "PCI slot detection driver"
+ default n
+ help
+ This driver will attempt to discover all PCI slots in your system,
+ and creates entries in /sys/bus/pci/slots/. This feature can
+ help you correlate PCI bus addresses with the physical geography
+ of your slots. If you are unsure, say N.
+
config ACPI_POWER
bool
default y
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 40b0fcae4c7..52a4cd4b81d 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -21,7 +21,7 @@ obj-$(CONFIG_X86) += blacklist.o
#
# ACPI Core Subsystem (Interpreter)
#
-obj-y += osl.o utils.o \
+obj-y += osl.o utils.o reboot.o\
dispatcher/ events/ executer/ hardware/ \
namespace/ parser/ resources/ tables/ \
utilities/
@@ -48,6 +48,7 @@ obj-$(CONFIG_ACPI_DOCK) += dock.o
obj-$(CONFIG_ACPI_BAY) += bay.o
obj-$(CONFIG_ACPI_VIDEO) += video.o
obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o
+obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o
obj-$(CONFIG_ACPI_POWER) += power.o
obj-$(CONFIG_ACPI_PROCESSOR) += processor.o
obj-$(CONFIG_ACPI_CONTAINER) += container.o
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c
index 61b6c5beb2d..e6caf5d42e0 100644
--- a/drivers/acpi/bay.c
+++ b/drivers/acpi/bay.c
@@ -380,6 +380,9 @@ static int __init bay_init(void)
if (acpi_disabled)
return -ENODEV;
+ if (acpi_disabled)
+ return -ENODEV;
+
/* look for dockable drive bays */
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, find_bay, &bays, NULL);
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index a6dbcf4d9ef..ccae305ee55 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -295,6 +295,28 @@ int acpi_bus_set_power(acpi_handle handle, int state)
EXPORT_SYMBOL(acpi_bus_set_power);
+bool acpi_bus_power_manageable(acpi_handle handle)
+{
+ struct acpi_device *device;
+ int result;
+
+ result = acpi_bus_get_device(handle, &device);
+ return result ? false : device->flags.power_manageable;
+}
+
+EXPORT_SYMBOL(acpi_bus_power_manageable);
+
+bool acpi_bus_can_wakeup(acpi_handle handle)
+{
+ struct acpi_device *device;
+ int result;
+
+ result = acpi_bus_get_device(handle, &device);
+ return result ? false : device->wakeup.flags.valid;
+}
+
+EXPORT_SYMBOL(acpi_bus_can_wakeup);
+
/* --------------------------------------------------------------------------
Event Management
-------------------------------------------------------------------------- */
@@ -612,7 +634,7 @@ static int __init acpi_bus_init_irq(void)
return 0;
}
-acpi_native_uint acpi_gbl_permanent_mmap;
+u8 acpi_gbl_permanent_mmap;
void __init acpi_early_init(void)
diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c
index 610b1ee102b..949f7c75029 100644
--- a/drivers/acpi/dispatcher/dsinit.c
+++ b/drivers/acpi/dispatcher/dsinit.c
@@ -151,7 +151,7 @@ acpi_ds_init_one_object(acpi_handle obj_handle,
******************************************************************************/
acpi_status
-acpi_ds_initialize_objects(acpi_native_uint table_index,
+acpi_ds_initialize_objects(u32 table_index,
struct acpi_namespace_node * start_node)
{
acpi_status status;
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index 2509809a36c..4613b9ca579 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -377,7 +377,6 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
}
info->parameters = &this_walk_state->operands[0];
- info->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/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
index a818e0ddb99..6a81c4400ed 100644
--- a/drivers/acpi/dispatcher/dsopcode.c
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -691,12 +691,6 @@ acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
status = acpi_ex_resolve_operands(op->common.aml_opcode,
ACPI_WALK_OPERANDS, walk_state);
-
- ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
- acpi_ps_get_opcode_name(op->common.aml_opcode),
- walk_state->num_operands,
- "after AcpiExResolveOperands");
-
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)",
acpi_ps_get_opcode_name(op->common.aml_opcode),
@@ -785,10 +779,6 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
return_ACPI_STATUS(status);
}
- ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
- acpi_ps_get_opcode_name(op->common.aml_opcode),
- 1, "after AcpiExResolveOperands");
-
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
return_ACPI_STATUS(AE_NOT_EXIST);
@@ -848,7 +838,7 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
union acpi_operand_object **operand;
struct acpi_namespace_node *node;
union acpi_parse_object *next_op;
- acpi_native_uint table_index;
+ u32 table_index;
struct acpi_table_header *table;
ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op);
@@ -882,10 +872,6 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
return_ACPI_STATUS(status);
}
- ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
- acpi_ps_get_opcode_name(op->common.aml_opcode),
- 1, "after AcpiExResolveOperands");
-
operand = &walk_state->operands[0];
/* Find the ACPI table */
@@ -1091,10 +1077,8 @@ acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state,
return_ACPI_STATUS(status);
}
- ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
- acpi_ps_get_opcode_name(op->common.aml_opcode),
- 1, "after AcpiExResolveOperands");
-
+ ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS,
+ acpi_ps_get_opcode_name(op->common.aml_opcode), 1);
/*
* Get the bank_value operand and save it
* (at Top of stack)
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c
index b246b9657ea..b5072fa9c92 100644
--- a/drivers/acpi/dispatcher/dswexec.c
+++ b/drivers/acpi/dispatcher/dswexec.c
@@ -408,14 +408,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
[walk_state->
num_operands - 1]),
walk_state);
- if (ACPI_SUCCESS(status)) {
- ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS,
- ACPI_IMODE_EXECUTE,
- acpi_ps_get_opcode_name
- (walk_state->opcode),
- walk_state->num_operands,
- "after ExResolveOperands");
- }
}
if (ACPI_SUCCESS(status)) {
diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c
index 1386ced332e..b00d4af791a 100644
--- a/drivers/acpi/dispatcher/dswstate.c
+++ b/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)
{
- acpi_native_uint index;
+ u32 index;
union acpi_generic_state *state;
acpi_status status;
@@ -122,7 +122,7 @@ acpi_ds_result_pop(union acpi_operand_object **object,
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Obj=%p [%s] Index=%X State=%p Num=%X\n", *object,
acpi_ut_get_object_type_name(*object),
- (u32) index, walk_state, walk_state->result_count));
+ index, walk_state, walk_state->result_count));
return (AE_OK);
}
@@ -146,7 +146,7 @@ acpi_ds_result_push(union acpi_operand_object * object,
{
union acpi_generic_state *state;
acpi_status status;
- acpi_native_uint index;
+ u32 index;
ACPI_FUNCTION_NAME(ds_result_push);
@@ -400,7 +400,7 @@ void
acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
struct acpi_walk_state *walk_state)
{
- acpi_native_int i;
+ s32 i;
union acpi_operand_object *obj_desc;
ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete);
@@ -409,7 +409,7 @@ acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
return;
}
- for (i = (acpi_native_int) (pop_count - 1); i >= 0; i--) {
+ for (i = (s32) pop_count - 1; i >= 0; i--) {
if (walk_state->num_operands == 0) {
return;
}
@@ -615,14 +615,8 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
walk_state->pass_number = pass_number;
if (info) {
- if (info->parameter_type == ACPI_PARAM_GPE) {
- walk_state->gpe_event_info =
- ACPI_CAST_PTR(struct acpi_gpe_event_info,
- info->parameters);
- } else {
- walk_state->params = info->parameters;
- walk_state->caller_return_desc = &info->return_object;
- }
+ walk_state->params = info->parameters;
+ walk_state->caller_return_desc = &info->return_object;
}
status = acpi_ps_init_scope(&walk_state->parser_state, op);
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index bb7c51f712b..1e872e79db3 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -920,6 +920,9 @@ static int __init dock_init(void)
if (acpi_disabled)
return 0;
+ if (acpi_disabled)
+ return 0;
+
/* look for a dock station */
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, find_dock, &num, NULL);
diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c
index 5d30e5be1b1..c56c5c6ea77 100644
--- a/drivers/acpi/events/evevent.c
+++ b/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)
{
- acpi_native_uint i;
+ u32 i;
acpi_status status;
/*
@@ -231,7 +231,7 @@ u32 acpi_ev_fixed_event_detect(void)
u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
u32 fixed_status;
u32 fixed_enable;
- acpi_native_uint i;
+ u32 i;
ACPI_FUNCTION_NAME(ev_fixed_event_detect);
@@ -260,7 +260,7 @@ u32 acpi_ev_fixed_event_detect(void)
/* Found an active (signalled) event */
acpi_os_fixed_event_count(i);
- int_status |= acpi_ev_fixed_event_dispatch((u32) i);
+ int_status |= acpi_ev_fixed_event_dispatch(i);
}
}
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
index 5354be44f87..c5e53aae86f 100644
--- a/drivers/acpi/events/evgpe.c
+++ b/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);
}
- /* Mark wake-disabled or HW disable, or both */
+ /* Clear the appropriate enabled flags for this GPE */
switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
case ACPI_GPE_TYPE_WAKE:
@@ -273,13 +273,23 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
/* Disable the requested runtime GPE */
ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
-
- /* fallthrough */
+ break;
default:
- acpi_hw_write_gpe_enable_reg(gpe_event_info);
+ break;
}
+ /*
+ * Even if we don't know the GPE type, make sure that we always
+ * disable it. low_disable_gpe will just clear the enable bit for this
+ * GPE and write it. It will not write out the current GPE enable mask,
+ * since this may inadvertently enable GPEs too early, if a rogue GPE has
+ * come in during ACPICA initialization - possibly as a result of AML or
+ * other code that has enabled the GPE.
+ */
+ status = acpi_hw_low_disable_gpe(gpe_event_info);
+ return_ACPI_STATUS(status);
+
return_ACPI_STATUS(AE_OK);
}
@@ -305,7 +315,7 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
{
union acpi_operand_object *obj_desc;
struct acpi_gpe_block_info *gpe_block;
- acpi_native_uint i;
+ u32 i;
ACPI_FUNCTION_ENTRY();
@@ -379,8 +389,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
u32 status_reg;
u32 enable_reg;
acpi_cpu_flags flags;
- acpi_native_uint i;
- acpi_native_uint j;
+ u32 i;
+ u32 j;
ACPI_FUNCTION_NAME(ev_gpe_detect);
@@ -462,13 +472,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
*/
int_status |=
acpi_ev_gpe_dispatch(&gpe_block->
- event_info[(i *
- ACPI_GPE_REGISTER_WIDTH)
- +
- j],
- (u32) j +
- gpe_register_info->
- base_gpe_number);
+ event_info[((acpi_size) i * ACPI_GPE_REGISTER_WIDTH) + j], j + gpe_register_info->base_gpe_number);
}
}
}
@@ -555,10 +559,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
*/
info->prefix_node =
local_gpe_event_info.dispatch.method_node;
- info->parameters =
- ACPI_CAST_PTR(union acpi_operand_object *,
- gpe_event_info);
- info->parameter_type = ACPI_PARAM_GPE;
info->flags = ACPI_IGNORE_RETURN_VALUE;
status = acpi_ns_evaluate(info);
diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c
index e6c4d4c49e7..73c058e2f5c 100644
--- a/drivers/acpi/events/evgpeblk.c
+++ b/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;
- acpi_native_uint i;
- acpi_native_uint j;
+ u32 i;
+ u32 j;
ACPI_FUNCTION_TRACE(ev_delete_gpe_handlers);
@@ -203,7 +203,8 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
gpe_event_info =
&gpe_block->
- event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
+ event_info[((acpi_size) i *
+ ACPI_GPE_REGISTER_WIDTH) + j];
if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
ACPI_GPE_DISPATCH_HANDLER) {
@@ -744,8 +745,8 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
struct acpi_gpe_event_info *gpe_event_info = NULL;
struct acpi_gpe_event_info *this_event;
struct acpi_gpe_register_info *this_register;
- acpi_native_uint i;
- acpi_native_uint j;
+ u32 i;
+ u32 j;
acpi_status status;
ACPI_FUNCTION_TRACE(ev_create_gpe_info_blocks);
@@ -983,8 +984,8 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
struct acpi_gpe_walk_info gpe_info;
u32 wake_gpe_count;
u32 gpe_enabled_count;
- acpi_native_uint i;
- acpi_native_uint j;
+ u32 i;
+ u32 j;
ACPI_FUNCTION_TRACE(ev_initialize_gpe_block);
@@ -1033,7 +1034,8 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
gpe_event_info =
&gpe_block->
- event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
+ event_info[((acpi_size) i *
+ ACPI_GPE_REGISTER_WIDTH) + j];
if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
ACPI_GPE_DISPATCH_METHOD)
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index 2113e58e222..1d5670be729 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -575,7 +575,7 @@ acpi_status acpi_ev_release_global_lock(void)
void acpi_ev_terminate(void)
{
- acpi_native_uint i;
+ u32 i;
acpi_status status;
ACPI_FUNCTION_TRACE(ev_terminate);
@@ -589,7 +589,7 @@ void acpi_ev_terminate(void)
/* Disable all fixed events */
for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
- status = acpi_disable_event((u32) i, 0);
+ status = acpi_disable_event(i, 0);
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO,
"Could not disable fixed event %d",
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c
index 1628f593475..236fbd1ca43 100644
--- a/drivers/acpi/events/evregion.c
+++ b/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;
- acpi_native_uint i;
+ u32 i;
ACPI_FUNCTION_TRACE(ev_install_region_handlers);
@@ -151,7 +151,7 @@ acpi_status acpi_ev_install_region_handlers(void)
acpi_status acpi_ev_initialize_op_regions(void)
{
acpi_status status;
- acpi_native_uint i;
+ u32 i;
ACPI_FUNCTION_TRACE(ev_initialize_op_regions);
@@ -219,7 +219,6 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
info->prefix_node = region_obj2->extra.method_REG;
info->pathname = NULL;
info->parameters = args;
- info->parameter_type = ACPI_PARAM_ARGS;
info->flags = ACPI_IGNORE_RETURN_VALUE;
/*
diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c
index 2e3d2c5e4f4..6b94b38df07 100644
--- a/drivers/acpi/events/evrgnini.c
+++ b/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;
- acpi_native_uint i;
+ u32 i;
/*
* Get the _HID and check for a PCI Root Bridge
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c
index 99a7502e6a8..73bfd6bf962 100644
--- a/drivers/acpi/events/evxfevnt.c
+++ b/drivers/acpi/events/evxfevnt.c
@@ -472,7 +472,6 @@ acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
}
ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
-#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
* FUNCTION: acpi_get_event_status
@@ -489,6 +488,7 @@ ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
{
acpi_status status = AE_OK;
+ u32 value;
ACPI_FUNCTION_TRACE(acpi_get_event_status);
@@ -506,7 +506,20 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
status =
acpi_get_register(acpi_gbl_fixed_event_info[event].
- status_register_id, event_status);
+ enable_register_id, &value);
+ if (ACPI_FAILURE(status))
+ return_ACPI_STATUS(status);
+
+ *event_status = value;
+
+ status =
+ acpi_get_register(acpi_gbl_fixed_event_info[event].
+ status_register_id, &value);
+ if (ACPI_FAILURE(status))
+ return_ACPI_STATUS(status);
+
+ if (value)
+ *event_status |= ACPI_EVENT_FLAG_SET;
return_ACPI_STATUS(status);
}
@@ -566,7 +579,6 @@ acpi_get_gpe_status(acpi_handle gpe_device,
}
ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
-#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
* FUNCTION: acpi_install_gpe_block
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
index 39d74219058..2a32c843cb4 100644
--- a/drivers/acpi/executer/exconfig.c
+++ b/drivers/acpi/executer/exconfig.c
@@ -53,7 +53,7 @@ ACPI_MODULE_NAME("exconfig")
/* Local prototypes */
static acpi_status
-acpi_ex_add_table(acpi_native_uint table_index,
+acpi_ex_add_table(u32 table_index,
struct acpi_namespace_node *parent_node,
union acpi_operand_object **ddb_handle);
@@ -73,7 +73,7 @@ acpi_ex_add_table(acpi_native_uint table_index,
******************************************************************************/
static acpi_status
-acpi_ex_add_table(acpi_native_uint table_index,
+acpi_ex_add_table(u32 table_index,
struct acpi_namespace_node *parent_node,
union acpi_operand_object **ddb_handle)
{
@@ -96,7 +96,8 @@ acpi_ex_add_table(acpi_native_uint table_index,
/* Install the new table into the local data structures */
- obj_desc->reference.object = ACPI_CAST_PTR(void, table_index);
+ obj_desc->reference.object = ACPI_CAST_PTR(void,
+ (unsigned long)table_index);
/* Add the table to the namespace */
@@ -128,12 +129,12 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
{
acpi_status status;
union acpi_operand_object **operand = &walk_state->operands[0];
- acpi_native_uint table_index;
struct acpi_namespace_node *parent_node;
struct acpi_namespace_node *start_node;
struct acpi_namespace_node *parameter_node = NULL;
union acpi_operand_object *ddb_handle;
struct acpi_table_header *table;
+ u32 table_index;
ACPI_FUNCTION_TRACE(ex_load_table_op);
@@ -280,7 +281,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
{
union acpi_operand_object *ddb_handle;
struct acpi_table_desc table_desc;
- acpi_native_uint table_index;
+ u32 table_index;
acpi_status status;
u32 length;
@@ -437,7 +438,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
{
acpi_status status = AE_OK;
union acpi_operand_object *table_desc = ddb_handle;
- acpi_native_uint table_index;
+ u32 table_index;
struct acpi_table_header *table;
ACPI_FUNCTION_TRACE(ex_unload_table);
@@ -454,9 +455,9 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- /* Get the table index from the ddb_handle */
+ /* Get the table index from the ddb_handle (acpi_size for 64-bit case) */
- table_index = (acpi_native_uint) table_desc->reference.object;
+ table_index = (u32) (acpi_size) table_desc->reference.object;
/* Invoke table handler if present */
diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c
index fd954b4ed83..261d97516d9 100644
--- a/drivers/acpi/executer/exconvrt.c
+++ b/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;
- acpi_native_uint i;
- acpi_native_uint j;
- acpi_native_uint k = 0;
- acpi_native_uint hex_length;
- acpi_native_uint decimal_length;
+ u32 i;
+ u32 j;
+ u32 k = 0;
+ u32 hex_length;
+ u32 decimal_length;
u32 remainder;
u8 supress_zeros;
@@ -348,7 +348,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer,
/* hex_length: 2 ascii hex chars per data byte */
- hex_length = (acpi_native_uint) ACPI_MUL_2(data_width);
+ hex_length = ACPI_MUL_2(data_width);
for (i = 0, j = (hex_length - 1); i < hex_length; i++, j--) {
/* Get one hex digit, most significant digits first */
diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c
index 60e62c4f057..ad09696d506 100644
--- a/drivers/acpi/executer/excreate.c
+++ b/drivers/acpi/executer/excreate.c
@@ -45,8 +45,6 @@
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
-#include <acpi/acevents.h>
-#include <acpi/actables.h>
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("excreate")
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
index 74f1b22601b..2be2e2bf95b 100644
--- a/drivers/acpi/executer/exdump.c
+++ b/drivers/acpi/executer/exdump.c
@@ -580,25 +580,22 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
case ACPI_TYPE_BUFFER:
- acpi_os_printf("Buffer len %X @ %p\n",
+ acpi_os_printf("Buffer length %.2X @ %p\n",
obj_desc->buffer.length,
obj_desc->buffer.pointer);
- length = obj_desc->buffer.length;
- if (length > 64) {
- length = 64;
- }
-
/* Debug only -- dump the buffer contents */
if (obj_desc->buffer.pointer) {
- acpi_os_printf("Buffer Contents: ");
-
- for (index = 0; index < length; index++) {
- acpi_os_printf(" %02x",
- obj_desc->buffer.pointer[index]);
+ length = obj_desc->buffer.length;
+ if (length > 128) {
+ length = 128;
}
- acpi_os_printf("\n");
+
+ acpi_os_printf
+ ("Buffer Contents: (displaying length 0x%.2X)\n",
+ length);
+ ACPI_DUMP_BUFFER(obj_desc->buffer.pointer, length);
}
break;
@@ -756,54 +753,42 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
*
* FUNCTION: acpi_ex_dump_operands
*
- * PARAMETERS: Operands - Operand list
- * interpreter_mode - Load or Exec
- * Ident - Identification
- * num_levels - # of stack entries to dump above line
- * Note - Output notation
- * module_name - Caller's module name
- * line_number - Caller's invocation line number
+ * PARAMETERS: Operands - A list of Operand objects
+ * opcode_name - AML opcode name
+ * num_operands - Operand count for this opcode
*
- * DESCRIPTION: Dump the object stack
+ * DESCRIPTION: Dump the operands associated with the opcode
*
******************************************************************************/
void
acpi_ex_dump_operands(union acpi_operand_object **operands,
- acpi_interpreter_mode interpreter_mode,
- char *ident,
- u32 num_levels,
- char *note, char *module_name, u32 line_number)
+ const char *opcode_name, u32 num_operands)
{
- acpi_native_uint i;
-
ACPI_FUNCTION_NAME(ex_dump_operands);
- if (!ident) {
- ident = "?";
- }
-
- if (!note) {
- note = "?";
+ if (!opcode_name) {
+ opcode_name = "UNKNOWN";
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "************* Operand Stack Contents (Opcode [%s], %d Operands)\n",
- ident, num_levels));
+ "**** Start operand dump for opcode [%s], %d operands\n",
+ opcode_name, num_operands));
- if (num_levels == 0) {
- num_levels = 1;
+ if (num_operands == 0) {
+ num_operands = 1;
}
- /* Dump the operand stack starting at the top */
+ /* Dump the individual operands */
- for (i = 0; num_levels > 0; i--, num_levels--) {
- acpi_ex_dump_operand(operands[i], 0);
+ while (num_operands) {
+ acpi_ex_dump_operand(*operands, 0);
+ operands++;
+ num_operands--;
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "************* Operand Stack dump from %s(%d), %s\n",
- module_name, line_number, note));
+ "**** End operand dump for [%s]\n", opcode_name));
return;
}
diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c
index e336b5dc7a5..9ff9d1f4615 100644
--- a/drivers/acpi/executer/exfldio.c
+++ b/drivers/acpi/executer/exfldio.c
@@ -153,14 +153,15 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
/*
* Slack mode only: We will go ahead and allow access to this
* field if it is within the region length rounded up to the next
- * access width boundary.
+ * access width boundary. acpi_size cast for 64-bit compile.
*/
if (ACPI_ROUND_UP(rgn_desc->region.length,
obj_desc->common_field.
access_byte_width) >=
- (obj_desc->common_field.base_byte_offset +
- (acpi_native_uint) obj_desc->common_field.
- access_byte_width + field_datum_byte_offset)) {
+ ((acpi_size) obj_desc->common_field.
+ base_byte_offset +
+ obj_desc->common_field.access_byte_width +
+ field_datum_byte_offset)) {
return_ACPI_STATUS(AE_OK);
}
}
diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c
index cc956a5b526..731414a581a 100644
--- a/drivers/acpi/executer/exmisc.c
+++ b/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/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c
index 3a2f8cd4c62..5d438c32989 100644
--- a/drivers/acpi/executer/exprep.c
+++ b/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 =
- ((union acpi_parse_object *)(info->data_register_node))->
- named.data;
+ ACPI_CAST_PTR(union acpi_parse_object,
+ info->data_register_node)->named.data;
second_desc->extra.aml_length =
- ((union acpi_parse_object *)(info->data_register_node))->
- named.length;
+ ACPI_CAST_PTR(union acpi_parse_object,
+ info->data_register_node)->named.length;
break;
diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c
index 7cd8bb54fa0..7a41c409ae4 100644
--- a/drivers/acpi/executer/exregion.c
+++ b/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_native_uint) address, window_size);
+ acpi_os_map_memory((acpi_physical_address) address, window_size);
if (!mem_info->mapped_logical_address) {
ACPI_ERROR((AE_INFO,
"Could not map memory at %8.8X%8.8X, size %X",
diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c
index 73e29e566a7..54085f16ec2 100644
--- a/drivers/acpi/executer/exresop.c
+++ b/drivers/acpi/executer/exresop.c
@@ -698,5 +698,9 @@ acpi_ex_resolve_operands(u16 opcode,
}
}
+ ACPI_DUMP_OPERANDS(walk_state->operands,
+ acpi_ps_get_opcode_name(opcode),
+ walk_state->num_operands);
+
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c
index 76c875bc315..38b55e35249 100644
--- a/drivers/acpi/executer/exstore.c
+++ b/drivers/acpi/executer/exstore.c
@@ -343,12 +343,6 @@ acpi_ex_store(union acpi_operand_object *source_desc,
acpi_ut_get_object_type_name(dest_desc),
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/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 6cf10cbc1ee..55c17afbe66 100644
--- a/drivers/acpi/fan.c
+++ b/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[12] = { '\0' };
+ char state_string[3] = { '\0' };
if (count > sizeof(state_string) - 1)
return -EINVAL;
@@ -157,6 +157,12 @@ acpi_fan_write_state(struct file *file, const char __user * buffer,
return -EFAULT;
state_string[count] = '\0';
+ if ((state_string[0] < '0') || (state_string[0] > '3'))
+ return -EINVAL;
+ if (state_string[1] == '\n')
+ state_string[1] = '\0';
+ if (state_string[1] != '\0')
+ return -EINVAL;
result = acpi_bus_set_power(device->handle,
simple_strtoul(state_string, NULL, 0));
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 9b227d4dc9c..0f2dd81736b 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -166,6 +166,8 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
"firmware_node");
ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
"physical_node");
+ if (acpi_dev->wakeup.flags.valid)
+ device_set_wakeup_capable(dev, true);
}
return 0;
@@ -336,6 +338,9 @@ static int __init acpi_rtc_init(void)
if (acpi_disabled)
return 0;
+ if (acpi_disabled)
+ return 0;
+
if (dev) {
rtc_wake_setup();
rtc_info.wake_on = rtc_wake_on;
diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c
index 14bc4f456ae..0b80db9d919 100644
--- a/drivers/acpi/hardware/hwgpe.c
+++ b/drivers/acpi/hardware/hwgpe.c
@@ -55,6 +55,54 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
/******************************************************************************
*
+ * 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
*
* PARAMETERS: gpe_event_info - Info block for the GPE to be enabled
@@ -68,7 +116,7 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
******************************************************************************/
acpi_status
-acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info *gpe_event_info)
+acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)
{
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
@@ -138,7 +186,6 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
*
******************************************************************************/
-#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
acpi_event_status * event_status)
@@ -198,7 +245,6 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
unlock_and_exit:
return (status);
}
-#endif /* ACPI_FUTURE_USAGE */
/******************************************************************************
*
diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c
index 5445751b8a3..0ab22004728 100644
--- a/drivers/acpi/namespace/nsdump.c
+++ b/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)
{
- acpi_native_uint i;
+ u32 i;
ACPI_FUNCTION_NAME(ns_print_pathname);
@@ -515,12 +515,12 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
if (obj_type > ACPI_TYPE_LOCAL_MAX) {
acpi_os_printf
- ("(Ptr to ACPI Object type %X [UNKNOWN])\n",
+ ("(Pointer to ACPI Object type %.2X [UNKNOWN])\n",
obj_type);
bytes_to_dump = 32;
} else {
acpi_os_printf
- ("(Ptr to ACPI Object type %X [%s])\n",
+ ("(Pointer to ACPI Object type %.2X [%s])\n",
obj_type, acpi_ut_get_type_name(obj_type));
bytes_to_dump =
sizeof(union acpi_operand_object);
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
index 14bdfa92bea..d369164e00b 100644
--- a/drivers/acpi/namespace/nseval.c
+++ b/drivers/acpi/namespace/nseval.c
@@ -138,6 +138,41 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
return_ACPI_STATUS(AE_NULL_OBJECT);
}
+ /*
+ * 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/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
index 6d6d930c8e1..e4c57510d79 100644
--- a/drivers/acpi/namespace/nsinit.c
+++ b/drivers/acpi/namespace/nsinit.c
@@ -542,7 +542,6 @@ acpi_ns_init_one_device(acpi_handle obj_handle,
info->prefix_node = device_node;
info->pathname = METHOD_NAME__INI;
info->parameters = NULL;
- info->parameter_type = ACPI_PARAM_ARGS;
info->flags = ACPI_IGNORE_RETURN_VALUE;
/*
diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c
index 2c92f6cf5ce..a4a412b7c02 100644
--- a/drivers/acpi/namespace/nsload.c
+++ b/drivers/acpi/namespace/nsload.c
@@ -71,8 +71,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle);
******************************************************************************/
acpi_status
-acpi_ns_load_table(acpi_native_uint table_index,
- struct acpi_namespace_node *node)
+acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
{
acpi_status status;
diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c
index 46a79b0103b..a82271a9dbb 100644
--- a/drivers/acpi/namespace/nsparse.c
+++ b/drivers/acpi/namespace/nsparse.c
@@ -63,13 +63,13 @@ ACPI_MODULE_NAME("nsparse")
*
******************************************************************************/
acpi_status
-acpi_ns_one_complete_parse(acpi_native_uint pass_number,
- acpi_native_uint table_index,
- struct acpi_namespace_node * start_node)
+acpi_ns_one_complete_parse(u32 pass_number,
+ u32 table_index,
+ struct acpi_namespace_node *start_node)
{
union acpi_parse_object *parse_root;
acpi_status status;
- acpi_native_uint aml_length;
+ u32 aml_length;
u8 *aml_start;
struct acpi_walk_state *walk_state;
struct acpi_table_header *table;
@@ -112,8 +112,8 @@ acpi_ns_one_complete_parse(acpi_native_uint pass_number,
aml_start = (u8 *) table + sizeof(struct acpi_table_header);
aml_length = table->length - sizeof(struct acpi_table_header);
status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL,
- aml_start, (u32) aml_length,
- NULL, (u8) pass_number);
+ aml_start, aml_length, NULL,
+ (u8) pass_number);
}
if (ACPI_FAILURE(status)) {
@@ -158,8 +158,7 @@ acpi_ns_one_complete_parse(acpi_native_uint pass_number,
******************************************************************************/
acpi_status
-acpi_ns_parse_table(acpi_native_uint table_index,
- struct acpi_namespace_node *start_node)
+acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
{
acpi_status status;
diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c
index 64c039843ed..b0817e1127b 100644
--- a/drivers/acpi/namespace/nsutils.c
+++ b/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(char *module_name,
+acpi_ns_report_error(const char *module_name,
u32 line_number,
- char *internal_name, acpi_status lookup_status)
+ const char *internal_name, acpi_status lookup_status)
{
acpi_status status;
u32 bad_name;
@@ -130,11 +130,11 @@ acpi_ns_report_error(char *module_name,
******************************************************************************/
void
-acpi_ns_report_method_error(char *module_name,
+acpi_ns_report_method_error(const char *module_name,
u32 line_number,
- char *message,
+ const char *message,
struct acpi_namespace_node *prefix_node,
- char *path, acpi_status method_status)
+ const char *path, acpi_status method_status)
{
acpi_status status;
struct acpi_namespace_node *node = prefix_node;
@@ -167,7 +167,8 @@ acpi_ns_report_method_error(char *module_name,
******************************************************************************/
void
-acpi_ns_print_node_pathname(struct acpi_namespace_node *node, char *message)
+acpi_ns_print_node_pathname(struct acpi_namespace_node *node,
+ const char *message)
{
struct acpi_buffer buffer;
acpi_status status;
@@ -296,7 +297,7 @@ u32 acpi_ns_local(acpi_object_type type)
void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info)
{
- char *next_external_char;
+ const char *next_external_char;
u32 i;
ACPI_FUNCTION_ENTRY();
@@ -363,9 +364,9 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
{
u32 num_segments = info->num_segments;
char *internal_name = info->internal_name;
- char *external_name = info->next_external_char;
+ const char *external_name = info->next_external_char;
char *result = NULL;
- acpi_native_uint i;
+ u32 i;
ACPI_FUNCTION_TRACE(ns_build_internal_name);
@@ -400,12 +401,11 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
result = &internal_name[i];
} else if (num_segments == 2) {
internal_name[i] = AML_DUAL_NAME_PREFIX;
- result = &internal_name[(acpi_native_uint) (i + 1)];
+ result = &internal_name[(acpi_size) i + 1];
} else {
internal_name[i] = AML_MULTI_NAME_PREFIX_OP;
- internal_name[(acpi_native_uint) (i + 1)] =
- (char)num_segments;
- result = &internal_name[(acpi_native_uint) (i + 2)];
+ internal_name[(acpi_size) i + 1] = (char)num_segments;
+ result = &internal_name[(acpi_size) i + 2];
}
}
@@ -472,7 +472,8 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
*
*******************************************************************************/
-acpi_status acpi_ns_internalize_name(char *external_name, char **converted_name)
+acpi_status
+acpi_ns_internalize_name(const char *external_name, char **converted_name)
{
char *internal_name;
struct acpi_namestring_info info;
@@ -528,15 +529,15 @@ acpi_status acpi_ns_internalize_name(char *external_name, char **converted_name)
acpi_status
acpi_ns_externalize_name(u32 internal_name_length,
- char *internal_name,
+ const char *internal_name,
u32 * converted_name_length, char **converted_name)
{
- acpi_native_uint names_index = 0;
- acpi_native_uint num_segments = 0;
- acpi_native_uint required_length;
- acpi_native_uint prefix_length = 0;
- acpi_native_uint i = 0;
- acpi_native_uint j = 0;
+ u32 names_index = 0;
+ u32 num_segments = 0;
+ u32 required_length;
+ u32 prefix_length = 0;
+ u32 i = 0;
+ u32 j = 0;
ACPI_FUNCTION_TRACE(ns_externalize_name);
@@ -582,9 +583,8 @@ acpi_ns_externalize_name(u32 internal_name_length,
/* <count> 4-byte names */
names_index = prefix_length + 2;
- num_segments = (acpi_native_uint) (u8)
- internal_name[(acpi_native_uint)
- (prefix_length + 1)];
+ num_segments = (u8)
+ internal_name[(acpi_size) prefix_length + 1];
break;
case AML_DUAL_NAME_PREFIX:
@@ -823,7 +823,7 @@ u32 acpi_ns_opens_scope(acpi_object_type type)
acpi_status
acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
- char *pathname,
+ const char *pathname,
u32 flags, struct acpi_namespace_node **return_node)
{
union acpi_generic_state scope_info;
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
index a8d549187c8..38be5865d95 100644
--- a/drivers/acpi/namespace/nsxfeval.c
+++ b/drivers/acpi/namespace/nsxfeval.c
@@ -182,7 +182,6 @@ acpi_evaluate_object(acpi_handle handle,
}
info->pathname = pathname;
- info->parameter_type = ACPI_PARAM_ARGS;
/* Convert and validate the device handle */
@@ -442,7 +441,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
u32 flags;
struct acpica_device_id hid;
struct acpi_compatible_id_list *cid;
- acpi_native_uint i;
+ u32 i;
int found;
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 658e5f3abae..cb9864e39ba 100644
--- a/drivers/acpi/numa.c
+++ b/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 type 0x%x) in proximity domain %d %s%s\n",
+ "SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s\n",
(unsigned long)p->base_address,
(unsigned long)p->length,
- p->memory_type, p->proximity_domain,
+ p->proximity_domain,
(p->flags & ACPI_SRAT_MEM_ENABLED)?
"enabled" : "disabled",
(p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)?
diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c
index e9446377884..d830b29b85b 100644
--- a/drivers/acpi/parser/psargs.c
+++ b/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;
- acpi_native_uint byte_count;
+ u32 byte_count;
u8 byte_zero_mask = 0x3F; /* Default [0:5] */
ACPI_FUNCTION_TRACE(ps_get_next_package_length);
@@ -86,7 +86,7 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state)
* used to encode the package length, either 0,1,2, or 3
*/
byte_count = (aml[0] >> 6);
- parser_state->aml += (byte_count + 1);
+ parser_state->aml += ((acpi_size) byte_count + 1);
/* Get bytes 3, 2, 1 as needed */
diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c
index 52581454c47..270469aae84 100644
--- a/drivers/acpi/parser/psxface.c
+++ b/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)
{
- acpi_native_uint i;
+ u32 i;
- if ((info->parameter_type == ACPI_PARAM_ARGS) && (info->parameters)) {
+ if (info->parameters) {
/* Update reference count for each parameter */
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 89022a74fae..11acaee14d6 100644
--- a/drivers/acpi/pci_irq.c
+++ b/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[%c] connected to %s; "
+ "%04x:%02x:%02x PCI INT %c connected to %s; "
"changing to %s\n",
entry->id.segment, entry->id.bus,
entry->id.device, 'A' + entry->pin,
@@ -429,7 +429,7 @@ acpi_pci_irq_derive(struct pci_dev *dev,
{
struct pci_dev *bridge = dev;
int irq = -1;
- u8 bridge_pin = 0;
+ u8 bridge_pin = 0, orig_pin = pin;
if (!dev)
@@ -463,8 +463,8 @@ acpi_pci_irq_derive(struct pci_dev *dev,
}
if (irq < 0) {
- printk(KERN_WARNING PREFIX "Unable to derive IRQ for device %s\n",
- pci_name(dev));
+ dev_warn(&dev->dev, "can't derive routing for PCI INT %c\n",
+ 'A' + orig_pin);
return -1;
}
@@ -487,6 +487,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
int triggering = ACPI_LEVEL_SENSITIVE;
int polarity = ACPI_ACTIVE_LOW;
char *link = NULL;
+ char link_desc[16];
int rc;
@@ -503,7 +504,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
pin--;
if (!dev->bus) {
- printk(KERN_ERR PREFIX "Invalid (NULL) 'bus' field\n");
+ dev_err(&dev->dev, "invalid (NULL) 'bus' field\n");
return -ENODEV;
}
@@ -538,8 +539,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
* driver reported one, then use it. Exit in any case.
*/
if (irq < 0) {
- printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: no GSI",
- pci_name(dev), ('A' + pin));
+ dev_warn(&dev->dev, "PCI INT %c: no GSI", 'A' + pin);
/* Interrupt Line values above 0xF are forbidden */
if (dev->irq > 0 && (dev->irq <= 0xF)) {
printk(" - using IRQ %d\n", dev->irq);
@@ -554,21 +554,21 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
rc = acpi_register_gsi(irq, triggering, polarity);
if (rc < 0) {
- printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: failed "
- "to register GSI\n", pci_name(dev), ('A' + pin));
+ dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
+ 'A' + pin);
return rc;
}
dev->irq = rc;
- printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ",
- pci_name(dev), 'A' + pin);
-
if (link)
- printk("Link [%s] -> ", link);
+ snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link);
+ else
+ link_desc[0] = '\0';
- printk("GSI %u (%s, %s) -> IRQ %d\n", irq,
- (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
- (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
+ dev_info(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n",
+ 'A' + pin, link_desc, irq,
+ (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
+ (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
return 0;
}
@@ -616,10 +616,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
* (e.g. PCI_UNDEFINED_IRQ).
*/
- printk(KERN_INFO PREFIX "PCI interrupt for device %s disabled\n",
- pci_name(dev));
-
+ dev_info(&dev->dev, "PCI INT %c disabled\n", 'A' + pin);
acpi_unregister_gsi(gsi);
-
- return;
}
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c
new file mode 100644
index 00000000000..b9ab030a52d
--- /dev/null
+++ b/drivers/acpi/pci_slot.c
@@ -0,0 +1,368 @@
+/*
+ * pci_slot.c - ACPI PCI Slot Driver
+ *
+ * The code here is heavily leveraged from the acpiphp module.
+ * Thanks to Matthew Wilcox <matthew@wil.cx> for much guidance.
+ * Thanks to Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> for code
+ * review and fixes.
+ *
+ * Copyright (C) 2007 Alex Chiang <achiang@hp.com>
+ * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/acpi.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+static int debug;
+static int check_sta_before_sun;
+
+#define DRIVER_VERSION "0.1"
+#define DRIVER_AUTHOR "Alex Chiang <achiang@hp.com>"
+#define DRIVER_DESC "ACPI PCI Slot Detection Driver"
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
+module_param(debug, bool, 0644);
+
+#define _COMPONENT ACPI_PCI_COMPONENT
+ACPI_MODULE_NAME("pci_slot");
+
+#define MY_NAME "pci_slot"
+#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
+#define dbg(format, arg...) \
+ do { \
+ if (debug) \
+ printk(KERN_DEBUG "%s: " format, \
+ MY_NAME , ## arg); \
+ } while (0)
+
+#define SLOT_NAME_SIZE 20 /* Inspired by #define in acpiphp.h */
+
+struct acpi_pci_slot {
+ acpi_handle root_handle; /* handle of the root bridge */
+ struct pci_slot *pci_slot; /* corresponding pci_slot */
+ struct list_head list; /* node in the list of slots */
+};
+
+static int acpi_pci_slot_add(acpi_handle handle);
+static void acpi_pci_slot_remove(acpi_handle handle);
+
+static LIST_HEAD(slot_list);
+static DEFINE_MUTEX(slot_list_lock);
+static struct acpi_pci_driver acpi_pci_slot_driver = {
+ .add = acpi_pci_slot_add,
+ .remove = acpi_pci_slot_remove,
+};
+
+static int
+check_slot(acpi_handle handle, int *device, unsigned long *sun)
+{
+ int retval = 0;
+ unsigned long adr, sta;
+ acpi_status status;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+
+ acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+ dbg("Checking slot on path: %s\n", (char *)buffer.pointer);
+
+ if (check_sta_before_sun) {
+ /* If SxFy doesn't have _STA, we just assume it's there */
+ status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+ if (ACPI_SUCCESS(status) && !(sta & ACPI_STA_DEVICE_PRESENT)) {
+ retval = -1;
+ goto out;
+ }
+ }
+
+ status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
+ if (ACPI_FAILURE(status)) {
+ dbg("_ADR returned %d on %s\n", status, (char *)buffer.pointer);
+ retval = -1;
+ goto out;
+ }
+
+ *device = (adr >> 16) & 0xffff;
+
+ /* No _SUN == not a slot == bail */
+ status = acpi_evaluate_integer(handle, "_SUN", NULL, sun);
+ if (ACPI_FAILURE(status)) {
+ dbg("_SUN returned %d on %s\n", status, (char *)buffer.pointer);
+ retval = -1;
+ goto out;
+ }
+
+out:
+ kfree(buffer.pointer);
+ return retval;
+}
+
+struct callback_args {
+ acpi_walk_callback user_function; /* only for walk_p2p_bridge */
+ struct pci_bus *pci_bus;
+ acpi_handle root_handle;
+};
+
+/*
+ * register_slot
+ *
+ * Called once for each SxFy object in the namespace. Don't worry about
+ * calling pci_create_slot multiple times for the same pci_bus:device,
+ * since each subsequent call simply bumps the refcount on the pci_slot.
+ *
+ * The number of calls to pci_destroy_slot from unregister_slot is
+ * symmetrical.
+ */
+static acpi_status
+register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+ int device;
+ unsigned long sun;
+ char name[SLOT_NAME_SIZE];
+ struct acpi_pci_slot *slot;
+ struct pci_slot *pci_slot;
+ struct callback_args *parent_context = context;
+ struct pci_bus *pci_bus = parent_context->pci_bus;
+
+ if (check_slot(handle, &device, &sun))
+ return AE_OK;
+
+ slot = kmalloc(sizeof(*slot), GFP_KERNEL);
+ if (!slot) {
+ err("%s: cannot allocate memory\n", __func__);
+ return AE_OK;
+ }
+
+ snprintf(name, sizeof(name), "%u", (u32)sun);
+ pci_slot = pci_create_slot(pci_bus, device, name);
+ if (IS_ERR(pci_slot)) {
+ err("pci_create_slot returned %ld\n", PTR_ERR(pci_slot));
+ kfree(slot);
+ }
+
+ slot->root_handle = parent_context->root_handle;
+ slot->pci_slot = pci_slot;
+ INIT_LIST_HEAD(&slot->list);
+ mutex_lock(&slot_list_lock);
+ list_add(&slot->list, &slot_list);
+ mutex_unlock(&slot_list_lock);
+
+ dbg("pci_slot: %p, pci_bus: %x, device: %d, name: %s\n",
+ pci_slot, pci_bus->number, device, name);
+
+ return AE_OK;
+}
+
+/*
+ * walk_p2p_bridge - discover and walk p2p bridges
+ * @handle: points to an acpi_pci_root
+ * @context: p2p_bridge_context pointer
+ *
+ * Note that when we call ourselves recursively, we pass a different
+ * value of pci_bus in the child_context.
+ */
+static acpi_status
+walk_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+ int device, function;
+ unsigned long adr;
+ acpi_status status;
+ acpi_handle dummy_handle;
+ acpi_walk_callback user_function;
+
+ struct pci_dev *dev;
+ struct pci_bus *pci_bus;
+ struct callback_args child_context;
+ struct callback_args *parent_context = context;
+
+ pci_bus = parent_context->pci_bus;
+ user_function = parent_context->user_function;
+
+ status = acpi_get_handle(handle, "_ADR", &dummy_handle);
+ if (ACPI_FAILURE(status))
+ return AE_OK;
+
+ status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
+ if (ACPI_FAILURE(status))
+ return AE_OK;
+
+ device = (adr >> 16) & 0xffff;
+ function = adr & 0xffff;
+
+ dev = pci_get_slot(pci_bus, PCI_DEVFN(device, function));
+ if (!dev || !dev->subordinate)
+ goto out;
+
+ child_context.pci_bus = dev->subordinate;
+ child_context.user_function = user_function;
+ child_context.root_handle = parent_context->root_handle;
+
+ dbg("p2p bridge walk, pci_bus = %x\n", dev->subordinate->number);
+ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
+ user_function, &child_context, NULL);
+ if (ACPI_FAILURE(status))
+ goto out;
+
+ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
+ walk_p2p_bridge, &child_context, NULL);
+out:
+ pci_dev_put(dev);
+ return AE_OK;
+}
+
+/*
+ * walk_root_bridge - generic root bridge walker
+ * @handle: points to an acpi_pci_root
+ * @user_function: user callback for slot objects
+ *
+ * Call user_function for all objects underneath this root bridge.
+ * Walk p2p bridges underneath us and call user_function on those too.
+ */
+static int
+walk_root_bridge(acpi_handle handle, acpi_walk_callback user_function)
+{
+ int seg, bus;
+ unsigned long tmp;
+ acpi_status status;
+ acpi_handle dummy_handle;
+ struct pci_bus *pci_bus;
+ struct callback_args context;
+
+ /* If the bridge doesn't have _STA, we assume it is always there */
+ status = acpi_get_handle(handle, "_STA", &dummy_handle);
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp);
+ if (ACPI_FAILURE(status)) {
+ info("%s: _STA evaluation failure\n", __func__);
+ return 0;
+ }
+ if ((tmp & ACPI_STA_DEVICE_FUNCTIONING) == 0)
+ /* don't register this object */
+ return 0;
+ }
+
+ status = acpi_evaluate_integer(handle, "_SEG", NULL, &tmp);
+ seg = ACPI_SUCCESS(status) ? tmp : 0;
+
+ status = acpi_evaluate_integer(handle, "_BBN", NULL, &tmp);
+ bus = ACPI_SUCCESS(status) ? tmp : 0;
+
+ pci_bus = pci_find_bus(seg, bus);
+ if (!pci_bus)
+ return 0;
+
+ context.pci_bus = pci_bus;
+ context.user_function = user_function;
+ context.root_handle = handle;
+
+ dbg("root bridge walk, pci_bus = %x\n", pci_bus->number);
+ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
+ user_function, &context, NULL);
+ if (ACPI_FAILURE(status))
+ return status;
+
+ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
+ walk_p2p_bridge, &context, NULL);
+ if (ACPI_FAILURE(status))
+ err("%s: walk_p2p_bridge failure - %d\n", __func__, status);
+
+ return status;
+}
+
+/*
+ * acpi_pci_slot_add
+ * @handle: points to an acpi_pci_root
+ */
+static int
+acpi_pci_slot_add(acpi_handle handle)
+{
+ acpi_status status;
+
+ status = walk_root_bridge(handle, register_slot);
+ if (ACPI_FAILURE(status))
+ err("%s: register_slot failure - %d\n", __func__, status);
+
+ return status;
+}
+
+/*
+ * acpi_pci_slot_remove
+ * @handle: points to an acpi_pci_root
+ */
+static void
+acpi_pci_slot_remove(acpi_handle handle)
+{
+ struct acpi_pci_slot *slot, *tmp;
+
+ mutex_lock(&slot_list_lock);
+ list_for_each_entry_safe(slot, tmp, &slot_list, list) {
+ if (slot->root_handle == handle) {
+ list_del(&slot->list);
+ pci_destroy_slot(slot->pci_slot);
+ kfree(slot);
+ }
+ }
+ mutex_unlock(&slot_list_lock);
+}
+
+static int do_sta_before_sun(const struct dmi_system_id *d)
+{
+ info("%s detected: will evaluate _STA before calling _SUN\n", d->ident);
+ check_sta_before_sun = 1;
+ return 0;
+}
+
+static struct dmi_system_id acpi_pci_slot_dmi_table[] __initdata = {
+ /*
+ * Fujitsu Primequest machines will return 1023 to indicate an
+ * error if the _SUN method is evaluated on SxFy objects that
+ * are not present (as indicated by _STA), so for those machines,
+ * we want to check _STA before evaluating _SUN.
+ */
+ {
+ .callback = do_sta_before_sun,
+ .ident = "Fujitsu PRIMEQUEST",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "FUJITSU LIMITED"),
+ DMI_MATCH(DMI_BIOS_VERSION, "PRIMEQUEST"),
+ },
+ },
+ {}
+};
+
+static int __init
+acpi_pci_slot_init(void)
+{
+ dmi_check_system(acpi_pci_slot_dmi_table);
+ acpi_pci_register_driver(&acpi_pci_slot_driver);
+ return 0;
+}
+
+static void __exit
+acpi_pci_slot_exit(void)
+{
+ acpi_pci_unregister_driver(&acpi_pci_slot_driver);
+}
+
+module_init(acpi_pci_slot_init);
+module_exit(acpi_pci_slot_exit);
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 81e4f081a4a..4ab21cb1c8c 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -292,69 +292,135 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
return 0;
}
+/**
+ * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in
+ * ACPI 3.0) _PSW (Power State Wake)
+ * @dev: Device to handle.
+ * @enable: 0 - disable, 1 - enable the wake capabilities of the device.
+ * @sleep_state: Target sleep state of the system.
+ * @dev_state: Target power state of the device.
+ *
+ * Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
+ * State Wake) for the device, if present. On failure reset the device's
+ * wakeup.flags.valid flag.
+ *
+ * RETURN VALUE:
+ * 0 if either _DSW or _PSW has been successfully executed
+ * 0 if neither _DSW nor _PSW has been found
+ * -ENODEV if the execution of either _DSW or _PSW has failed
+ */
+int acpi_device_sleep_wake(struct acpi_device *dev,
+ int enable, int sleep_state, int dev_state)
+{
+ union acpi_object in_arg[3];
+ struct acpi_object_list arg_list = { 3, in_arg };
+ acpi_status status = AE_OK;
+
+ /*
+ * Try to execute _DSW first.
+ *
+ * Three agruments are needed for the _DSW object:
+ * Argument 0: enable/disable the wake capabilities
+ * Argument 1: target system state
+ * Argument 2: target device state
+ * When _DSW object is called to disable the wake capabilities, maybe
+ * the first argument is filled. The values of the other two agruments
+ * are meaningless.
+ */
+ in_arg[0].type = ACPI_TYPE_INTEGER;
+ in_arg[0].integer.value = enable;
+ in_arg[1].type = ACPI_TYPE_INTEGER;
+ in_arg[1].integer.value = sleep_state;
+ in_arg[2].type = ACPI_TYPE_INTEGER;
+ in_arg[2].integer.value = dev_state;
+ status = acpi_evaluate_object(dev->handle, "_DSW", &arg_list, NULL);
+ if (ACPI_SUCCESS(status)) {
+ return 0;
+ } else if (status != AE_NOT_FOUND) {
+ printk(KERN_ERR PREFIX "_DSW execution failed\n");
+ dev->wakeup.flags.valid = 0;
+ return -ENODEV;
+ }
+
+ /* Execute _PSW */
+ arg_list.count = 1;
+ in_arg[0].integer.value = enable;
+ status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
+ if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
+ printk(KERN_ERR PREFIX "_PSW execution failed\n");
+ dev->wakeup.flags.valid = 0;
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
/*
* Prepare a wakeup device, two steps (Ref ACPI 2.0:P229):
* 1. Power on the power resources required for the wakeup device
- * 2. Enable _PSW (power state wake) for the device if present
+ * 2. Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
+ * State Wake) for the device, if present
*/
-int acpi_enable_wakeup_device_power(struct acpi_device *dev)
+int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
{
- union acpi_object arg = { ACPI_TYPE_INTEGER };
- struct acpi_object_list arg_list = { 1, &arg };
- acpi_status status = AE_OK;
- int i;
- int ret = 0;
+ int i, err;
if (!dev || !dev->wakeup.flags.valid)
- return -1;
+ return -EINVAL;
+
+ /*
+ * Do not execute the code below twice in a row without calling
+ * acpi_disable_wakeup_device_power() in between for the same device
+ */
+ if (dev->wakeup.flags.prepared)
+ return 0;
- arg.integer.value = 1;
/* Open power resource */
for (i = 0; i < dev->wakeup.resources.count; i++) {
- ret = acpi_power_on(dev->wakeup.resources.handles[i], dev);
+ int ret = acpi_power_on(dev->wakeup.resources.handles[i], dev);
if (ret) {
printk(KERN_ERR PREFIX "Transition power state\n");
dev->wakeup.flags.valid = 0;
- return -1;
+ return -ENODEV;
}
}
- /* Execute PSW */
- status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
- if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
- printk(KERN_ERR PREFIX "Evaluate _PSW\n");
- dev->wakeup.flags.valid = 0;
- ret = -1;
- }
+ /*
+ * Passing 3 as the third argument below means the device may be placed
+ * in arbitrary power state afterwards.
+ */
+ err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
+ if (!err)
+ dev->wakeup.flags.prepared = 1;
- return ret;
+ return err;
}
/*
* Shutdown a wakeup device, counterpart of above method
- * 1. Disable _PSW (power state wake)
+ * 1. Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
+ * State Wake) for the device, if present
* 2. Shutdown down the power resources
*/
int acpi_disable_wakeup_device_power(struct acpi_device *dev)
{
- union acpi_object arg = { ACPI_TYPE_INTEGER };
- struct acpi_object_list arg_list = { 1, &arg };
- acpi_status status = AE_OK;
- int i;
- int ret = 0;
-
+ int i, ret;
if (!dev || !dev->wakeup.flags.valid)
- return -1;
+ return -EINVAL;
- arg.integer.value = 0;
- /* Execute PSW */
- status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
- if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
- printk(KERN_ERR PREFIX "Evaluate _PSW\n");
- dev->wakeup.flags.valid = 0;
- return -1;
- }
+ /*
+ * Do not execute the code below twice in a row without calling
+ * acpi_enable_wakeup_device_power() in between for the same device
+ */
+ if (!dev->wakeup.flags.prepared)
+ return 0;
+
+ dev->wakeup.flags.prepared = 0;
+
+ ret = acpi_device_sleep_wake(dev, 0, 0, 0);
+ if (ret)
+ return ret;
/* Close power resource */
for (i = 0; i < dev->wakeup.resources.count; i++) {
@@ -362,7 +428,7 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
if (ret) {
printk(KERN_ERR PREFIX "Transition power state\n");
dev->wakeup.flags.valid = 0;
- return -1;
+ return -ENODEV;
}
}
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 9dd0fa93b9e..ec0f2d581ec 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -118,8 +118,31 @@ static const struct file_operations acpi_processor_info_fops = {
.release = single_release,
};
-struct acpi_processor *processors[NR_CPUS];
+DEFINE_PER_CPU(struct acpi_processor *, processors);
struct acpi_processor_errata errata __read_mostly;
+static int set_no_mwait(const struct dmi_system_id *id)
+{
+ printk(KERN_NOTICE PREFIX "%s detected - "
+ "disable mwait for CPU C-stetes\n", id->ident);
+ idle_nomwait = 1;
+ return 0;
+}
+
+static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
+ {
+ set_no_mwait, "IFL91 board", {
+ DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
+ DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"),
+ DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL},
+ {
+ set_no_mwait, "Extensa 5220", {
+ DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+ DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
+ DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
+ {},
+};
/* --------------------------------------------------------------------------
Errata Handling
@@ -265,7 +288,20 @@ static int acpi_processor_set_pdc(struct acpi_processor *pr)
if (!pdc_in)
return status;
+ if (idle_nomwait) {
+ /*
+ * If mwait is disabled for CPU C-states, the C2C3_FFH access
+ * mode will be disabled in the parameter of _PDC object.
+ * Of course C1_FFH access mode will also be disabled.
+ */
+ union acpi_object *obj;
+ u32 *buffer = NULL;
+ obj = pdc_in->pointer;
+ buffer = (u32 *)(obj->buffer.pointer);
+ buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
+
+ }
status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL);
if (ACPI_FAILURE(status))
@@ -614,14 +650,14 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid)
return 0;
}
-static void *processor_device_array[NR_CPUS];
+static DEFINE_PER_CPU(void *, processor_device_array);
static int __cpuinit acpi_processor_start(struct acpi_device *device)
{
int result = 0;
acpi_status status = AE_OK;
struct acpi_processor *pr;
-
+ struct sys_device *sysdev;
pr = acpi_driver_data(device);
@@ -638,20 +674,24 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
* ACPI id of processors can be reported wrongly by the BIOS.
* Don't trust it blindly
*/
- if (processor_device_array[pr->id] != NULL &&
- processor_device_array[pr->id] != device) {
+ if (per_cpu(processor_device_array, pr->id) != NULL &&
+ per_cpu(processor_device_array, pr->id) != device) {
printk(KERN_WARNING "BIOS reported wrong ACPI id "
"for the processor\n");
return -ENODEV;
}
- processor_device_array[pr->id] = device;
+ per_cpu(processor_device_array, pr->id) = device;
- processors[pr->id] = pr;
+ per_cpu(processors, pr->id) = pr;
result = acpi_processor_add_fs(device);
if (result)
goto end;
+ sysdev = get_cpu_sysdev(pr->id);
+ if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev"))
+ return -EFAULT;
+
status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
acpi_processor_notify, pr);
@@ -749,7 +789,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
- struct acpi_processor *pr = processors[cpu];
+ struct acpi_processor *pr = per_cpu(processors, cpu);
if (action == CPU_ONLINE && pr) {
acpi_processor_ppc_has_changed(pr);
@@ -810,6 +850,8 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
acpi_processor_notify);
+ sysfs_remove_link(&device->dev.kobj, "sysdev");
+
acpi_processor_remove_fs(device);
if (pr->cdev) {
@@ -819,8 +861,8 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
pr->cdev = NULL;
}
- processors[pr->id] = NULL;
- processor_device_array[pr->id] = NULL;
+ per_cpu(processors, pr->id) = NULL;
+ per_cpu(processor_device_array, pr->id) = NULL;
kfree(pr);
return 0;
@@ -1014,9 +1056,9 @@ static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
static int acpi_processor_handle_eject(struct acpi_processor *pr)
{
- if (cpu_online(pr->id)) {
- return (-EINVAL);
- }
+ if (cpu_online(pr->id))
+ cpu_down(pr->id);
+
arch_unregister_cpu(pr->id);
acpi_unmap_lsapic(pr->id);
return (0);
@@ -1068,8 +1110,6 @@ static int __init acpi_processor_init(void)
{
int result = 0;
-
- memset(&processors, 0, sizeof(processors));
memset(&errata, 0, sizeof(errata));
#ifdef CONFIG_SMP
@@ -1083,6 +1123,11 @@ static int __init acpi_processor_init(void)
return -ENOMEM;
acpi_processor_dir->owner = THIS_MODULE;
+ /*
+ * Check whether the system is DMI table. If yes, OSPM
+ * should not use mwait for CPU-states.
+ */
+ dmi_check_system(processor_idle_dmi_table);
result = cpuidle_register_driver(&acpi_idle_driver);
if (result < 0)
goto out_proc;
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 4976e5db2b3..d592dbb1d12 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -41,6 +41,7 @@
#include <linux/pm_qos_params.h>
#include <linux/clockchips.h>
#include <linux/cpuidle.h>
+#include <linux/cpuidle.h>
/*
* Include the apic definitions for x86 to have the APIC timer related defines
@@ -57,6 +58,7 @@
#include <acpi/acpi_bus.h>
#include <acpi/processor.h>
+#include <asm/processor.h>
#define ACPI_PROCESSOR_COMPONENT 0x01000000
#define ACPI_PROCESSOR_CLASS "processor"
@@ -401,7 +403,7 @@ static void acpi_processor_idle(void)
*/
local_irq_disable();
- pr = processors[smp_processor_id()];
+ pr = __get_cpu_var(processors);
if (!pr) {
local_irq_enable();
return;
@@ -955,6 +957,21 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
} else {
continue;
}
+ if (cx.type == ACPI_STATE_C1 &&
+ (idle_halt || idle_nomwait)) {
+ /*
+ * In most cases the C1 space_id obtained from
+ * _CST object is FIXED_HARDWARE access mode.
+ * But when the option of idle=halt is added,
+ * the entry_method type should be changed from
+ * CSTATE_FFH to CSTATE_HALT.
+ * When the option of idle=nomwait is added,
+ * the C1 entry_method type should be
+ * CSTATE_HALT.
+ */
+ cx.entry_method = ACPI_CSTATE_HALT;
+ snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT");
+ }
} else {
snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI IOPORT 0x%x",
cx.address);
@@ -1431,7 +1448,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
struct acpi_processor *pr;
struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
- pr = processors[smp_processor_id()];
+ pr = __get_cpu_var(processors);
if (unlikely(!pr))
return 0;
@@ -1471,7 +1488,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
u32 t1, t2;
int sleep_ticks = 0;
- pr = processors[smp_processor_id()];
+ pr = __get_cpu_var(processors);
if (unlikely(!pr))
return 0;
@@ -1549,7 +1566,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
u32 t1, t2;
int sleep_ticks = 0;
- pr = processors[smp_processor_id()];
+ pr = __get_cpu_var(processors);
if (unlikely(!pr))
return 0;
@@ -1780,6 +1797,15 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
return 0;
if (!first_run) {
+ if (idle_halt) {
+ /*
+ * When the boot option of "idle=halt" is added, halt
+ * is used for CPU IDLE.
+ * In such case C2/C3 is meaningless. So the max_cstate
+ * is set to one.
+ */
+ max_cstate = 1;
+ }
dmi_check_system(processor_power_dmi_table);
max_cstate = acpi_processor_cstate_check(max_cstate);
if (max_cstate < ACPI_C_STATES_MAX)
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index d80b2d1441a..b4749969c6b 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/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 = processors[policy->cpu];
+ pr = per_cpu(processors, policy->cpu);
if (!pr || !pr->performance)
goto out;
@@ -572,7 +572,7 @@ int acpi_processor_preregister_performance(
/* Call _PSD for all CPUs */
for_each_possible_cpu(i) {
- pr = processors[i];
+ pr = per_cpu(processors, i);
if (!pr) {
/* Look only at processors in ACPI namespace */
continue;
@@ -603,7 +603,7 @@ int acpi_processor_preregister_performance(
* domain info.
*/
for_each_possible_cpu(i) {
- pr = processors[i];
+ pr = per_cpu(processors, i);
if (!pr)
continue;
@@ -624,7 +624,7 @@ int acpi_processor_preregister_performance(
cpus_clear(covered_cpus);
for_each_possible_cpu(i) {
- pr = processors[i];
+ pr = per_cpu(processors, i);
if (!pr)
continue;
@@ -651,7 +651,7 @@ int acpi_processor_preregister_performance(
if (i == j)
continue;
- match_pr = processors[j];
+ match_pr = per_cpu(processors, j);
if (!match_pr)
continue;
@@ -680,7 +680,7 @@ int acpi_processor_preregister_performance(
if (i == j)
continue;
- match_pr = processors[j];
+ match_pr = per_cpu(processors, j);
if (!match_pr)
continue;
@@ -697,7 +697,7 @@ int acpi_processor_preregister_performance(
err_ret:
for_each_possible_cpu(i) {
- pr = processors[i];
+ pr = per_cpu(processors, i);
if (!pr || !pr->performance)
continue;
@@ -728,7 +728,7 @@ acpi_processor_register_performance(struct acpi_processor_performance
mutex_lock(&performance_mutex);
- pr = processors[cpu];
+ pr = per_cpu(processors, cpu);
if (!pr) {
mutex_unlock(&performance_mutex);
return -ENODEV;
@@ -766,7 +766,7 @@ acpi_processor_unregister_performance(struct acpi_processor_performance
mutex_lock(&performance_mutex);
- pr = processors[cpu];
+ pr = per_cpu(processors, cpu);
if (!pr) {
mutex_unlock(&performance_mutex);
return;
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index bb06738860c..0622ace0522 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/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 = processors[i];
+ pr = per_cpu(processors, i);
if (!pr)
continue;
@@ -93,7 +93,7 @@ static int acpi_processor_update_tsd_coord(void)
cpus_clear(covered_cpus);
for_each_possible_cpu(i) {
- pr = processors[i];
+ pr = per_cpu(processors, i);
if (!pr)
continue;
@@ -119,7 +119,7 @@ static int acpi_processor_update_tsd_coord(void)
if (i == j)
continue;
- match_pr = processors[j];
+ match_pr = per_cpu(processors, j);
if (!match_pr)
continue;
@@ -152,7 +152,7 @@ static int acpi_processor_update_tsd_coord(void)
if (i == j)
continue;
- match_pr = processors[j];
+ match_pr = per_cpu(processors, j);
if (!match_pr)
continue;
@@ -172,7 +172,7 @@ static int acpi_processor_update_tsd_coord(void)
err_ret:
for_each_possible_cpu(i) {
- pr = processors[i];
+ pr = per_cpu(processors, i);
if (!pr)
continue;
@@ -214,7 +214,7 @@ static int acpi_processor_throttling_notifier(unsigned long event, void *data)
struct acpi_processor_throttling *p_throttling;
cpu = p_tstate->cpu;
- pr = processors[cpu];
+ pr = per_cpu(processors, cpu);
if (!pr) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid pr pointer\n"));
return 0;
@@ -1035,7 +1035,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* cpus.
*/
for_each_cpu_mask(i, online_throttling_cpus) {
- match_pr = processors[i];
+ match_pr = per_cpu(processors, i);
/*
* If the pointer is invalid, we will report the
* error message and continue.
@@ -1232,7 +1232,10 @@ static ssize_t acpi_processor_write_throttling(struct file *file,
int result = 0;
struct seq_file *m = file->private_data;
struct acpi_processor *pr = m->private;
- char state_string[12] = { '\0' };
+ char state_string[5] = "";
+ char *charp = NULL;
+ size_t state_val = 0;
+ char tmpbuf[5] = "";
if (!pr || (count > sizeof(state_string) - 1))
return -EINVAL;
@@ -1241,10 +1244,23 @@ static ssize_t acpi_processor_write_throttling(struct file *file,
return -EFAULT;
state_string[count] = '\0';
+ if ((count > 0) && (state_string[count-1] == '\n'))
+ state_string[count-1] = '\0';
- result = acpi_processor_set_throttling(pr,
- simple_strtoul(state_string,
- NULL, 0));
+ charp = state_string;
+ if ((state_string[0] == 't') || (state_string[0] == 'T'))
+ charp++;
+
+ state_val = simple_strtoul(charp, NULL, 0);
+ if (state_val >= pr->throttling.state_count)
+ return -EINVAL;
+
+ snprintf(tmpbuf, 5, "%zu", state_val);
+
+ if (strcmp(tmpbuf, charp) != 0)
+ return -EINVAL;
+
+ result = acpi_processor_set_throttling(pr, state_val);
if (result)
return result;
diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c
new file mode 100644
index 00000000000..a6b662c00b6
--- /dev/null
+++ b/drivers/acpi/reboot.c
@@ -0,0 +1,50 @@
+
+#include <linux/pci.h>
+#include <linux/acpi.h>
+#include <acpi/reboot.h>
+
+void acpi_reboot(void)
+{
+ struct acpi_generic_address *rr;
+ struct pci_bus *bus0;
+ u8 reset_value;
+ unsigned int devfn;
+
+ if (acpi_disabled)
+ return;
+
+ rr = &acpi_gbl_FADT.reset_register;
+
+ /* Is the reset register supported? */
+ if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) ||
+ rr->bit_width != 8 || rr->bit_offset != 0)
+ return;
+
+ reset_value = acpi_gbl_FADT.reset_value;
+
+ /* The reset register can only exist in I/O, Memory or PCI config space
+ * on a device on bus 0. */
+ switch (rr->space_id) {
+ case ACPI_ADR_SPACE_PCI_CONFIG:
+ /* The reset register can only live on bus 0. */
+ bus0 = pci_find_bus(0, 0);
+ if (!bus0)
+ return;
+ /* Form PCI device/function pair. */
+ devfn = PCI_DEVFN((rr->address >> 32) & 0xffff,
+ (rr->address >> 16) & 0xffff);
+ printk(KERN_DEBUG "Resetting with ACPI PCI RESET_REG.");
+ /* Write the value that resets us. */
+ pci_bus_write_config_byte(bus0, devfn,
+ (rr->address & 0xffff), reset_value);
+ break;
+
+ case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+ case ACPI_ADR_SPACE_SYSTEM_IO:
+ printk(KERN_DEBUG "ACPI MEMORY or I/O RESET_REG.\n");
+ acpi_hw_low_level_write(8, reset_value, rr);
+ break;
+ }
+ /* Wait ten seconds */
+ acpi_os_stall(10000000);
+}
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c
index 8a112d11d49..f61ebc679e6 100644
--- a/drivers/acpi/resources/rscalc.c
+++ b/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)
{
- acpi_native_uint bits_set;
+ u8 bits_set;
ACPI_FUNCTION_ENTRY();
@@ -84,7 +84,7 @@ static u8 acpi_rs_count_set_bits(u16 bit_field)
bit_field &= (u16) (bit_field - 1);
}
- return ((u8) bits_set);
+ return bits_set;
}
/*******************************************************************************
diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c
index faddaee1bc0..7804a8c40e7 100644
--- a/drivers/acpi/resources/rscreate.c
+++ b/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,9 +240,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
/* 1) First subobject: Dereference the PRT.Address */
obj_desc = sub_object_list[0];
- if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
- user_prt->address = obj_desc->integer.value;
- } else {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) {
ACPI_ERROR((AE_INFO,
"(PRT[%X].Address) Need Integer, found %s",
index,
@@ -250,12 +248,12 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
return_ACPI_STATUS(AE_BAD_DATA);
}
+ user_prt->address = obj_desc->integer.value;
+
/* 2) Second subobject: Dereference the PRT.Pin */
obj_desc = sub_object_list[1];
- if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
- user_prt->pin = (u32) obj_desc->integer.value;
- } else {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) {
ACPI_ERROR((AE_INFO,
"(PRT[%X].Pin) Need Integer, found %s",
index,
@@ -284,6 +282,25 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
}
}
+ user_prt->pin = (u32) obj_desc->integer.value;
+
+ /*
+ * If the BIOS has erroneously reversed the _PRT source_name (index 2)
+ * and the source_index (index 3), fix it. _PRT is important enough to
+ * workaround this BIOS error. This also provides compatibility with
+ * other ACPI implementations.
+ */
+ obj_desc = sub_object_list[3];
+ if (!obj_desc
+ || (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) {
+ sub_object_list[3] = sub_object_list[2];
+ sub_object_list[2] = obj_desc;
+
+ ACPI_WARNING((AE_INFO,
+ "(PRT[%X].Source) SourceName and SourceIndex are reversed, fixed",
+ index));
+ }
+
/*
* 3) Third subobject: Dereference the PRT.source_name
* The name may be unresolved (slack mode), so allow a null object
@@ -364,9 +381,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
/* 4) Fourth subobject: Dereference the PRT.source_index */
obj_desc = sub_object_list[source_index_index];
- if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
- user_prt->source_index = (u32) obj_desc->integer.value;
- } else {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) {
ACPI_ERROR((AE_INFO,
"(PRT[%X].SourceIndex) Need Integer, found %s",
index,
@@ -374,6 +389,8 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
return_ACPI_STATUS(AE_BAD_DATA);
}
+ user_prt->source_index = (u32) obj_desc->integer.value;
+
/* Point to the next union acpi_operand_object in the top level package */
top_object_list++;
diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c
index de1ac3881b2..96a6c035325 100644
--- a/drivers/acpi/resources/rsmisc.c
+++ b/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_native_uint) resource) & 0x3) {
+ if (((acpi_size) resource) & 0x3) {
/* Each internal resource struct is expected to be 32-bit aligned */
diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c
index befe2302f41..f7b3bcd59ba 100644
--- a/drivers/acpi/resources/rsutils.c
+++ b/drivers/acpi/resources/rsutils.c
@@ -62,7 +62,7 @@ ACPI_MODULE_NAME("rsutils")
******************************************************************************/
u8 acpi_rs_decode_bitmask(u16 mask, u8 * list)
{
- acpi_native_uint i;
+ u8 i;
u8 bit_count;
ACPI_FUNCTION_ENTRY();
@@ -71,7 +71,7 @@ u8 acpi_rs_decode_bitmask(u16 mask, u8 * list)
for (i = 0, bit_count = 0; mask; i++) {
if (mask & 0x0001) {
- list[bit_count] = (u8) i;
+ list[bit_count] = i;
bit_count++;
}
@@ -96,8 +96,8 @@ u8 acpi_rs_decode_bitmask(u16 mask, u8 * list)
u16 acpi_rs_encode_bitmask(u8 * list, u8 count)
{
- acpi_native_uint i;
- acpi_native_uint mask;
+ u32 i;
+ u16 mask;
ACPI_FUNCTION_ENTRY();
@@ -107,7 +107,7 @@ u16 acpi_rs_encode_bitmask(u8 * list, u8 count)
mask |= (0x1 << list[i]);
}
- return ((u16) mask);
+ return mask;
}
/*******************************************************************************
@@ -130,7 +130,7 @@ u16 acpi_rs_encode_bitmask(u8 * list, u8 count)
void
acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)
{
- acpi_native_uint i;
+ u32 i;
ACPI_FUNCTION_ENTRY();
@@ -679,7 +679,6 @@ acpi_rs_set_srs_method_data(struct acpi_namespace_node *node,
info->prefix_node = node;
info->pathname = METHOD_NAME__SRS;
info->parameters = args;
- info->parameter_type = ACPI_PARAM_ARGS;
info->flags = ACPI_IGNORE_RETURN_VALUE;
/*
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 6d85289f1c1..f3132aa47a6 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -6,6 +6,8 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/acpi.h>
+#include <linux/signal.h>
+#include <linux/kthread.h>
#include <acpi/acpi_drivers.h>
#include <acpi/acinterp.h> /* for acpi_ex_eisa_id_to_string() */
@@ -92,17 +94,37 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha
}
static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
-static int acpi_eject_operation(acpi_handle handle, int lockable)
+static int acpi_bus_hot_remove_device(void *context)
{
+ struct acpi_device *device;
+ acpi_handle handle = context;
struct acpi_object_list arg_list;
union acpi_object arg;
acpi_status status = AE_OK;
- /*
- * TBD: evaluate _PS3?
- */
+ if (acpi_bus_get_device(handle, &device))
+ return 0;
+
+ if (!device)
+ return 0;
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Hot-removing device %s...\n", device->dev.bus_id));
+
- if (lockable) {
+ if (acpi_bus_trim(device, 1)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Removing device failed\n"));
+ return -1;
+ }
+
+ /* power off device */
+ status = acpi_evaluate_object(handle, "_PS3", NULL, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Power-off device failed\n"));
+
+ if (device->flags.lockable) {
arg_list.count = 1;
arg_list.pointer = &arg;
arg.type = ACPI_TYPE_INTEGER;
@@ -118,26 +140,22 @@ static int acpi_eject_operation(acpi_handle handle, int lockable)
/*
* TBD: _EJD support.
*/
-
status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
- if (ACPI_FAILURE(status)) {
- return (-ENODEV);
- }
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
- return (0);
+ return 0;
}
static ssize_t
acpi_eject_store(struct device *d, struct device_attribute *attr,
const char *buf, size_t count)
{
- int result;
int ret = count;
- int islockable;
acpi_status status;
- acpi_handle handle;
acpi_object_type type = 0;
struct acpi_device *acpi_device = to_acpi_device(d);
+ struct task_struct *task;
if ((!count) || (buf[0] != '1')) {
return -EINVAL;
@@ -154,18 +172,12 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
goto err;
}
- islockable = acpi_device->flags.lockable;
- handle = acpi_device->handle;
-
- result = acpi_bus_trim(acpi_device, 1);
-
- if (!result)
- result = acpi_eject_operation(handle, islockable);
-
- if (result) {
- ret = -EBUSY;
- }
- err:
+ /* remove the device in another thread to fix the deadlock issue */
+ task = kthread_run(acpi_bus_hot_remove_device,
+ acpi_device->handle, "acpi_hot_remove_device");
+ if (IS_ERR(task))
+ ret = PTR_ERR(task);
+err:
return ret;
}
@@ -691,9 +703,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
acpi_status status = 0;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *package = NULL;
- union acpi_object in_arg[3];
- struct acpi_object_list arg_list = { 3, in_arg };
- acpi_status psw_status = AE_OK;
+ int psw_error;
struct acpi_device_id button_device_ids[] = {
{"PNP0C0D", 0},
@@ -725,39 +735,11 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
* So it is necessary to call _DSW object first. Only when it is not
* present will the _PSW object used.
*/
- /*
- * Three agruments are needed for the _DSW object.
- * Argument 0: enable/disable the wake capabilities
- * When _DSW object is called to disable the wake capabilities, maybe
- * the first argument is filled. The value of the other two agruments
- * is meaningless.
- */
- in_arg[0].type = ACPI_TYPE_INTEGER;
- in_arg[0].integer.value = 0;
- in_arg[1].type = ACPI_TYPE_INTEGER;
- in_arg[1].integer.value = 0;
- in_arg[2].type = ACPI_TYPE_INTEGER;
- in_arg[2].integer.value = 0;
- psw_status = acpi_evaluate_object(device->handle, "_DSW",
- &arg_list, NULL);
- if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND))
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in evaluate _DSW\n"));
- /*
- * When the _DSW object is not present, OSPM will call _PSW object.
- */
- if (psw_status == AE_NOT_FOUND) {
- /*
- * Only one agruments is required for the _PSW object.
- * agrument 0: enable/disable the wake capabilities
- */
- arg_list.count = 1;
- in_arg[0].integer.value = 0;
- psw_status = acpi_evaluate_object(device->handle, "_PSW",
- &arg_list, NULL);
- if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND))
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in "
- "evaluate _PSW\n"));
- }
+ psw_error = acpi_device_sleep_wake(device, 0, 0, 0);
+ if (psw_error)
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "error in _DSW or _PSW evaluation\n"));
+
/* Power button, Lid switch always enable wakeup */
if (!acpi_match_device_ids(device, button_device_ids))
device->wakeup.flags.run_wake = 1;
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index 495c63a3e0a..0489a7d1d42 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -24,10 +24,6 @@
u8 sleep_states[ACPI_S_STATE_COUNT];
-#ifdef CONFIG_PM_SLEEP
-static u32 acpi_target_sleep_state = ACPI_STATE_S0;
-#endif
-
static int acpi_sleep_prepare(u32 acpi_state)
{
#ifdef CONFIG_ACPI_SLEEP
@@ -49,9 +45,96 @@ static int acpi_sleep_prepare(u32 acpi_state)
return 0;
}
-#ifdef CONFIG_SUSPEND
-static struct platform_suspend_ops acpi_suspend_ops;
+#ifdef CONFIG_PM_SLEEP
+static u32 acpi_target_sleep_state = ACPI_STATE_S0;
+
+/*
+ * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the
+ * user to request that behavior by using the 'acpi_old_suspend_ordering'
+ * kernel command line option that causes the following variable to be set.
+ */
+static bool old_suspend_ordering;
+void __init acpi_old_suspend_ordering(void)
+{
+ old_suspend_ordering = true;
+}
+
+/**
+ * acpi_pm_disable_gpes - Disable the GPEs.
+ */
+static int acpi_pm_disable_gpes(void)
+{
+ acpi_hw_disable_all_gpes();
+ return 0;
+}
+
+/**
+ * __acpi_pm_prepare - Prepare the platform to enter the target state.
+ *
+ * If necessary, set the firmware waking vector and do arch-specific
+ * nastiness to get the wakeup code to the waking vector.
+ */
+static int __acpi_pm_prepare(void)
+{
+ int error = acpi_sleep_prepare(acpi_target_sleep_state);
+
+ if (error)
+ acpi_target_sleep_state = ACPI_STATE_S0;
+ return error;
+}
+
+/**
+ * acpi_pm_prepare - Prepare the platform to enter the target sleep
+ * state and disable the GPEs.
+ */
+static int acpi_pm_prepare(void)
+{
+ int error = __acpi_pm_prepare();
+
+ if (!error)
+ acpi_hw_disable_all_gpes();
+ return error;
+}
+
+/**
+ * acpi_pm_finish - Instruct the platform to leave a sleep state.
+ *
+ * This is called after we wake back up (or if entering the sleep state
+ * failed).
+ */
+static void acpi_pm_finish(void)
+{
+ u32 acpi_state = acpi_target_sleep_state;
+
+ if (acpi_state == ACPI_STATE_S0)
+ return;
+
+ printk(KERN_INFO PREFIX "Waking up from system sleep state S%d\n",
+ acpi_state);
+ acpi_disable_wakeup_device(acpi_state);
+ acpi_leave_sleep_state(acpi_state);
+
+ /* reset firmware waking vector */
+ acpi_set_firmware_waking_vector((acpi_physical_address) 0);
+
+ acpi_target_sleep_state = ACPI_STATE_S0;
+}
+
+/**
+ * acpi_pm_end - Finish up suspend sequence.
+ */
+static void acpi_pm_end(void)
+{
+ /*
+ * This is necessary in case acpi_pm_finish() is not called during a
+ * failing transition to a sleep state.
+ */
+ acpi_target_sleep_state = ACPI_STATE_S0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_SUSPEND
extern void do_suspend_lowlevel(void);
static u32 acpi_suspend_states[] = {
@@ -61,13 +144,10 @@ 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.
*/
-
static int acpi_suspend_begin(suspend_state_t pm_state)
{
u32 acpi_state = acpi_suspend_states[pm_state];
@@ -84,25 +164,6 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
}
/**
- * acpi_suspend_prepare - Do preliminary suspend work.
- *
- * If necessary, set the firmware waking vector and do arch-specific
- * nastiness to get the wakeup code to the waking vector.
- */
-
-static int acpi_suspend_prepare(void)
-{
- int error = acpi_sleep_prepare(acpi_target_sleep_state);
-
- if (error) {
- acpi_target_sleep_state = ACPI_STATE_S0;
- return error;
- }
-
- return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT;
-}
-
-/**
* acpi_suspend_enter - Actually enter a sleep state.
* @pm_state: ignored
*
@@ -110,7 +171,6 @@ static int acpi_suspend_prepare(void)
* assembly, which in turn call acpi_enter_sleep_state().
* It's unfortunate, but it works. Please fix if you're feeling frisky.
*/
-
static int acpi_suspend_enter(suspend_state_t pm_state)
{
acpi_status status = AE_OK;
@@ -167,46 +227,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}
-/**
- * acpi_suspend_finish - Instruct the platform to leave a sleep state.
- *
- * This is called after we wake back up (or if entering the sleep state
- * failed).
- */
-
-static void acpi_suspend_finish(void)
-{
- u32 acpi_state = acpi_target_sleep_state;
-
- acpi_disable_wakeup_device(acpi_state);
- acpi_leave_sleep_state(acpi_state);
-
- /* reset firmware waking vector */
- 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
-}
-
-/**
- * acpi_suspend_end - Finish up suspend sequence.
- */
-
-static void acpi_suspend_end(void)
-{
- /*
- * This is necessary in case acpi_suspend_finish() is not called during a
- * failing transition to a sleep state.
- */
- acpi_target_sleep_state = ACPI_STATE_S0;
-}
-
static int acpi_suspend_state_valid(suspend_state_t pm_state)
{
u32 acpi_state;
@@ -226,30 +246,39 @@ static int acpi_suspend_state_valid(suspend_state_t pm_state)
static struct platform_suspend_ops acpi_suspend_ops = {
.valid = acpi_suspend_state_valid,
.begin = acpi_suspend_begin,
- .prepare = acpi_suspend_prepare,
+ .prepare = acpi_pm_prepare,
.enter = acpi_suspend_enter,
- .finish = acpi_suspend_finish,
- .end = acpi_suspend_end,
+ .finish = acpi_pm_finish,
+ .end = acpi_pm_end,
};
-/*
- * Toshiba fails to preserve interrupts over S1, reinitialization
- * of 8259 is needed after S1 resume.
+/**
+ * acpi_suspend_begin_old - Set the target system sleep state to the
+ * state associated with given @pm_state, if supported, and
+ * execute the _PTS control method. This function is used if the
+ * pre-ACPI 2.0 suspend ordering has been requested.
*/
-static int __init init_ints_after_s1(const struct dmi_system_id *d)
+static int acpi_suspend_begin_old(suspend_state_t pm_state)
{
- printk(KERN_WARNING "%s with broken S1 detected.\n", d->ident);
- init_8259A_after_S1 = 1;
- return 0;
+ int error = acpi_suspend_begin(pm_state);
+
+ if (!error)
+ error = __acpi_pm_prepare();
+ return error;
}
-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"),},
- },
- {},
+/*
+ * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has
+ * been requested.
+ */
+static struct platform_suspend_ops acpi_suspend_ops_old = {
+ .valid = acpi_suspend_state_valid,
+ .begin = acpi_suspend_begin_old,
+ .prepare = acpi_pm_disable_gpes,
+ .enter = acpi_suspend_enter,
+ .finish = acpi_pm_finish,
+ .end = acpi_pm_end,
+ .recover = acpi_pm_finish,
};
#endif /* CONFIG_SUSPEND */
@@ -257,22 +286,9 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
static int acpi_hibernation_begin(void)
{
acpi_target_sleep_state = ACPI_STATE_S4;
-
return 0;
}
-static int acpi_hibernation_prepare(void)
-{
- int error = acpi_sleep_prepare(ACPI_STATE_S4);
-
- if (error) {
- acpi_target_sleep_state = ACPI_STATE_S0;
- return error;
- }
-
- return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT;
-}
-
static int acpi_hibernation_enter(void)
{
acpi_status status = AE_OK;
@@ -302,52 +318,55 @@ static void acpi_hibernation_leave(void)
acpi_leave_sleep_state_prep(ACPI_STATE_S4);
}
-static void acpi_hibernation_finish(void)
+static void acpi_pm_enable_gpes(void)
{
- acpi_disable_wakeup_device(ACPI_STATE_S4);
- acpi_leave_sleep_state(ACPI_STATE_S4);
-
- /* reset firmware waking vector */
- acpi_set_firmware_waking_vector((acpi_physical_address) 0);
-
- acpi_target_sleep_state = ACPI_STATE_S0;
+ acpi_hw_enable_all_runtime_gpes();
}
-static void acpi_hibernation_end(void)
-{
- /*
- * This is necessary in case acpi_hibernation_finish() is not called
- * during a failing transition to the sleep state.
- */
- acpi_target_sleep_state = ACPI_STATE_S0;
-}
+static struct platform_hibernation_ops acpi_hibernation_ops = {
+ .begin = acpi_hibernation_begin,
+ .end = acpi_pm_end,
+ .pre_snapshot = acpi_pm_prepare,
+ .finish = acpi_pm_finish,
+ .prepare = acpi_pm_prepare,
+ .enter = acpi_hibernation_enter,
+ .leave = acpi_hibernation_leave,
+ .pre_restore = acpi_pm_disable_gpes,
+ .restore_cleanup = acpi_pm_enable_gpes,
+};
-static int acpi_hibernation_pre_restore(void)
+/**
+ * acpi_hibernation_begin_old - Set the target system sleep state to
+ * ACPI_STATE_S4 and execute the _PTS control method. This
+ * function is used if the pre-ACPI 2.0 suspend ordering has been
+ * requested.
+ */
+static int acpi_hibernation_begin_old(void)
{
- acpi_status status;
-
- status = acpi_hw_disable_all_gpes();
-
- return ACPI_SUCCESS(status) ? 0 : -EFAULT;
-}
+ int error = acpi_sleep_prepare(ACPI_STATE_S4);
-static void acpi_hibernation_restore_cleanup(void)
-{
- acpi_hw_enable_all_runtime_gpes();
+ if (!error)
+ acpi_target_sleep_state = ACPI_STATE_S4;
+ return error;
}
-static struct platform_hibernation_ops acpi_hibernation_ops = {
- .begin = acpi_hibernation_begin,
- .end = acpi_hibernation_end,
- .pre_snapshot = acpi_hibernation_prepare,
- .finish = acpi_hibernation_finish,
- .prepare = acpi_hibernation_prepare,
+/*
+ * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has
+ * been requested.
+ */
+static struct platform_hibernation_ops acpi_hibernation_ops_old = {
+ .begin = acpi_hibernation_begin_old,
+ .end = acpi_pm_end,
+ .pre_snapshot = acpi_pm_disable_gpes,
+ .finish = acpi_pm_finish,
+ .prepare = acpi_pm_disable_gpes,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
- .pre_restore = acpi_hibernation_pre_restore,
- .restore_cleanup = acpi_hibernation_restore_cleanup,
+ .pre_restore = acpi_pm_disable_gpes,
+ .restore_cleanup = acpi_pm_enable_gpes,
+ .recover = acpi_pm_finish,
};
-#endif /* CONFIG_HIBERNATION */
+#endif /* CONFIG_HIBERNATION */
int acpi_suspend(u32 acpi_state)
{
@@ -368,8 +387,8 @@ int acpi_suspend(u32 acpi_state)
/**
* acpi_pm_device_sleep_state - return preferred power state of ACPI device
* in the system sleep state given by %acpi_target_sleep_state
- * @dev: device to examine
- * @wake: if set, the device should be able to wake up the system
+ * @dev: device to examine; its driver model wakeup flags control
+ * whether it should be able to wake up the system
* @d_min_p: used to store the upper limit of allowed states range
* Return value: preferred power state of the device on success, -ENODEV on
* failure (ie. if there's no 'struct acpi_device' for @dev)
@@ -387,7 +406,7 @@ int acpi_suspend(u32 acpi_state)
* via @wake.
*/
-int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p)
+int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
{
acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
struct acpi_device *adev;
@@ -426,7 +445,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p)
* can wake the system. _S0W may be valid, too.
*/
if (acpi_target_sleep_state == ACPI_STATE_S0 ||
- (wake && adev->wakeup.state.enabled &&
+ (device_may_wakeup(dev) && adev->wakeup.state.enabled &&
adev->wakeup.sleep_state <= acpi_target_sleep_state)) {
acpi_status status;
@@ -448,6 +467,31 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p)
*d_min_p = d_min;
return d_max;
}
+
+/**
+ * acpi_pm_device_sleep_wake - enable or disable the system wake-up
+ * capability of given device
+ * @dev: device to handle
+ * @enable: 'true' - enable, 'false' - disable the wake-up capability
+ */
+int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
+{
+ acpi_handle handle;
+ struct acpi_device *adev;
+
+ if (!device_may_wakeup(dev))
+ return -EINVAL;
+
+ handle = DEVICE_ACPI_HANDLE(dev);
+ if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
+ printk(KERN_DEBUG "ACPI handle has no context!\n");
+ return -ENODEV;
+ }
+
+ return enable ?
+ acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) :
+ acpi_disable_wakeup_device_power(adev);
+}
#endif
static void acpi_power_off_prepare(void)
@@ -472,8 +516,6 @@ int __init acpi_sleep_init(void)
u8 type_a, type_b;
#ifdef CONFIG_SUSPEND
int i = 0;
-
- dmi_check_system(acpisleep_dmi_table);
#endif
if (acpi_disabled)
@@ -491,13 +533,15 @@ int __init acpi_sleep_init(void)
}
}
- suspend_set_ops(&acpi_suspend_ops);
+ suspend_set_ops(old_suspend_ordering ?
+ &acpi_suspend_ops_old : &acpi_suspend_ops);
#endif
#ifdef CONFIG_HIBERNATION
status = acpi_get_sleep_type_data(ACPI_STATE_S4, &type_a, &type_b);
if (ACPI_SUCCESS(status)) {
- hibernation_set_ops(&acpi_hibernation_ops);
+ hibernation_set_ops(old_suspend_ordering ?
+ &acpi_hibernation_ops_old : &acpi_hibernation_ops);
sleep_states[ACPI_STATE_S4] = 1;
printk(" S4");
}
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c
index ed8e41becf0..38655eb132d 100644
--- a/drivers/acpi/sleep/wakeup.c
+++ b/drivers/acpi/sleep/wakeup.c
@@ -42,7 +42,7 @@ void acpi_enable_wakeup_device_prep(u8 sleep_state)
continue;
spin_unlock(&acpi_device_lock);
- acpi_enable_wakeup_device_power(dev);
+ acpi_enable_wakeup_device_power(dev, sleep_state);
spin_lock(&acpi_device_lock);
}
spin_unlock(&acpi_device_lock);
@@ -66,13 +66,15 @@ void acpi_enable_wakeup_device(u8 sleep_state)
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
struct acpi_device *dev =
container_of(node, struct acpi_device, wakeup_list);
+
if (!dev->wakeup.flags.valid)
continue;
+
/* If users want to disable run-wake GPE,
* we only disable it for wake and leave it for runtime
*/
- if (!dev->wakeup.state.enabled ||
- sleep_state > (u32) dev->wakeup.sleep_state) {
+ if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared)
+ || sleep_state > (u32) dev->wakeup.sleep_state) {
if (dev->wakeup.flags.run_wake) {
spin_unlock(&acpi_device_lock);
/* set_gpe_type will disable GPE, leave it like that */
@@ -110,8 +112,9 @@ void acpi_disable_wakeup_device(u8 sleep_state)
if (!dev->wakeup.flags.valid)
continue;
- if (!dev->wakeup.state.enabled ||
- sleep_state > (u32) dev->wakeup.sleep_state) {
+
+ if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared)
+ || sleep_state > (u32) dev->wakeup.sleep_state) {
if (dev->wakeup.flags.run_wake) {
spin_unlock(&acpi_device_lock);
acpi_set_gpe_type(dev->wakeup.gpe_device,
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index 5bd2dec9a7a..d8e3f153b29 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -167,7 +167,13 @@ static int acpi_system_sysfs_init(void)
#define COUNT_ERROR 2 /* other */
#define NUM_COUNTERS_EXTRA 3
-static u32 *all_counters;
+#define ACPI_EVENT_VALID 0x01
+struct event_counter {
+ u32 count;
+ u32 flags;
+};
+
+static struct event_counter *all_counters;
static u32 num_gpes;
static u32 num_counters;
static struct attribute **all_attrs;
@@ -202,9 +208,44 @@ static int count_num_gpes(void)
return count;
}
+static int get_gpe_device(int index, acpi_handle *handle)
+{
+ struct acpi_gpe_xrupt_info *gpe_xrupt_info;
+ struct acpi_gpe_block_info *gpe_block;
+ acpi_cpu_flags flags;
+ struct acpi_namespace_node *node;
+
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+ gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
+ while (gpe_xrupt_info) {
+ gpe_block = gpe_xrupt_info->gpe_block_list_head;
+ node = gpe_block->node;
+ while (gpe_block) {
+ index -= gpe_block->register_count *
+ ACPI_GPE_REGISTER_WIDTH;
+ if (index < 0) {
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+ /* return NULL if it's FADT GPE */
+ if (node->type != ACPI_TYPE_DEVICE)
+ *handle = NULL;
+ else
+ *handle = node;
+ return 0;
+ }
+ node = gpe_block->node;
+ gpe_block = gpe_block->next;
+ }
+ gpe_xrupt_info = gpe_xrupt_info->next;
+ }
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+
+ return -ENODEV;
+}
+
static void delete_gpe_attr_array(void)
{
- u32 *tmp = all_counters;
+ struct event_counter *tmp = all_counters;
all_counters = NULL;
kfree(tmp);
@@ -230,9 +271,10 @@ void acpi_os_gpe_count(u32 gpe_number)
return;
if (gpe_number < num_gpes)
- all_counters[gpe_number]++;
+ all_counters[gpe_number].count++;
else
- all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR]++;
+ all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR].
+ count++;
return;
}
@@ -243,44 +285,144 @@ void acpi_os_fixed_event_count(u32 event_number)
return;
if (event_number < ACPI_NUM_FIXED_EVENTS)
- all_counters[num_gpes + event_number]++;
+ all_counters[num_gpes + event_number].count++;
else
- all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR]++;
+ all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR].
+ count++;
return;
}
+static int get_status(u32 index, acpi_event_status *status, acpi_handle *handle)
+{
+ int result = 0;
+
+ if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS)
+ goto end;
+
+ if (index < num_gpes) {
+ result = get_gpe_device(index, handle);
+ if (result) {
+ ACPI_EXCEPTION((AE_INFO, AE_NOT_FOUND,
+ "Invalid GPE 0x%x\n", index));
+ goto end;
+ }
+ result = acpi_get_gpe_status(*handle, index,
+ ACPI_NOT_ISR, status);
+ } else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS))
+ result = acpi_get_event_status(index - num_gpes, status);
+
+ /*
+ * sleep/power button GPE/Fixed Event is enabled after acpi_system_init,
+ * check the status at runtime and mark it as valid once it's enabled
+ */
+ if (!result && (*status & ACPI_EVENT_FLAG_ENABLED))
+ all_counters[index].flags |= ACPI_EVENT_VALID;
+end:
+ return result;
+}
+
static ssize_t counter_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
- all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI] =
+ int index = attr - counter_attrs;
+ int size;
+ acpi_handle handle;
+ acpi_event_status status;
+ int result = 0;
+
+ all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI].count =
acpi_irq_handled;
- all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE] =
+ all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE].count =
acpi_gpe_count;
- return sprintf(buf, "%d\n", all_counters[attr - counter_attrs]);
+ size = sprintf(buf, "%8d", all_counters[index].count);
+
+ /* "gpe_all" or "sci" */
+ if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS)
+ goto end;
+
+ result = get_status(index, &status, &handle);
+ if (result)
+ goto end;
+
+ if (!(all_counters[index].flags & ACPI_EVENT_VALID))
+ size += sprintf(buf + size, " invalid");
+ else if (status & ACPI_EVENT_FLAG_ENABLED)
+ size += sprintf(buf + size, " enable");
+ else
+ size += sprintf(buf + size, " disable");
+
+end:
+ size += sprintf(buf + size, "\n");
+ return result ? result : size;
}
/*
* counter_set() sets the specified counter.
* setting the total "sci" file to any value clears all counters.
+ * enable/disable/clear a gpe/fixed event in user space.
*/
static ssize_t counter_set(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf, size_t size)
{
int index = attr - counter_attrs;
+ acpi_event_status status;
+ acpi_handle handle;
+ int result = 0;
if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) {
int i;
for (i = 0; i < num_counters; ++i)
- all_counters[i] = 0;
+ all_counters[i].count = 0;
acpi_gpe_count = 0;
acpi_irq_handled = 0;
+ goto end;
+ }
+ /* show the event status for both GPEs and Fixed Events */
+ result = get_status(index, &status, &handle);
+ if (result)
+ goto end;
+
+ if (!(all_counters[index].flags & ACPI_EVENT_VALID)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Can not change Invalid GPE/Fixed Event status\n"));
+ return -EINVAL;
+ }
+
+ if (index < num_gpes) {
+ if (!strcmp(buf, "disable\n") &&
+ (status & ACPI_EVENT_FLAG_ENABLED))
+ result = acpi_disable_gpe(handle, index, ACPI_NOT_ISR);
+ else if (!strcmp(buf, "enable\n") &&
+ !(status & ACPI_EVENT_FLAG_ENABLED))
+ result = acpi_enable_gpe(handle, index, ACPI_NOT_ISR);
+ else if (!strcmp(buf, "clear\n") &&
+ (status & ACPI_EVENT_FLAG_SET))
+ result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR);
+ else
+ all_counters[index].count = strtoul(buf, NULL, 0);
+ } else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) {
+ int event = index - num_gpes;
+ if (!strcmp(buf, "disable\n") &&
+ (status & ACPI_EVENT_FLAG_ENABLED))
+ result = acpi_disable_event(event, ACPI_NOT_ISR);
+ else if (!strcmp(buf, "enable\n") &&
+ !(status & ACPI_EVENT_FLAG_ENABLED))
+ result = acpi_enable_event(event, ACPI_NOT_ISR);
+ else if (!strcmp(buf, "clear\n") &&
+ (status & ACPI_EVENT_FLAG_SET))
+ result = acpi_clear_event(event);
+ else
+ all_counters[index].count = strtoul(buf, NULL, 0);
} else
- all_counters[index] = strtoul(buf, NULL, 0);
+ all_counters[index].count = strtoul(buf, NULL, 0);
- return size;
+ if (ACPI_FAILURE(result))
+ result = -EINVAL;
+end:
+ return result ? result : size;
}
void acpi_irq_stats_init(void)
@@ -298,7 +440,8 @@ void acpi_irq_stats_init(void)
if (all_attrs == NULL)
return;
- all_counters = kzalloc(sizeof(u32) * (num_counters), GFP_KERNEL);
+ all_counters = kzalloc(sizeof(struct event_counter) * (num_counters),
+ GFP_KERNEL);
if (all_counters == NULL)
goto fail;
diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c
index 949d4114eb9..ccb5b64bbef 100644
--- a/drivers/acpi/tables/tbfadt.c
+++ b/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 bit_width, u64 address)
+ u8 byte_width, u64 address)
{
/*
@@ -136,7 +136,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
/* All other fields are byte-wide */
generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO;
- generic_address->bit_width = bit_width;
+ generic_address->bit_width = byte_width << 3;
generic_address->bit_offset = 0;
generic_address->access_width = 0;
}
@@ -155,7 +155,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
*
******************************************************************************/
-void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags)
+void acpi_tb_parse_fadt(u32 table_index, u8 flags)
{
u32 length;
struct acpi_table_header *table;
@@ -280,7 +280,7 @@ static void acpi_tb_convert_fadt(void)
{
u8 pm1_register_length;
struct acpi_generic_address *target;
- acpi_native_uint i;
+ u32 i;
/* Update the local FADT table header length */
@@ -343,9 +343,11 @@ static void acpi_tb_convert_fadt(void)
*
* The PM event blocks are split into two register blocks, first is the
* PM Status Register block, followed immediately by the PM Enable Register
- * block. Each is of length (pm1_event_length/2)
+ * block. Each is of length (xpm1x_event_block.bit_width/2)
*/
- pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length);
+ WARN_ON(ACPI_MOD_16(acpi_gbl_FADT.xpm1a_event_block.bit_width));
+ pm1_register_length = (u8) ACPI_DIV_16(acpi_gbl_FADT
+ .xpm1a_event_block.bit_width);
/* The PM1A register block is required */
@@ -360,14 +362,17 @@ static void acpi_tb_convert_fadt(void)
/* The PM1B register block is optional, ignore if not present */
if (acpi_gbl_FADT.xpm1b_event_block.address) {
+ WARN_ON(ACPI_MOD_16(acpi_gbl_FADT.xpm1b_event_block.bit_width));
+ pm1_register_length = (u8) ACPI_DIV_16(acpi_gbl_FADT
+ .xpm1b_event_block
+ .bit_width);
acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
pm1_register_length,
(acpi_gbl_FADT.xpm1b_event_block.
address + pm1_register_length));
/* Don't forget to copy space_id of the GAS */
acpi_gbl_xpm1b_enable.space_id =
- acpi_gbl_FADT.xpm1a_event_block.space_id;
-
+ acpi_gbl_FADT.xpm1b_event_block.space_id;
}
}
@@ -396,7 +401,7 @@ static void acpi_tb_validate_fadt(void)
u32 *address32;
struct acpi_generic_address *address64;
u8 length;
- acpi_native_uint i;
+ u32 i;
/* Examine all of the 64-bit extended address fields (X fields) */
diff --git a/drivers/acpi/tables/tbfind.c b/drivers/acpi/tables/tbfind.c
index 9ca3afc98c8..531584defbb 100644
--- a/drivers/acpi/tables/tbfind.c
+++ b/drivers/acpi/tables/tbfind.c
@@ -65,10 +65,9 @@ ACPI_MODULE_NAME("tbfind")
******************************************************************************/
acpi_status
acpi_tb_find_table(char *signature,
- char *oem_id,
- char *oem_table_id, acpi_native_uint * table_index)
+ char *oem_id, char *oem_table_id, u32 *table_index)
{
- acpi_native_uint i;
+ u32 i;
acpi_status status;
struct acpi_table_header header;
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
index 5336ce88f89..b22185f55a1 100644
--- a/drivers/acpi/tables/tbinstal.c
+++ b/drivers/acpi/tables/tbinstal.c
@@ -107,11 +107,10 @@ acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc)
******************************************************************************/
acpi_status
-acpi_tb_add_table(struct acpi_table_desc *table_desc,
- acpi_native_uint * table_index)
+acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
{
- acpi_native_uint i;
- acpi_native_uint length;
+ u32 i;
+ u32 length;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(tb_add_table);
@@ -207,8 +206,8 @@ acpi_status acpi_tb_resize_root_table_list(void)
/* Increase the Table Array size */
- tables = ACPI_ALLOCATE_ZEROED((acpi_gbl_root_table_list.size +
- ACPI_ROOT_TABLE_SIZE_INCREMENT)
+ tables = ACPI_ALLOCATE_ZEROED(((acpi_size) acpi_gbl_root_table_list.
+ size + ACPI_ROOT_TABLE_SIZE_INCREMENT)
* sizeof(struct acpi_table_desc));
if (!tables) {
ACPI_ERROR((AE_INFO,
@@ -220,7 +219,7 @@ acpi_status acpi_tb_resize_root_table_list(void)
if (acpi_gbl_root_table_list.tables) {
ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
- acpi_gbl_root_table_list.size *
+ (acpi_size) acpi_gbl_root_table_list.size *
sizeof(struct acpi_table_desc));
if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
@@ -253,7 +252,7 @@ acpi_status acpi_tb_resize_root_table_list(void)
acpi_status
acpi_tb_store_table(acpi_physical_address address,
struct acpi_table_header *table,
- u32 length, u8 flags, acpi_native_uint * table_index)
+ u32 length, u8 flags, u32 *table_index)
{
acpi_status status = AE_OK;
@@ -334,7 +333,7 @@ void acpi_tb_delete_table(struct acpi_table_desc *table_desc)
void acpi_tb_terminate(void)
{
- acpi_native_uint i;
+ u32 i;
ACPI_FUNCTION_TRACE(tb_terminate);
@@ -374,7 +373,7 @@ void acpi_tb_terminate(void)
*
******************************************************************************/
-void acpi_tb_delete_namespace_by_owner(acpi_native_uint table_index)
+void acpi_tb_delete_namespace_by_owner(u32 table_index)
{
acpi_owner_id owner_id;
@@ -403,7 +402,7 @@ void acpi_tb_delete_namespace_by_owner(acpi_native_uint table_index)
*
******************************************************************************/
-acpi_status acpi_tb_allocate_owner_id(acpi_native_uint table_index)
+acpi_status acpi_tb_allocate_owner_id(u32 table_index)
{
acpi_status status = AE_BAD_PARAMETER;
@@ -431,7 +430,7 @@ acpi_status acpi_tb_allocate_owner_id(acpi_native_uint table_index)
*
******************************************************************************/
-acpi_status acpi_tb_release_owner_id(acpi_native_uint table_index)
+acpi_status acpi_tb_release_owner_id(u32 table_index)
{
acpi_status status = AE_BAD_PARAMETER;
@@ -462,8 +461,7 @@ acpi_status acpi_tb_release_owner_id(acpi_native_uint table_index)
*
******************************************************************************/
-acpi_status
-acpi_tb_get_owner_id(acpi_native_uint table_index, acpi_owner_id * owner_id)
+acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id)
{
acpi_status status = AE_BAD_PARAMETER;
@@ -490,7 +488,7 @@ acpi_tb_get_owner_id(acpi_native_uint table_index, acpi_owner_id * owner_id)
*
******************************************************************************/
-u8 acpi_tb_is_table_loaded(acpi_native_uint table_index)
+u8 acpi_tb_is_table_loaded(u32 table_index)
{
u8 is_loaded = FALSE;
@@ -518,7 +516,7 @@ u8 acpi_tb_is_table_loaded(acpi_native_uint table_index)
*
******************************************************************************/
-void acpi_tb_set_table_loaded_flag(acpi_native_uint table_index, u8 is_loaded)
+void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded)
{
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c
index bc019b9b6a6..0cc92ef5236 100644
--- a/drivers/acpi/tables/tbutils.c
+++ b/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,
- acpi_native_uint table_entry_size);
+acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size);
+
/*******************************************************************************
*
* FUNCTION: acpi_tb_check_xsdt
@@ -238,7 +238,7 @@ acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length)
*
******************************************************************************/
-u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length)
+u8 acpi_tb_checksum(u8 *buffer, u32 length)
{
u8 sum = 0;
u8 *end = buffer + length;
@@ -268,7 +268,7 @@ u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length)
void
acpi_tb_install_table(acpi_physical_address address,
- u8 flags, char *signature, acpi_native_uint table_index)
+ u8 flags, char *signature, u32 table_index)
{
struct acpi_table_header *table;
@@ -336,8 +336,7 @@ acpi_tb_install_table(acpi_physical_address address,
******************************************************************************/
static acpi_physical_address
-acpi_tb_get_root_table_entry(u8 * table_entry,
- acpi_native_uint table_entry_size)
+acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size)
{
u64 address64;
@@ -395,8 +394,8 @@ acpi_status __init
acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
{
struct acpi_table_rsdp *rsdp;
- acpi_native_uint table_entry_size;
- acpi_native_uint i;
+ u32 table_entry_size;
+ u32 i;
u32 table_count;
struct acpi_table_header *table;
acpi_physical_address address;
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
index 0e319604d3e..fd7770aa106 100644
--- a/drivers/acpi/tables/tbxface.c
+++ b/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,
- initial_table_count *
+ (acpi_size) initial_table_count *
sizeof(struct acpi_table_desc));
acpi_gbl_root_table_list.tables = initial_table_array;
@@ -183,9 +183,9 @@ acpi_status acpi_reallocate_root_table(void)
return_ACPI_STATUS(AE_SUPPORT);
}
- new_size =
- (acpi_gbl_root_table_list.count +
- ACPI_ROOT_TABLE_SIZE_INCREMENT) * sizeof(struct acpi_table_desc);
+ new_size = ((acpi_size) acpi_gbl_root_table_list.count +
+ ACPI_ROOT_TABLE_SIZE_INCREMENT) *
+ sizeof(struct acpi_table_desc);
/* Create new array and copy the old array */
@@ -222,7 +222,7 @@ acpi_status acpi_reallocate_root_table(void)
acpi_status acpi_load_table(struct acpi_table_header *table_ptr)
{
acpi_status status;
- acpi_native_uint table_index;
+ u32 table_index;
struct acpi_table_desc table_desc;
if (!table_ptr)
@@ -264,11 +264,10 @@ ACPI_EXPORT_SYMBOL(acpi_load_table)
*****************************************************************************/
acpi_status
acpi_get_table_header(char *signature,
- acpi_native_uint instance,
- struct acpi_table_header * out_table_header)
+ u32 instance, struct acpi_table_header *out_table_header)
{
- acpi_native_uint i;
- acpi_native_uint j;
+ u32 i;
+ u32 j;
struct acpi_table_header *header;
/* Parameter validation */
@@ -378,10 +377,10 @@ ACPI_EXPORT_SYMBOL(acpi_unload_table_id)
*****************************************************************************/
acpi_status
acpi_get_table(char *signature,
- acpi_native_uint instance, struct acpi_table_header **out_table)
+ u32 instance, struct acpi_table_header **out_table)
{
- acpi_native_uint i;
- acpi_native_uint j;
+ u32 i;
+ u32 j;
acpi_status status;
/* Parameter validation */
@@ -435,8 +434,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_table)
*
******************************************************************************/
acpi_status
-acpi_get_table_by_index(acpi_native_uint table_index,
- struct acpi_table_header ** table)
+acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table)
{
acpi_status status;
@@ -493,7 +491,7 @@ static acpi_status acpi_tb_load_namespace(void)
{
acpi_status status;
struct acpi_table_header *table;
- acpi_native_uint i;
+ u32 i;
ACPI_FUNCTION_TRACE(tb_load_namespace);
diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c
index b8c0dfa084f..2d157e0f98d 100644
--- a/drivers/acpi/tables/tbxfroot.c
+++ b/drivers/acpi/tables/tbxfroot.c
@@ -118,7 +118,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
*
******************************************************************************/
-acpi_status acpi_find_root_pointer(acpi_native_uint * table_address)
+acpi_status acpi_find_root_pointer(acpi_size *table_address)
{
u8 *table_ptr;
u8 *mem_rover;
@@ -153,7 +153,7 @@ acpi_status acpi_find_root_pointer(acpi_native_uint * table_address)
* 1b) Search EBDA paragraphs (EBDA is required to be a
* minimum of 1_k length)
*/
- table_ptr = acpi_os_map_memory((acpi_native_uint)
+ table_ptr = acpi_os_map_memory((acpi_physical_address)
physical_address,
ACPI_EBDA_WINDOW_SIZE);
if (!table_ptr) {
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c
index ede084829a7..3dfb8a442b2 100644
--- a/drivers/acpi/utilities/utalloc.c
+++ b/drivers/acpi/utilities/utalloc.c
@@ -309,7 +309,8 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
*
******************************************************************************/
-void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line)
+void *acpi_ut_allocate(acpi_size size,
+ u32 component, const char *module, u32 line)
{
void *allocation;
@@ -353,7 +354,7 @@ void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line)
******************************************************************************/
void *acpi_ut_allocate_zeroed(acpi_size size,
- u32 component, char *module, u32 line)
+ u32 component, const char *module, u32 line)
{
void *allocation;
diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
index 655c290aca7..53499ac9098 100644
--- a/drivers/acpi/utilities/utcopy.c
+++ b/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;
- acpi_native_uint i;
+ u32 i;
ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage);
@@ -599,7 +599,7 @@ acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
/* Truncate package and delete it */
- package_object->package.count = (u32) i;
+ package_object->package.count = i;
package_elements[i] = NULL;
acpi_ut_remove_reference(package_object);
return_ACPI_STATUS(status);
diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c
index f938f465efa..fd66ecb6741 100644
--- a/drivers/acpi/utilities/utdebug.c
+++ b/drivers/acpi/utilities/utdebug.c
@@ -157,7 +157,8 @@ void ACPI_INTERNAL_VAR_XFACE
acpi_ut_debug_print(u32 requested_debug_level,
u32 line_number,
const char *function_name,
- char *module_name, u32 component_id, char *format, ...)
+ const char *module_name,
+ u32 component_id, const char *format, ...)
{
acpi_thread_id thread_id;
va_list args;
@@ -228,7 +229,8 @@ void ACPI_INTERNAL_VAR_XFACE
acpi_ut_debug_print_raw(u32 requested_debug_level,
u32 line_number,
const char *function_name,
- char *module_name, u32 component_id, char *format, ...)
+ const char *module_name,
+ u32 component_id, const char *format, ...)
{
va_list args;
@@ -261,7 +263,8 @@ ACPI_EXPORT_SYMBOL(acpi_ut_debug_print_raw)
******************************************************************************/
void
acpi_ut_trace(u32 line_number,
- const char *function_name, char *module_name, u32 component_id)
+ const char *function_name,
+ const char *module_name, u32 component_id)
{
acpi_gbl_nesting_level++;
@@ -293,7 +296,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_trace)
void
acpi_ut_trace_ptr(u32 line_number,
const char *function_name,
- char *module_name, u32 component_id, void *pointer)
+ const char *module_name, u32 component_id, void *pointer)
{
acpi_gbl_nesting_level++;
acpi_ut_track_stack_ptr();
@@ -324,7 +327,7 @@ acpi_ut_trace_ptr(u32 line_number,
void
acpi_ut_trace_str(u32 line_number,
const char *function_name,
- char *module_name, u32 component_id, char *string)
+ const char *module_name, u32 component_id, char *string)
{
acpi_gbl_nesting_level++;
@@ -356,7 +359,7 @@ acpi_ut_trace_str(u32 line_number,
void
acpi_ut_trace_u32(u32 line_number,
const char *function_name,
- char *module_name, u32 component_id, u32 integer)
+ const char *module_name, u32 component_id, u32 integer)
{
acpi_gbl_nesting_level++;
@@ -386,7 +389,8 @@ acpi_ut_trace_u32(u32 line_number,
void
acpi_ut_exit(u32 line_number,
- const char *function_name, char *module_name, u32 component_id)
+ const char *function_name,
+ const char *module_name, u32 component_id)
{
acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
@@ -417,7 +421,8 @@ ACPI_EXPORT_SYMBOL(acpi_ut_exit)
void
acpi_ut_status_exit(u32 line_number,
const char *function_name,
- char *module_name, u32 component_id, acpi_status status)
+ const char *module_name,
+ u32 component_id, acpi_status status)
{
if (ACPI_SUCCESS(status)) {
@@ -458,7 +463,8 @@ ACPI_EXPORT_SYMBOL(acpi_ut_status_exit)
void
acpi_ut_value_exit(u32 line_number,
const char *function_name,
- char *module_name, u32 component_id, acpi_integer value)
+ const char *module_name,
+ u32 component_id, acpi_integer value)
{
acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
@@ -490,7 +496,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_value_exit)
void
acpi_ut_ptr_exit(u32 line_number,
const char *function_name,
- char *module_name, u32 component_id, u8 * ptr)
+ const char *module_name, u32 component_id, u8 *ptr)
{
acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
@@ -519,8 +525,8 @@ acpi_ut_ptr_exit(u32 line_number,
void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
{
- acpi_native_uint i = 0;
- acpi_native_uint j;
+ u32 i = 0;
+ u32 j;
u32 temp32;
u8 buf_char;
@@ -539,7 +545,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
/* Print current offset */
- acpi_os_printf("%6.4X: ", (u32) i);
+ acpi_os_printf("%6.4X: ", i);
/* Print 16 hex chars */
@@ -549,7 +555,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
/* Dump fill spaces */
acpi_os_printf("%*s", ((display * 2) + 1), " ");
- j += (acpi_native_uint) display;
+ j += display;
continue;
}
@@ -557,32 +563,38 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
case DB_BYTE_DISPLAY:
default: /* Default is BYTE display */
- acpi_os_printf("%02X ", buffer[i + j]);
+ acpi_os_printf("%02X ",
+ buffer[(acpi_size) i + j]);
break;
case DB_WORD_DISPLAY:
- ACPI_MOVE_16_TO_32(&temp32, &buffer[i + j]);
+ ACPI_MOVE_16_TO_32(&temp32,
+ &buffer[(acpi_size) i + j]);
acpi_os_printf("%04X ", temp32);
break;
case DB_DWORD_DISPLAY:
- ACPI_MOVE_32_TO_32(&temp32, &buffer[i + j]);
+ ACPI_MOVE_32_TO_32(&temp32,
+ &buffer[(acpi_size) i + j]);
acpi_os_printf("%08X ", temp32);
break;
case DB_QWORD_DISPLAY:
- ACPI_MOVE_32_TO_32(&temp32, &buffer[i + j]);
+ ACPI_MOVE_32_TO_32(&temp32,
+ &buffer[(acpi_size) i + j]);
acpi_os_printf("%08X", temp32);
- ACPI_MOVE_32_TO_32(&temp32, &buffer[i + j + 4]);
+ ACPI_MOVE_32_TO_32(&temp32,
+ &buffer[(acpi_size) i + j +
+ 4]);
acpi_os_printf("%08X ", temp32);
break;
}
- j += (acpi_native_uint) display;
+ j += display;
}
/*
@@ -596,7 +608,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
return;
}
- buf_char = buffer[i + j];
+ buf_char = buffer[(acpi_size) i + j];
if (ACPI_IS_PRINT(buf_char)) {
acpi_os_printf("%c", buf_char);
} else {
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
index 1fbc35139e8..c5c791a575c 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/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;
- acpi_native_uint i;
+ u32 i;
ACPI_FUNCTION_TRACE_PTR(ut_update_object_reference, object);
diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c
index 05e61be267d..352747e49c7 100644
--- a/drivers/acpi/utilities/uteval.c
+++ b/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;
- acpi_native_uint i;
+ u32 i;
ACPI_FUNCTION_TRACE(ut_osi_implementation);
@@ -217,7 +217,6 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
info->prefix_node = prefix_node;
info->pathname = path;
- info->parameter_type = ACPI_PARAM_ARGS;
/* Evaluate the object/method */
@@ -514,7 +513,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node * device_node,
u32 count;
u32 size;
struct acpi_compatible_id_list *cid_list;
- acpi_native_uint i;
+ u32 i;
ACPI_FUNCTION_TRACE(ut_execute_CID);
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
index 1f057b71db1..f34be677355 100644
--- a/drivers/acpi/utilities/utmisc.c
+++ b/drivers/acpi/utilities/utmisc.c
@@ -64,7 +64,7 @@ ACPI_MODULE_NAME("utmisc")
******************************************************************************/
const char *acpi_ut_validate_exception(acpi_status status)
{
- acpi_status sub_status;
+ u32 sub_status;
const char *exception = NULL;
ACPI_FUNCTION_ENTRY();
@@ -85,32 +85,28 @@ const char *acpi_ut_validate_exception(acpi_status status)
case AE_CODE_PROGRAMMER:
if (sub_status <= AE_CODE_PGM_MAX) {
- exception =
- acpi_gbl_exception_names_pgm[sub_status - 1];
+ exception = acpi_gbl_exception_names_pgm[sub_status];
}
break;
case AE_CODE_ACPI_TABLES:
if (sub_status <= AE_CODE_TBL_MAX) {
- exception =
- acpi_gbl_exception_names_tbl[sub_status - 1];
+ exception = acpi_gbl_exception_names_tbl[sub_status];
}
break;
case AE_CODE_AML:
if (sub_status <= AE_CODE_AML_MAX) {
- exception =
- acpi_gbl_exception_names_aml[sub_status - 1];
+ exception = acpi_gbl_exception_names_aml[sub_status];
}
break;
case AE_CODE_CONTROL:
if (sub_status <= AE_CODE_CTRL_MAX) {
- exception =
- acpi_gbl_exception_names_ctrl[sub_status - 1];
+ exception = acpi_gbl_exception_names_ctrl[sub_status];
}
break;
@@ -165,9 +161,9 @@ u8 acpi_ut_is_aml_table(struct acpi_table_header *table)
acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
{
- acpi_native_uint i;
- acpi_native_uint j;
- acpi_native_uint k;
+ u32 i;
+ u32 j;
+ u32 k;
acpi_status status;
ACPI_FUNCTION_TRACE(ut_allocate_owner_id);
@@ -273,7 +269,7 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr)
{
acpi_owner_id owner_id = *owner_id_ptr;
acpi_status status;
- acpi_native_uint index;
+ u32 index;
u32 bit;
ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id);
@@ -593,7 +589,7 @@ acpi_ut_display_init_pathname(u8 type,
*
******************************************************************************/
-u8 acpi_ut_valid_acpi_char(char character, acpi_native_uint position)
+u8 acpi_ut_valid_acpi_char(char character, u32 position)
{
if (!((character >= 'A' && character <= 'Z') ||
@@ -628,7 +624,7 @@ u8 acpi_ut_valid_acpi_char(char character, acpi_native_uint position)
u8 acpi_ut_valid_acpi_name(u32 name)
{
- acpi_native_uint i;
+ u32 i;
ACPI_FUNCTION_ENTRY();
@@ -657,7 +653,7 @@ u8 acpi_ut_valid_acpi_name(u32 name)
acpi_name acpi_ut_repair_name(char *name)
{
- acpi_native_uint i;
+ u32 i;
char new_name[ACPI_NAME_SIZE];
for (i = 0; i < ACPI_NAME_SIZE; i++) {
@@ -1024,7 +1020,7 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
******************************************************************************/
void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_error(char *module_name, u32 line_number, char *format, ...)
+acpi_ut_error(const char *module_name, u32 line_number, const char *format, ...)
{
va_list args;
@@ -1037,8 +1033,8 @@ acpi_ut_error(char *module_name, u32 line_number, char *format, ...)
}
void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_exception(char *module_name,
- u32 line_number, acpi_status status, char *format, ...)
+acpi_ut_exception(const char *module_name,
+ u32 line_number, acpi_status status, const char *format, ...)
{
va_list args;
@@ -1054,7 +1050,8 @@ acpi_ut_exception(char *module_name,
EXPORT_SYMBOL(acpi_ut_exception);
void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_warning(char *module_name, u32 line_number, char *format, ...)
+acpi_ut_warning(const char *module_name,
+ u32 line_number, const char *format, ...)
{
va_list args;
@@ -1067,7 +1064,7 @@ acpi_ut_warning(char *module_name, u32 line_number, char *format, ...)
}
void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_info(char *module_name, u32 line_number, char *format, ...)
+acpi_ut_info(const char *module_name, u32 line_number, const char *format, ...)
{
va_list args;
diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c
index f7d602b1a89..7331dde9e1b 100644
--- a/drivers/acpi/utilities/utmutex.c
+++ b/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_MAX_MUTEX; i++) {
+ for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
if (i == mutex_id) {
ACPI_ERROR((AE_INFO,
@@ -315,7 +315,7 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
* ordering rule. This indicates a coding error somewhere in
* the ACPI subsystem code.
*/
- for (i = mutex_id; i < ACPI_MAX_MUTEX; i++) {
+ for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
if (i == mutex_id) {
continue;
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c
index e68466de804..e25484495e6 100644
--- a/drivers/acpi/utilities/utobject.c
+++ b/drivers/acpi/utilities/utobject.c
@@ -83,7 +83,8 @@ acpi_ut_get_element_length(u8 object_type,
*
******************************************************************************/
-union acpi_operand_object *acpi_ut_create_internal_object_dbg(char *module_name,
+union acpi_operand_object *acpi_ut_create_internal_object_dbg(const char
+ *module_name,
u32 line_number,
u32 component_id,
acpi_object_type
@@ -175,8 +176,8 @@ union acpi_operand_object *acpi_ut_create_package_object(u32 count)
* Create the element array. Count+1 allows the array to be null
* terminated.
*/
- package_elements = ACPI_ALLOCATE_ZEROED((acpi_size)
- (count + 1) * sizeof(void *));
+ package_elements = ACPI_ALLOCATE_ZEROED(((acpi_size) count +
+ 1) * sizeof(void *));
if (!package_elements) {
acpi_ut_remove_reference(package_desc);
return_PTR(NULL);
@@ -347,7 +348,7 @@ u8 acpi_ut_valid_internal_object(void *object)
*
******************************************************************************/
-void *acpi_ut_allocate_object_desc_dbg(char *module_name,
+void *acpi_ut_allocate_object_desc_dbg(const char *module_name,
u32 line_number, u32 component_id)
{
union acpi_operand_object *object;
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index d089c4519d4..64c889331f3 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -631,6 +631,76 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
* device : video output device (LCD, CRT, ..)
*
* Return Value:
+ * Maximum brightness level
+ *
+ * Allocate and initialize device->brightness.
+ */
+
+static int
+acpi_video_init_brightness(struct acpi_video_device *device)
+{
+ union acpi_object *obj = NULL;
+ int i, max_level = 0, count = 0;
+ union acpi_object *o;
+ struct acpi_video_device_brightness *br = NULL;
+
+ if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available "
+ "LCD brightness level\n"));
+ goto out;
+ }
+
+ if (obj->package.count < 2)
+ goto out;
+
+ br = kzalloc(sizeof(*br), GFP_KERNEL);
+ if (!br) {
+ printk(KERN_ERR "can't allocate memory\n");
+ goto out;
+ }
+
+ br->levels = kmalloc(obj->package.count * sizeof *(br->levels),
+ GFP_KERNEL);
+ if (!br->levels)
+ goto out_free;
+
+ for (i = 0; i < obj->package.count; i++) {
+ o = (union acpi_object *)&obj->package.elements[i];
+ if (o->type != ACPI_TYPE_INTEGER) {
+ printk(KERN_ERR PREFIX "Invalid data\n");
+ continue;
+ }
+ br->levels[count] = (u32) o->integer.value;
+
+ if (br->levels[count] > max_level)
+ max_level = br->levels[count];
+ count++;
+ }
+
+ if (count < 2)
+ goto out_free_levels;
+
+ br->count = count;
+ device->brightness = br;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "found %d brightness levels\n", count));
+ kfree(obj);
+ return max_level;
+
+out_free_levels:
+ kfree(br->levels);
+out_free:
+ kfree(br);
+out:
+ device->brightness = NULL;
+ kfree(obj);
+ return 0;
+}
+
+/*
+ * Arg:
+ * device : video output device (LCD, CRT, ..)
+ *
+ * Return Value:
* None
*
* Find out all required AML methods defined under the output
@@ -640,10 +710,7 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
static void acpi_video_device_find_cap(struct acpi_video_device *device)
{
acpi_handle h_dummy1;
- int i;
u32 max_level = 0;
- union acpi_object *obj = NULL;
- struct acpi_video_device_brightness *br = NULL;
memset(&device->cap, 0, sizeof(device->cap));
@@ -672,53 +739,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
device->cap._DSS = 1;
}
- if (ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
-
- if (obj->package.count >= 2) {
- int count = 0;
- union acpi_object *o;
-
- br = kzalloc(sizeof(*br), GFP_KERNEL);
- if (!br) {
- printk(KERN_ERR "can't allocate memory\n");
- } else {
- br->levels = kmalloc(obj->package.count *
- sizeof *(br->levels), GFP_KERNEL);
- if (!br->levels)
- goto out;
-
- for (i = 0; i < obj->package.count; i++) {
- o = (union acpi_object *)&obj->package.
- elements[i];
- if (o->type != ACPI_TYPE_INTEGER) {
- printk(KERN_ERR PREFIX "Invalid data\n");
- continue;
- }
- br->levels[count] = (u32) o->integer.value;
-
- if (br->levels[count] > max_level)
- max_level = br->levels[count];
- count++;
- }
- out:
- if (count < 2) {
- kfree(br->levels);
- kfree(br);
- } else {
- br->count = count;
- device->brightness = br;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "found %d brightness levels\n",
- count));
- }
- }
- }
-
- } else {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available LCD brightness level\n"));
- }
-
- kfree(obj);
+ max_level = acpi_video_init_brightness(device);
if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){
int result;
@@ -1695,6 +1716,8 @@ static void
acpi_video_switch_brightness(struct acpi_video_device *device, int event)
{
unsigned long level_current, level_next;
+ if (!device->brightness)
+ return;
acpi_video_device_lcd_get_level_current(device, &level_current);
level_next = acpi_video_get_next_level(device, level_current, event);
acpi_video_device_lcd_set_level(device, level_next);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 911ec600fe7..3f940393d6c 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -453,6 +453,8 @@ int platform_driver_register(struct platform_driver *drv)
drv->driver.suspend = platform_drv_suspend;
if (drv->resume)
drv->driver.resume = platform_drv_resume;
+ if (drv->pm)
+ drv->driver.pm = &drv->pm->base;
return driver_register(&drv->driver);
}
EXPORT_SYMBOL_GPL(platform_driver_register);
@@ -560,7 +562,9 @@ static int platform_match(struct device *dev, struct device_driver *drv)
return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
}
-static int platform_suspend(struct device *dev, pm_message_t mesg)
+#ifdef CONFIG_PM_SLEEP
+
+static int platform_legacy_suspend(struct device *dev, pm_message_t mesg)
{
int ret = 0;
@@ -570,7 +574,7 @@ static int platform_suspend(struct device *dev, pm_message_t mesg)
return ret;
}
-static int platform_suspend_late(struct device *dev, pm_message_t mesg)
+static int platform_legacy_suspend_late(struct device *dev, pm_message_t mesg)
{
struct platform_driver *drv = to_platform_driver(dev->driver);
struct platform_device *pdev;
@@ -583,7 +587,7 @@ static int platform_suspend_late(struct device *dev, pm_message_t mesg)
return ret;
}
-static int platform_resume_early(struct device *dev)
+static int platform_legacy_resume_early(struct device *dev)
{
struct platform_driver *drv = to_platform_driver(dev->driver);
struct platform_device *pdev;
@@ -596,7 +600,7 @@ static int platform_resume_early(struct device *dev)
return ret;
}
-static int platform_resume(struct device *dev)
+static int platform_legacy_resume(struct device *dev)
{
int ret = 0;
@@ -606,15 +610,291 @@ static int platform_resume(struct device *dev)
return ret;
}
+static int platform_pm_prepare(struct device *dev)
+{
+ struct device_driver *drv = dev->driver;
+ int ret = 0;
+
+ if (drv && drv->pm && drv->pm->prepare)
+ ret = drv->pm->prepare(dev);
+
+ return ret;
+}
+
+static void platform_pm_complete(struct device *dev)
+{
+ struct device_driver *drv = dev->driver;
+
+ if (drv && drv->pm && drv->pm->complete)
+ drv->pm->complete(dev);
+}
+
+#ifdef CONFIG_SUSPEND
+
+static int platform_pm_suspend(struct device *dev)
+{
+ struct device_driver *drv = dev->driver;
+ int ret = 0;
+
+ if (drv && drv->pm) {
+ if (drv->pm->suspend)
+ ret = drv->pm->suspend(dev);
+ } else {
+ ret = platform_legacy_suspend(dev, PMSG_SUSPEND);
+ }
+
+ return ret;
+}
+
+static int platform_pm_suspend_noirq(struct device *dev)
+{
+ struct platform_driver *pdrv;
+ int ret = 0;
+
+ if (!dev->driver)
+ return 0;
+
+ pdrv = to_platform_driver(dev->driver);
+ if (pdrv->pm) {
+ if (pdrv->pm->suspend_noirq)
+ ret = pdrv->pm->suspend_noirq(dev);
+ } else {
+ ret = platform_legacy_suspend_late(dev, PMSG_SUSPEND);
+ }
+
+ return ret;
+}
+
+static int platform_pm_resume(struct device *dev)
+{
+ struct device_driver *drv = dev->driver;
+ int ret = 0;
+
+ if (drv && drv->pm) {
+ if (drv->pm->resume)
+ ret = drv->pm->resume(dev);
+ } else {
+ ret = platform_legacy_resume(dev);
+ }
+
+ return ret;
+}
+
+static int platform_pm_resume_noirq(struct device *dev)
+{
+ struct platform_driver *pdrv;
+ int ret = 0;
+
+ if (!dev->driver)
+ return 0;
+
+ pdrv = to_platform_driver(dev->driver);
+ if (pdrv->pm) {
+ if (pdrv->pm->resume_noirq)
+ ret = pdrv->pm->resume_noirq(dev);
+ } else {
+ ret = platform_legacy_resume_early(dev);
+ }
+
+ return ret;
+}
+
+#else /* !CONFIG_SUSPEND */
+
+#define platform_pm_suspend NULL
+#define platform_pm_resume NULL
+#define platform_pm_suspend_noirq NULL
+#define platform_pm_resume_noirq NULL
+
+#endif /* !CONFIG_SUSPEND */
+
+#ifdef CONFIG_HIBERNATION
+
+static int platform_pm_freeze(struct device *dev)
+{
+ struct device_driver *drv = dev->driver;
+ int ret = 0;
+
+ if (!drv)
+ return 0;
+
+ if (drv->pm) {
+ if (drv->pm->freeze)
+ ret = drv->pm->freeze(dev);
+ } else {
+ ret = platform_legacy_suspend(dev, PMSG_FREEZE);
+ }
+
+ return ret;
+}
+
+static int platform_pm_freeze_noirq(struct device *dev)
+{
+ struct platform_driver *pdrv;
+ int ret = 0;
+
+ if (!dev->driver)
+ return 0;
+
+ pdrv = to_platform_driver(dev->driver);
+ if (pdrv->pm) {
+ if (pdrv->pm->freeze_noirq)
+ ret = pdrv->pm->freeze_noirq(dev);
+ } else {
+ ret = platform_legacy_suspend_late(dev, PMSG_FREEZE);
+ }
+
+ return ret;
+}
+
+static int platform_pm_thaw(struct device *dev)
+{
+ struct device_driver *drv = dev->driver;
+ int ret = 0;
+
+ if (drv && drv->pm) {
+ if (drv->pm->thaw)
+ ret = drv->pm->thaw(dev);
+ } else {
+ ret = platform_legacy_resume(dev);
+ }
+
+ return ret;
+}
+
+static int platform_pm_thaw_noirq(struct device *dev)
+{
+ struct platform_driver *pdrv;
+ int ret = 0;
+
+ if (!dev->driver)
+ return 0;
+
+ pdrv = to_platform_driver(dev->driver);
+ if (pdrv->pm) {
+ if (pdrv->pm->thaw_noirq)
+ ret = pdrv->pm->thaw_noirq(dev);
+ } else {
+ ret = platform_legacy_resume_early(dev);
+ }
+
+ return ret;
+}
+
+static int platform_pm_poweroff(struct device *dev)
+{
+ struct device_driver *drv = dev->driver;
+ int ret = 0;
+
+ if (drv && drv->pm) {
+ if (drv->pm->poweroff)
+ ret = drv->pm->poweroff(dev);
+ } else {
+ ret = platform_legacy_suspend(dev, PMSG_HIBERNATE);
+ }
+
+ return ret;
+}
+
+static int platform_pm_poweroff_noirq(struct device *dev)
+{
+ struct platform_driver *pdrv;
+ int ret = 0;
+
+ if (!dev->driver)
+ return 0;
+
+ pdrv = to_platform_driver(dev->driver);
+ if (pdrv->pm) {
+ if (pdrv->pm->poweroff_noirq)
+ ret = pdrv->pm->poweroff_noirq(dev);
+ } else {
+ ret = platform_legacy_suspend_late(dev, PMSG_HIBERNATE);
+ }
+
+ return ret;
+}
+
+static int platform_pm_restore(struct device *dev)
+{
+ struct device_driver *drv = dev->driver;
+ int ret = 0;
+
+ if (drv && drv->pm) {
+ if (drv->pm->restore)
+ ret = drv->pm->restore(dev);
+ } else {
+ ret = platform_legacy_resume(dev);
+ }
+
+ return ret;
+}
+
+static int platform_pm_restore_noirq(struct device *dev)
+{
+ struct platform_driver *pdrv;
+ int ret = 0;
+
+ if (!dev->driver)
+ return 0;
+
+ pdrv = to_platform_driver(dev->driver);
+ if (pdrv->pm) {
+ if (pdrv->pm->restore_noirq)
+ ret = pdrv->pm->restore_noirq(dev);
+ } else {
+ ret = platform_legacy_resume_early(dev);
+ }
+
+ return ret;
+}
+
+#else /* !CONFIG_HIBERNATION */
+
+#define platform_pm_freeze NULL
+#define platform_pm_thaw NULL
+#define platform_pm_poweroff NULL
+#define platform_pm_restore NULL
+#define platform_pm_freeze_noirq NULL
+#define platform_pm_thaw_noirq NULL
+#define platform_pm_poweroff_noirq NULL
+#define platform_pm_restore_noirq NULL
+
+#endif /* !CONFIG_HIBERNATION */
+
+struct pm_ext_ops platform_pm_ops = {
+ .base = {
+ .prepare = platform_pm_prepare,
+ .complete = platform_pm_complete,
+ .suspend = platform_pm_suspend,
+ .resume = platform_pm_resume,
+ .freeze = platform_pm_freeze,
+ .thaw = platform_pm_thaw,
+ .poweroff = platform_pm_poweroff,
+ .restore = platform_pm_restore,
+ },
+ .suspend_noirq = platform_pm_suspend_noirq,
+ .resume_noirq = platform_pm_resume_noirq,
+ .freeze_noirq = platform_pm_freeze_noirq,
+ .thaw_noirq = platform_pm_thaw_noirq,
+ .poweroff_noirq = platform_pm_poweroff_noirq,
+ .restore_noirq = platform_pm_restore_noirq,
+};
+
+#define PLATFORM_PM_OPS_PTR &platform_pm_ops
+
+#else /* !CONFIG_PM_SLEEP */
+
+#define PLATFORM_PM_OPS_PTR NULL
+
+#endif /* !CONFIG_PM_SLEEP */
+
struct bus_type platform_bus_type = {
.name = "platform",
.dev_attrs = platform_dev_attrs,
.match = platform_match,
.uevent = platform_uevent,
- .suspend = platform_suspend,
- .suspend_late = platform_suspend_late,
- .resume_early = platform_resume_early,
- .resume = platform_resume,
+ .pm = PLATFORM_PM_OPS_PTR,
};
EXPORT_SYMBOL_GPL(platform_bus_type);
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 45cc3d9eacb..3250c5257b7 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -12,11 +12,9 @@
* and add it to the list of power-controlled devices. sysfs entries for
* controlling device power management will also be added.
*
- * A different set of lists than the global subsystem list are used to
- * keep track of power info because we use different lists to hold
- * devices based on what stage of the power management process they
- * are in. The power domain dependencies may also differ from the
- * ancestral dependencies that the subsystem list maintains.
+ * A separate list is used for keeping track of power info, because the power
+ * domain dependencies may differ from the ancestral dependencies that the
+ * subsystem list maintains.
*/
#include <linux/device.h>
@@ -30,31 +28,40 @@
#include "power.h"
/*
- * The entries in the dpm_active list are in a depth first order, simply
+ * The entries in the dpm_list list are in a depth first order, simply
* because children are guaranteed to be discovered after parents, and
* are inserted at the back of the list on discovery.
*
- * All the other lists are kept in the same order, for consistency.
- * However the lists aren't always traversed in the same order.
- * Semaphores must be acquired from the top (i.e., front) down
- * and released in the opposite order. Devices must be suspended
- * from the bottom (i.e., end) up and resumed in the opposite order.
- * That way no parent will be suspended while it still has an active
- * child.
- *
* Since device_pm_add() may be called with a device semaphore held,
* we must never try to acquire a device semaphore while holding
* dpm_list_mutex.
*/
-LIST_HEAD(dpm_active);
-static LIST_HEAD(dpm_off);
-static LIST_HEAD(dpm_off_irq);
+LIST_HEAD(dpm_list);
static DEFINE_MUTEX(dpm_list_mtx);
-/* 'true' if all devices have been suspended, protected by dpm_list_mtx */
-static bool all_sleeping;
+/*
+ * Set once the preparation of devices for a PM transition has started, reset
+ * before starting to resume devices. Protected by dpm_list_mtx.
+ */
+static bool transition_started;
+
+/**
+ * device_pm_lock - lock the list of active devices used by the PM core
+ */
+void device_pm_lock(void)
+{
+ mutex_lock(&dpm_list_mtx);
+}
+
+/**
+ * device_pm_unlock - unlock the list of active devices used by the PM core
+ */
+void device_pm_unlock(void)
+{
+ mutex_unlock(&dpm_list_mtx);
+}
/**
* device_pm_add - add a device to the list of active devices
@@ -68,17 +75,25 @@ int device_pm_add(struct device *dev)
dev->bus ? dev->bus->name : "No Bus",
kobject_name(&dev->kobj));
mutex_lock(&dpm_list_mtx);
- if ((dev->parent && dev->parent->power.sleeping) || all_sleeping) {
- if (dev->parent->power.sleeping)
- dev_warn(dev, "parent %s is sleeping\n",
+ if (dev->parent) {
+ if (dev->parent->power.status >= DPM_SUSPENDING) {
+ dev_warn(dev, "parent %s is sleeping, will not add\n",
dev->parent->bus_id);
- else
- dev_warn(dev, "all devices are sleeping\n");
+ WARN_ON(true);
+ }
+ } else if (transition_started) {
+ /*
+ * We refuse to register parentless devices while a PM
+ * transition is in progress in order to avoid leaving them
+ * unhandled down the road
+ */
WARN_ON(true);
}
error = dpm_sysfs_add(dev);
- if (!error)
- list_add_tail(&dev->power.entry, &dpm_active);
+ if (!error) {
+ dev->power.status = DPM_ON;
+ list_add_tail(&dev->power.entry, &dpm_list);
+ }
mutex_unlock(&dpm_list_mtx);
return error;
}
@@ -100,73 +115,243 @@ void device_pm_remove(struct device *dev)
mutex_unlock(&dpm_list_mtx);
}
+/**
+ * pm_op - execute the PM operation appropiate for given PM event
+ * @dev: Device.
+ * @ops: PM operations to choose from.
+ * @state: PM transition of the system being carried out.
+ */
+static int pm_op(struct device *dev, struct pm_ops *ops, pm_message_t state)
+{
+ int error = 0;
+
+ switch (state.event) {
+#ifdef CONFIG_SUSPEND
+ case PM_EVENT_SUSPEND:
+ if (ops->suspend) {
+ error = ops->suspend(dev);
+ suspend_report_result(ops->suspend, error);
+ }
+ break;
+ case PM_EVENT_RESUME:
+ if (ops->resume) {
+ error = ops->resume(dev);
+ suspend_report_result(ops->resume, error);
+ }
+ break;
+#endif /* CONFIG_SUSPEND */
+#ifdef CONFIG_HIBERNATION
+ case PM_EVENT_FREEZE:
+ case PM_EVENT_QUIESCE:
+ if (ops->freeze) {
+ error = ops->freeze(dev);
+ suspend_report_result(ops->freeze, error);
+ }
+ break;
+ case PM_EVENT_HIBERNATE:
+ if (ops->poweroff) {
+ error = ops->poweroff(dev);
+ suspend_report_result(ops->poweroff, error);
+ }
+ break;
+ case PM_EVENT_THAW:
+ case PM_EVENT_RECOVER:
+ if (ops->thaw) {
+ error = ops->thaw(dev);
+ suspend_report_result(ops->thaw, error);
+ }
+ break;
+ case PM_EVENT_RESTORE:
+ if (ops->restore) {
+ error = ops->restore(dev);
+ suspend_report_result(ops->restore, error);
+ }
+ break;
+#endif /* CONFIG_HIBERNATION */
+ default:
+ error = -EINVAL;
+ }
+ return error;
+}
+
+/**
+ * pm_noirq_op - execute the PM operation appropiate for given PM event
+ * @dev: Device.
+ * @ops: PM operations to choose from.
+ * @state: PM transition of the system being carried out.
+ *
+ * The operation is executed with interrupts disabled by the only remaining
+ * functional CPU in the system.
+ */
+static int pm_noirq_op(struct device *dev, struct pm_ext_ops *ops,
+ pm_message_t state)
+{
+ int error = 0;
+
+ switch (state.event) {
+#ifdef CONFIG_SUSPEND
+ case PM_EVENT_SUSPEND:
+ if (ops->suspend_noirq) {
+ error = ops->suspend_noirq(dev);
+ suspend_report_result(ops->suspend_noirq, error);
+ }
+ break;
+ case PM_EVENT_RESUME:
+ if (ops->resume_noirq) {
+ error = ops->resume_noirq(dev);
+ suspend_report_result(ops->resume_noirq, error);
+ }
+ break;
+#endif /* CONFIG_SUSPEND */
+#ifdef CONFIG_HIBERNATION
+ case PM_EVENT_FREEZE:
+ case PM_EVENT_QUIESCE:
+ if (ops->freeze_noirq) {
+ error = ops->freeze_noirq(dev);
+ suspend_report_result(ops->freeze_noirq, error);
+ }
+ break;
+ case PM_EVENT_HIBERNATE:
+ if (ops->poweroff_noirq) {
+ error = ops->poweroff_noirq(dev);
+ suspend_report_result(ops->poweroff_noirq, error);
+ }
+ break;
+ case PM_EVENT_THAW:
+ case PM_EVENT_RECOVER:
+ if (ops->thaw_noirq) {
+ error = ops->thaw_noirq(dev);
+ suspend_report_result(ops->thaw_noirq, error);
+ }
+ break;
+ case PM_EVENT_RESTORE:
+ if (ops->restore_noirq) {
+ error = ops->restore_noirq(dev);
+ suspend_report_result(ops->restore_noirq, error);
+ }
+ break;
+#endif /* CONFIG_HIBERNATION */
+ default:
+ error = -EINVAL;
+ }
+ return error;
+}
+
+static char *pm_verb(int event)
+{
+ switch (event) {
+ case PM_EVENT_SUSPEND:
+ return "suspend";
+ case PM_EVENT_RESUME:
+ return "resume";
+ case PM_EVENT_FREEZE:
+ return "freeze";
+ case PM_EVENT_QUIESCE:
+ return "quiesce";
+ case PM_EVENT_HIBERNATE:
+ return "hibernate";
+ case PM_EVENT_THAW:
+ return "thaw";
+ case PM_EVENT_RESTORE:
+ return "restore";
+ case PM_EVENT_RECOVER:
+ return "recover";
+ default:
+ return "(unknown PM event)";
+ }
+}
+
+static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info)
+{
+ dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event),
+ ((state.event & PM_EVENT_SLEEP) && device_may_wakeup(dev)) ?
+ ", may wakeup" : "");
+}
+
+static void pm_dev_err(struct device *dev, pm_message_t state, char *info,
+ int error)
+{
+ printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n",
+ kobject_name(&dev->kobj), pm_verb(state.event), info, error);
+}
+
/*------------------------- Resume routines -------------------------*/
/**
- * resume_device_early - Power on one device (early resume).
+ * resume_device_noirq - Power on one device (early resume).
* @dev: Device.
+ * @state: PM transition of the system being carried out.
*
* Must be called with interrupts disabled.
*/
-static int resume_device_early(struct device *dev)
+static int resume_device_noirq(struct device *dev, pm_message_t state)
{
int error = 0;
TRACE_DEVICE(dev);
TRACE_RESUME(0);
- if (dev->bus && dev->bus->resume_early) {
- dev_dbg(dev, "EARLY resume\n");
+ if (!dev->bus)
+ goto End;
+
+ if (dev->bus->pm) {
+ pm_dev_dbg(dev, state, "EARLY ");
+ error = pm_noirq_op(dev, dev->bus->pm, state);
+ } else if (dev->bus->resume_early) {
+ pm_dev_dbg(dev, state, "legacy EARLY ");
error = dev->bus->resume_early(dev);
}
-
+ End:
TRACE_RESUME(error);
return error;
}
/**
* dpm_power_up - Power on all regular (non-sysdev) devices.
+ * @state: PM transition of the system being carried out.
*
- * Walk the dpm_off_irq list and power each device up. This
- * is used for devices that required they be powered down with
- * interrupts disabled. As devices are powered on, they are moved
- * to the dpm_off list.
+ * Execute the appropriate "noirq resume" callback for all devices marked
+ * as DPM_OFF_IRQ.
*
* Must be called with interrupts disabled and only one CPU running.
*/
-static void dpm_power_up(void)
+static void dpm_power_up(pm_message_t state)
{
+ struct device *dev;
- while (!list_empty(&dpm_off_irq)) {
- struct list_head *entry = dpm_off_irq.next;
- struct device *dev = to_device(entry);
+ list_for_each_entry(dev, &dpm_list, power.entry)
+ if (dev->power.status > DPM_OFF) {
+ int error;
- list_move_tail(entry, &dpm_off);
- resume_device_early(dev);
- }
+ dev->power.status = DPM_OFF;
+ error = resume_device_noirq(dev, state);
+ if (error)
+ pm_dev_err(dev, state, " early", error);
+ }
}
/**
* device_power_up - Turn on all devices that need special attention.
+ * @state: PM transition of the system being carried out.
*
* Power on system devices, then devices that required we shut them down
* with interrupts disabled.
*
* Must be called with interrupts disabled.
*/
-void device_power_up(void)
+void device_power_up(pm_message_t state)
{
sysdev_resume();
- dpm_power_up();
+ dpm_power_up(state);
}
EXPORT_SYMBOL_GPL(device_power_up);
/**
* resume_device - Restore state for one device.
* @dev: Device.
- *
+ * @state: PM transition of the system being carried out.
*/
-static int resume_device(struct device *dev)
+static int resume_device(struct device *dev, pm_message_t state)
{
int error = 0;
@@ -175,21 +360,40 @@ static int resume_device(struct device *dev)
down(&dev->sem);
- if (dev->bus && dev->bus->resume) {
- dev_dbg(dev,"resuming\n");
- error = dev->bus->resume(dev);
+ if (dev->bus) {
+ if (dev->bus->pm) {
+ pm_dev_dbg(dev, state, "");
+ error = pm_op(dev, &dev->bus->pm->base, state);
+ } else if (dev->bus->resume) {
+ pm_dev_dbg(dev, state, "legacy ");
+ error = dev->bus->resume(dev);
+ }
+ if (error)
+ goto End;
}
- if (!error && dev->type && dev->type->resume) {
- dev_dbg(dev,"resuming\n");
- error = dev->type->resume(dev);
+ if (dev->type) {
+ if (dev->type->pm) {
+ pm_dev_dbg(dev, state, "type ");
+ error = pm_op(dev, dev->type->pm, state);
+ } else if (dev->type->resume) {
+ pm_dev_dbg(dev, state, "legacy type ");
+ error = dev->type->resume(dev);
+ }
+ if (error)
+ goto End;
}
- if (!error && dev->class && dev->class->resume) {
- dev_dbg(dev,"class resume\n");
- error = dev->class->resume(dev);
+ if (dev->class) {
+ if (dev->class->pm) {
+ pm_dev_dbg(dev, state, "class ");
+ error = pm_op(dev, dev->class->pm, state);
+ } else if (dev->class->resume) {
+ pm_dev_dbg(dev, state, "legacy class ");
+ error = dev->class->resume(dev);
+ }
}
-
+ End:
up(&dev->sem);
TRACE_RESUME(error);
@@ -198,78 +402,161 @@ static int resume_device(struct device *dev)
/**
* dpm_resume - Resume every device.
+ * @state: PM transition of the system being carried out.
*
- * Resume the devices that have either not gone through
- * the late suspend, or that did go through it but also
- * went through the early resume.
+ * Execute the appropriate "resume" callback for all devices the status of
+ * which indicates that they are inactive.
+ */
+static void dpm_resume(pm_message_t state)
+{
+ struct list_head list;
+
+ INIT_LIST_HEAD(&list);
+ mutex_lock(&dpm_list_mtx);
+ transition_started = false;
+ while (!list_empty(&dpm_list)) {
+ struct device *dev = to_device(dpm_list.next);
+
+ get_device(dev);
+ if (dev->power.status >= DPM_OFF) {
+ int error;
+
+ dev->power.status = DPM_RESUMING;
+ mutex_unlock(&dpm_list_mtx);
+
+ error = resume_device(dev, state);
+
+ mutex_lock(&dpm_list_mtx);
+ if (error)
+ pm_dev_err(dev, state, "", error);
+ } else if (dev->power.status == DPM_SUSPENDING) {
+ /* Allow new children of the device to be registered */
+ dev->power.status = DPM_RESUMING;
+ }
+ if (!list_empty(&dev->power.entry))
+ list_move_tail(&dev->power.entry, &list);
+ put_device(dev);
+ }
+ list_splice(&list, &dpm_list);
+ mutex_unlock(&dpm_list_mtx);
+}
+
+/**
+ * complete_device - Complete a PM transition for given device
+ * @dev: Device.
+ * @state: PM transition of the system being carried out.
+ */
+static void complete_device(struct device *dev, pm_message_t state)
+{
+ down(&dev->sem);
+
+ if (dev->class && dev->class->pm && dev->class->pm->complete) {
+ pm_dev_dbg(dev, state, "completing class ");
+ dev->class->pm->complete(dev);
+ }
+
+ if (dev->type && dev->type->pm && dev->type->pm->complete) {
+ pm_dev_dbg(dev, state, "completing type ");
+ dev->type->pm->complete(dev);
+ }
+
+ if (dev->bus && dev->bus->pm && dev->bus->pm->base.complete) {
+ pm_dev_dbg(dev, state, "completing ");
+ dev->bus->pm->base.complete(dev);
+ }
+
+ up(&dev->sem);
+}
+
+/**
+ * dpm_complete - Complete a PM transition for all devices.
+ * @state: PM transition of the system being carried out.
*
- * Take devices from the dpm_off_list, resume them,
- * and put them on the dpm_locked list.
+ * Execute the ->complete() callbacks for all devices that are not marked
+ * as DPM_ON.
*/
-static void dpm_resume(void)
+static void dpm_complete(pm_message_t state)
{
+ struct list_head list;
+
+ INIT_LIST_HEAD(&list);
mutex_lock(&dpm_list_mtx);
- all_sleeping = false;
- while(!list_empty(&dpm_off)) {
- struct list_head *entry = dpm_off.next;
- struct device *dev = to_device(entry);
+ while (!list_empty(&dpm_list)) {
+ struct device *dev = to_device(dpm_list.prev);
- list_move_tail(entry, &dpm_active);
- dev->power.sleeping = false;
- mutex_unlock(&dpm_list_mtx);
- resume_device(dev);
- mutex_lock(&dpm_list_mtx);
+ get_device(dev);
+ if (dev->power.status > DPM_ON) {
+ dev->power.status = DPM_ON;
+ mutex_unlock(&dpm_list_mtx);
+
+ complete_device(dev, state);
+
+ mutex_lock(&dpm_list_mtx);
+ }
+ if (!list_empty(&dev->power.entry))
+ list_move(&dev->power.entry, &list);
+ put_device(dev);
}
+ list_splice(&list, &dpm_list);
mutex_unlock(&dpm_list_mtx);
}
/**
* device_resume - Restore state of each device in system.
+ * @state: PM transition of the system being carried out.
*
* Resume all the devices, unlock them all, and allow new
* devices to be registered once again.
*/
-void device_resume(void)
+void device_resume(pm_message_t state)
{
might_sleep();
- dpm_resume();
+ dpm_resume(state);
+ dpm_complete(state);
}
EXPORT_SYMBOL_GPL(device_resume);
/*------------------------- Suspend routines -------------------------*/
-static inline char *suspend_verb(u32 event)
+/**
+ * resume_event - return a PM message representing the resume event
+ * corresponding to given sleep state.
+ * @sleep_state: PM message representing a sleep state.
+ */
+static pm_message_t resume_event(pm_message_t sleep_state)
{
- switch (event) {
- case PM_EVENT_SUSPEND: return "suspend";
- case PM_EVENT_FREEZE: return "freeze";
- case PM_EVENT_PRETHAW: return "prethaw";
- default: return "(unknown suspend event)";
+ switch (sleep_state.event) {
+ case PM_EVENT_SUSPEND:
+ return PMSG_RESUME;
+ case PM_EVENT_FREEZE:
+ case PM_EVENT_QUIESCE:
+ return PMSG_RECOVER;
+ case PM_EVENT_HIBERNATE:
+ return PMSG_RESTORE;
}
-}
-
-static void
-suspend_device_dbg(struct device *dev, pm_message_t state, char *info)
-{
- dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event),
- ((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ?
- ", may wakeup" : "");
+ return PMSG_ON;
}
/**
- * suspend_device_late - Shut down one device (late suspend).
+ * suspend_device_noirq - Shut down one device (late suspend).
* @dev: Device.
- * @state: Power state device is entering.
+ * @state: PM transition of the system being carried out.
*
* This is called with interrupts off and only a single CPU running.
*/
-static int suspend_device_late(struct device *dev, pm_message_t state)
+static int suspend_device_noirq(struct device *dev, pm_message_t state)
{
int error = 0;
- if (dev->bus && dev->bus->suspend_late) {
- suspend_device_dbg(dev, state, "LATE ");
+ if (!dev->bus)
+ return 0;
+
+ if (dev->bus->pm) {
+ pm_dev_dbg(dev, state, "LATE ");
+ error = pm_noirq_op(dev, dev->bus->pm, state);
+ } else if (dev->bus->suspend_late) {
+ pm_dev_dbg(dev, state, "legacy LATE ");
error = dev->bus->suspend_late(dev, state);
suspend_report_result(dev->bus->suspend_late, error);
}
@@ -278,37 +565,30 @@ static int suspend_device_late(struct device *dev, pm_message_t state)
/**
* device_power_down - Shut down special devices.
- * @state: Power state to enter.
+ * @state: PM transition of the system being carried out.
*
- * Power down devices that require interrupts to be disabled
- * and move them from the dpm_off list to the dpm_off_irq list.
+ * Power down devices that require interrupts to be disabled.
* Then power down system devices.
*
* Must be called with interrupts disabled and only one CPU running.
*/
int device_power_down(pm_message_t state)
{
+ struct device *dev;
int error = 0;
- while (!list_empty(&dpm_off)) {
- struct list_head *entry = dpm_off.prev;
- struct device *dev = to_device(entry);
-
- error = suspend_device_late(dev, state);
+ list_for_each_entry_reverse(dev, &dpm_list, power.entry) {
+ error = suspend_device_noirq(dev, state);
if (error) {
- printk(KERN_ERR "Could not power down device %s: "
- "error %d\n",
- kobject_name(&dev->kobj), error);
+ pm_dev_err(dev, state, " late", error);
break;
}
- if (!list_empty(&dev->power.entry))
- list_move(&dev->power.entry, &dpm_off_irq);
+ dev->power.status = DPM_OFF_IRQ;
}
-
if (!error)
error = sysdev_suspend(state);
if (error)
- dpm_power_up();
+ dpm_power_up(resume_event(state));
return error;
}
EXPORT_SYMBOL_GPL(device_power_down);
@@ -316,7 +596,7 @@ EXPORT_SYMBOL_GPL(device_power_down);
/**
* suspend_device - Save state of one device.
* @dev: Device.
- * @state: Power state device is entering.
+ * @state: PM transition of the system being carried out.
*/
static int suspend_device(struct device *dev, pm_message_t state)
{
@@ -324,24 +604,43 @@ static int suspend_device(struct device *dev, pm_message_t state)
down(&dev->sem);
- if (dev->class && dev->class->suspend) {
- suspend_device_dbg(dev, state, "class ");
- error = dev->class->suspend(dev, state);
- suspend_report_result(dev->class->suspend, error);
+ if (dev->class) {
+ if (dev->class->pm) {
+ pm_dev_dbg(dev, state, "class ");
+ error = pm_op(dev, dev->class->pm, state);
+ } else if (dev->class->suspend) {
+ pm_dev_dbg(dev, state, "legacy class ");
+ error = dev->class->suspend(dev, state);
+ suspend_report_result(dev->class->suspend, error);
+ }
+ if (error)
+ goto End;
}
- if (!error && dev->type && dev->type->suspend) {
- suspend_device_dbg(dev, state, "type ");
- error = dev->type->suspend(dev, state);
- suspend_report_result(dev->type->suspend, error);
+ if (dev->type) {
+ if (dev->type->pm) {
+ pm_dev_dbg(dev, state, "type ");
+ error = pm_op(dev, dev->type->pm, state);
+ } else if (dev->type->suspend) {
+ pm_dev_dbg(dev, state, "legacy type ");
+ error = dev->type->suspend(dev, state);
+ suspend_report_result(dev->type->suspend, error);
+ }
+ if (error)
+ goto End;
}
- if (!error && dev->bus && dev->bus->suspend) {
- suspend_device_dbg(dev, state, "");
- error = dev->bus->suspend(dev, state);
- suspend_report_result(dev->bus->suspend, error);
+ if (dev->bus) {
+ if (dev->bus->pm) {
+ pm_dev_dbg(dev, state, "");
+ error = pm_op(dev, &dev->bus->pm->base, state);
+ } else if (dev->bus->suspend) {
+ pm_dev_dbg(dev, state, "legacy ");
+ error = dev->bus->suspend(dev, state);
+ suspend_report_result(dev->bus->suspend, error);
+ }
}
-
+ End:
up(&dev->sem);
return error;
@@ -349,67 +648,139 @@ static int suspend_device(struct device *dev, pm_message_t state)
/**
* dpm_suspend - Suspend every device.
- * @state: Power state to put each device in.
- *
- * Walk the dpm_locked list. Suspend each device and move it
- * to the dpm_off list.
+ * @state: PM transition of the system being carried out.
*
- * (For historical reasons, if it returns -EAGAIN, that used to mean
- * that the device would be called again with interrupts disabled.
- * These days, we use the "suspend_late()" callback for that, so we
- * print a warning and consider it an error).
+ * Execute the appropriate "suspend" callbacks for all devices.
*/
static int dpm_suspend(pm_message_t state)
{
+ struct list_head list;
int error = 0;
+ INIT_LIST_HEAD(&list);
mutex_lock(&dpm_list_mtx);
- while (!list_empty(&dpm_active)) {
- struct list_head *entry = dpm_active.prev;
- struct device *dev = to_device(entry);
+ while (!list_empty(&dpm_list)) {
+ struct device *dev = to_device(dpm_list.prev);
- WARN_ON(dev->parent && dev->parent->power.sleeping);
-
- dev->power.sleeping = true;
+ get_device(dev);
mutex_unlock(&dpm_list_mtx);
+
error = suspend_device(dev, state);
+
mutex_lock(&dpm_list_mtx);
if (error) {
- printk(KERN_ERR "Could not suspend device %s: "
- "error %d%s\n",
- kobject_name(&dev->kobj),
- error,
- (error == -EAGAIN ?
- " (please convert to suspend_late)" :
- ""));
- dev->power.sleeping = false;
+ pm_dev_err(dev, state, "", error);
+ put_device(dev);
break;
}
+ dev->power.status = DPM_OFF;
if (!list_empty(&dev->power.entry))
- list_move(&dev->power.entry, &dpm_off);
+ list_move(&dev->power.entry, &list);
+ put_device(dev);
}
- if (!error)
- all_sleeping = true;
+ list_splice(&list, dpm_list.prev);
mutex_unlock(&dpm_list_mtx);
+ return error;
+}
+
+/**
+ * prepare_device - Execute the ->prepare() callback(s) for given device.
+ * @dev: Device.
+ * @state: PM transition of the system being carried out.
+ */
+static int prepare_device(struct device *dev, pm_message_t state)
+{
+ int error = 0;
+
+ down(&dev->sem);
+
+ if (dev->bus && dev->bus->pm && dev->bus->pm->base.prepare) {
+ pm_dev_dbg(dev, state, "preparing ");
+ error = dev->bus->pm->base.prepare(dev);
+ suspend_report_result(dev->bus->pm->base.prepare, error);
+ if (error)
+ goto End;
+ }
+
+ if (dev->type && dev->type->pm && dev->type->pm->prepare) {
+ pm_dev_dbg(dev, state, "preparing type ");
+ error = dev->type->pm->prepare(dev);
+ suspend_report_result(dev->type->pm->prepare, error);
+ if (error)
+ goto End;
+ }
+
+ if (dev->class && dev->class->pm && dev->class->pm->prepare) {
+ pm_dev_dbg(dev, state, "preparing class ");
+ error = dev->class->pm->prepare(dev);
+ suspend_report_result(dev->class->pm->prepare, error);
+ }
+ End:
+ up(&dev->sem);
+
+ return error;
+}
+
+/**
+ * dpm_prepare - Prepare all devices for a PM transition.
+ * @state: PM transition of the system being carried out.
+ *
+ * Execute the ->prepare() callback for all devices.
+ */
+static int dpm_prepare(pm_message_t state)
+{
+ struct list_head list;
+ int error = 0;
+
+ INIT_LIST_HEAD(&list);
+ mutex_lock(&dpm_list_mtx);
+ transition_started = true;
+ while (!list_empty(&dpm_list)) {
+ struct device *dev = to_device(dpm_list.next);
+
+ get_device(dev);
+ dev->power.status = DPM_PREPARING;
+ mutex_unlock(&dpm_list_mtx);
+ error = prepare_device(dev, state);
+
+ mutex_lock(&dpm_list_mtx);
+ if (error) {
+ dev->power.status = DPM_ON;
+ if (error == -EAGAIN) {
+ put_device(dev);
+ continue;
+ }
+ printk(KERN_ERR "PM: Failed to prepare device %s "
+ "for power transition: error %d\n",
+ kobject_name(&dev->kobj), error);
+ put_device(dev);
+ break;
+ }
+ dev->power.status = DPM_SUSPENDING;
+ if (!list_empty(&dev->power.entry))
+ list_move_tail(&dev->power.entry, &list);
+ put_device(dev);
+ }
+ list_splice(&list, &dpm_list);
+ mutex_unlock(&dpm_list_mtx);
return error;
}
/**
* device_suspend - Save state and stop all devices in system.
- * @state: new power management state
+ * @state: PM transition of the system being carried out.
*
- * Prevent new devices from being registered, then lock all devices
- * and suspend them.
+ * Prepare and suspend all devices.
*/
int device_suspend(pm_message_t state)
{
int error;
might_sleep();
- error = dpm_suspend(state);
- if (error)
- device_resume();
+ error = dpm_prepare(state);
+ if (!error)
+ error = dpm_suspend(state);
return error;
}
EXPORT_SYMBOL_GPL(device_suspend);
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index a6894f2a4b9..a3252c0e288 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -4,7 +4,7 @@
* main.c
*/
-extern struct list_head dpm_active; /* The active device list */
+extern struct list_head dpm_list; /* The active device list */
static inline struct device *to_device(struct list_head *entry)
{
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index d11f74b038d..596aeecfdff 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -6,9 +6,6 @@
#include <linux/string.h>
#include "power.h"
-int (*platform_enable_wakeup)(struct device *dev, int is_on);
-
-
/*
* wakeup - Report/change current wakeup option for device
*
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c
index 87a7f1d0257..9b1b20b59e0 100644
--- a/drivers/base/power/trace.c
+++ b/drivers/base/power/trace.c
@@ -188,9 +188,9 @@ static int show_file_hash(unsigned int value)
static int show_dev_hash(unsigned int value)
{
int match = 0;
- struct list_head * entry = dpm_active.prev;
+ struct list_head *entry = dpm_list.prev;
- while (entry != &dpm_active) {
+ while (entry != &dpm_list) {
struct device * dev = to_device(entry);
unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH);
if (hash == value) {
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 0d1d2133d9b..61ad8d639ba 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -433,4 +433,16 @@ config VIRTIO_BLK
This is the virtual block driver for virtio. It can be used with
lguest or QEMU based VMMs (like KVM or Xen). Say Y or M.
+config BLK_DEV_HD
+ bool "Very old hard disk (MFM/RLL/IDE) driver"
+ depends on HAVE_IDE
+ depends on !ARM || ARCH_RPC || ARCH_SHARK || BROKEN
+ help
+ This is a very old hard disk driver that lacks the enhanced
+ functionality of the newer ones.
+
+ It is required for systems with ancient MFM/RLL/ESDI drives.
+
+ If unsure, say N.
+
endif # BLK_DEV
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 5e584306be9..204332b2957 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -29,5 +29,6 @@ obj-$(CONFIG_VIRTIO_BLK) += virtio_blk.o
obj-$(CONFIG_VIODASD) += viodasd.o
obj-$(CONFIG_BLK_DEV_SX8) += sx8.o
obj-$(CONFIG_BLK_DEV_UB) += ub.o
+obj-$(CONFIG_BLK_DEV_HD) += hd.o
obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o
diff --git a/drivers/ide/legacy/hd.c b/drivers/block/hd.c
index abdedf56643..682243bf2e4 100644
--- a/drivers/ide/legacy/hd.c
+++ b/drivers/block/hd.c
@@ -37,7 +37,6 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/ioport.h>
-#include <linux/mc146818rtc.h> /* CMOS defines */
#include <linux/init.h>
#include <linux/blkpg.h>
#include <linux/hdreg.h>
@@ -812,4 +811,4 @@ static int __init parse_hd_setup(char *line)
}
__setup("hd=", parse_hd_setup);
-module_init(hd_init);
+late_initcall(hd_init);
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c
index da8a1658a27..aaca40283be 100644
--- a/drivers/char/apm-emulation.c
+++ b/drivers/char/apm-emulation.c
@@ -59,6 +59,55 @@ struct apm_queue {
};
/*
+ * 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
*/
struct apm_user {
@@ -69,13 +118,7 @@ struct apm_user {
unsigned int reader: 1;
int suspend_result;
- unsigned int suspend_state;
-#define SUSPEND_NONE 0 /* no suspend pending */
-#define SUSPEND_PENDING 1 /* suspend pending read */
-#define SUSPEND_READ 2 /* suspend read, pending ack */
-#define SUSPEND_ACKED 3 /* suspend acked */
-#define SUSPEND_WAIT 4 /* waiting for suspend */
-#define SUSPEND_DONE 5 /* suspend completed */
+ enum apm_suspend_state suspend_state;
struct apm_queue queue;
};
@@ -83,7 +126,8 @@ struct apm_user {
/*
* Local variables
*/
-static int suspends_pending;
+static atomic_t suspend_acks_pending = ATOMIC_INIT(0);
+static atomic_t userspace_notification_inhibit = ATOMIC_INIT(0);
static int apm_disabled;
static struct task_struct *kapmd_tsk;
@@ -166,78 +210,6 @@ static void queue_event(apm_event_t event)
wake_up_interruptible(&apm_waitqueue);
}
-/*
- * queue_suspend_event - queue an APM suspend event.
- *
- * Check that we're in a state where we can suspend. If not,
- * return -EBUSY. Otherwise, queue an event to all "writer"
- * users. If there are no "writer" users, return '1' to
- * indicate that we can immediately suspend.
- */
-static int queue_suspend_event(apm_event_t event, struct apm_user *sender)
-{
- struct apm_user *as;
- int ret = 1;
-
- mutex_lock(&state_lock);
- down_read(&user_list_lock);
-
- /*
- * If a thread is still processing, we can't suspend, so reject
- * the request.
- */
- list_for_each_entry(as, &apm_user_list, list) {
- if (as != sender && as->reader && as->writer && as->suser &&
- as->suspend_state != SUSPEND_NONE) {
- ret = -EBUSY;
- goto out;
- }
- }
-
- list_for_each_entry(as, &apm_user_list, list) {
- if (as != sender && as->reader && as->writer && as->suser) {
- as->suspend_state = SUSPEND_PENDING;
- suspends_pending++;
- queue_add_event(&as->queue, event);
- ret = 0;
- }
- }
- out:
- up_read(&user_list_lock);
- mutex_unlock(&state_lock);
- wake_up_interruptible(&apm_waitqueue);
- return ret;
-}
-
-static void apm_suspend(void)
-{
- struct apm_user *as;
- int err = pm_suspend(PM_SUSPEND_MEM);
-
- /*
- * Anyone on the APM queues will think we're still suspended.
- * Send a message so everyone knows we're now awake again.
- */
- queue_event(APM_NORMAL_RESUME);
-
- /*
- * Finally, wake up anyone who is sleeping on the suspend.
- */
- mutex_lock(&state_lock);
- down_read(&user_list_lock);
- list_for_each_entry(as, &apm_user_list, list) {
- if (as->suspend_state == SUSPEND_WAIT ||
- as->suspend_state == SUSPEND_ACKED) {
- as->suspend_result = err;
- as->suspend_state = SUSPEND_DONE;
- }
- }
- up_read(&user_list_lock);
- mutex_unlock(&state_lock);
-
- wake_up(&apm_suspend_waitqueue);
-}
-
static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
{
struct apm_user *as = fp->private_data;
@@ -308,25 +280,22 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
as->suspend_result = -EINTR;
- if (as->suspend_state == SUSPEND_READ) {
- int pending;
-
+ switch (as->suspend_state) {
+ case SUSPEND_READ:
/*
* If we read a suspend command from /dev/apm_bios,
* then the corresponding APM_IOC_SUSPEND ioctl is
* interpreted as an acknowledge.
*/
as->suspend_state = SUSPEND_ACKED;
- suspends_pending--;
- pending = suspends_pending == 0;
+ atomic_dec(&suspend_acks_pending);
mutex_unlock(&state_lock);
/*
- * If there are no further acknowledges required,
- * suspend the system.
+ * suspend_acks_pending changed, the notifier needs to
+ * be woken up for this
*/
- if (pending)
- apm_suspend();
+ wake_up(&apm_suspend_waitqueue);
/*
* Wait for the suspend/resume to complete. If there
@@ -342,35 +311,21 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
* try_to_freeze() in freezer_count() will not trigger
*/
freezer_count();
- } else {
+ break;
+ case SUSPEND_ACKTO:
+ as->suspend_result = -ETIMEDOUT;
+ mutex_unlock(&state_lock);
+ break;
+ default:
as->suspend_state = SUSPEND_WAIT;
mutex_unlock(&state_lock);
/*
* Otherwise it is a request to suspend the system.
- * Queue an event for all readers, and expect an
- * acknowledge from all writers who haven't already
- * acknowledged.
- */
- err = queue_suspend_event(APM_USER_SUSPEND, as);
- if (err < 0) {
- /*
- * Avoid taking the lock here - this
- * should be fine.
- */
- as->suspend_state = SUSPEND_NONE;
- break;
- }
-
- if (err > 0)
- apm_suspend();
-
- /*
- * Wait for the suspend/resume to complete. If there
- * are pending acknowledges, we wait here for them.
+ * Just invoke pm_suspend(), we'll handle it from
+ * there via the notifier.
*/
- wait_event_freezable(apm_suspend_waitqueue,
- as->suspend_state == SUSPEND_DONE);
+ as->suspend_result = pm_suspend(PM_SUSPEND_MEM);
}
mutex_lock(&state_lock);
@@ -386,7 +341,6 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
static int apm_release(struct inode * inode, struct file * filp)
{
struct apm_user *as = filp->private_data;
- int pending = 0;
filp->private_data = NULL;
@@ -396,18 +350,15 @@ static int apm_release(struct inode * inode, struct file * filp)
/*
* We are now unhooked from the chain. As far as new
- * events are concerned, we no longer exist. However, we
- * need to balance suspends_pending, which means the
- * possibility of sleeping.
+ * events are concerned, we no longer exist.
*/
mutex_lock(&state_lock);
- if (as->suspend_state != SUSPEND_NONE) {
- suspends_pending -= 1;
- pending = suspends_pending == 0;
- }
+ if (as->suspend_state == SUSPEND_PENDING ||
+ as->suspend_state == SUSPEND_READ)
+ atomic_dec(&suspend_acks_pending);
mutex_unlock(&state_lock);
- if (pending)
- apm_suspend();
+
+ wake_up(&apm_suspend_waitqueue);
kfree(as);
return 0;
@@ -545,7 +496,6 @@ static int kapmd(void *arg)
{
do {
apm_event_t event;
- int ret;
wait_event_interruptible(kapmd_wait,
!queue_empty(&kapmd_queue) || kthread_should_stop());
@@ -570,20 +520,13 @@ static int kapmd(void *arg)
case APM_USER_SUSPEND:
case APM_SYS_SUSPEND:
- ret = queue_suspend_event(event, NULL);
- if (ret < 0) {
- /*
- * We were busy. Try again in 50ms.
- */
- queue_add_event(&kapmd_queue, event);
- msleep(50);
- }
- if (ret > 0)
- apm_suspend();
+ pm_suspend(PM_SUSPEND_MEM);
break;
case APM_CRITICAL_SUSPEND:
- apm_suspend();
+ atomic_inc(&userspace_notification_inhibit);
+ pm_suspend(PM_SUSPEND_MEM);
+ atomic_dec(&userspace_notification_inhibit);
break;
}
} while (1);
@@ -591,6 +534,120 @@ static int kapmd(void *arg)
return 0;
}
+static int apm_suspend_notifier(struct notifier_block *nb,
+ unsigned long event,
+ void *dummy)
+{
+ struct apm_user *as;
+ int err;
+
+ /* short-cut emergency suspends */
+ if (atomic_read(&userspace_notification_inhibit))
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case PM_SUSPEND_PREPARE:
+ /*
+ * Queue an event to all "writer" users that we want
+ * to suspend and need their ack.
+ */
+ mutex_lock(&state_lock);
+ down_read(&user_list_lock);
+
+ list_for_each_entry(as, &apm_user_list, list) {
+ if (as->suspend_state != SUSPEND_WAIT && as->reader &&
+ as->writer && as->suser) {
+ as->suspend_state = SUSPEND_PENDING;
+ atomic_inc(&suspend_acks_pending);
+ queue_add_event(&as->queue, APM_USER_SUSPEND);
+ }
+ }
+
+ up_read(&user_list_lock);
+ mutex_unlock(&state_lock);
+ wake_up_interruptible(&apm_waitqueue);
+
+ /*
+ * Wait for the the suspend_acks_pending variable to drop to
+ * zero, meaning everybody acked the suspend event (or the
+ * process was killed.)
+ *
+ * If the app won't answer within a short while we assume it
+ * locked up and ignore it.
+ */
+ err = wait_event_interruptible_timeout(
+ apm_suspend_waitqueue,
+ atomic_read(&suspend_acks_pending) == 0,
+ 5*HZ);
+
+ /* timed out */
+ if (err == 0) {
+ /*
+ * Move anybody who timed out to "ack timeout" state.
+ *
+ * We could time out and the userspace does the ACK
+ * right after we time out but before we enter the
+ * locked section here, but that's fine.
+ */
+ mutex_lock(&state_lock);
+ down_read(&user_list_lock);
+ list_for_each_entry(as, &apm_user_list, list) {
+ if (as->suspend_state == SUSPEND_PENDING ||
+ as->suspend_state == SUSPEND_READ) {
+ as->suspend_state = SUSPEND_ACKTO;
+ atomic_dec(&suspend_acks_pending);
+ }
+ }
+ up_read(&user_list_lock);
+ mutex_unlock(&state_lock);
+ }
+
+ /* let suspend proceed */
+ if (err >= 0)
+ return NOTIFY_OK;
+
+ /* interrupted by signal */
+ return NOTIFY_BAD;
+
+ case PM_POST_SUSPEND:
+ /*
+ * Anyone on the APM queues will think we're still suspended.
+ * Send a message so everyone knows we're now awake again.
+ */
+ queue_event(APM_NORMAL_RESUME);
+
+ /*
+ * Finally, wake up anyone who is sleeping on the suspend.
+ */
+ mutex_lock(&state_lock);
+ down_read(&user_list_lock);
+ list_for_each_entry(as, &apm_user_list, list) {
+ if (as->suspend_state == SUSPEND_ACKED) {
+ /*
+ * TODO: maybe grab error code, needs core
+ * changes to push the error to the notifier
+ * chain (could use the second parameter if
+ * implemented)
+ */
+ as->suspend_result = 0;
+ as->suspend_state = SUSPEND_DONE;
+ }
+ }
+ up_read(&user_list_lock);
+ mutex_unlock(&state_lock);
+
+ wake_up(&apm_suspend_waitqueue);
+ return NOTIFY_OK;
+
+ default:
+ return NOTIFY_DONE;
+ }
+}
+
+static struct notifier_block apm_notif_block = {
+ .notifier_call = apm_suspend_notifier,
+};
+
static int __init apm_init(void)
{
int ret;
@@ -604,7 +661,7 @@ static int __init apm_init(void)
if (IS_ERR(kapmd_tsk)) {
ret = PTR_ERR(kapmd_tsk);
kapmd_tsk = NULL;
- return ret;
+ goto out;
}
wake_up_process(kapmd_tsk);
@@ -613,16 +670,27 @@ static int __init apm_init(void)
#endif
ret = misc_register(&apm_device);
- if (ret != 0) {
- remove_proc_entry("apm", NULL);
- kthread_stop(kapmd_tsk);
- }
+ if (ret)
+ goto out_stop;
+ ret = register_pm_notifier(&apm_notif_block);
+ if (ret)
+ goto out_unregister;
+
+ return 0;
+
+ out_unregister:
+ misc_deregister(&apm_device);
+ out_stop:
+ remove_proc_entry("apm", NULL);
+ kthread_stop(kapmd_tsk);
+ out:
return ret;
}
static void __exit apm_exit(void)
{
+ unregister_pm_notifier(&apm_notif_block);
misc_deregister(&apm_device);
remove_proc_entry("apm", NULL);
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index 59ca35156d8..e4a4fbd37d7 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -1439,7 +1439,7 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
DEBUGP(4, dev, "CMM_ABSENT flag set\n");
goto out;
}
- rc = EINVAL;
+ rc = -EINVAL;
if (_IOC_TYPE(cmd) != CM_IOC_MAGIC) {
DEBUGP(4, dev, "ioctype mismatch\n");
diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c
index 466b9ee9279..f97b5b35687 100644
--- a/drivers/hwmon/ad7418.c
+++ b/drivers/hwmon/ad7418.c
@@ -23,12 +23,9 @@
#include "lm75.h"
-#define DRV_VERSION "0.3"
+#define DRV_VERSION "0.4"
-/* Addresses to scan */
-static const unsigned short normal_i2c[] = { 0x28, I2C_CLIENT_END };
-/* Insmod parameters */
-I2C_CLIENT_INSMOD_3(ad7416, ad7417, ad7418);
+enum chips { ad7416, ad7417, ad7418 };
/* AD7418 registers */
#define AD7418_REG_TEMP_IN 0x00
@@ -46,7 +43,6 @@ 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;
@@ -58,16 +54,25 @@ struct ad7418_data {
u16 in[4];
};
-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 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 struct i2c_driver ad7418_driver = {
.driver = {
.name = "ad7418",
},
- .attach_adapter = ad7418_attach_adapter,
- .detach_client = ad7418_detach_client,
+ .probe = ad7418_probe,
+ .remove = ad7418_remove,
+ .id_table = ad7418_id,
};
/* All registers are word-sized, except for the configuration registers.
@@ -192,13 +197,6 @@ 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,
@@ -225,98 +223,46 @@ static struct attribute *ad7418_attributes[] = {
NULL
};
-static int ad7418_detect(struct i2c_adapter *adapter, int address, int kind)
+static int ad7418_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct i2c_client *client;
+ struct i2c_adapter *adapter = client->adapter;
struct ad7418_data *data;
- int err = 0;
+ int err;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
- I2C_FUNC_SMBUS_WORD_DATA))
+ I2C_FUNC_SMBUS_WORD_DATA)) {
+ err = -EOPNOTSUPP;
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);
-
- /* 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;
- }
+ data->type = id->driver_data;
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 */
@@ -324,7 +270,7 @@ static int ad7418_detect(struct i2c_adapter *adapter, int address, int kind)
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs)))
- goto exit_detach;
+ goto exit_free;
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -336,20 +282,17 @@ static int ad7418_detect(struct i2c_adapter *adapter, int address, int kind)
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_detach_client(struct i2c_client *client)
+static int ad7418_remove(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/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index ecbf69484bf..b11e06f644b 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -78,7 +78,6 @@ 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;
@@ -98,23 +97,42 @@ struct adm1021_data {
u8 remote_temp_offset_prec;
};
-static int adm1021_attach_adapter(struct i2c_adapter *adapter);
-static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind);
+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 void adm1021_init_client(struct i2c_client *client);
-static int adm1021_detach_client(struct i2c_client *client);
+static int adm1021_remove(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",
},
- .attach_adapter = adm1021_attach_adapter,
- .detach_client = adm1021_detach_client,
+ .probe = adm1021_probe,
+ .remove = adm1021_remove,
+ .id_table = adm1021_id,
+ .detect = adm1021_detect,
+ .address_data = &addr_data,
};
static ssize_t show_temp(struct device *dev,
@@ -216,13 +234,6 @@ 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,
@@ -243,36 +254,21 @@ static const struct attribute_group adm1021_group = {
.attrs = adm1021_attributes,
};
-static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int adm1021_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
+ 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");
- 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;
+ return -ENODEV;
}
- 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);
@@ -284,8 +280,7 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
|| (conv_rate & 0xF8) != 0x00) {
pr_debug("adm1021: detect failed, "
"chip not detected!\n");
- err = -ENODEV;
- goto error1;
+ return -ENODEV;
}
}
@@ -336,24 +331,36 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
type_name = "mc1066";
}
pr_debug("adm1021: Detected chip %s at adapter %d, address 0x%02x.\n",
- type_name, i2c_adapter_id(adapter), address);
+ type_name, i2c_adapter_id(adapter), client->addr);
+ strlcpy(info->type, type_name, I2C_NAME_SIZE);
- /* Fill in the remaining client fields */
- strlcpy(client->name, type_name, I2C_NAME_SIZE);
- data->type = kind;
- mutex_init(&data->update_lock);
+ return 0;
+}
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(client)))
- goto error1;
+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;
+ }
+
+ i2c_set_clientdata(client, data);
+ data->type = id->driver_data;
+ mutex_init(&data->update_lock);
/* Initialize the ADM1021 chip */
- if (kind != lm84 && !read_only)
+ if (data->type != lm84 && !read_only)
adm1021_init_client(client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &adm1021_group)))
- goto error2;
+ goto error1;
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -365,8 +372,6 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
error3:
sysfs_remove_group(&client->dev.kobj, &adm1021_group);
-error2:
- i2c_detach_client(client);
error1:
kfree(data);
error0:
@@ -382,17 +387,13 @@ static void adm1021_init_client(struct i2c_client *client)
i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04);
}
-static int adm1021_detach_client(struct i2c_client *client)
+static int adm1021_remove(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/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c
index 1d76de7d75c..4db04d603ec 100644
--- a/drivers/hwmon/adm1025.c
+++ b/drivers/hwmon/adm1025.c
@@ -2,7 +2,7 @@
* adm1025.c
*
* Copyright (C) 2000 Chen-Yuan Wu <gwu@esoft.com>
- * Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2008 Jean Delvare <khali@linux-fr.org>
*
* 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,22 +109,35 @@ static const int in_scale[6] = { 2500, 2250, 3300, 5000, 12000, 3300 };
* Functions declaration
*/
-static int adm1025_attach_adapter(struct i2c_adapter *adapter);
-static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind);
+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 void adm1025_init_client(struct i2c_client *client);
-static int adm1025_detach_client(struct i2c_client *client);
+static int adm1025_remove(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",
},
- .attach_adapter = adm1025_attach_adapter,
- .detach_client = adm1025_detach_client,
+ .probe = adm1025_probe,
+ .remove = adm1025_remove,
+ .id_table = adm1025_id,
+ .detect = adm1025_detect,
+ .address_data = &addr_data,
};
/*
@@ -132,7 +145,6 @@ 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 */
@@ -344,13 +356,6 @@ 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,
@@ -403,31 +408,16 @@ static const struct attribute_group adm1025_group_in4 = {
.attrs = adm1025_attributes_in4,
};
-/*
- * 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)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int adm1025_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *client;
- struct adm1025_data *data;
- int err = 0;
+ struct i2c_adapter *adapter = client->adapter;
const char *name = "";
u8 config;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- 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;
+ return -ENODEV;
/*
* Now we do the remaining detection. A negative kind means that
@@ -448,8 +438,8 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
ADM1025_REG_STATUS2) & 0xBC) != 0x00) {
dev_dbg(&adapter->dev,
"ADM1025 detection failed at 0x%02x.\n",
- address);
- goto exit_free;
+ client->addr);
+ return -ENODEV;
}
}
@@ -465,7 +455,7 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
}
} else
if (man_id == 0xA1) { /* Philips */
- if (address != 0x2E
+ if (client->addr != 0x2E
&& (chip_id & 0xF0) == 0x20) { /* NE1619 */
kind = ne1619;
}
@@ -475,7 +465,7 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
dev_info(&adapter->dev,
"Unsupported chip (man_id=0x%02X, "
"chip_id=0x%02X).\n", man_id, chip_id);
- goto exit_free;
+ return -ENODEV;
}
}
@@ -484,23 +474,36 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
} else if (kind == ne1619) {
name = "ne1619";
}
+ strlcpy(info->type, name, I2C_NAME_SIZE);
- /* We can fill in the remaining client fields */
- strlcpy(client->name, name, I2C_NAME_SIZE);
- mutex_init(&data->update_lock);
+ return 0;
+}
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(client)))
- goto exit_free;
+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);
+ mutex_init(&data->update_lock);
/* Initialize the ADM1025 chip */
adm1025_init_client(client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &adm1025_group)))
- goto exit_detach;
+ goto exit_free;
/* 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)))
@@ -518,8 +521,6 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
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:
@@ -568,18 +569,14 @@ static void adm1025_init_client(struct i2c_client *client)
(reg&0x7E)|0x01);
}
-static int adm1025_detach_client(struct i2c_client *client)
+static int adm1025_remove(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/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index 904c6ce9d83..7fe2441fc84 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -259,7 +259,6 @@ struct pwm_data {
};
struct adm1026_data {
- struct i2c_client client;
struct device *hwmon_dev;
struct mutex update_lock;
@@ -293,10 +292,11 @@ struct adm1026_data {
u8 config3; /* Register value */
};
-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_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_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,22 +305,24 @@ 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",
},
- .attach_adapter = adm1026_attach_adapter,
- .detach_client = adm1026_detach_client,
+ .probe = adm1026_probe,
+ .remove = adm1026_remove,
+ .id_table = adm1026_id,
+ .detect = adm1026_detect,
+ .address_data = &addr_data,
};
-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;
@@ -1647,48 +1649,32 @@ static const struct attribute_group adm1026_group_in8_9 = {
.attrs = adm1026_attributes_in8_9,
};
-static int adm1026_detect(struct i2c_adapter *adapter, int address,
- int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int adm1026_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
+ 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 */
- goto exit;
+ 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 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(&client->dev, "Detecting device at %d,0x%02x with"
+ dev_dbg(&adapter->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(&client->dev, "Autodetecting device at %d,0x%02x "
+ dev_dbg(&adapter->dev, "Autodetecting device at %d,0x%02x "
"...\n", i2c_adapter_id(adapter), address);
if (company == ADM1026_COMPANY_ANALOG_DEV
&& verstep == ADM1026_VERSTEP_ADM1026) {
@@ -1704,7 +1690,7 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address,
verstep);
kind = any_chip;
} else {
- dev_dbg(&client->dev, ": Autodetection "
+ dev_dbg(&adapter->dev, ": Autodetection "
"failed\n");
/* Not an ADM1026 ... */
if (kind == 0) { /* User used force=x,y */
@@ -1713,33 +1699,29 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address,
"force_adm1026.\n",
i2c_adapter_id(adapter), address);
}
- goto exitfree;
+ return -ENODEV;
}
}
+ strlcpy(info->type, "adm1026", I2C_NAME_SIZE);
- /* 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;
+ 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;
}
- strlcpy(client->name, type_name, I2C_NAME_SIZE);
- /* Fill in the remaining client fields */
+ i2c_set_clientdata(client, data);
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();
@@ -1748,7 +1730,7 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address,
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &adm1026_group)))
- goto exitdetach;
+ goto exitfree;
if (data->config1 & CFG1_AIN8_9)
err = sysfs_create_group(&client->dev.kobj,
&adm1026_group_in8_9);
@@ -1773,15 +1755,13 @@ exitremove:
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_detach_client(struct i2c_client *client)
+static int adm1026_remove(struct i2c_client *client)
{
struct adm1026_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
@@ -1790,7 +1770,6 @@ static int adm1026_detach_client(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/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c
index 2c6608d453c..ba84ca5923f 100644
--- a/drivers/hwmon/adm1029.c
+++ b/drivers/hwmon/adm1029.c
@@ -115,9 +115,11 @@ static const u8 ADM1029_REG_FAN_DIV[] = {
* Functions declaration
*/
-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 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 struct adm1029_data *adm1029_update_device(struct device *dev);
static int adm1029_init_client(struct i2c_client *client);
@@ -125,12 +127,22 @@ 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",
},
- .attach_adapter = adm1029_attach_adapter,
- .detach_client = adm1029_detach_client,
+ .probe = adm1029_probe,
+ .remove = adm1029_remove,
+ .id_table = adm1029_id,
+ .detect = adm1029_detect,
+ .address_data = &addr_data,
};
/*
@@ -138,7 +150,6 @@ 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 */
@@ -284,37 +295,14 @@ static const struct attribute_group adm1029_group = {
* Real code
*/
-static int adm1029_attach_adapter(struct i2c_adapter *adapter)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int adm1029_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_probe(adapter, &addr_data, adm1029_detect);
-}
+ struct i2c_adapter *adapter = client->adapter;
-/*
- * 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))
- 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;
+ return -ENODEV;
/* Now we do the detection and identification. A negative kind
* means that the driver was loaded with no force parameter
@@ -362,32 +350,41 @@ static int adm1029_detect(struct i2c_adapter *adapter, int address, 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);
- goto exit_free;
+ return -ENODEV;
}
}
+ strlcpy(info->type, "adm1029", I2C_NAME_SIZE);
- if (kind == adm1029) {
- name = "adm1029";
+ 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;
}
- /* We can fill in the remaining client fields */
- 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 */
- if ((err = i2c_attach_client(client)))
- goto exit_free;
-
/*
* Initialize the ADM1029 chip
* Check config register
*/
- if (adm1029_init_client(client) == 0)
- goto exit_detach;
+ if (adm1029_init_client(client) == 0) {
+ err = -ENODEV;
+ goto exit_free;
+ }
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &adm1029_group)))
- goto exit_detach;
+ goto exit_free;
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -399,8 +396,6 @@ static int adm1029_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove_files:
sysfs_remove_group(&client->dev.kobj, &adm1029_group);
- exit_detach:
- i2c_detach_client(client);
exit_free:
kfree(data);
exit:
@@ -424,17 +419,13 @@ static int adm1029_init_client(struct i2c_client *client)
return 1;
}
-static int adm1029_detach_client(struct i2c_client *client)
+static int adm1029_remove(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/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
index 2bffcab7dc9..789441830cd 100644
--- a/drivers/hwmon/adm1031.c
+++ b/drivers/hwmon/adm1031.c
@@ -70,7 +70,6 @@ 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;
@@ -99,19 +98,32 @@ struct adm1031_data {
s8 temp_crit[3];
};
-static int adm1031_attach_adapter(struct i2c_adapter *adapter);
-static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind);
+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 void adm1031_init_client(struct i2c_client *client);
-static int adm1031_detach_client(struct i2c_client *client);
+static int adm1031_remove(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",
},
- .attach_adapter = adm1031_attach_adapter,
- .detach_client = adm1031_detach_client,
+ .probe = adm1031_probe,
+ .remove = adm1031_remove,
+ .id_table = adm1031_id,
+ .detect = adm1031_detect,
+ .address_data = &addr_data,
};
static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg)
@@ -693,13 +705,6 @@ 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,
@@ -770,27 +775,15 @@ static const struct attribute_group adm1031_group_opt = {
.attrs = adm1031_attributes_opt,
};
-/* This function is called by i2c_probe */
-static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int adm1031_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *client;
- struct adm1031_data *data;
- int err = 0;
+ struct i2c_adapter *adapter = client->adapter;
const char *name = "";
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- 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;
+ return -ENODEV;
if (kind < 0) {
int id, co;
@@ -798,7 +791,7 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
co = i2c_smbus_read_byte_data(client, 0x3e);
if (!((id == 0x31 || id == 0x30) && co == 0x41))
- goto exit_free;
+ return -ENODEV;
kind = (id == 0x30) ? adm1030 : adm1031;
}
@@ -809,28 +802,43 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, 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;
}
- data->chip_type = kind;
+ strlcpy(info->type, name, I2C_NAME_SIZE);
- strlcpy(client->name, 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;
+ }
+
+ i2c_set_clientdata(client, data);
+ data->chip_type = id->driver_data;
mutex_init(&data->update_lock);
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(client)))
- goto exit_free;
+ if (data->chip_type == adm1030)
+ data->chan_select_table = &auto_channel_select_table_adm1030;
+ else
+ data->chan_select_table = &auto_channel_select_table_adm1031;
/* Initialize the ADM1031 chip */
adm1031_init_client(client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group)))
- goto exit_detach;
+ goto exit_free;
- if (kind == adm1031) {
+ if (data->chip_type == adm1031) {
if ((err = sysfs_create_group(&client->dev.kobj,
&adm1031_group_opt)))
goto exit_remove;
@@ -847,25 +855,19 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
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_detach_client(struct i2c_client *client)
+static int adm1031_remove(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/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c
index 149ef25252e..2444b15f2e9 100644
--- a/drivers/hwmon/adm9240.c
+++ b/drivers/hwmon/adm9240.c
@@ -130,25 +130,37 @@ static inline unsigned int AOUT_FROM_REG(u8 reg)
return SCALE(reg, 1250, 255);
}
-static int adm9240_attach_adapter(struct i2c_adapter *adapter);
-static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind);
+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 void adm9240_init_client(struct i2c_client *client);
-static int adm9240_detach_client(struct i2c_client *client);
+static int adm9240_remove(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",
},
- .attach_adapter = adm9240_attach_adapter,
- .detach_client = adm9240_detach_client,
+ .probe = adm9240_probe,
+ .remove = adm9240_remove,
+ .id_table = adm9240_id,
+ .detect = adm9240_detect,
+ .address_data = &addr_data,
};
/* per client data */
struct adm9240_data {
- enum chips type;
- struct i2c_client client;
struct device *hwmon_dev;
struct mutex update_lock;
char valid;
@@ -532,28 +544,17 @@ static const struct attribute_group adm9240_group = {
/*** sensor chip detect and driver install ***/
-static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int adm9240_detect(struct i2c_client *new_client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *new_client;
- struct adm9240_data *data;
- int err = 0;
+ struct i2c_adapter *adapter = new_client->adapter;
const char *name = "";
+ int address = new_client->addr;
u8 man_id, die_rev;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- 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;
+ return -ENODEV;
if (kind == 0) {
kind = adm9240;
@@ -566,7 +567,7 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
!= address) {
dev_err(&adapter->dev, "detect fail: address match, "
"0x%02x\n", address);
- goto exit_free;
+ return -ENODEV;
}
/* check known chip manufacturer */
@@ -581,7 +582,7 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
} else {
dev_err(&adapter->dev, "detect fail: unknown manuf, "
"0x%02x\n", man_id);
- goto exit_free;
+ return -ENODEV;
}
/* successful detect, print chip info */
@@ -600,20 +601,31 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
} else if (kind == lm81) {
name = "lm81";
}
+ strlcpy(info->type, name, I2C_NAME_SIZE);
- /* fill in the remaining client fields and attach */
- strlcpy(new_client->name, name, I2C_NAME_SIZE);
- data->type = kind;
- mutex_init(&data->update_lock);
+ return 0;
+}
- if ((err = i2c_attach_client(new_client)))
- goto exit_free;
+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);
+ mutex_init(&data->update_lock);
adm9240_init_client(new_client);
/* populate sysfs filesystem */
if ((err = sysfs_create_group(&new_client->dev.kobj, &adm9240_group)))
- goto exit_detach;
+ goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -625,32 +637,19 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
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_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)
+static int adm9240_remove(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/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
index 5c8b6e0ff47..5c39b4af1b2 100644
--- a/drivers/hwmon/ads7828.c
+++ b/drivers/hwmon/ads7828.c
@@ -64,7 +64,6 @@ 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 */
@@ -73,7 +72,10 @@ struct ads7828_data {
};
/* Function declaration - necessary due to function dependencies */
-static int ads7828_detect(struct i2c_adapter *adapter, int address, int kind);
+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);
/* The ADS7828 returns the 12-bit sample in two bytes,
these are read as a word then byte-swapped */
@@ -156,58 +158,43 @@ static const struct attribute_group ads7828_group = {
.attrs = ads7828_attributes,
};
-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)
+static int ads7828_remove(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",
},
- .attach_adapter = ads7828_attach_adapter,
- .detach_client = ads7828_detach_client,
+ .probe = ads7828_probe,
+ .remove = ads7828_remove,
+ .id_table = ads7828_id,
+ .detect = ads7828_detect,
+ .address_data = &addr_data,
};
-/* This function is called by i2c_probe */
-static int ads7828_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int ads7828_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *client;
- struct ads7828_data *data;
- int err = 0;
- const char *name = "";
+ struct i2c_adapter *adapter = client->adapter;
/* Check we have a valid client */
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_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.
- 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;
+ return -ENODEV;
/* Now, we do the remaining detection. There is no identification
dedicated register so attempt to sanity check using knowledge of
@@ -225,32 +212,34 @@ static int ads7828_detect(struct i2c_adapter *adapter, int address, int kind)
printk(KERN_DEBUG
"%s : Doesn't look like an ads7828 device\n",
__func__);
- goto exit_free;
+ return -ENODEV;
}
}
}
+ strlcpy(info->type, "ads7828", I2C_NAME_SIZE);
- /* Determine the chip type - only one kind supported! */
- if (kind <= 0)
- kind = ads7828;
+ return 0;
+}
- if (kind == ads7828)
- name = "ads7828";
+static int ads7828_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct ads7828_data *data;
+ int err;
- /* Fill in the remaining client fields, put it into the global list */
- strlcpy(client->name, name, I2C_NAME_SIZE);
+ data = kzalloc(sizeof(struct ads7828_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ 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_detach;
+ goto exit_free;
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -262,8 +251,6 @@ static int ads7828_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove:
sysfs_remove_group(&client->dev.kobj, &ads7828_group);
-exit_detach:
- i2c_detach_client(client);
exit_free:
kfree(data);
exit:
diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c
index 6b5325f33a2..d368d8f845e 100644
--- a/drivers/hwmon/adt7470.c
+++ b/drivers/hwmon/adt7470.c
@@ -138,7 +138,6 @@ 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;
@@ -164,16 +163,28 @@ struct adt7470_data {
u8 pwm_auto_temp[ADT7470_PWM_COUNT];
};
-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 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 struct i2c_driver adt7470_driver = {
+ .class = I2C_CLASS_HWMON,
.driver = {
.name = "adt7470",
},
- .attach_adapter = adt7470_attach_adapter,
- .detach_client = adt7470_detach_client,
+ .probe = adt7470_probe,
+ .remove = adt7470_remove,
+ .id_table = adt7470_id,
+ .detect = adt7470_detect,
+ .address_data = &addr_data,
};
/*
@@ -1004,64 +1015,52 @@ static struct attribute *adt7470_attr[] =
NULL
};
-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)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int adt7470_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *client;
- struct adt7470_data *data;
- int err = 0;
+ struct i2c_adapter *adapter = client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- 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);
+ return -ENODEV;
if (kind <= 0) {
int vendor, device, revision;
vendor = i2c_smbus_read_byte_data(client, ADT7470_REG_VENDOR);
- if (vendor != ADT7470_VENDOR) {
- err = -ENODEV;
- goto exit_free;
- }
+ if (vendor != ADT7470_VENDOR)
+ return -ENODEV;
device = i2c_smbus_read_byte_data(client, ADT7470_REG_DEVICE);
- if (device != ADT7470_DEVICE) {
- err = -ENODEV;
- goto exit_free;
- }
+ if (device != ADT7470_DEVICE)
+ return -ENODEV;
revision = i2c_smbus_read_byte_data(client,
ADT7470_REG_REVISION);
- if (revision != ADT7470_REVISION) {
- err = -ENODEV;
- goto exit_free;
- }
+ if (revision != ADT7470_REVISION)
+ return -ENODEV;
} else
dev_dbg(&adapter->dev, "detection forced\n");
- strlcpy(client->name, "adt7470", I2C_NAME_SIZE);
+ strlcpy(info->type, "adt7470", I2C_NAME_SIZE);
- if ((err = i2c_attach_client(client)))
- goto exit_free;
+ return 0;
+}
+
+static int adt7470_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct adt7470_data *data;
+ int err;
+
+ data = kzalloc(sizeof(struct adt7470_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->lock);
dev_info(&client->dev, "%s chip found\n", client->name);
@@ -1071,7 +1070,7 @@ static int adt7470_detect(struct i2c_adapter *adapter, int address, int kind)
/* Register sysfs hooks */
data->attrs.attrs = adt7470_attr;
if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs)))
- goto exit_detach;
+ goto exit_free;
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -1083,21 +1082,18 @@ static int adt7470_detect(struct i2c_adapter *adapter, int address, int kind)
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_detach_client(struct i2c_client *client)
+static int adt7470_remove(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/drivers/hwmon/adt7473.c b/drivers/hwmon/adt7473.c
index 93dbf5e7ff8..ce4a7cb5a11 100644
--- a/drivers/hwmon/adt7473.c
+++ b/drivers/hwmon/adt7473.c
@@ -143,7 +143,6 @@ 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;
@@ -178,16 +177,28 @@ struct adt7473_data {
u8 max_duty_at_overheat;
};
-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 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 struct i2c_driver adt7473_driver = {
+ .class = I2C_CLASS_HWMON,
.driver = {
.name = "adt7473",
},
- .attach_adapter = adt7473_attach_adapter,
- .detach_client = adt7473_detach_client,
+ .probe = adt7473_probe,
+ .remove = adt7473_remove,
+ .id_table = adt7473_id,
+ .detect = adt7473_detect,
+ .address_data = &addr_data,
};
/*
@@ -1042,66 +1053,52 @@ static struct attribute *adt7473_attr[] =
NULL
};
-static int adt7473_attach_adapter(struct i2c_adapter *adapter)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int adt7473_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- 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;
+ struct i2c_adapter *adapter = client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- 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);
+ return -ENODEV;
if (kind <= 0) {
int vendor, device, revision;
vendor = i2c_smbus_read_byte_data(client, ADT7473_REG_VENDOR);
- if (vendor != ADT7473_VENDOR) {
- err = -ENODEV;
- goto exit_free;
- }
+ if (vendor != ADT7473_VENDOR)
+ return -ENODEV;
device = i2c_smbus_read_byte_data(client, ADT7473_REG_DEVICE);
- if (device != ADT7473_DEVICE) {
- err = -ENODEV;
- goto exit_free;
- }
+ if (device != ADT7473_DEVICE)
+ return -ENODEV;
revision = i2c_smbus_read_byte_data(client,
ADT7473_REG_REVISION);
- if (revision != ADT7473_REV_68 && revision != ADT7473_REV_69) {
- err = -ENODEV;
- goto exit_free;
- }
+ if (revision != ADT7473_REV_68 && revision != ADT7473_REV_69)
+ return -ENODEV;
} else
dev_dbg(&adapter->dev, "detection forced\n");
- strlcpy(client->name, "adt7473", I2C_NAME_SIZE);
+ strlcpy(info->type, "adt7473", I2C_NAME_SIZE);
- err = i2c_attach_client(client);
- if (err)
- goto exit_free;
+ 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);
dev_info(&client->dev, "%s chip found\n", client->name);
@@ -1112,7 +1109,7 @@ static int adt7473_detect(struct i2c_adapter *adapter, int address, int kind)
data->attrs.attrs = adt7473_attr;
err = sysfs_create_group(&client->dev.kobj, &data->attrs);
if (err)
- goto exit_detach;
+ goto exit_free;
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -1124,21 +1121,18 @@ static int adt7473_detect(struct i2c_adapter *adapter, int address, int kind)
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_detach_client(struct i2c_client *client)
+static int adt7473_remove(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/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index fe2eea4d799..8a45a2e6ba8 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -176,10 +176,8 @@ 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 */
@@ -206,18 +204,30 @@ 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_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 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 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",
},
- .attach_adapter = asb100_attach_adapter,
- .detach_client = asb100_detach_client,
+ .probe = asb100_probe,
+ .remove = asb100_remove,
+ .id_table = asb100_id,
+ .detect = asb100_detect,
+ .address_data = &addr_data,
};
/* 7 Voltages */
@@ -619,35 +629,13 @@ static const struct attribute_group asb100_group = {
.attrs = asb100_attributes,
};
-/* 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)
+static int asb100_detect_subclients(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);
-
- 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;
- }
+ struct i2c_adapter *adapter = client->adapter;
id = i2c_adapter_id(adapter);
@@ -665,37 +653,34 @@ static int asb100_detect_subclients(struct i2c_adapter *adapter, int address,
asb100_write_value(client, ASB100_REG_I2C_SUBADDR,
(force_subclients[2] & 0x07) |
((force_subclients[3] & 0x07) << 4));
- data->lm75[0]->addr = force_subclients[2];
- data->lm75[1]->addr = force_subclients[3];
+ sc_addr[0] = force_subclients[2];
+ sc_addr[1] = force_subclients[3];
} else {
int val = asb100_read_value(client, ASB100_REG_I2C_SUBADDR);
- data->lm75[0]->addr = 0x48 + (val & 0x07);
- data->lm75[1]->addr = 0x48 + ((val >> 4) & 0x07);
+ sc_addr[0] = 0x48 + (val & 0x07);
+ sc_addr[1] = 0x48 + ((val >> 4) & 0x07);
}
- if (data->lm75[0]->addr == data->lm75[1]->addr) {
+ if (sc_addr[0] == sc_addr[1]) {
dev_err(&client->dev, "duplicate addresses 0x%x "
- "for subclients\n", data->lm75[0]->addr);
+ "for subclients\n", sc_addr[0]);
err = -ENODEV;
goto ERROR_SC_2;
}
- 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]))) {
+ data->lm75[0] = i2c_new_dummy(adapter, sc_addr[0]);
+ if (!data->lm75[0]) {
dev_err(&client->dev, "subclient %d registration "
- "at address 0x%x failed.\n", i, data->lm75[0]->addr);
+ "at address 0x%x failed.\n", 1, sc_addr[0]);
+ err = -ENOMEM;
goto ERROR_SC_2;
}
- if ((err = i2c_attach_client(data->lm75[1]))) {
+ data->lm75[1] = i2c_new_dummy(adapter, sc_addr[1]);
+ if (!data->lm75[1]) {
dev_err(&client->dev, "subclient %d registration "
- "at address 0x%x failed.\n", i, data->lm75[1]->addr);
+ "at address 0x%x failed.\n", 2, sc_addr[1]);
+ err = -ENOMEM;
goto ERROR_SC_3;
}
@@ -703,55 +688,31 @@ static int asb100_detect_subclients(struct i2c_adapter *adapter, int address,
/* Undo inits in case of errors */
ERROR_SC_3:
- i2c_detach_client(data->lm75[0]);
+ i2c_unregister_device(data->lm75[0]);
ERROR_SC_2:
- kfree(data->lm75[1]);
-ERROR_SC_1:
- kfree(data->lm75[0]);
-ERROR_SC_0:
return err;
}
-static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int asb100_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- int err;
- struct i2c_client *client;
- struct asb100_data *data;
+ struct i2c_adapter *adapter = client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
pr_debug("asb100.o: detect failed, "
"smbus byte data not supported!\n");
- err = -ENODEV;
- goto ERROR0;
+ 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 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 = asb100_read_value(client, ASB100_REG_BANK);
- int val2 = asb100_read_value(client, ASB100_REG_CHIPMAN);
+ int val1 = i2c_smbus_read_byte_data(client, ASB100_REG_BANK);
+ int val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN);
/* If we're in bank 0 */
if ((!(val1 & 0x07)) &&
@@ -761,48 +722,60 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
((val1 & 0x80) && (val2 != 0x06)))) {
pr_debug("asb100.o: detect failed, "
"bad chip id 0x%02x!\n", val2);
- err = -ENODEV;
- goto ERROR1;
+ return -ENODEV;
}
} /* 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 */
- asb100_write_value(client, ASB100_REG_BANK,
- (asb100_read_value(client, ASB100_REG_BANK) & 0x78) | 0x80);
+ i2c_smbus_write_byte_data(client, ASB100_REG_BANK,
+ (i2c_smbus_read_byte_data(client, ASB100_REG_BANK) & 0x78)
+ | 0x80);
/* Determine the chip type. */
if (kind <= 0) {
- int val1 = asb100_read_value(client, ASB100_REG_WCHIPID);
- int val2 = asb100_read_value(client, ASB100_REG_CHIPMAN);
+ int val1 = i2c_smbus_read_byte_data(client, ASB100_REG_WCHIPID);
+ int val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN);
if ((val1 == 0x31) && (val2 == 0x06))
kind = asb100;
else {
if (kind == 0)
- dev_warn(&client->dev, "ignoring "
+ dev_warn(&adapter->dev, "ignoring "
"'force' parameter for unknown chip "
"at adapter %d, address 0x%02x.\n",
- i2c_adapter_id(adapter), address);
- err = -ENODEV;
- goto ERROR1;
+ i2c_adapter_id(adapter), client->addr);
+ return -ENODEV;
}
}
- /* 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);
+ strlcpy(info->type, "asb100", I2C_NAME_SIZE);
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(client)))
- goto ERROR1;
+ 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);
+ mutex_init(&data->update_lock);
/* Attach secondary lm75 clients */
- if ((err = asb100_detect_subclients(adapter, address, kind,
- client)))
- goto ERROR2;
+ err = asb100_detect_subclients(client);
+ if (err)
+ goto ERROR1;
/* Initialize the chip */
asb100_init_client(client);
@@ -827,39 +800,25 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
ERROR4:
sysfs_remove_group(&client->dev.kobj, &asb100_group);
ERROR3:
- 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);
+ i2c_unregister_device(data->lm75[1]);
+ i2c_unregister_device(data->lm75[0]);
ERROR1:
kfree(data);
ERROR0:
return err;
}
-static int asb100_detach_client(struct i2c_client *client)
+static int asb100_remove(struct i2c_client *client)
{
struct asb100_data *data = i2c_get_clientdata(client);
- int err;
-
- /* main client */
- if (data) {
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &asb100_group);
- }
- if ((err = i2c_detach_client(client)))
- return err;
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &asb100_group);
- /* main client */
- if (data)
- kfree(data);
+ i2c_unregister_device(data->lm75[1]);
+ i2c_unregister_device(data->lm75[0]);
- /* subclient */
- else
- kfree(client);
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index 01c17e387f0..d191118ba0c 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -46,21 +46,32 @@ static const unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END };
I2C_CLIENT_INSMOD_1(atxp1);
-static int atxp1_attach_adapter(struct i2c_adapter * adapter);
-static int atxp1_detach_client(struct i2c_client * client);
+static int atxp1_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int atxp1_remove(struct i2c_client *client);
static struct atxp1_data * atxp1_update_device(struct device *dev);
-static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind);
+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 struct i2c_driver atxp1_driver = {
+ .class = I2C_CLASS_HWMON,
.driver = {
.name = "atxp1",
},
- .attach_adapter = atxp1_attach_adapter,
- .detach_client = atxp1_detach_client,
+ .probe = atxp1_probe,
+ .remove = atxp1_remove,
+ .id_table = atxp1_id,
+ .detect = atxp1_detect,
+ .address_data = &addr_data,
};
struct atxp1_data {
- struct i2c_client client;
struct device *hwmon_dev;
struct mutex update_lock;
unsigned long last_updated;
@@ -263,35 +274,16 @@ static const struct attribute_group atxp1_group = {
};
-static int atxp1_attach_adapter(struct i2c_adapter *adapter)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int atxp1_detect(struct i2c_client *new_client, int kind,
+ struct i2c_board_info *info)
{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_probe(adapter, &addr_data, &atxp1_detect);
-};
+ struct i2c_adapter *adapter = new_client->adapter;
-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))
- 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;
+ return -ENODEV;
/* Detect ATXP1, checking if vendor ID registers are all zero */
if (!((i2c_smbus_read_byte_data(new_client, 0x3e) == 0) &&
@@ -305,35 +297,46 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
if (!((i2c_smbus_read_byte_data(new_client, 0x10) == temp) &&
(i2c_smbus_read_byte_data(new_client, 0x11) == temp) ))
- goto exit_free;
+ return -ENODEV;
}
/* Get VRM */
- data->vrm = vid_which_vrm();
+ temp = vid_which_vrm();
- 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;
+ if ((temp != 90) && (temp != 91)) {
+ dev_err(&adapter->dev, "atxp1: Not supporting VRM %d.%d\n",
+ temp / 10, temp % 10);
+ return -ENODEV;
}
- strncpy(new_client->name, "atxp1", I2C_NAME_SIZE);
-
- data->valid = 0;
+ strlcpy(info->type, "atxp1", I2C_NAME_SIZE);
- mutex_init(&data->update_lock);
+ return 0;
+}
- err = i2c_attach_client(new_client);
+static int atxp1_probe(struct i2c_client *new_client,
+ const struct i2c_device_id *id)
+{
+ struct atxp1_data *data;
+ int err;
- if (err)
- {
- dev_err(&new_client->dev, "Attach client error.\n");
- goto exit_free;
+ data = kzalloc(sizeof(struct atxp1_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
}
+ /* Get VRM */
+ data->vrm = vid_which_vrm();
+
+ i2c_set_clientdata(new_client, data);
+ data->valid = 0;
+
+ mutex_init(&data->update_lock);
+
/* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group)))
- goto exit_detach;
+ goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -348,30 +351,22 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
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_detach_client(struct i2c_client * client)
+static int atxp1_remove(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);
- err = i2c_detach_client(client);
-
- if (err)
- dev_err(&client->dev, "Failed to detach client.\n");
- else
- kfree(data);
+ kfree(data);
- return err;
+ return 0;
};
static int __init atxp1_init(void)
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index 5f300ffed65..7415381601c 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -72,7 +72,6 @@ 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 */
@@ -82,20 +81,32 @@ struct ds1621_data {
u8 conf; /* Register encoding, combined */
};
-static int ds1621_attach_adapter(struct i2c_adapter *adapter);
-static int ds1621_detect(struct i2c_adapter *adapter, int address,
- int kind);
+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 void ds1621_init_client(struct i2c_client *client);
-static int ds1621_detach_client(struct i2c_client *client);
+static int ds1621_remove(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",
},
- .attach_adapter = ds1621_attach_adapter,
- .detach_client = ds1621_detach_client,
+ .probe = ds1621_probe,
+ .remove = ds1621_remove,
+ .id_table = ds1621_id,
+ .detect = ds1621_detect,
+ .address_data = &addr_data,
};
/* All registers are word-sized, except for the configuration register.
@@ -199,40 +210,18 @@ static const struct attribute_group ds1621_group = {
};
-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)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int ds1621_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
+ struct i2c_adapter *adapter = client->adapter;
int conf, temp;
- struct i2c_client *client;
- struct ds1621_data *data;
- int i, err = 0;
+ int i;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_WORD_DATA
| I2C_FUNC_SMBUS_WRITE_BYTE))
- 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;
+ return -ENODEV;
/* Now, we do the remaining detection. It is lousy. */
if (kind < 0) {
@@ -241,29 +230,41 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address,
improbable in our case. */
conf = ds1621_read_value(client, DS1621_REG_CONF);
if (conf & DS1621_REG_CONFIG_NVB)
- goto exit_free;
+ return -ENODEV;
/* The 7 lowest bits of a temperature should always be 0. */
- for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
+ for (i = 0; i < ARRAY_SIZE(DS1621_REG_TEMP); i++) {
temp = ds1621_read_value(client, DS1621_REG_TEMP[i]);
if (temp & 0x007f)
- goto exit_free;
+ return -ENODEV;
}
}
- /* Fill in remaining client fields and put it into the global list */
- strlcpy(client->name, "ds1621", I2C_NAME_SIZE);
- mutex_init(&data->update_lock);
+ strlcpy(info->type, "ds1621", I2C_NAME_SIZE);
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(client)))
- goto exit_free;
+ 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);
+ mutex_init(&data->update_lock);
/* Initialize the DS1621 chip */
ds1621_init_client(client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &ds1621_group)))
- goto exit_detach;
+ goto exit_free;
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -275,25 +276,19 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address,
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_detach_client(struct i2c_client *client)
+static int ds1621_remove(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/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
index dc1f30e432e..1692de36996 100644
--- a/drivers/hwmon/f75375s.c
+++ b/drivers/hwmon/f75375s.c
@@ -87,7 +87,6 @@ I2C_CLIENT_INSMOD_2(f75373, f75375);
struct f75375_data {
unsigned short addr;
- struct i2c_client *client;
struct device *hwmon_dev;
const char *name;
@@ -114,21 +113,12 @@ struct f75375_data {
s8 temp_max_hyst[2];
};
-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_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
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 },
@@ -137,12 +127,15 @@ 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)
@@ -607,22 +600,6 @@ 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)
{
@@ -651,7 +628,6 @@ 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;
@@ -700,29 +676,13 @@ static int f75375_remove(struct i2c_client *client)
return 0;
}
-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)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int f75375_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *client;
+ struct i2c_adapter *adapter = client->adapter;
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);
@@ -736,7 +696,7 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
dev_err(&adapter->dev,
"failed,%02X,%02X,%02X\n",
chipid, version, vendid);
- goto exit_free;
+ return -ENODEV;
}
}
@@ -746,43 +706,18 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
name = "f75373";
}
dev_info(&adapter->dev, "found %s version: %02X\n", name, version);
- 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;
+ strlcpy(info->type, name, I2C_NAME_SIZE);
return 0;
-
-exit_detach:
- i2c_detach_client(client);
-exit_free:
- kfree(client);
-exit:
- return err;
}
static int __init sensors_f75375_init(void)
{
- 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;
+ return i2c_add_driver(&f75375_driver);
}
static void __exit sensors_f75375_exit(void)
{
- i2c_del_driver(&f75375_legacy_driver);
i2c_del_driver(&f75375_driver);
}
diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c
index ed26b66e083..12c70e402cb 100644
--- a/drivers/hwmon/fscher.c
+++ b/drivers/hwmon/fscher.c
@@ -106,9 +106,11 @@ I2C_CLIENT_INSMOD_1(fscher);
* Functions declaration
*/
-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 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 struct fscher_data *fscher_update_device(struct device *dev);
static void fscher_init_client(struct i2c_client *client);
@@ -119,12 +121,21 @@ 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",
},
- .attach_adapter = fscher_attach_adapter,
- .detach_client = fscher_detach_client,
+ .probe = fscher_probe,
+ .remove = fscher_remove,
+ .id_table = fscher_id,
+ .detect = fscher_detect,
+ .address_data = &addr_data,
};
/*
@@ -132,7 +143,6 @@ 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 */
@@ -283,38 +293,14 @@ static const struct attribute_group fscher_group = {
* Real code
*/
-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)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int fscher_detect(struct i2c_client *new_client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *new_client;
- struct fscher_data *data;
- int err = 0;
+ struct i2c_adapter *adapter = new_client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_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.
- * 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;
+ return -ENODEV;
/* Do the remaining detection unless force or force_fscher parameter */
if (kind < 0) {
@@ -324,24 +310,35 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
FSCHER_REG_IDENT_1) != 0x45) /* 'E' */
|| (i2c_smbus_read_byte_data(new_client,
FSCHER_REG_IDENT_2) != 0x52)) /* 'R' */
- goto exit_free;
+ 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;
}
- /* Fill in the remaining client fields and put it into the
- * global list */
- strlcpy(new_client->name, "fscher", I2C_NAME_SIZE);
+ 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;
-
fscher_init_client(new_client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &fscher_group)))
- goto exit_detach;
+ goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -353,25 +350,19 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
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_detach_client(struct i2c_client *client)
+static int fscher_remove(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/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c
index bd89d270a5e..96717036893 100644
--- a/drivers/hwmon/fschmd.c
+++ b/drivers/hwmon/fschmd.c
@@ -171,20 +171,37 @@ static const int FSCHMD_NO_TEMP_SENSORS[5] = { 3, 3, 4, 3, 5 };
* Functions declarations
*/
-static int fschmd_attach_adapter(struct i2c_adapter *adapter);
-static int fschmd_detach_client(struct i2c_client *client);
+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 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,
},
- .attach_adapter = fschmd_attach_adapter,
- .detach_client = fschmd_detach_client,
+ .probe = fschmd_probe,
+ .remove = fschmd_remove,
+ .id_table = fschmd_id,
+ .detect = fschmd_detect,
+ .address_data = &addr_data,
};
/*
@@ -192,7 +209,6 @@ static struct i2c_driver fschmd_driver = {
*/
struct fschmd_data {
- struct i2c_client client;
struct device *hwmon_dev;
struct mutex update_lock;
int kind;
@@ -269,7 +285,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(&data->client,
+ i2c_smbus_write_byte_data(to_i2c_client(dev),
FSCHMD_REG_TEMP_LIMIT[data->kind][index], v);
data->temp_max[index] = v;
mutex_unlock(&data->update_lock);
@@ -346,14 +362,14 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute
mutex_lock(&data->update_lock);
- reg = i2c_smbus_read_byte_data(&data->client,
+ reg = i2c_smbus_read_byte_data(to_i2c_client(dev),
FSCHMD_REG_FAN_RIPPLE[data->kind][index]);
/* bits 2..7 reserved => mask with 0x03 */
reg &= ~0x03;
reg |= v;
- i2c_smbus_write_byte_data(&data->client,
+ i2c_smbus_write_byte_data(to_i2c_client(dev),
FSCHMD_REG_FAN_RIPPLE[data->kind][index], reg);
data->fan_ripple[index] = reg;
@@ -416,7 +432,7 @@ static ssize_t store_pwm_auto_point1_pwm(struct device *dev,
mutex_lock(&data->update_lock);
- i2c_smbus_write_byte_data(&data->client,
+ i2c_smbus_write_byte_data(to_i2c_client(dev),
FSCHMD_REG_FAN_MIN[data->kind][index], v);
data->fan_min[index] = v;
@@ -448,14 +464,14 @@ static ssize_t store_alert_led(struct device *dev,
mutex_lock(&data->update_lock);
- reg = i2c_smbus_read_byte_data(&data->client, FSCHMD_REG_CONTROL);
+ reg = i2c_smbus_read_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL);
if (v)
reg |= FSCHMD_CONTROL_ALERT_LED_MASK;
else
reg &= ~FSCHMD_CONTROL_ALERT_LED_MASK;
- i2c_smbus_write_byte_data(&data->client, FSCHMD_REG_CONTROL, reg);
+ i2c_smbus_write_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL, reg);
data->global_control = reg;
@@ -600,32 +616,15 @@ static void fschmd_dmi_decode(const struct dmi_header *header)
}
}
-static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind)
+static int fschmd_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *client;
- struct fschmd_data *data;
- u8 revision;
- const char * const names[5] = { "Poseidon", "Hermes", "Scylla",
- "Heracles", "Heimdall" };
+ struct i2c_adapter *adapter = client->adapter;
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 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);
+ return -ENODEV;
/* Detect & Identify the chip */
if (kind <= 0) {
@@ -650,9 +649,31 @@ static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind)
else if (!strcmp(id, "HMD"))
kind = fschmd;
else
- goto exit_free;
+ return -ENODEV;
}
+ 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 */
@@ -674,11 +695,6 @@ static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind)
/* 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,
@@ -726,25 +742,14 @@ static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
exit_detach:
- fschmd_detach_client(client); /* will also free data for us */
- return err;
-
-exit_free:
- kfree(data);
+ fschmd_remove(client); /* will also free data for us */
return err;
}
-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)
+static int fschmd_remove(struct i2c_client *client)
{
struct fschmd_data *data = i2c_get_clientdata(client);
- int i, err;
+ int i;
/* Check if registered in case we're called from fschmd_detect
to cleanup after an error */
@@ -760,9 +765,6 @@ static int fschmd_detach_client(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/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c
index 00f48484e54..8a7bcf500b4 100644
--- a/drivers/hwmon/fscpos.c
+++ b/drivers/hwmon/fscpos.c
@@ -87,9 +87,11 @@ static u8 FSCPOS_REG_TEMP_STATE[] = { 0x71, 0x81, 0x91 };
/*
* Functions declaration
*/
-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_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_read_value(struct i2c_client *client, u8 reg);
static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value);
@@ -101,19 +103,27 @@ 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",
},
- .attach_adapter = fscpos_attach_adapter,
- .detach_client = fscpos_detach_client,
+ .probe = fscpos_probe,
+ .remove = fscpos_remove,
+ .id_table = fscpos_id,
+ .detect = fscpos_detect,
+ .address_data = &addr_data,
};
/*
* 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 */
@@ -470,39 +480,14 @@ static const struct attribute_group fscpos_group = {
.attrs = fscpos_attributes,
};
-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)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int fscpos_detect(struct i2c_client *new_client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *new_client;
- struct fscpos_data *data;
- int err = 0;
+ struct i2c_adapter *adapter = new_client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_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.
- * 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;
+ return -ENODEV;
/* Do the remaining detection unless force or force_fscpos parameter */
if (kind < 0) {
@@ -512,22 +497,30 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
!= 0x45) /* 'E' */
|| (fscpos_read_value(new_client, FSCPOS_REG_IDENT_2)
!= 0x47))/* 'G' */
- {
- dev_dbg(&new_client->dev, "fscpos detection failed\n");
- goto exit_free;
- }
+ return -ENODEV;
}
- /* Fill in the remaining client fields and put it in the global list */
- strlcpy(new_client->name, "fscpos", I2C_NAME_SIZE);
+ strlcpy(info->type, "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);
@@ -536,7 +529,7 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
/* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &fscpos_group)))
- goto exit_detach;
+ goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -548,24 +541,19 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
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_detach_client(struct i2c_client *client)
+static int fscpos_remove(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/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c
index 33e9e8a8d1c..7820df45d77 100644
--- a/drivers/hwmon/gl518sm.c
+++ b/drivers/hwmon/gl518sm.c
@@ -114,7 +114,6 @@ 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;
@@ -138,21 +137,33 @@ struct gl518_data {
u8 beep_enable; /* Boolean */
};
-static int gl518_attach_adapter(struct i2c_adapter *adapter);
-static int gl518_detect(struct i2c_adapter *adapter, int address, int kind);
+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 void gl518_init_client(struct i2c_client *client);
-static int gl518_detach_client(struct i2c_client *client);
+static int gl518_remove(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",
},
- .attach_adapter = gl518_attach_adapter,
- .detach_client = gl518_detach_client,
+ .probe = gl518_probe,
+ .remove = gl518_remove,
+ .id_table = gl518_id,
+ .detect = gl518_detect,
+ .address_data = &addr_data,
};
/*
@@ -472,46 +483,23 @@ static const struct attribute_group gl518_group_r80 = {
* Real code
*/
-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)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int gl518_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
+ 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))
- 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;
+ return -ENODEV;
/* 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))
- goto exit_free;
+ return -ENODEV;
}
/* Determine the chip type. */
@@ -526,19 +514,32 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
dev_info(&adapter->dev,
"Ignoring 'force' parameter for unknown "
"chip at adapter %d, address 0x%02x\n",
- i2c_adapter_id(adapter), address);
- goto exit_free;
+ i2c_adapter_id(adapter), client->addr);
+ return -ENODEV;
}
}
- /* Fill in the remaining client fields */
- strlcpy(client->name, "gl518sm", I2C_NAME_SIZE);
- data->type = kind;
- mutex_init(&data->update_lock);
+ strlcpy(info->type, "gl518sm", I2C_NAME_SIZE);
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(client)))
- goto exit_free;
+ 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;
+ mutex_init(&data->update_lock);
/* Initialize the GL518SM chip */
data->alarm_mask = 0xff;
@@ -546,7 +547,7 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &gl518_group)))
- goto exit_detach;
+ goto exit_free;
if (data->type == gl518sm_r80)
if ((err = sysfs_create_group(&client->dev.kobj,
&gl518_group_r80)))
@@ -564,8 +565,6 @@ exit_remove_files:
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:
@@ -591,19 +590,15 @@ static void gl518_init_client(struct i2c_client *client)
gl518_write_value(client, GL518_REG_CONF, 0x40 | regvalue);
}
-static int gl518_detach_client(struct i2c_client *client)
+static int gl518_remove(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/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c
index 8984ef14162..19616f2242b 100644
--- a/drivers/hwmon/gl520sm.c
+++ b/drivers/hwmon/gl520sm.c
@@ -79,26 +79,37 @@ static const u8 GL520_REG_TEMP_MAX_HYST[] = { 0x06, 0x18 };
* Function declarations
*/
-static int gl520_attach_adapter(struct i2c_adapter *adapter);
-static int gl520_detect(struct i2c_adapter *adapter, int address, int kind);
+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 void gl520_init_client(struct i2c_client *client);
-static int gl520_detach_client(struct i2c_client *client);
+static int gl520_remove(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",
},
- .attach_adapter = gl520_attach_adapter,
- .detach_client = gl520_detach_client,
+ .probe = gl520_probe,
+ .remove = gl520_remove,
+ .id_table = gl520_id,
+ .detect = gl520_detect,
+ .address_data = &addr_data,
};
/* 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 */
@@ -669,37 +680,15 @@ static const struct attribute_group gl520_group_opt = {
* Real code
*/
-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)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int gl520_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *client;
- struct gl520_data *data;
- int err = 0;
+ struct i2c_adapter *adapter = client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_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.
- 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;
+ return -ENODEV;
/* Determine the chip type. */
if (kind < 0) {
@@ -707,24 +696,36 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, 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");
- goto exit_free;
+ return -ENODEV;
}
}
- /* Fill in the remaining client fields */
- strlcpy(client->name, "gl520sm", I2C_NAME_SIZE);
- mutex_init(&data->update_lock);
+ strlcpy(info->type, "gl520sm", I2C_NAME_SIZE);
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(client)))
- goto exit_free;
+ 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);
+ mutex_init(&data->update_lock);
/* Initialize the GL520SM chip */
gl520_init_client(client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &gl520_group)))
- goto exit_detach;
+ goto exit_free;
if (data->two_temps) {
if ((err = device_create_file(&client->dev,
@@ -764,8 +765,6 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
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:
@@ -811,18 +810,14 @@ static void gl520_init_client(struct i2c_client *client)
gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask);
}
-static int gl520_detach_client(struct i2c_client *client)
+static int gl520_remove(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/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index 11628700808..3195a265f0e 100644
--- a/drivers/hwmon/lm63.c
+++ b/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-2006 Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2004-2008 Jean Delvare <khali@linux-fr.org>
* Based on the lm90 driver.
*
* The LM63 is a sensor chip made by National Semiconductor. It measures
@@ -128,24 +128,36 @@ I2C_CLIENT_INSMOD_1(lm63);
* Functions declaration
*/
-static int lm63_attach_adapter(struct i2c_adapter *adapter);
-static int lm63_detach_client(struct i2c_client *client);
+static int lm63_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int lm63_remove(struct i2c_client *client);
static struct lm63_data *lm63_update_device(struct device *dev);
-static int lm63_detect(struct i2c_adapter *adapter, int address, int kind);
+static int lm63_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
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",
},
- .attach_adapter = lm63_attach_adapter,
- .detach_client = lm63_detach_client,
+ .probe = lm63_probe,
+ .remove = lm63_remove,
+ .id_table = lm63_id,
+ .detect = lm63_detect,
+ .address_data = &addr_data,
};
/*
@@ -153,7 +165,6 @@ 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 */
@@ -411,43 +422,14 @@ static const struct attribute_group lm63_group_fan1 = {
* Real code
*/
-static int lm63_attach_adapter(struct i2c_adapter *adapter)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int lm63_detect(struct i2c_client *new_client, int kind,
+ struct i2c_board_info *info)
{
- 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;
+ struct i2c_adapter *adapter = new_client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- 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;
+ return -ENODEV;
if (kind < 0) { /* must identify */
u8 man_id, chip_id, reg_config1, reg_config2;
@@ -477,25 +459,38 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
dev_dbg(&adapter->dev, "Unsupported chip "
"(man_id=0x%02X, chip_id=0x%02X).\n",
man_id, chip_id);
- goto exit_free;
+ return -ENODEV;
}
}
- strlcpy(new_client->name, "lm63", I2C_NAME_SIZE);
+ 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);
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_detach;
+ goto exit_free;
if (data->config & 0x04) { /* tachometer enabled */
if ((err = sysfs_create_group(&new_client->dev.kobj,
&lm63_group_fan1)))
@@ -513,8 +508,6 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
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:
@@ -556,18 +549,14 @@ static void lm63_init_client(struct i2c_client *client)
(data->config_fan & 0x20) ? "manual" : "auto");
}
-static int lm63_detach_client(struct i2c_client *client)
+static int lm63_remove(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/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index 36d5a8c3ad8..866b401ab6e 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -52,7 +52,6 @@ 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;
@@ -65,23 +64,35 @@ struct lm77_data {
u8 alarms;
};
-static int lm77_attach_adapter(struct i2c_adapter *adapter);
-static int lm77_detect(struct i2c_adapter *adapter, int address, int kind);
+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 void lm77_init_client(struct i2c_client *client);
-static int lm77_detach_client(struct i2c_client *client);
+static int lm77_remove(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",
},
- .attach_adapter = lm77_attach_adapter,
- .detach_client = lm77_detach_client,
+ .probe = lm77_probe,
+ .remove = lm77_remove,
+ .id_table = lm77_id,
+ .detect = lm77_detect,
+ .address_data = &addr_data,
};
/* straight from the datasheet */
@@ -215,13 +226,6 @@ 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,
@@ -240,32 +244,15 @@ static const struct attribute_group lm77_group = {
.attrs = lm77_attributes,
};
-/* This function is called by i2c_probe */
-static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int lm77_detect(struct i2c_client *new_client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *new_client;
- struct lm77_data *data;
- int err = 0;
- const char *name = "";
+ struct i2c_adapter *adapter = new_client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_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.
- 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;
+ return -ENODEV;
/* Here comes the remaining detection. Since the LM77 has no
register dedicated to identification, we have to rely on the
@@ -294,7 +281,7 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, 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)
- goto exit_free;
+ return -ENODEV;
/* sign bits */
if (((cur & 0x00f0) != 0xf0 && (cur & 0x00f0) != 0x0)
@@ -302,51 +289,55 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
|| ((crit & 0x00f0) != 0xf0 && (crit & 0x00f0) != 0x0)
|| ((min & 0x00f0) != 0xf0 && (min & 0x00f0) != 0x0)
|| ((max & 0x00f0) != 0xf0 && (max & 0x00f0) != 0x0))
- goto exit_free;
+ return -ENODEV;
/* unused bits */
if (conf & 0xe0)
- goto exit_free;
+ return -ENODEV;
/* 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)
- goto exit_free;
+ return -ENODEV;
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)
- goto exit_free;
+ return -ENODEV;
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)
- goto exit_free;
+ return -ENODEV;
}
- /* Determine the chip type - only one kind supported! */
- if (kind <= 0)
- kind = lm77;
+ strlcpy(info->type, "lm77", I2C_NAME_SIZE);
- if (kind == lm77) {
- name = "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;
}
- /* Fill in the remaining client fields and put it into the global list */
- strlcpy(new_client->name, name, I2C_NAME_SIZE);
+ 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;
-
/* 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_detach;
+ goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -358,20 +349,17 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
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_detach_client(struct i2c_client *client)
+static int lm77_remove(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/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index 26c91c9d476..bcffc189940 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -108,7 +108,6 @@ 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 */
@@ -132,10 +131,12 @@ struct lm80_data {
* Functions declaration
*/
-static int lm80_attach_adapter(struct i2c_adapter *adapter);
-static int lm80_detect(struct i2c_adapter *adapter, int address, int kind);
+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 void lm80_init_client(struct i2c_client *client);
-static int lm80_detach_client(struct i2c_client *client);
+static int lm80_remove(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);
@@ -144,12 +145,22 @@ 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",
},
- .attach_adapter = lm80_attach_adapter,
- .detach_client = lm80_detach_client,
+ .probe = lm80_probe,
+ .remove = lm80_remove,
+ .id_table = lm80_id,
+ .detect = lm80_detect,
+ .address_data = &addr_data,
};
/*
@@ -383,13 +394,6 @@ 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,
@@ -442,53 +446,46 @@ static const struct attribute_group lm80_group = {
.attrs = lm80_attributes,
};
-static int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int lm80_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
+ 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))
- 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;
+ return -ENODEV;
/* Now, we do the remaining detection. It is lousy. */
if (lm80_read_value(client, LM80_REG_ALARM2) & 0xc0)
- goto error_free;
+ return -ENODEV;
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))
- goto error_free;
+ return -ENODEV;
}
- /* Determine the chip type - only one kind supported! */
- kind = lm80;
- name = "lm80";
+ strlcpy(info->type, "lm80", I2C_NAME_SIZE);
- /* Fill in the remaining client fields */
- strlcpy(client->name, name, I2C_NAME_SIZE);
- mutex_init(&data->update_lock);
+ return 0;
+}
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(client)))
- goto error_free;
+static int lm80_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct lm80_data *data;
+ int err;
+
+ data = kzalloc(sizeof(struct lm80_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
/* Initialize the LM80 chip */
lm80_init_client(client);
@@ -499,7 +496,7 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &lm80_group)))
- goto error_detach;
+ goto error_free;
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -511,23 +508,18 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
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_detach_client(struct i2c_client *client)
+static int lm80_remove(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/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index 6a8642fa25f..e59e2d1f080 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -1,7 +1,7 @@
/*
* lm83.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
- * Copyright (C) 2003-2006 Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2008 Jean Delvare <khali@linux-fr.org>
*
* 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,21 +118,34 @@ static const u8 LM83_REG_W_HIGH[] = {
* Functions declaration
*/
-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 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 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",
},
- .attach_adapter = lm83_attach_adapter,
- .detach_client = lm83_detach_client,
+ .probe = lm83_probe,
+ .remove = lm83_remove,
+ .id_table = lm83_id,
+ .detect = lm83_detect,
+ .address_data = &addr_data,
};
/*
@@ -140,7 +153,6 @@ 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 */
@@ -278,40 +290,15 @@ static const struct attribute_group lm83_group_opt = {
* Real code
*/
-static int lm83_attach_adapter(struct i2c_adapter *adapter)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int lm83_detect(struct i2c_client *new_client, int kind,
+ struct i2c_board_info *info)
{
- 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;
+ struct i2c_adapter *adapter = new_client->adapter;
const char *name = "";
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- 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;
+ return -ENODEV;
/* Now we do the detection and identification. A negative kind
* means that the driver was loaded with no force parameter
@@ -335,8 +322,9 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, 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", address);
- goto exit_free;
+ "LM83 detection failed at 0x%02x.\n",
+ new_client->addr);
+ return -ENODEV;
}
}
@@ -361,7 +349,7 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
dev_info(&adapter->dev,
"Unsupported chip (man_id=0x%02X, "
"chip_id=0x%02X).\n", man_id, chip_id);
- goto exit_free;
+ return -ENODEV;
}
}
@@ -372,15 +360,27 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
name = "lm82";
}
- /* We can fill in the remaining client fields */
- strlcpy(new_client->name, name, I2C_NAME_SIZE);
+ 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);
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_detect(struct i2c_adapter *adapter, int address, int kind)
*/
if ((err = sysfs_create_group(&new_client->dev.kobj, &lm83_group)))
- goto exit_detach;
+ goto exit_free;
- if (kind == lm83) {
+ if (id->driver_data == lm83) {
if ((err = sysfs_create_group(&new_client->dev.kobj,
&lm83_group_opt)))
goto exit_remove_files;
@@ -408,26 +408,20 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
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_detach_client(struct i2c_client *client)
+static int lm83_remove(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/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index e1c183f0aae..21970f0d53a 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -5,7 +5,7 @@
* Philip Edelbrock <phil@netroedge.com>
* Stephen Rousset <stephen.rousset@rocketlogix.com>
* Dan Eaton <dan.eaton@rocketlogix.com>
- * Copyright (C) 2004,2007 Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2004-2008 Jean Delvare <khali@linux-fr.org>
*
* Original port to Linux 2.6 by Jeff Oliver.
*
@@ -157,22 +157,35 @@ static u8 LM87_REG_TEMP_LOW[3] = { 0x3A, 0x38, 0x2C };
* Functions declaration
*/
-static int lm87_attach_adapter(struct i2c_adapter *adapter);
-static int lm87_detect(struct i2c_adapter *adapter, int address, int kind);
+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 void lm87_init_client(struct i2c_client *client);
-static int lm87_detach_client(struct i2c_client *client);
+static int lm87_remove(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",
},
- .attach_adapter = lm87_attach_adapter,
- .detach_client = lm87_detach_client,
+ .probe = lm87_probe,
+ .remove = lm87_remove,
+ .id_table = lm87_id,
+ .detect = lm87_detect,
+ .address_data = &addr_data,
};
/*
@@ -180,7 +193,6 @@ 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 */
@@ -562,13 +574,6 @@ 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,
@@ -656,33 +661,15 @@ static const struct attribute_group lm87_group_opt = {
.attrs = lm87_attributes_opt,
};
-/*
- * 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)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int lm87_detect(struct i2c_client *new_client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *new_client;
- struct lm87_data *data;
- int err = 0;
+ struct i2c_adapter *adapter = new_client->adapter;
static const char *names[] = { "lm87", "adm1024" };
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- 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;
+ return -ENODEV;
/* Default to an LM87 if forced */
if (kind == 0)
@@ -704,20 +691,32 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
|| (lm87_read_value(new_client, LM87_REG_CONFIG) & 0x80)) {
dev_dbg(&adapter->dev,
"LM87 detection failed at 0x%02x.\n",
- address);
- goto exit_free;
+ new_client->addr);
+ return -ENODEV;
}
}
- /* We can fill in the remaining client fields */
- strlcpy(new_client->name, names[kind - 1], I2C_NAME_SIZE);
+ 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);
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);
@@ -732,7 +731,7 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
/* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &lm87_group)))
- goto exit_detach;
+ goto exit_free;
if (data->channel & CHAN_NO_FAN(0)) {
if ((err = device_create_file(&new_client->dev,
@@ -832,8 +831,6 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
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:
@@ -877,18 +874,14 @@ static void lm87_init_client(struct i2c_client *client)
}
}
-static int lm87_detach_client(struct i2c_client *client)
+static int lm87_remove(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/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index d1a3da3dd8e..c24fe36ac78 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -187,23 +187,44 @@ I2C_CLIENT_INSMOD_7(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680);
* Functions declaration
*/
-static int lm90_attach_adapter(struct i2c_adapter *adapter);
-static int lm90_detect(struct i2c_adapter *adapter, int address,
- int kind);
+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 void lm90_init_client(struct i2c_client *client);
-static int lm90_detach_client(struct i2c_client *client);
+static int lm90_remove(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",
},
- .attach_adapter = lm90_attach_adapter,
- .detach_client = lm90_detach_client,
+ .probe = lm90_probe,
+ .remove = lm90_remove,
+ .id_table = lm90_id,
+ .detect = lm90_detect,
+ .address_data = &addr_data,
};
/*
@@ -211,7 +232,6 @@ 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 */
@@ -477,40 +497,16 @@ static int lm90_read_reg(struct i2c_client* client, u8 reg, u8 *value)
return 0;
}
-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)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int lm90_detect(struct i2c_client *new_client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *new_client;
- struct lm90_data *data;
- int err = 0;
+ struct i2c_adapter *adapter = new_client->adapter;
+ int address = new_client->addr;
const char *name = "";
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- 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;
+ return -ENODEV;
/*
* Now we do the remaining detection. A negative kind means that
@@ -538,7 +534,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
LM90_REG_R_CONFIG1)) < 0
|| (reg_convrate = i2c_smbus_read_byte_data(new_client,
LM90_REG_R_CONVRATE)) < 0)
- goto exit_free;
+ return -ENODEV;
if ((address == 0x4C || address == 0x4D)
&& man_id == 0x01) { /* National Semiconductor */
@@ -546,7 +542,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
if ((reg_config2 = i2c_smbus_read_byte_data(new_client,
LM90_REG_R_CONFIG2)) < 0)
- goto exit_free;
+ return -ENODEV;
if ((reg_config1 & 0x2A) == 0x00
&& (reg_config2 & 0xF8) == 0x00
@@ -610,10 +606,11 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
dev_info(&adapter->dev,
"Unsupported chip (man_id=0x%02X, "
"chip_id=0x%02X).\n", man_id, chip_id);
- goto exit_free;
+ return -ENODEV;
}
}
+ /* Fill the i2c board info */
if (kind == lm90) {
name = "lm90";
} else if (kind == adm1032) {
@@ -621,7 +618,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
/* The ADM1032 supports PEC, but only if combined
transactions are not used. */
if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
- new_client->flags |= I2C_CLIENT_PEC;
+ info->flags |= I2C_CLIENT_PEC;
} else if (kind == lm99) {
name = "lm99";
} else if (kind == lm86) {
@@ -633,23 +630,39 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, 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;
- /* We can fill in the remaining client fields */
- strlcpy(new_client->name, name, I2C_NAME_SIZE);
- data->valid = 0;
- data->kind = kind;
+ data = kzalloc(sizeof(struct lm90_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ i2c_set_clientdata(new_client, data);
mutex_init(&data->update_lock);
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(new_client)))
- goto exit_free;
+ /* 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;
+ }
/* 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_detach;
+ goto exit_free;
if (new_client->flags & I2C_CLIENT_PEC) {
if ((err = device_create_file(&new_client->dev,
&dev_attr_pec)))
@@ -672,8 +685,6 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
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:
@@ -710,10 +721,9 @@ static void lm90_init_client(struct i2c_client *client)
i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config);
}
-static int lm90_detach_client(struct i2c_client *client)
+static int lm90_remove(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);
@@ -722,9 +732,6 @@ static int lm90_detach_client(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/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c
index c31942e0824..b2e00c5a7ee 100644
--- a/drivers/hwmon/lm92.c
+++ b/drivers/hwmon/lm92.c
@@ -1,6 +1,6 @@
/*
* lm92 - Hardware monitoring driver
- * Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2005-2008 Jean Delvare <khali@linux-fr.org>
*
* Based on the lm90 driver, with some ideas taken from the lm_sensors
* lm92 driver as well.
@@ -96,7 +96,6 @@ 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 */
@@ -319,32 +318,15 @@ static const struct attribute_group lm92_group = {
.attrs = lm92_attributes,
};
-/* 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)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int lm92_detect(struct i2c_client *new_client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *new_client;
- struct lm92_data *data;
- int err = 0;
- char *name;
+ struct i2c_adapter *adapter = new_client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_WORD_DATA))
- 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;
+ return -ENODEV;
/* A negative kind means that the driver was loaded with no force
parameter (default), so we must identify the chip. */
@@ -364,34 +346,36 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
kind = lm92; /* No separate prefix */
}
else
- 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;
+ return -ENODEV;
}
- /* Fill in the remaining client fields */
- strlcpy(new_client->name, name, I2C_NAME_SIZE);
+ 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;
+ }
+
+ i2c_set_clientdata(new_client, data);
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_detach;
+ goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -403,32 +387,19 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
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_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)
+static int lm92_remove(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;
}
@@ -438,12 +409,23 @@ static int lm92_detach_client(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",
},
- .attach_adapter = lm92_attach_adapter,
- .detach_client = lm92_detach_client,
+ .probe = lm92_probe,
+ .remove = lm92_remove,
+ .id_table = lm92_id,
+ .detect = lm92_detect,
+ .address_data = &addr_data,
};
static int __init sensors_lm92_init(void)
diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c
index 5e678f5c883..fc36cadf36f 100644
--- a/drivers/hwmon/lm93.c
+++ b/drivers/hwmon/lm93.c
@@ -200,7 +200,6 @@ struct block1_t {
* Client-specific data
*/
struct lm93_data {
- struct i2c_client client;
struct device *hwmon_dev;
struct mutex update_lock;
@@ -2501,45 +2500,14 @@ static void lm93_init_client(struct i2c_client *client)
"chip to signal ready!\n");
}
-static int lm93_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int lm93_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- 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;
- }
+ struct i2c_adapter *adapter = client->adapter;
- /* 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;
+ if (!i2c_check_functionality(adapter, LM93_SMBUS_FUNC_MIN))
+ return -ENODEV;
/* detection */
if (kind < 0) {
@@ -2548,7 +2516,7 @@ static int lm93_detect(struct i2c_adapter *adapter, int address, int kind)
if (mfr != 0x01) {
dev_dbg(&adapter->dev,"detect failed, "
"bad manufacturer id 0x%02x!\n", mfr);
- goto err_free;
+ return -ENODEV;
}
}
@@ -2563,31 +2531,61 @@ static int lm93_detect(struct i2c_adapter *adapter, int address, int kind)
if (kind == 0)
dev_dbg(&adapter->dev,
"(ignored 'force' parameter)\n");
- goto err_free;
+ return -ENODEV;
}
}
- /* fill in remaining client fields */
- strlcpy(client->name, "lm93", I2C_NAME_SIZE);
+ strlcpy(info->type, "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_detach;
+ goto err_free;
/* Register hwmon driver class */
data->hwmon_dev = hwmon_device_register(&client->dev);
@@ -2597,43 +2595,39 @@ static int lm93_detect(struct i2c_adapter *adapter, int address, int kind)
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;
}
-/* 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)
+static int lm93_remove(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);
- err = i2c_detach_client(client);
- if (!err)
- kfree(data);
- return err;
+ kfree(data);
+ return 0;
}
+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",
},
- .attach_adapter = lm93_attach_adapter,
- .detach_client = lm93_detach_client,
+ .probe = lm93_probe,
+ .remove = lm93_remove,
+ .id_table = lm93_id,
+ .detect = lm93_detect,
+ .address_data = &addr_data,
};
static int __init lm93_init(void)
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c
index 7e7267a0454..1ab1cacad59 100644
--- a/drivers/hwmon/max1619.c
+++ b/drivers/hwmon/max1619.c
@@ -79,23 +79,34 @@ I2C_CLIENT_INSMOD_1(max1619);
* Functions declaration
*/
-static int max1619_attach_adapter(struct i2c_adapter *adapter);
-static int max1619_detect(struct i2c_adapter *adapter, int address,
- int kind);
+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 void max1619_init_client(struct i2c_client *client);
-static int max1619_detach_client(struct i2c_client *client);
+static int max1619_remove(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",
},
- .attach_adapter = max1619_attach_adapter,
- .detach_client = max1619_detach_client,
+ .probe = max1619_probe,
+ .remove = max1619_remove,
+ .id_table = max1619_id,
+ .detect = max1619_detect,
+ .address_data = &addr_data,
};
/*
@@ -103,7 +114,6 @@ 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 */
@@ -208,41 +218,15 @@ static const struct attribute_group max1619_group = {
* Real code
*/
-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)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int max1619_detect(struct i2c_client *new_client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *new_client;
- struct max1619_data *data;
- int err = 0;
- const char *name = "";
+ struct i2c_adapter *adapter = new_client->adapter;
u8 reg_config=0, reg_convrate=0, reg_status=0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- 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;
+ return -ENODEV;
/*
* Now we do the remaining detection. A negative kind means that
@@ -265,8 +249,8 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
|| reg_convrate > 0x07 || (reg_status & 0x61 ) !=0x00) {
dev_dbg(&adapter->dev,
"MAX1619 detection failed at 0x%02x.\n",
- address);
- goto exit_free;
+ new_client->addr);
+ return -ENODEV;
}
}
@@ -285,28 +269,37 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
dev_info(&adapter->dev,
"Unsupported chip (man_id=0x%02X, "
"chip_id=0x%02X).\n", man_id, chip_id);
- goto exit_free;
+ return -ENODEV;
}
}
- if (kind == max1619)
- name = "max1619";
+ 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;
+ }
- /* We can fill in the remaining client fields */
- strlcpy(new_client->name, name, I2C_NAME_SIZE);
+ 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;
-
/* 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_detach;
+ goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -318,8 +311,6 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
exit_remove_files:
sysfs_remove_group(&new_client->dev.kobj, &max1619_group);
-exit_detach:
- i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -341,17 +332,13 @@ static void max1619_init_client(struct i2c_client *client)
config & 0xBF); /* run */
}
-static int max1619_detach_client(struct i2c_client *client)
+static int max1619_remove(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/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c
index 52d528b76cc..f27af6a9da4 100644
--- a/drivers/hwmon/max6650.c
+++ b/drivers/hwmon/max6650.c
@@ -104,22 +104,34 @@ I2C_CLIENT_INSMOD_1(max6650);
#define DIV_FROM_REG(reg) (1 << (reg & 7))
-static int max6650_attach_adapter(struct i2c_adapter *adapter);
-static int max6650_detect(struct i2c_adapter *adapter, int address, int kind);
+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_init_client(struct i2c_client *client);
-static int max6650_detach_client(struct i2c_client *client);
+static int max6650_remove(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",
},
- .attach_adapter = max6650_attach_adapter,
- .detach_client = max6650_detach_client,
+ .probe = max6650_probe,
+ .remove = max6650_remove,
+ .id_table = max6650_id,
+ .detect = max6650_detect,
+ .address_data = &addr_data,
};
/*
@@ -128,7 +140,6 @@ 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 */
@@ -437,47 +448,21 @@ static struct attribute_group max6650_attr_grp = {
* Real code
*/
-static int max6650_attach_adapter(struct i2c_adapter *adapter)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int max6650_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- 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;
+ struct i2c_adapter *adapter = client->adapter;
+ int address = client->addr;
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 0;
- }
-
- if (!(data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL))) {
- dev_err(&adapter->dev, "max6650: out of memory.\n");
- return -ENOMEM;
+ return -ENODEV;
}
- 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
@@ -501,28 +486,40 @@ static int max6650_detect(struct i2c_adapter *adapter, int address, int kind)
||(i2c_smbus_read_byte_data(client, MAX6650_REG_COUNT) & 0xFC))) {
dev_dbg(&adapter->dev,
"max6650: detection failed at 0x%02x.\n", address);
- goto err_free;
+ return -ENODEV;
}
dev_info(&adapter->dev, "max6650: chip found at 0x%02x.\n", address);
- strlcpy(client->name, "max6650", I2C_NAME_SIZE);
- mutex_init(&data->update_lock);
+ strlcpy(info->type, "max6650", I2C_NAME_SIZE);
- if ((err = i2c_attach_client(client))) {
- dev_err(&adapter->dev, "max6650: failed to attach client.\n");
- goto err_free;
+ return 0;
+}
+
+static int max6650_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct max6650_data *data;
+ int err;
+
+ if (!(data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL))) {
+ dev_err(&client->dev, "out of memory.\n");
+ return -ENOMEM;
}
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+
/*
* Initialize the max6650 chip
*/
- if (max6650_init_client(client))
- goto err_detach;
+ err = max6650_init_client(client);
+ if (err)
+ goto err_free;
err = sysfs_create_group(&client->dev.kobj, &max6650_attr_grp);
if (err)
- goto err_detach;
+ goto err_free;
data->hwmon_dev = hwmon_device_register(&client->dev);
if (!IS_ERR(data->hwmon_dev))
@@ -531,24 +528,19 @@ static int max6650_detect(struct i2c_adapter *adapter, int address, int kind)
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_detach_client(struct i2c_client *client)
+static int max6650_remove(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);
- err = i2c_detach_client(client);
- if (!err)
- kfree(data);
- return err;
+ kfree(data);
+ return 0;
}
static int max6650_init_client(struct i2c_client *client)
diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c
index 3c9db6598ba..8bb5cb532d4 100644
--- a/drivers/hwmon/smsc47m192.c
+++ b/drivers/hwmon/smsc47m192.c
@@ -96,7 +96,6 @@ 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 */
@@ -114,18 +113,29 @@ struct smsc47m192_data {
u8 vrm;
};
-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 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 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",
},
- .attach_adapter = smsc47m192_attach_adapter,
- .detach_client = smsc47m192_detach_client,
+ .probe = smsc47m192_probe,
+ .remove = smsc47m192_remove,
+ .id_table = smsc47m192_id,
+ .detect = smsc47m192_detect,
+ .address_data = &addr_data,
};
/* Voltages */
@@ -440,17 +450,6 @@ 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;
@@ -481,31 +480,15 @@ static void smsc47m192_init_client(struct i2c_client *client)
}
}
-/* This function is called by i2c_probe */
-static int smsc47m192_detect(struct i2c_adapter *adapter, int address,
- int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int smsc47m192_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *client;
- struct smsc47m192_data *data;
- int err = 0;
- int version, config;
+ struct i2c_adapter *adapter = client->adapter;
+ int version;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- 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;
+ return -ENODEV;
/* Detection criteria from sensors_detect script */
if (kind < 0) {
@@ -523,26 +506,39 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address,
} else {
dev_dbg(&adapter->dev,
"SMSC47M192 detection failed at 0x%02x\n",
- address);
- goto exit_free;
+ client->addr);
+ return -ENODEV;
}
}
- /* Fill in the remaining client fields and put into the global list */
- strlcpy(client->name, "smsc47m192", I2C_NAME_SIZE);
+ 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);
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_detach;
+ goto exit_free;
/* Pin 110 is either in4 (+12V) or VID4 */
config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG);
@@ -563,26 +559,20 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address,
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_detach_client(struct i2c_client *client)
+static int smsc47m192_remove(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/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c
index 76a3859c3fb..3b01001108c 100644
--- a/drivers/hwmon/thmc50.c
+++ b/drivers/hwmon/thmc50.c
@@ -60,7 +60,6 @@ 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;
@@ -77,17 +76,31 @@ struct thmc50_data {
u8 alarms;
};
-static int thmc50_attach_adapter(struct i2c_adapter *adapter);
-static int thmc50_detach_client(struct i2c_client *client);
+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 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",
},
- .attach_adapter = thmc50_attach_adapter,
- .detach_client = thmc50_detach_client,
+ .probe = thmc50_probe,
+ .remove = thmc50_remove,
+ .id_table = thmc50_id,
+ .detect = thmc50_detect,
+ .address_data = &addr_data,
};
static ssize_t show_analog_out(struct device *dev,
@@ -250,39 +263,23 @@ static const struct attribute_group temp3_group = {
.attrs = temp3_attributes,
};
-static int thmc50_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int thmc50_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
unsigned company;
unsigned revision;
unsigned config;
- struct i2c_client *client;
- struct thmc50_data *data;
- struct device *dev;
+ struct i2c_adapter *adapter = client->adapter;
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");
- 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;
+ return -ENODEV;
}
- 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));
@@ -307,21 +304,22 @@ static int thmc50_detect(struct i2c_adapter *adapter, int address, int kind)
}
if (err == -ENODEV) {
pr_debug("thmc50: Detection of THMC50/ADM1022 failed\n");
- goto exit_free;
+ return err;
}
- 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] == address) {
+ adm1022_temp3[i + 1] == client->addr) {
/* enable 2nd remote temp */
- data->has_temp3 = 1;
+ config |= (1 << 7);
+ i2c_smbus_write_byte_data(client,
+ THMC50_REG_CONF,
+ config);
break;
}
} else {
@@ -330,19 +328,33 @@ static int thmc50_detect(struct i2c_adapter *adapter, int address, int kind)
pr_debug("thmc50: Detected %s (version %x, revision %x)\n",
type_name, (revision >> 4) - 0xc, revision & 0xf);
- /* 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);
+ strlcpy(info->type, type_name, I2C_NAME_SIZE);
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(client)))
- goto exit_free;
+ 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;
+ mutex_init(&data->update_lock);
thmc50_init_client(client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &thmc50_group)))
- goto exit_detach;
+ goto exit_free;
/* Register ADM1022 sysfs hooks */
if (data->has_temp3)
@@ -364,34 +376,21 @@ exit_remove_sysfs:
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_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)
+static int thmc50_remove(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;
@@ -412,8 +411,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->has_temp3)
- config |= 0x80; /* enable 2nd remote temp */
+ if (data->type == adm1022 && (config & (1 << 7)))
+ data->has_temp3 = 1;
i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config);
}
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index 85077c4c803..e4e91c9d480 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -247,7 +247,6 @@ static u8 div_to_reg(int nr, long val)
}
struct w83791d_data {
- struct i2c_client client;
struct device *hwmon_dev;
struct mutex update_lock;
@@ -286,9 +285,11 @@ struct w83791d_data {
u8 vrm; /* hwmon-vid */
};
-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_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_read(struct i2c_client *client, u8 register);
static int w83791d_write(struct i2c_client *client, u8 register, u8 value);
@@ -300,12 +301,22 @@ 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",
},
- .attach_adapter = w83791d_attach_adapter,
- .detach_client = w83791d_detach_client,
+ .probe = w83791d_probe,
+ .remove = w83791d_remove,
+ .id_table = w83791d_id,
+ .detect = w83791d_detect,
+ .address_data = &addr_data,
};
/* following are the sysfs callback functions */
@@ -905,49 +916,12 @@ 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_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)
+static int w83791d_detect_subclients(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;
@@ -971,10 +945,7 @@ static int w83791d_detect_subclients(struct i2c_adapter *adapter, int address,
val = w83791d_read(client, W83791D_REG_I2C_SUBADDR);
if (!(val & 0x08)) {
- err = w83791d_create_subclient(adapter, client,
- val & 0x7, &data->lm75[0]);
- if (err < 0)
- goto error_sc_0;
+ data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (val & 0x7));
}
if (!(val & 0x80)) {
if ((data->lm75[0] != NULL) &&
@@ -986,10 +957,8 @@ static int w83791d_detect_subclients(struct i2c_adapter *adapter, int address,
err = -ENODEV;
goto error_sc_1;
}
- err = w83791d_create_subclient(adapter, client,
- (val >> 4) & 0x7, &data->lm75[1]);
- if (err < 0)
- goto error_sc_1;
+ data->lm75[1] = i2c_new_dummy(adapter,
+ 0x48 + ((val >> 4) & 0x7));
}
return 0;
@@ -997,53 +966,31 @@ static int w83791d_detect_subclients(struct i2c_adapter *adapter, int address,
/* Undo inits in case of errors */
error_sc_1:
- if (data->lm75[0] != NULL) {
- i2c_detach_client(data->lm75[0]);
- kfree(data->lm75[0]);
- }
+ if (data->lm75[0] != NULL)
+ i2c_unregister_device(data->lm75[0]);
error_sc_0:
return err;
}
-static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int w83791d_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- struct i2c_client *client;
- struct device *dev;
- struct w83791d_data *data;
- int i, val1, val2;
- int err = 0;
- const char *client_name = "";
+ struct i2c_adapter *adapter = client->adapter;
+ int val1, val2;
+ unsigned short address = client->addr;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
- goto error0;
+ 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 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) {
- dev_dbg(dev, "Detection failed at step 1\n");
- goto error1;
+ return -ENODEV;
}
val1 = w83791d_read(client, W83791D_REG_BANK);
val2 = w83791d_read(client, W83791D_REG_CHIPMAN);
@@ -1052,15 +999,13 @@ static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind)
/* yes it is Bank0 */
if (((!(val1 & 0x80)) && (val2 != 0xa3)) ||
((val1 & 0x80) && (val2 != 0x5c))) {
- dev_dbg(dev, "Detection failed at step 2\n");
- goto error1;
+ return -ENODEV;
}
}
/* If Winbond chip, address of chip and W83791D_REG_I2C_ADDR
should match */
if (w83791d_read(client, W83791D_REG_I2C_ADDR) != address) {
- dev_dbg(dev, "Detection failed at step 3\n");
- goto error1;
+ return -ENODEV;
}
}
@@ -1075,30 +1020,33 @@ static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind)
/* get vendor ID */
val2 = w83791d_read(client, W83791D_REG_CHIPMAN);
if (val2 != 0x5c) { /* the vendor is NOT Winbond */
- dev_dbg(dev, "Detection failed at step 4\n");
- goto error1;
+ return -ENODEV;
}
val1 = w83791d_read(client, W83791D_REG_WCHIPID);
if (val1 == 0x71) {
kind = w83791d;
} else {
if (kind == 0)
- dev_warn(dev,
+ dev_warn(&adapter->dev,
"w83791d: Ignoring 'force' parameter "
"for unknown chip at adapter %d, "
"address 0x%02x\n",
i2c_adapter_id(adapter), address);
- goto error1;
+ return -ENODEV;
}
}
- if (kind == w83791d) {
- client_name = "w83791d";
- } else {
- dev_err(dev, "w83791d: Internal error: unknown kind (%d)?!?\n",
- kind);
- 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;
#ifdef DEBUG
val1 = w83791d_read(client, W83791D_REG_DID_VID4);
@@ -1106,15 +1054,18 @@ static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind)
(val1 >> 5) & 0x07, (val1 >> 1) & 0x0f, val1);
#endif
- /* Fill in the remaining client fields and put into the global list */
- strlcpy(client->name, client_name, I2C_NAME_SIZE);
+ data = kzalloc(sizeof(struct w83791d_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto error0;
+ }
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(client)))
- goto error1;
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
- if ((err = w83791d_detect_subclients(adapter, address, kind, client)))
- goto error2;
+ err = w83791d_detect_subclients(client);
+ if (err)
+ goto error1;
/* Initialize the chip */
w83791d_init_client(client);
@@ -1141,43 +1092,29 @@ static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind)
error4:
sysfs_remove_group(&client->dev.kobj, &w83791d_group);
error3:
- 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);
+ if (data->lm75[0] != NULL)
+ i2c_unregister_device(data->lm75[0]);
+ if (data->lm75[1] != NULL)
+ i2c_unregister_device(data->lm75[1]);
error1:
kfree(data);
error0:
return err;
}
-static int w83791d_detach_client(struct i2c_client *client)
+static int w83791d_remove(struct i2c_client *client)
{
struct w83791d_data *data = i2c_get_clientdata(client);
- int err;
-
- /* main client */
- if (data) {
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &w83791d_group);
- }
- if ((err = i2c_detach_client(client)))
- return err;
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &w83791d_group);
- /* main client */
- if (data)
- kfree(data);
- /* subclient */
- else
- kfree(client);
+ if (data->lm75[0] != NULL)
+ i2c_unregister_device(data->lm75[0]);
+ if (data->lm75[1] != NULL)
+ i2c_unregister_device(data->lm75[1]);
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index 299629d47ed..cf94c5b0c87 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -267,9 +267,7 @@ 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 */
@@ -299,9 +297,11 @@ struct w83792d_data {
u8 sf2_levels[3][4]; /* Smart FanII: Fan1,2,3 duty cycle levels */
};
-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 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 struct w83792d_data *w83792d_update_device(struct device *dev);
#ifdef DEBUG
@@ -310,12 +310,22 @@ 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",
},
- .attach_adapter = w83792d_attach_adapter,
- .detach_client = w83792d_detach_client,
+ .probe = w83792d_probe,
+ .remove = w83792d_remove,
+ .id_table = w83792d_id,
+ .detect = w83792d_detect,
+ .address_data = &addr_data,
};
static inline long in_count_from_reg(int nr, struct w83792d_data *data)
@@ -864,53 +874,14 @@ 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_adapter *adapter, int address, int kind,
- struct i2c_client *new_client)
+w83792d_detect_subclients(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);
@@ -932,10 +903,7 @@ w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR);
if (!(val & 0x08)) {
- err = w83792d_create_subclient(adapter, new_client, val & 0x7,
- &data->lm75[0]);
- if (err < 0)
- goto ERROR_SC_0;
+ data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (val & 0x7));
}
if (!(val & 0x80)) {
if ((data->lm75[0] != NULL) &&
@@ -945,10 +913,8 @@ w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
err = -ENODEV;
goto ERROR_SC_1;
}
- err = w83792d_create_subclient(adapter, new_client,
- (val >> 4) & 0x7, &data->lm75[1]);
- if (err < 0)
- goto ERROR_SC_1;
+ data->lm75[1] = i2c_new_dummy(adapter,
+ 0x48 + ((val >> 4) & 0x7));
}
return 0;
@@ -956,10 +922,8 @@ w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
/* Undo inits in case of errors */
ERROR_SC_1:
- if (data->lm75[0] != NULL) {
- i2c_detach_client(data->lm75[0]);
- kfree(data->lm75[0]);
- }
+ if (data->lm75[0] != NULL)
+ i2c_unregister_device(data->lm75[0]);
ERROR_SC_0:
return err;
}
@@ -1294,47 +1258,25 @@ static const struct attribute_group w83792d_group = {
.attrs = w83792d_attributes,
};
+/* Return 0 if detection is successful, -ENODEV otherwise */
static int
-w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
+w83792d_detect(struct i2c_client *client, int kind, struct i2c_board_info *info)
{
- int i = 0, val1 = 0, val2;
- struct i2c_client *client;
- struct device *dev;
- struct w83792d_data *data;
- int err = 0;
- const char *client_name = "";
+ struct i2c_adapter *adapter = client->adapter;
+ int val1, val2;
+ unsigned short address = client->addr;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
- 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;
+ return -ENODEV;
}
- 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) {
- dev_dbg(dev, "Detection failed at step 1\n");
- goto ERROR1;
+ return -ENODEV;
}
val1 = w83792d_read_value(client, W83792D_REG_BANK);
val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN);
@@ -1342,16 +1284,14 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
if (!(val1 & 0x07)) { /* is Bank0 */
if (((!(val1 & 0x80)) && (val2 != 0xa3)) ||
((val1 & 0x80) && (val2 != 0x5c))) {
- dev_dbg(dev, "Detection failed at step 2\n");
- goto ERROR1;
+ return -ENODEV;
}
}
/* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR
should match */
if (w83792d_read_value(client,
W83792D_REG_I2C_ADDR) != address) {
- dev_dbg(dev, "Detection failed at step 3\n");
- goto ERROR1;
+ return -ENODEV;
}
}
@@ -1367,45 +1307,48 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
/* get vendor ID */
val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN);
if (val2 != 0x5c) { /* the vendor is NOT Winbond */
- goto ERROR1;
+ return -ENODEV;
}
val1 = w83792d_read_value(client, W83792D_REG_WCHIPID);
if (val1 == 0x7a) {
kind = w83792d;
} else {
if (kind == 0)
- dev_warn(dev,
+ dev_warn(&adapter->dev,
"w83792d: Ignoring 'force' parameter for"
" unknown chip at adapter %d, address"
" 0x%02x\n", i2c_adapter_id(adapter),
address);
- goto ERROR1;
+ return -ENODEV;
}
}
- if (kind == w83792d) {
- client_name = "w83792d";
- } else {
- dev_err(dev, "w83792d: Internal error: unknown kind (%d)?!?\n",
- kind);
- 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;
- /* Fill in the remaining client fields and put into the global list */
- strlcpy(client->name, client_name, I2C_NAME_SIZE);
- data->type = kind;
+ data = kzalloc(sizeof(struct w83792d_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto ERROR0;
+ }
+ i2c_set_clientdata(client, data);
data->valid = 0;
mutex_init(&data->update_lock);
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(client)))
+ err = w83792d_detect_subclients(client);
+ if (err)
goto ERROR1;
- if ((err = w83792d_detect_subclients(adapter, address,
- kind, client)))
- goto ERROR2;
-
/* Initialize the chip */
w83792d_init_client(client);
@@ -1457,16 +1400,10 @@ exit_remove_files:
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_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);
+ if (data->lm75[0] != NULL)
+ i2c_unregister_device(data->lm75[0]);
+ if (data->lm75[1] != NULL)
+ i2c_unregister_device(data->lm75[1]);
ERROR1:
kfree(data);
ERROR0:
@@ -1474,30 +1411,23 @@ ERROR0:
}
static int
-w83792d_detach_client(struct i2c_client *client)
+w83792d_remove(struct i2c_client *client)
{
struct w83792d_data *data = i2c_get_clientdata(client);
- 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]);
- }
+ int i;
- if ((err = i2c_detach_client(client)))
- return err;