aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@tglx.tec.linutronix.de>2005-06-26 23:20:36 +0200
committerThomas Gleixner <tglx@mtd.linutronix.de>2005-06-26 23:20:36 +0200
commit7ca6448dbfb398bba36eda3c01bc14b86c3675be (patch)
tree82d934ebf07f22a2c64c3b6d82ec24082878b43a /drivers
parentf1f67a9874f1a4bba1adff6d694aa52e5f52ff1a (diff)
parent7d681b23d6cc14a8c026ea6756242cb522cbbcae (diff)
downloadmrst-s0i3-test-7ca6448dbfb398bba36eda3c01bc14b86c3675be.tar.gz
mrst-s0i3-test-7ca6448dbfb398bba36eda3c01bc14b86c3675be.tar.xz
mrst-s0i3-test-7ca6448dbfb398bba36eda3c01bc14b86c3675be.zip
Merge with rsync://fileserver/linux
Update to Linus latest
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/acorn/char/pcf8583.c3
-rw-r--r--drivers/acpi/Kconfig7
-rw-r--r--drivers/acpi/pci_irq.c5
-rw-r--r--drivers/acpi/processor_idle.c2
-rw-r--r--drivers/acpi/scan.c4
-rw-r--r--drivers/atm/Makefile3
-rw-r--r--drivers/atm/fore200e.c6
-rw-r--r--drivers/atm/he.c6
-rw-r--r--drivers/atm/nicstar.c20
-rw-r--r--drivers/atm/zatm.c11
-rw-r--r--drivers/base/Makefile4
-rw-r--r--drivers/base/base.h2
-rw-r--r--drivers/base/bus.c296
-rw-r--r--drivers/base/class.c194
-rw-r--r--drivers/base/class_simple.c199
-rw-r--r--drivers/base/core.c66
-rw-r--r--drivers/base/cpu.c11
-rw-r--r--drivers/base/dd.c248
-rw-r--r--drivers/base/dmapool.c2
-rw-r--r--drivers/base/driver.c39
-rw-r--r--drivers/base/node.c22
-rw-r--r--drivers/base/power/resume.c8
-rw-r--r--drivers/base/power/suspend.c16
-rw-r--r--drivers/base/power/sysfs.c4
-rw-r--r--drivers/base/sys.c4
-rw-r--r--drivers/block/aoe/aoechr.c10
-rw-r--r--drivers/block/as-iosched.c12
-rw-r--r--drivers/block/cciss.c12
-rw-r--r--drivers/block/cfq-iosched.c13
-rw-r--r--drivers/block/deadline-iosched.c12
-rw-r--r--drivers/block/elevator.c22
-rw-r--r--drivers/block/genhd.c27
-rw-r--r--drivers/block/ioctl.c74
-rw-r--r--drivers/block/ll_rw_blk.c208
-rw-r--r--drivers/block/loop.c81
-rw-r--r--drivers/block/paride/pd.c2
-rw-r--r--drivers/block/paride/pg.c14
-rw-r--r--drivers/block/paride/pt.c20
-rw-r--r--drivers/block/pktcdvd.c39
-rw-r--r--drivers/block/sx8.c4
-rw-r--r--drivers/block/ub.c600
-rw-r--r--drivers/bluetooth/hci_ldisc.c2
-rw-r--r--drivers/cdrom/cm206.c113
-rw-r--r--drivers/cdrom/sonycd535.c3
-rw-r--r--drivers/cdrom/viocd.c14
-rw-r--r--drivers/char/Kconfig8
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/agp/agp.h2
-rw-r--r--drivers/char/agp/ali-agp.c4
-rw-r--r--drivers/char/agp/amd-k7-agp.c6
-rw-r--r--drivers/char/agp/amd64-agp.c4
-rw-r--r--drivers/char/agp/ati-agp.c6
-rw-r--r--drivers/char/agp/backend.c6
-rw-r--r--drivers/char/agp/efficeon-agp.c2
-rw-r--r--drivers/char/agp/generic.c36
-rw-r--r--drivers/char/agp/hp-agp.c4
-rw-r--r--drivers/char/agp/i460-agp.c4
-rw-r--r--drivers/char/agp/intel-agp.c21
-rw-r--r--drivers/char/agp/sgi-agp.c12
-rw-r--r--drivers/char/agp/sworks-agp.c8
-rw-r--r--drivers/char/agp/uninorth-agp.c2
-rw-r--r--drivers/char/amiserial.c22
-rw-r--r--drivers/char/applicom.c2
-rw-r--r--drivers/char/drm/drm_pciids.h1
-rw-r--r--drivers/char/drm/radeon_irq.c5
-rw-r--r--drivers/char/ds1620.c3
-rw-r--r--drivers/char/dsp56k.c14
-rw-r--r--drivers/char/ftape/compressor/zftape-compress.c4
-rw-r--r--drivers/char/ftape/zftape/zftape-init.c30
-rw-r--r--drivers/char/hpet.c2
-rw-r--r--drivers/char/hvcs.c14
-rw-r--r--drivers/char/i8k.c909
-rw-r--r--drivers/char/ip2/i2cmd.c6
-rw-r--r--drivers/char/ip2/i2cmd.h12
-rw-r--r--drivers/char/ip2main.c34
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c208
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c48
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c137
-rw-r--r--drivers/char/isicom.c12
-rw-r--r--drivers/char/istallion.c13
-rw-r--r--drivers/char/lp.c12
-rw-r--r--drivers/char/mbcs.c4
-rw-r--r--drivers/char/mem.c68
-rw-r--r--drivers/char/misc.c24
-rw-r--r--drivers/char/mwave/3780i.c6
-rw-r--r--drivers/char/mwave/3780i.h4
-rw-r--r--drivers/char/mwave/mwavedd.c2
-rw-r--r--drivers/char/mwave/tp3780i.c14
-rw-r--r--drivers/char/mxser.c38
-rw-r--r--drivers/char/n_hdlc.c2
-rw-r--r--drivers/char/n_r3964.c2
-rw-r--r--drivers/char/nvram.c6
-rw-r--r--drivers/char/ppdev.c12
-rw-r--r--drivers/char/raw.c18
-rw-r--r--drivers/char/rio/func.h1
-rw-r--r--drivers/char/rio/rio_linux.c5
-rw-r--r--drivers/char/rio/rioinit.c7
-rw-r--r--drivers/char/rio/riotty.c15
-rw-r--r--drivers/char/rocket.c226
-rw-r--r--drivers/char/rocket_int.h40
-rw-r--r--drivers/char/snsc.c7
-rw-r--r--drivers/char/stallion.c10
-rw-r--r--drivers/char/sysrq.c24
-rw-r--r--drivers/char/tipar.c14
-rw-r--r--drivers/char/toshiba.c60
-rw-r--r--drivers/char/tpm/tpm.c360
-rw-r--r--drivers/char/tpm/tpm.h38
-rw-r--r--drivers/char/tpm/tpm_atmel.c63
-rw-r--r--drivers/char/tpm/tpm_nsc.c199
-rw-r--r--drivers/char/tty_io.c63
-rw-r--r--drivers/char/vc_screen.c16
-rw-r--r--drivers/char/viotape.c16
-rw-r--r--drivers/char/vr41xx_giu.c743
-rw-r--r--drivers/char/vt.c4
-rw-r--r--drivers/char/watchdog/Kconfig10
-rw-r--r--drivers/char/watchdog/Makefile1
-rw-r--r--drivers/char/watchdog/ixp2000_wdt.c7
-rw-r--r--drivers/char/watchdog/wdrtas.c696
-rw-r--r--drivers/cpufreq/Kconfig24
-rw-r--r--drivers/cpufreq/Makefile1
-rw-r--r--drivers/cpufreq/cpufreq.c12
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c586
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c180
-rw-r--r--drivers/cpufreq/cpufreq_stats.c47
-rw-r--r--drivers/dio/dio-sysfs.c10
-rw-r--r--drivers/eisa/eisa-bus.c4
-rw-r--r--drivers/fc4/fc.c32
-rw-r--r--drivers/fc4/fc_syms.c1
-rw-r--r--drivers/fc4/fcp_impl.h1
-rw-r--r--drivers/firmware/edd.c2
-rw-r--r--drivers/firmware/efivars.c11
-rw-r--r--drivers/firmware/pcdp.c12
-rw-r--r--drivers/firmware/pcdp.h2
-rw-r--r--drivers/i2c/algos/i2c-algo-pca.c8
-rw-r--r--drivers/i2c/algos/i2c-algo-sibyte.c1
-rw-r--r--drivers/i2c/busses/Kconfig34
-rw-r--r--drivers/i2c/busses/i2c-ali1535.c1
-rw-r--r--drivers/i2c/busses/i2c-ali1563.c46
-rw-r--r--drivers/i2c/busses/i2c-ali15x3.c1
-rw-r--r--drivers/i2c/busses/i2c-amd756.c1
-rw-r--r--drivers/i2c/busses/i2c-amd8111.c1
-rw-r--r--drivers/i2c/busses/i2c-au1550.c1
-rw-r--r--drivers/i2c/busses/i2c-elektor.c1
-rw-r--r--drivers/i2c/busses/i2c-frodo.c1
-rw-r--r--drivers/i2c/busses/i2c-i801.c1
-rw-r--r--drivers/i2c/busses/i2c-i810.c1
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c2
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.h1
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c2
-rw-r--r--drivers/i2c/busses/i2c-isa.c1
-rw-r--r--drivers/i2c/busses/i2c-ite.c1
-rw-r--r--drivers/i2c/busses/i2c-ixp2000.c8
-rw-r--r--drivers/i2c/busses/i2c-ixp4xx.c5
-rw-r--r--drivers/i2c/busses/i2c-keywest.c1
-rw-r--r--drivers/i2c/busses/i2c-mpc.c202
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c1
-rw-r--r--drivers/i2c/busses/i2c-parport-light.c1
-rw-r--r--drivers/i2c/busses/i2c-parport.c3
-rw-r--r--drivers/i2c/busses/i2c-pca-isa.c1
-rw-r--r--drivers/i2c/busses/i2c-piix4.c1
-rw-r--r--drivers/i2c/busses/i2c-prosavage.c1
-rw-r--r--drivers/i2c/busses/i2c-rpx.c1
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c3
-rw-r--r--drivers/i2c/busses/i2c-savage4.c1
-rw-r--r--drivers/i2c/busses/i2c-sibyte.c1
-rw-r--r--drivers/i2c/busses/i2c-sis5595.c1
-rw-r--r--drivers/i2c/busses/i2c-sis630.c1
-rw-r--r--drivers/i2c/busses/i2c-sis96x.c1
-rw-r--r--drivers/i2c/busses/i2c-stub.c1
-rw-r--r--drivers/i2c/busses/i2c-via.c1
-rw-r--r--drivers/i2c/busses/i2c-viapro.c1
-rw-r--r--drivers/i2c/busses/i2c-voodoo3.c1
-rw-r--r--drivers/i2c/busses/scx200_acb.c1
-rw-r--r--drivers/i2c/chips/Kconfig117
-rw-r--r--drivers/i2c/chips/Makefile10
-rw-r--r--drivers/i2c/chips/adm1021.c15
-rw-r--r--drivers/i2c/chips/adm1025.c33
-rw-r--r--drivers/i2c/chips/adm1026.c578
-rw-r--r--drivers/i2c/chips/adm1031.c46
-rw-r--r--drivers/i2c/chips/adm9240.c791
-rw-r--r--drivers/i2c/chips/asb100.c51
-rw-r--r--drivers/i2c/chips/atxp1.c361
-rw-r--r--drivers/i2c/chips/ds1337.c97
-rw-r--r--drivers/i2c/chips/ds1374.c260
-rw-r--r--drivers/i2c/chips/ds1621.c10
-rw-r--r--drivers/i2c/chips/eeprom.c1
-rw-r--r--drivers/i2c/chips/fscher.c9
-rw-r--r--drivers/i2c/chips/fscpos.c16
-rw-r--r--drivers/i2c/chips/gl518sm.c13
-rw-r--r--drivers/i2c/chips/gl520sm.c8
-rw-r--r--drivers/i2c/chips/isp1301_omap.c1
-rw-r--r--drivers/i2c/chips/it87.c404
-rw-r--r--drivers/i2c/chips/lm63.c262
-rw-r--r--drivers/i2c/chips/lm75.c5
-rw-r--r--drivers/i2c/chips/lm77.c15
-rw-r--r--drivers/i2c/chips/lm78.c41
-rw-r--r--drivers/i2c/chips/lm80.c21
-rw-r--r--drivers/i2c/chips/lm83.c160
-rw-r--r--drivers/i2c/chips/lm85.c77
-rw-r--r--drivers/i2c/chips/lm87.c47
-rw-r--r--drivers/i2c/chips/lm90.c273
-rw-r--r--drivers/i2c/chips/lm92.c14
-rw-r--r--drivers/i2c/chips/m41t00.c3
-rw-r--r--drivers/i2c/chips/max1619.c7
-rw-r--r--drivers/i2c/chips/max6875.c473
-rw-r--r--drivers/i2c/chips/pc87360.c69
-rw-r--r--drivers/i2c/chips/pca9539.c192
-rw-r--r--drivers/i2c/chips/pcf8574.c12
-rw-r--r--drivers/i2c/chips/pcf8591.c10
-rw-r--r--drivers/i2c/chips/rtc8564.c4
-rw-r--r--drivers/i2c/chips/sis5595.c35
-rw-r--r--drivers/i2c/chips/smsc47b397.c4
-rw-r--r--drivers/i2c/chips/smsc47m1.c30
-rw-r--r--drivers/i2c/chips/tps65010.c1072
-rw-r--r--drivers/i2c/chips/via686a.c337
-rw-r--r--drivers/i2c/chips/w83627ehf.c846
-rw-r--r--drivers/i2c/chips/w83627hf.c58
-rw-r--r--drivers/i2c/chips/w83781d.c130
-rw-r--r--drivers/i2c/chips/w83l785ts.c5
-rw-r--r--drivers/i2c/i2c-core.c106
-rw-r--r--drivers/i2c/i2c-dev.c3
-rw-r--r--drivers/ide/Kconfig4
-rw-r--r--drivers/ide/ide-cd.c141
-rw-r--r--drivers/ide/ide-disk.c44
-rw-r--r--drivers/ide/ide-floppy.c48
-rw-r--r--drivers/ide/ide-probe.c59
-rw-r--r--drivers/ide/ide-proc.c52
-rw-r--r--drivers/ide/ide-tape.c51
-rw-r--r--drivers/ide/ide.c307
-rw-r--r--drivers/ide/pci/amd74xx.c3
-rw-r--r--drivers/ide/pci/sgiioc4.c30
-rw-r--r--drivers/ieee1394/dv1394.c6
-rw-r--r--drivers/ieee1394/ieee1394_core.c12
-rw-r--r--drivers/ieee1394/ieee1394_core.h3
-rw-r--r--drivers/ieee1394/nodemgr.c29
-rw-r--r--drivers/ieee1394/raw1394.c10
-rw-r--r--drivers/ieee1394/sbp2.c156
-rw-r--r--drivers/ieee1394/sbp2.h4
-rw-r--r--drivers/ieee1394/video1394.c4
-rw-r--r--drivers/infiniband/core/sa_query.c35
-rw-r--r--drivers/infiniband/core/sysfs.c122
-rw-r--r--drivers/infiniband/core/user_mad.c4
-rw-r--r--drivers/infiniband/include/ib_sa.h4
-rw-r--r--drivers/input/evdev.c9
-rw-r--r--drivers/input/gameport/Kconfig20
-rw-r--r--drivers/input/gameport/gameport.c8
-rw-r--r--drivers/input/input.c10
-rw-r--r--drivers/input/joydev.c10
-rw-r--r--drivers/input/keyboard/atkbd.c12
-rw-r--r--drivers/input/mouse/alps.c2
-rw-r--r--drivers/input/mouse/psmouse-base.c7
-rw-r--r--drivers/input/mouse/psmouse.h4
-rw-r--r--drivers/input/mouse/synaptics.c39
-rw-r--r--drivers/input/mousedev.c31
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h32
-rw-r--r--drivers/input/serio/i8042.c52
-rw-r--r--drivers/input/serio/serio.c18
-rw-r--r--drivers/input/serio/serport.c2
-rw-r--r--drivers/input/touchscreen/gunze.c3
-rw-r--r--drivers/input/tsdev.c9
-rw-r--r--drivers/isdn/act2000/capi.c2
-rw-r--r--drivers/isdn/act2000/capi.h1
-rw-r--r--drivers/isdn/capi/capi.c14
-rw-r--r--drivers/isdn/hardware/avm/b1dma.c4
-rw-r--r--drivers/isdn/hardware/avm/c4.c6
-rw-r--r--drivers/isdn/hardware/avm/t1isa.c2
-rw-r--r--drivers/isdn/hisax/Makefile2
-rw-r--r--drivers/isdn/hisax/amd7930_fn.c8
-rw-r--r--drivers/isdn/hisax/asuscom.c4
-rw-r--r--drivers/isdn/hisax/avm_pci.c18
-rw-r--r--drivers/isdn/hisax/bkm_a4t.c4
-rw-r--r--drivers/isdn/hisax/bkm_a8.c6
-rw-r--r--drivers/isdn/hisax/callc.c6
-rw-r--r--drivers/isdn/hisax/config.c14
-rw-r--r--drivers/isdn/hisax/diva.c4
-rw-r--r--drivers/isdn/hisax/elsa.c8
-rw-r--r--drivers/isdn/hisax/elsa_ser.c20
-rw-r--r--drivers/isdn/hisax/enternow.h51
-rw-r--r--drivers/isdn/hisax/enternow_pci.c91
-rw-r--r--drivers/isdn/hisax/gazel.c5
-rw-r--r--drivers/isdn/hisax/hfc4s8s_l1.c2
-rw-r--r--drivers/isdn/hisax/hfc_2bds0.c12
-rw-r--r--drivers/isdn/hisax/hfc_2bs0.c12
-rw-r--r--drivers/isdn/hisax/hfc_pci.c12
-rw-r--r--drivers/isdn/hisax/hfc_pci.h1
-rw-r--r--drivers/isdn/hisax/hfc_sx.c10
-rw-r--r--drivers/isdn/hisax/hfc_sx.h1
-rw-r--r--drivers/isdn/hisax/hfc_usb.c6
-rw-r--r--drivers/isdn/hisax/hfc_usb.h4
-rw-r--r--drivers/isdn/hisax/hfcscard.c2
-rw-r--r--drivers/isdn/hisax/hisax.h5
-rw-r--r--drivers/isdn/hisax/hscx.c4
-rw-r--r--drivers/isdn/hisax/icc.c6
-rw-r--r--drivers/isdn/hisax/ipacx.c86
-rw-r--r--drivers/isdn/hisax/isac.c6
-rw-r--r--drivers/isdn/hisax/isar.c46
-rw-r--r--drivers/isdn/hisax/isdnl1.c8
-rw-r--r--drivers/isdn/hisax/isdnl2.c100
-rw-r--r--drivers/isdn/hisax/isdnl3.c2
-rw-r--r--drivers/isdn/hisax/isurf.c2
-rw-r--r--drivers/isdn/hisax/ix1_micro.c4
-rw-r--r--drivers/isdn/hisax/jade.c6
-rw-r--r--drivers/isdn/hisax/jade.h1
-rw-r--r--drivers/isdn/hisax/l3_1tr6.c2
-rw-r--r--drivers/isdn/hisax/l3dss1.c2
-rw-r--r--drivers/isdn/hisax/l3ni1.c4
-rw-r--r--drivers/isdn/hisax/mic.c4
-rw-r--r--drivers/isdn/hisax/netjet.c12
-rw-r--r--drivers/isdn/hisax/niccy.c4
-rw-r--r--drivers/isdn/hisax/nj_s.c2
-rw-r--r--drivers/isdn/hisax/nj_u.c2
-rw-r--r--drivers/isdn/hisax/q931.c4
-rw-r--r--drivers/isdn/hisax/s0box.c4
-rw-r--r--drivers/isdn/hisax/saphir.c2
-rw-r--r--drivers/isdn/hisax/sedlbauer.c6
-rw-r--r--drivers/isdn/hisax/sportster.c6
-rw-r--r--drivers/isdn/hisax/st5481.h4
-rw-r--r--drivers/isdn/hisax/st5481_hdlc.c580
-rw-r--r--drivers/isdn/hisax/st5481_hdlc.h62
-rw-r--r--drivers/isdn/hisax/st5481_usb.c10
-rw-r--r--drivers/isdn/hisax/tei.c2
-rw-r--r--drivers/isdn/hisax/teleint.c4
-rw-r--r--drivers/isdn/hisax/teles0.c4
-rw-r--r--drivers/isdn/hisax/teles3.c4
-rw-r--r--drivers/isdn/hisax/telespci.c4
-rw-r--r--drivers/isdn/hisax/w6692.c6
-rw-r--r--drivers/isdn/i4l/isdn_audio.c10
-rw-r--r--drivers/isdn/i4l/isdn_audio.h1
-rw-r--r--drivers/isdn/i4l/isdn_common.c6
-rw-r--r--drivers/isdn/i4l/isdn_common.h1
-rw-r--r--drivers/isdn/i4l/isdn_concap.c15
-rw-r--r--drivers/isdn/i4l/isdn_concap.h1
-rw-r--r--drivers/isdn/i4l/isdn_net.c10
-rw-r--r--drivers/isdn/i4l/isdn_tty.c4
-rw-r--r--drivers/isdn/i4l/isdn_tty.h1
-rw-r--r--drivers/isdn/i4l/isdn_ttyfax.c6
-rw-r--r--drivers/isdn/i4l/isdn_x25iface.c36
-rw-r--r--drivers/isdn/pcbit/callbacks.c17
-rw-r--r--drivers/isdn/pcbit/callbacks.h3
-rw-r--r--drivers/isdn/pcbit/capi.c10
-rw-r--r--drivers/isdn/pcbit/capi.h1
-rw-r--r--drivers/isdn/pcbit/drv.c16
-rw-r--r--drivers/isdn/sc/Makefile2
-rw-r--r--drivers/isdn/sc/command.c88
-rw-r--r--drivers/isdn/sc/debug.c46
-rw-r--r--drivers/isdn/sc/init.c21
-rw-r--r--drivers/isdn/sc/interrupt.c2
-rw-r--r--drivers/isdn/sc/ioctl.c5
-rw-r--r--drivers/isdn/sc/packet.c16
-rw-r--r--drivers/isdn/sc/shmem.c2
-rw-r--r--drivers/isdn/sc/timer.c18
-rw-r--r--drivers/macintosh/adb.c9
-rw-r--r--drivers/macintosh/therm_adt746x.c138
-rw-r--r--drivers/macintosh/therm_pm72.c4
-rw-r--r--drivers/macintosh/therm_windtunnel.c10
-rw-r--r--drivers/macintosh/via-pmu.c12
-rw-r--r--drivers/mca/mca-bus.c4
-rw-r--r--drivers/mca/mca-legacy.c1
-rw-r--r--drivers/md/Makefile3
-rw-r--r--drivers/md/bitmap.c1586
-rw-r--r--drivers/md/dm-crypt.c3
-rw-r--r--drivers/md/dm-ioctl.c14
-rw-r--r--drivers/md/dm-mpath.c3
-rw-r--r--drivers/md/linear.c3
-rw-r--r--drivers/md/md.c528
-rw-r--r--drivers/md/multipath.c3
-rw-r--r--drivers/md/raid0.c12
-rw-r--r--drivers/md/raid1.c242
-rw-r--r--drivers/md/raid10.c30
-rw-r--r--drivers/md/raid5.c12
-rw-r--r--drivers/md/raid6main.c12
-rw-r--r--drivers/media/common/ir-common.c72
-rw-r--r--drivers/media/common/saa7146_fops.c2
-rw-r--r--drivers/media/dvb/Kconfig2
-rw-r--r--drivers/media/dvb/Makefile2
-rw-r--r--drivers/media/dvb/b2c2/Kconfig1
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c26
-rw-r--r--drivers/media/dvb/b2c2/flexcop-misc.c11
-rw-r--r--drivers/media/dvb/b2c2/flexcop-reg.h3
-rw-r--r--drivers/media/dvb/bt8xx/dst.c122
-rw-r--r--drivers/media/dvb/dibusb/Kconfig62
-rw-r--r--drivers/media/dvb/dibusb/Makefile11
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-core.c558
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-dvb.c185
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c582
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-firmware.c87
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-remote.c316
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-usb.c303
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb.h327
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c7
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c13
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig99
-rw-r--r--drivers/media/dvb/dvb-usb/Makefile30
-rw-r--r--drivers/media/dvb/dvb-usb/a800.c176
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-common.c272
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mb.c316
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mc.c116
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb.h122
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.c282
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.h65
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u-fe.c (renamed from drivers/media/dvb/dibusb/dvb-fe-dtt200u.c)113
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.c171
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.h66
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-common.h44
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-dvb.c210
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-firmware.c100
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-i2c.c118
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h83
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-init.c211
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-remote.c175
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-urb.c211
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb.h315
-rw-r--r--drivers/media/dvb/dvb-usb/nova-t-usb2.c236
-rw-r--r--drivers/media/dvb/dvb-usb/umt-010.c162
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045-fe.c196
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.c263
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.h78
-rw-r--r--drivers/media/dvb/frontends/Kconfig8
-rw-r--r--drivers/media/dvb/frontends/Makefile1
-rw-r--r--drivers/media/dvb/frontends/bcm3510.c853
-rw-r--r--drivers/media/dvb/frontends/bcm3510.h40
-rw-r--r--drivers/media/dvb/frontends/bcm3510_priv.h460
-rw-r--r--drivers/media/dvb/frontends/dib3000-common.c2
-rw-r--r--drivers/media/dvb/frontends/dib3000.h5
-rw-r--r--drivers/media/dvb/frontends/dib3000mb.c20
-rw-r--r--drivers/media/dvb/frontends/dib3000mb_priv.h2
-rw-r--r--drivers/media/dvb/frontends/dib3000mc.c29
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c94
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.h9
-rw-r--r--drivers/media/video/Kconfig14
-rw-r--r--drivers/media/video/adv7170.c16
-rw-r--r--drivers/media/video/adv7175.c16
-rw-r--r--drivers/media/video/bt819.c16
-rw-r--r--drivers/media/video/bt832.c50
-rw-r--r--drivers/media/video/bt832.h36
-rw-r--r--drivers/media/video/bt856.c16
-rw-r--r--drivers/media/video/bttv-cards.c100
-rw-r--r--drivers/media/video/bttv-driver.c2
-rw-r--r--drivers/media/video/bttv-i2c.c5
-rw-r--r--drivers/media/video/bttv.h3
-rw-r--r--drivers/media/video/bttvp.h8
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c488
-rw-r--r--drivers/media/video/cx88/cx88-cards.c230
-rw-r--r--drivers/media/video/cx88/cx88-core.c28
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c2
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c18
-rw-r--r--drivers/media/video/cx88/cx88-input.c11
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c52
-rw-r--r--drivers/media/video/cx88/cx88-reg.h3
-rw-r--r--drivers/media/video/cx88/cx88-tvaudio.c103
-rw-r--r--drivers/media/video/cx88/cx88-vbi.c6
-rw-r--r--drivers/media/video/cx88/cx88-video.c59
-rw-r--r--drivers/media/video/cx88/cx88.h22
-rw-r--r--drivers/media/video/ir-kbd-gpio.c34
-rw-r--r--drivers/media/video/msp3400.c12
-rw-r--r--drivers/media/video/msp3400.h4
-rw-r--r--drivers/media/video/saa5246a.c1
-rw-r--r--drivers/media/video/saa5249.c1
-rw-r--r--drivers/media/video/saa7110.c16
-rw-r--r--drivers/media/video/saa7111.c16
-rw-r--r--drivers/media/video/saa7114.c16
-rw-r--r--drivers/media/video/saa7134/saa6752hs.c21
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c163
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c8
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-i2c.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c112
-rw-r--r--drivers/media/video/saa7134/saa7134-oss.c16
-rw-r--r--drivers/media/video/saa7134/saa7134-tvaudio.c21
-rw-r--r--drivers/media/video/saa7134/saa7134-vbi.c14
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c92
-rw-r--r--drivers/media/video/saa7134/saa7134.h17
-rw-r--r--drivers/media/video/saa7185.c16
-rw-r--r--drivers/media/video/tda7432.c1
-rw-r--r--drivers/media/video/tda9840.c1
-rw-r--r--drivers/media/video/tda9875.c1
-rw-r--r--drivers/media/video/tda9887.c41
-rw-r--r--drivers/media/video/tea6415c.c1
-rw-r--r--drivers/media/video/tea6420.c1
-rw-r--r--drivers/media/video/tuner-3036.c17
-rw-r--r--drivers/media/video/tuner-core.c205
-rw-r--r--drivers/media/video/tuner-simple.c53
-rw-r--r--drivers/media/video/tvaudio.c24
-rw-r--r--drivers/media/video/tveeprom.c3
-rw-r--r--drivers/media/video/tvmixer.c4
-rw-r--r--drivers/media/video/v4l1-compat.c10
-rw-r--r--drivers/media/video/video-buf-dvb.c3
-rw-r--r--drivers/media/video/vpx3220.c16
-rw-r--r--drivers/message/fusion/Kconfig56
-rw-r--r--drivers/message/fusion/Makefile44
-rw-r--r--drivers/message/fusion/lsi/mpi.h70
-rw-r--r--drivers/message/fusion/lsi/mpi_cnfg.h1007
-rw-r--r--drivers/message/fusion/lsi/mpi_fc.h7
-rw-r--r--drivers/message/fusion/lsi/mpi_history.txt451
-rw-r--r--drivers/message/fusion/lsi/mpi_inb.h7
-rw-r--r--drivers/message/fusion/lsi/mpi_init.h88
-rw-r--r--drivers/message/fusion/lsi/mpi_ioc.h246
-rw-r--r--drivers/message/fusion/lsi/mpi_lan.h6
-rw-r--r--drivers/message/fusion/lsi/mpi_raid.h17
-rw-r--r--drivers/message/fusion/lsi/mpi_sas.h171
-rw-r--r--drivers/message/fusion/lsi/mpi_targ.h160
-rw-r--r--drivers/message/fusion/lsi/mpi_tool.h57
-rw-r--r--drivers/message/fusion/lsi/mpi_type.h11
-rw-r--r--drivers/message/fusion/mptbase.c343
-rw-r--r--drivers/message/fusion/mptbase.h52
-rw-r--r--drivers/message/fusion/mptctl.c68
-rw-r--r--drivers/message/fusion/mptctl.h15
-rw-r--r--drivers/message/fusion/mptfc.c431
-rw-r--r--drivers/message/fusion/mptlan.c37
-rw-r--r--drivers/message/fusion/mptlan.h48
-rw-r--r--drivers/message/fusion/mptscsih.c795
-rw-r--r--drivers/message/fusion/mptscsih.h43
-rw-r--r--drivers/message/fusion/mptspi.c486
-rw-r--r--drivers/message/i2o/Kconfig46
-rw-r--r--drivers/message/i2o/Makefile3
-rw-r--r--drivers/message/i2o/bus-osm.c164
-rw-r--r--drivers/message/i2o/config-osm.c579
-rw-r--r--drivers/message/i2o/core.h58
-rw-r--r--drivers/message/i2o/debug.c3
-rw-r--r--drivers/message/i2o/device.c40
-rw-r--r--drivers/message/i2o/driver.c130
-rw-r--r--drivers/message/i2o/exec-osm.c131
-rw-r--r--drivers/message/i2o/i2o_block.c454
-rw-r--r--drivers/message/i2o/i2o_block.h34
-rw-r--r--drivers/message/i2o/i2o_config.c124
-rw-r--r--drivers/message/i2o/i2o_proc.c6
-rw-r--r--drivers/message/i2o/i2o_scsi.c505
-rw-r--r--drivers/message/i2o/iop.c566
-rw-r--r--drivers/message/i2o/pci.c246
-rw-r--r--drivers/misc/ibmasm/command.c30
-rw-r--r--drivers/misc/ibmasm/dot_command.c10
-rw-r--r--drivers/misc/ibmasm/event.c18
-rw-r--r--drivers/misc/ibmasm/heartbeat.c13
-rw-r--r--drivers/misc/ibmasm/ibmasm.h76
-rw-r--r--drivers/misc/ibmasm/ibmasmfs.c125
-rw-r--r--drivers/misc/ibmasm/lowlevel.c18
-rw-r--r--drivers/misc/ibmasm/module.c69
-rw-r--r--drivers/misc/ibmasm/r_heartbeat.c2
-rw-r--r--drivers/misc/ibmasm/remote.c304
-rw-r--r--drivers/misc/ibmasm/remote.h173
-rw-r--r--drivers/mmc/mmc_sysfs.c2
-rw-r--r--drivers/net/3c59x.c5
-rw-r--r--drivers/net/8139cp.c100
-rw-r--r--drivers/net/8139too.c196
-rw-r--r--drivers/net/8390.c4
-rw-r--r--drivers/net/Kconfig57
-rw-r--r--drivers/net/Makefile5
-rw-r--r--drivers/net/Space.c6
-rwxr-xr-xdrivers/net/amd8111e.c24
-rw-r--r--drivers/net/appletalk/ltpc.c6
-rw-r--r--drivers/net/arm/etherh.c16
-rw-r--r--drivers/net/au1000_eth.c10
-rw-r--r--drivers/net/bmac.c2
-rw-r--r--drivers/net/bnx2.c5530
-rw-r--r--drivers/net/bnx2.h4352
-rw-r--r--drivers/net/bnx2_fw.h2468
-rw-r--r--drivers/net/bonding/bond_main.c2
-rw-r--r--drivers/net/dm9000.c1219
-rw-r--r--drivers/net/dm9000.h135
-rw-r--r--drivers/net/e100.c165
-rw-r--r--drivers/net/e1000/e1000.h37
-rw-r--r--drivers/net/e1000/e1000_ethtool.c105
-rw-r--r--drivers/net/e1000/e1000_hw.c1987
-rw-r--r--drivers/net/e1000/e1000_hw.h570
-rw-r--r--drivers/net/e1000/e1000_main.c1148
-rw-r--r--drivers/net/e1000/e1000_osdep.h32
-rw-r--r--drivers/net/e1000/e1000_param.c3
-rw-r--r--drivers/net/fmv18x.c689
-rw-r--r--drivers/net/forcedeth.c103
-rw-r--r--drivers/net/hamradio/6pack.c2
-rw-r--r--drivers/net/hamradio/baycom_epp.c126
-rw-r--r--drivers/net/hamradio/mkiss.c2
-rw-r--r--drivers/net/irda/Kconfig2
-rw-r--r--drivers/net/irda/irtty-sir.c2
-rw-r--r--drivers/net/irda/sir_kthread.c3
-rw-r--r--drivers/net/irda/stir4200.c4
-rw-r--r--drivers/net/iseries_veth.c41
-rw-r--r--drivers/net/ixgb/ixgb.h2
-rw-r--r--drivers/net/ixgb/ixgb_ee.c24
-rw-r--r--drivers/net/ixgb/ixgb_ethtool.c4
-rw-r--r--drivers/net/ixgb/ixgb_main.c153
-rw-r--r--drivers/net/ixgb/ixgb_osdep.h3
-rw-r--r--drivers/net/natsemi.c6
-rw-r--r--drivers/net/ns83820.c69
-rw-r--r--drivers/net/pcmcia/3c574_cs.c3
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c17
-rw-r--r--drivers/net/pcnet32.c7
-rw-r--r--drivers/net/ppp_async.c2
-rw-r--r--drivers/net/ppp_generic.c191
-rw-r--r--drivers/net/ppp_synctty.c2
-rw-r--r--drivers/net/r8169.c345
-rw-r--r--drivers/net/shaper.c86
-rw-r--r--drivers/net/sis900.c52
-rw-r--r--drivers/net/sk98lin/skge.c8
-rw-r--r--drivers/net/sk_g16.c2066
-rw-r--r--drivers/net/sk_g16.h165
-rw-r--r--drivers/net/skge.c3386
-rw-r--r--drivers/net/skge.h3005
-rw-r--r--drivers/net/slip.c16
-rw-r--r--drivers/net/smc91x.c58
-rw-r--r--drivers/net/smc91x.h15
-rw-r--r--drivers/net/starfire.c142
-rw-r--r--drivers/net/starfire_firmware.h346
-rw-r--r--drivers/net/tg3.c925
-rw-r--r--drivers/net/tg3.h24
-rw-r--r--drivers/net/tlan.c16
-rw-r--r--drivers/net/tokenring/ibmtr.c11
-rw-r--r--drivers/net/tulip/media.c1
-rw-r--r--drivers/net/wan/Kconfig2
-rw-r--r--drivers/net/wan/cosa.c12
-rw-r--r--drivers/net/wan/hdlc_fr.c320
-rw-r--r--drivers/net/wan/hdlc_generic.c16
-rw-r--r--drivers/net/wan/lmc/lmc_main.c8
-rw-r--r--drivers/net/wan/x25_asy.c2
-rw-r--r--drivers/net/wireless/airo.c152
-rw-r--r--drivers/net/wireless/atmel_cs.c1
-rw-r--r--drivers/net/wireless/orinoco.c332
-rw-r--r--drivers/net/wireless/orinoco.h1
-rw-r--r--drivers/net/wireless/strip.c2
-rw-r--r--drivers/oprofile/buffer_sync.c33
-rw-r--r--drivers/oprofile/event_buffer.h3
-rw-r--r--drivers/parport/parport_pc.c4
-rw-r--r--drivers/parport/parport_serial.c5
-rw-r--r--drivers/parport/probe.c18
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_core.c304
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_pci.c149
-rw-r--r--drivers/pci/hotplug/cpqphp_sysfs.c4
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c4
-rw-r--r--drivers/pci/hotplug/rpadlpar_sysfs.c2
-rw-r--r--drivers/pci/hotplug/shpchp_sysfs.c4
-rw-r--r--drivers/pci/hotplug/shpchprm_acpi.c4
-rw-r--r--drivers/pci/pci-driver.c31
-rw-r--r--drivers/pci/pci-sysfs.c21
-rw-r--r--drivers/pci/pci.ids1
-rw-r--r--drivers/pci/pcie/portdrv_core.c139
-rw-r--r--drivers/pci/probe.c2
-rw-r--r--drivers/pci/quirks.c59
-rw-r--r--drivers/pcmcia/Kconfig6
-rw-r--r--drivers/pcmcia/cs.c13
-rw-r--r--drivers/pcmcia/ds.c4
-rw-r--r--drivers/pcmcia/m32r_cfc.c57
-rw-r--r--drivers/pcmcia/m32r_cfc.h8
-rw-r--r--drivers/pcmcia/ti113x.h167
-rw-r--r--drivers/pcmcia/yenta_socket.c60
-rw-r--r--drivers/pnp/card.c7
-rw-r--r--drivers/pnp/driver.c12
-rw-r--r--drivers/pnp/interface.c8
-rw-r--r--drivers/pnp/manager.c1
-rw-r--r--drivers/pnp/pnpbios/core.c2
-rw-r--r--drivers/s390/Kconfig7
-rw-r--r--drivers/s390/block/dasd.c30
-rw-r--r--drivers/s390/block/dasd_devmap.c10
-rw-r--r--drivers/s390/block/dasd_proc.c3
-rw-r--r--drivers/s390/block/dcssblk.c72
-rw-r--r--drivers/s390/char/Makefile1
-rw-r--r--drivers/s390/char/con3215.c4
-rw-r--r--drivers/s390/char/con3270.c4
-rw-r--r--drivers/s390/char/raw3270.c6
-rw-r--r--drivers/s390/char/tape_34xx.c6
-rw-r--r--drivers/s390/char/tape_class.c10
-rw-r--r--drivers/s390/char/tape_core.c12
-rw-r--r--drivers/s390/char/tape_proc.c1
-rw-r--r--drivers/s390/char/vmcp.c219
-rw-r--r--drivers/s390/char/vmcp.h30
-rw-r--r--drivers/s390/char/vmlogrdr.c32
-rw-r--r--drivers/s390/cio/blacklist.c6
-rw-r--r--drivers/s390/cio/ccwgroup.c36
-rw-r--r--drivers/s390/cio/chsc.c6
-rw-r--r--drivers/s390/cio/cio.c8
-rw-r--r--drivers/s390/cio/cmf.c12
-rw-r--r--drivers/s390/cio/css.c34
-rw-r--r--drivers/s390/cio/device.c98
-rw-r--r--drivers/s390/cio/qdio.c14
-rw-r--r--drivers/s390/cio/qdio.h16
-rw-r--r--drivers/s390/net/Makefile3
-rw-r--r--drivers/s390/net/claw.c44
-rw-r--r--drivers/s390/net/ctcdbug.c10
-rw-r--r--drivers/s390/net/ctcdbug.h18
-rw-r--r--drivers/s390/net/ctcmain.c634
-rw-r--r--drivers/s390/net/ctcmain.h276
-rw-r--r--drivers/s390/net/ctctty.c5
-rw-r--r--drivers/s390/net/cu3088.c4
-rw-r--r--drivers/s390/net/cu3088.h3
-rw-r--r--drivers/s390/net/iucv.c10
-rw-r--r--drivers/s390/net/iucv.h6
-rw-r--r--drivers/s390/net/lcs.c47
-rw-r--r--drivers/s390/net/netiucv.c56
-rw-r--r--drivers/s390/net/qeth.h49
-rw-r--r--drivers/s390/net/qeth_eddp.c51
-rw-r--r--drivers/s390/net/qeth_main.c330
-rw-r--r--drivers/s390/net/qeth_sys.c126
-rw-r--r--drivers/s390/net/qeth_tso.c285
-rw-r--r--drivers/s390/net/qeth_tso.h166
-rw-r--r--drivers/s390/net/smsgiucv.c4
-rw-r--r--drivers/s390/s390mach.c321
-rw-r--r--drivers/s390/s390mach.h35
-rw-r--r--drivers/s390/scsi/zfcp_aux.c37
-rw-r--r--drivers/s390/scsi/zfcp_def.h25
-rw-r--r--drivers/s390/scsi/zfcp_erp.c121
-rw-r--r--drivers/s390/scsi/zfcp_ext.h4
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c324
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c68
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c26
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_adapter.c10
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_port.c10
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_unit.c6
-rw-r--r--drivers/scsi/3w-9xxx.c3
-rw-r--r--drivers/scsi/3w-xxxx.c3
-rw-r--r--drivers/scsi/53c700.c28
-rw-r--r--drivers/scsi/BusLogic.c8
-rw-r--r--drivers/scsi/FlashPoint.c5676
-rw-r--r--drivers/scsi/Kconfig42
-rw-r--r--drivers/scsi/Makefile3
-rw-r--r--drivers/scsi/NCR5380.c42
-rw-r--r--drivers/scsi/NCR5380.h2
-rw-r--r--drivers/scsi/NCR53C9x.c6
-rw-r--r--drivers/scsi/NCR53c406a.c23
-rw-r--r--drivers/scsi/a2091.c7
-rw-r--r--drivers/scsi/a3000.c7
-rw-r--r--drivers/scsi/aacraid/aachba.c165
-rw-r--r--drivers/scsi/aacraid/aacraid.h468
-rw-r--r--drivers/scsi/aacraid/commctrl.c228
-rw-r--r--drivers/scsi/aacraid/comminit.c92
-rw-r--r--drivers/scsi/aacraid/commsup.c100
-rw-r--r--drivers/scsi/aacraid/dpcsup.c6
-rw-r--r--drivers/scsi/aacraid/linit.c179
-rw-r--r--drivers/scsi/aacraid/rkt.c43
-rw-r--r--drivers/scsi/aacraid/rx.c46
-rw-r--r--drivers/scsi/aacraid/sa.c35
-rw-r--r--drivers/scsi/aha152x.c2
-rw-r--r--drivers/scsi/aha1542.c22
-rw-r--r--drivers/scsi/aha1542.h1
-rw-r--r--drivers/scsi/ahci.c103
-rw-r--r--drivers/scsi/aic7xxx/aic7770_osm.c189
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c14
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h17
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.h2
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_core.c16
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c657
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.h64
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm_pci.c44
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_proc.c31
-rw-r--r--drivers/scsi/aic7xxx_old.c33
-rw-r--r--drivers/scsi/arm/cumana_1.c2
-rw-r--r--drivers/scsi/arm/ecoscsi.c2
-rw-r--r--drivers/scsi/arm/eesox.c4
-rw-r--r--drivers/scsi/arm/fas216.c3
-rw-r--r--drivers/scsi/arm/oak.c2
-rw-r--r--drivers/scsi/arm/powertec.c4
-rw-r--r--drivers/scsi/ata_piix.c18
-rw-r--r--drivers/scsi/atp870u.c4
-rw-r--r--drivers/scsi/ch.c1026
-rw-r--r--drivers/scsi/dc395x.c12
-rw-r--r--drivers/scsi/dmx3191d.c2
-rw-r--r--drivers/scsi/dpt_i2o.c89
-rw-r--r--drivers/scsi/dpti.h14
-rw-r--r--drivers/scsi/dtc.c2
-rw-r--r--drivers/scsi/dtc.h4
-rw-r--r--drivers/scsi/eata.c11
-rw-r--r--drivers/scsi/eata_pio.c5
-rw-r--r--drivers/scsi/fcal.c1
-rw-r--r--drivers/scsi/fd_mcs.c17
-rw-r--r--drivers/scsi/fdomain.c6
-rw-r--r--drivers/scsi/g_NCR5380.c2
-rw-r--r--drivers/scsi/g_NCR5380.h4
-rw-r--r--drivers/scsi/gdth.c23
-rw-r--r--drivers/scsi/gvp11.c8
-rw-r--r--drivers/scsi/hosts.c2
-rw-r--r--drivers/scsi/ibmmca.c28
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c4
-rw-r--r--drivers/scsi/ide-scsi.c97
-rw-r--r--drivers/scsi/imm.c9
-rw-r--r--drivers/scsi/in2000.c31
-rw-r--r--drivers/scsi/in2000.h2
-rw-r--r--drivers/scsi/initio.c89
-rw-r--r--drivers/scsi/initio.h18
-rw-r--r--drivers/scsi/ipr.c57
-rw-r--r--drivers/scsi/ipr.h4
-rw-r--r--drivers/scsi/ips.c21
-rw-r--r--drivers/scsi/libata-core.c535
-rw-r--r--drivers/scsi/libata-scsi.c2
-rw-r--r--drivers/scsi/libata.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c36
-rw-r--r--drivers/scsi/mac53c94.c11
-rw-r--r--drivers/scsi/mac_scsi.c2
-rw-r--r--drivers/scsi/mac_scsi.h2
-rw-r--r--drivers/scsi/megaraid.c14
-rw-r--r--drivers/scsi/megaraid/mega_common.h1
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c160
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.h64
-rw-r--r--drivers/scsi/megaraid/megaraid_mm.c9
-rw-r--r--drivers/scsi/megaraid/megaraid_mm.h4
-rw-r--r--drivers/scsi/mesh.c4
-rw-r--r--drivers/scsi/mvme147.c7
-rw-r--r--drivers/scsi/nsp32.c7
-rw-r--r--drivers/scsi/osst.c10
-rw-r--r--drivers/scsi/pas16.c2
-rw-r--r--drivers/scsi/pas16.h4
-rw-r--r--drivers/scsi/pci2000.c836
-rw-r--r--drivers/scsi/pci2220i.c2915
-rw-r--r--drivers/scsi/pci2220i.h39
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c15
-rw-r--r--drivers/scsi/pcmcia/qlogic_stub.c2
-rw-r--r--drivers/scsi/pcmcia/sym53c500_cs.c2
-rw-r--r--drivers/scsi/pluto.c1
-rw-r--r--drivers/scsi/ppa.c5
-rw-r--r--drivers/scsi/psi_dale.h564
-rw-r--r--drivers/scsi/psi_roy.h331
-rw-r--r--drivers/scsi/ql1040_fw.h4021
-rw-r--r--drivers/scsi/ql12160_fw.h3046
-rw-r--r--drivers/scsi/ql1280_fw.h3653
-rw-r--r--drivers/scsi/qla1280.c41
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c3
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h60
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h14
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c33
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c3
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c18
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c173
-rw-r--r--drivers/scsi/qlogicfas.c2
-rw-r--r--drivers/scsi/qlogicfas408.c26
-rw-r--r--drivers/scsi/qlogicfas408.h2
-rw-r--r--drivers/scsi/sata_nv.c2
-rw-r--r--drivers/scsi/sata_promise.c29
-rw-r--r--drivers/scsi/sata_qstor.c2
-rw-r--r--drivers/scsi/sata_sil.c10
-rw-r--r--drivers/scsi/sata_sis.c1
-rw-r--r--drivers/scsi/sata_svw.c28
-rw-r--r--drivers/scsi/sata_sx4.c2
-rw-r--r--drivers/scsi/sata_uli.c1
-rw-r--r--drivers/scsi/sata_via.c1
-rw-r--r--drivers/scsi/sata_vsc.c2
-rw-r--r--drivers/scsi/scsi.c16
-rw-r--r--drivers/scsi/scsi_debug.c2
-rw-r--r--drivers/scsi/scsi_error.c42
-rw-r--r--drivers/scsi/scsi_lib.c42
-rw-r--r--drivers/scsi/scsi_priv.h4
-rw-r--r--drivers/scsi/scsi_scan.c26
-rw-r--r--drivers/scsi/scsi_sysfs.c46
-rw-r--r--drivers/scsi/scsi_transport_spi.c93
-rw-r--r--drivers/scsi/sd.c36
-rw-r--r--drivers/scsi/seagate.c15
-rw-r--r--drivers/scsi/seagate.h2
-rw-r--r--drivers/scsi/sg.c16
-rw-r--r--drivers/scsi/sgiwd93.c7
-rw-r--r--drivers/scsi/st.c47
-rw-r--r--drivers/scsi/sun3x_esp.c2
-rw-r--r--drivers/scsi/sym53c416.c23
-rw-r--r--drivers/scsi/sym53c416.h3
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_defs.h2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c152
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.h27
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c65
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.h22
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_nvram.c7
-rw-r--r--drivers/scsi/t128.c2
-rw-r--r--drivers/scsi/t128.h4
-rw-r--r--drivers/scsi/tmscsim.c6
-rw-r--r--drivers/scsi/u14-34f.c8
-rw-r--r--drivers/scsi/ultrastor.c4
-rw-r--r--drivers/scsi/wd7000.c9
-rw-r--r--drivers/serial/68328serial.c9
-rw-r--r--drivers/serial/68360serial.c9
-rw-r--r--drivers/serial/8250.c64
-rw-r--r--drivers/serial/8250.h3
-rw-r--r--drivers/serial/Kconfig11
-rw-r--r--drivers/serial/Makefile2
-rw-r--r--drivers/serial/au1x00_uart.c10
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm2.c9
-rw-r--r--drivers/serial/icom.h2
-rw-r--r--drivers/serial/ioc4_serial.c336
-rw-r--r--drivers/serial/m32r_sio.c10
-rw-r--r--drivers/serial/mpsc.c8
-rw-r--r--drivers/serial/pxa.c10
-rw-r--r--drivers/serial/s3c2410.c4
-rw-r--r--drivers/serial/sa1100.c2
-rw-r--r--drivers/serial/sn_console.c1
-rw-r--r--drivers/serial/sunzilog.c8
-rw-r--r--drivers/serial/vr41xx_siu.c66
-rw-r--r--drivers/sh/superhyway/superhyway-sysfs.c2
-rw-r--r--drivers/sn/Kconfig20
-rw-r--r--drivers/sn/Makefile2
-rw-r--r--drivers/sn/ioc4.c418
-rw-r--r--drivers/telephony/ixj.c52
-rw-r--r--drivers/usb/atm/speedtch.c2
-rw-r--r--drivers/usb/core/devices.c2
-rw-r--r--drivers/usb/core/file.c13
-rw-r--r--drivers/usb/core/hcd.c63
-rw-r--r--drivers/usb/core/hcd.h2
-rw-r--r--drivers/usb/core/hub.c2
-rw-r--r--drivers/usb/core/inode.c13
-rw-r--r--drivers/usb/core/sysfs.c48
-rw-r--r--drivers/usb/core/usb.c53
-rw-r--r--drivers/usb/gadget/dummy_hcd.c4
-rw-r--r--drivers/usb/gadget/file_storage.c11
-rw-r--r--drivers/usb/gadget/net2280.c6
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.c2
-rw-r--r--drivers/usb/host/Kconfig11
-rw-r--r--drivers/usb/host/Makefile1
-rw-r--r--drivers/usb/host/ehci-dbg.c10
-rw-r--r--drivers/usb/host/ehci-hub.c5
-rw-r--r--drivers/usb/host/ohci-dbg.c10
-rw-r--r--drivers/usb/host/sl811-hcd.c146
-rw-r--r--drivers/usb/host/sl811_cs.c442
-rw-r--r--drivers/usb/input/aiptek.c78
-rw-r--r--drivers/usb/input/hid-core.c22
-rw-r--r--drivers/usb/media/pwc/ChangeLog143
-rw-r--r--drivers/usb/media/pwc/Makefile2
-rw-r--r--drivers/usb/media/pwc/pwc-ctrl.c14
-rw-r--r--drivers/usb/media/pwc/pwc-dec1.c42
-rw-r--r--drivers/usb/media/pwc/pwc-dec1.h36
-rw-r--r--drivers/usb/media/pwc/pwc-dec23.c623
-rw-r--r--drivers/usb/media/pwc/pwc-dec23.h58
-rw-r--r--drivers/usb/media/pwc/pwc-if.c13
-rw-r--r--drivers/usb/media/pwc/pwc-kiara.c573
-rw-r--r--drivers/usb/media/pwc/pwc-timon.c1130
-rw-r--r--drivers/usb/media/pwc/pwc-uncompress.c11
-rw-r--r--drivers/usb/misc/cytherm.c20
-rw-r--r--drivers/usb/misc/phidgetkit.c14
-rw-r--r--drivers/usb/misc/phidgetservo.c4
-rw-r--r--drivers/usb/misc/usbled.c4
-rw-r--r--drivers/usb/mon/Kconfig13
-rw-r--r--drivers/usb/mon/Makefile2
-rw-r--r--drivers/usb/net/kaweth.c2
-rw-r--r--drivers/usb/net/usbnet.c2
-rw-r--r--drivers/usb/serial/Kconfig11
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/cp2101.c363
-rw-r--r--drivers/usb/serial/ftdi_sio.c127
-rw-r--r--drivers/usb/serial/ftdi_sio.h2
-rw-r--r--drivers/usb/serial/option.c729
-rw-r--r--drivers/usb/serial/usb-serial.c20
-rw-r--r--drivers/usb/storage/scsiglue.c13
-rw-r--r--drivers/usb/storage/unusual_devs.h9
-rw-r--r--drivers/usb/storage/usb.c4
-rw-r--r--drivers/video/Kconfig16
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/arcfb.c684
-rw-r--r--drivers/video/aty/radeon_base.c7
-rw-r--r--drivers/video/au1100fb.c18
-rw-r--r--drivers/video/chipsfb.c3
-rw-r--r--drivers/video/console/Kconfig16
-rw-r--r--drivers/video/console/Makefile2
-rw-r--r--drivers/video/console/bitblit.c23
-rw-r--r--drivers/video/console/font_10x18.c5146
-rw-r--r--drivers/video/console/font_7x14.c4118
-rw-r--r--drivers/video/console/font_sun12x22.c1579
-rw-r--r--drivers/video/console/fonts.c8
-rw-r--r--drivers/video/console/vgacon.c17
-rw-r--r--drivers/video/fbmem.c77
-rw-r--r--drivers/video/fbsysfs.c4
-rw-r--r--drivers/video/gbefb.c4
-rw-r--r--drivers/video/i810/i810_main.c1
-rw-r--r--drivers/video/intelfb/intelfbdrv.c45
-rw-r--r--drivers/video/macmodes.c1
-rw-r--r--drivers/video/matrox/matroxfb_maven.c1
-rw-r--r--drivers/video/matrox/matroxfb_misc.c5
-rw-r--r--drivers/video/nvidia/nvidia.c18
-rw-r--r--drivers/video/pm3fb.c2
-rw-r--r--drivers/video/pxafb.c3
-rw-r--r--drivers/video/riva/fbdev.c19
-rw-r--r--drivers/video/s1d13xxxfb.c2
-rw-r--r--drivers/video/savage/savagefb_driver.c2
-rw-r--r--drivers/video/softcursor.c9
-rw-r--r--drivers/video/vesafb.c17
-rw-r--r--drivers/video/w100fb.c12
-rw-r--r--drivers/w1/Kconfig16
-rw-r--r--drivers/w1/ds_w1_bridge.c4
-rw-r--r--drivers/w1/matrox_w1.c10
-rw-r--r--drivers/w1/w1.c564
-rw-r--r--drivers/w1/w1.h113
-rw-r--r--drivers/w1/w1_family.c10
-rw-r--r--drivers/w1/w1_family.h20
-rw-r--r--drivers/w1/w1_int.c41
-rw-r--r--drivers/w1/w1_int.h6
-rw-r--r--drivers/w1/w1_io.c117
-rw-r--r--drivers/w1/w1_io.h9
-rw-r--r--drivers/w1/w1_log.h4
-rw-r--r--drivers/w1/w1_netlink.h4
-rw-r--r--drivers/w1/w1_smem.c54
-rw-r--r--drivers/w1/w1_therm.c104
-rw-r--r--drivers/zorro/zorro-sysfs.c4
986 files changed, 80049 insertions, 42861 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig
index ed41d9036bf..aed4a9b97c1 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -58,4 +58,6 @@ source "drivers/mmc/Kconfig"
source "drivers/infiniband/Kconfig"
+source "drivers/sn/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 15681de688f..3167be54fed 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -61,6 +61,6 @@ obj-$(CONFIG_EISA) += eisa/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_MMC) += mmc/
obj-$(CONFIG_INFINIBAND) += infiniband/
-obj-$(CONFIG_BLK_DEV_SGIIOC4) += sn/
+obj-$(CONFIG_SGI_IOC4) += sn/
obj-y += firmware/
obj-$(CONFIG_CRYPTO) += crypto/
diff --git a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c
index ad7ae7ab892..141b4c237a5 100644
--- a/drivers/acorn/char/pcf8583.c
+++ b/drivers/acorn/char/pcf8583.c
@@ -26,11 +26,8 @@ static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END };
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_addr,
- .normal_i2c_range = ignore,
.probe = ignore,
- .probe_range = ignore,
.ignore = ignore,
- .ignore_range = ignore,
.force = ignore,
};
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 0400a52d508..86c52520ed3 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -40,13 +40,12 @@ config ACPI
available at:
<http://www.acpi.info>
+if ACPI
+
config ACPI_BOOT
bool
- depends on ACPI || X86_HT
default y
-if ACPI
-
config ACPI_INTERPRETER
bool
depends on !IA64_SGI_SN
@@ -56,7 +55,7 @@ if ACPI_INTERPRETER
config ACPI_SLEEP
bool "Sleep States (EXPERIMENTAL)"
- depends on X86
+ depends on X86 && (!SMP || SUSPEND_SMP)
depends on EXPERIMENTAL && PM
default y
---help---
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 12b0eea6340..8dbf802ee7f 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -391,7 +391,6 @@ acpi_pci_irq_enable (
u8 pin = 0;
int edge_level = ACPI_LEVEL_SENSITIVE;
int active_high_low = ACPI_ACTIVE_LOW;
- extern int via_interrupt_line_quirk;
char *link = NULL;
ACPI_FUNCTION_TRACE("acpi_pci_irq_enable");
@@ -436,6 +435,7 @@ acpi_pci_irq_enable (
/* Interrupt Line values above 0xF are forbidden */
if (dev->irq >= 0 && (dev->irq <= 0xF)) {
printk(" - using IRQ %d\n", dev->irq);
+ acpi_register_gsi(dev->irq, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW);
return_VALUE(0);
}
else {
@@ -444,9 +444,6 @@ acpi_pci_irq_enable (
}
}
- if (via_interrupt_line_quirk)
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq & 15);
-
dev->irq = acpi_register_gsi(irq, edge_level, active_high_low);
printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ",
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index ff64d333e95..c9d671cf785 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -171,7 +171,7 @@ static void acpi_processor_idle (void)
int sleep_ticks = 0;
u32 t1, t2 = 0;
- pr = processors[_smp_processor_id()];
+ pr = processors[raw_smp_processor_id()];
if (!pr)
return;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 119c94093a1..e8588559328 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -65,14 +65,14 @@ static ssize_t acpi_device_attr_show(struct kobject *kobj,
{
struct acpi_device *device = to_acpi_device(kobj);
struct acpi_device_attribute *attribute = to_handle_attr(attr);
- return attribute->show ? attribute->show(device, buf) : 0;
+ return attribute->show ? attribute->show(device, buf) : -EIO;
}
static ssize_t acpi_device_attr_store(struct kobject *kobj,
struct attribute *attr, const char *buf, size_t len)
{
struct acpi_device *device = to_acpi_device(kobj);
struct acpi_device_attribute *attribute = to_handle_attr(attr);
- return attribute->store ? attribute->store(device, buf, len) : len;
+ return attribute->store ? attribute->store(device, buf, len) : -EIO;
}
static struct sysfs_ops acpi_device_sysfs_ops = {
diff --git a/drivers/atm/Makefile b/drivers/atm/Makefile
index d1dcd8eae3c..5b77188527a 100644
--- a/drivers/atm/Makefile
+++ b/drivers/atm/Makefile
@@ -39,7 +39,8 @@ ifeq ($(CONFIG_ATM_FORE200E_PCA),y)
fore_200e-objs += fore200e_pca_fw.o
# guess the target endianess to choose the right PCA-200E firmware image
ifeq ($(CONFIG_ATM_FORE200E_PCA_DEFAULT_FW),y)
- CONFIG_ATM_FORE200E_PCA_FW = $(shell if test -n "`$(CC) -E -dM $(src)/../../include/asm/byteorder.h | grep ' __LITTLE_ENDIAN '`"; then echo $(obj)/pca200e.bin; else echo $(obj)/pca200e_ecd.bin2; fi)
+ byteorder.h := include$(if $(patsubst $(srctree),,$(objtree)),2)/asm/byteorder.h
+ CONFIG_ATM_FORE200E_PCA_FW := $(obj)/pca200e$(if $(shell $(CC) -E -dM $(byteorder.h) | grep ' __LITTLE_ENDIAN '),.bin,_ecd.bin2)
endif
endif
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 9e65bfb85ba..5f702199543 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -383,8 +383,7 @@ fore200e_shutdown(struct fore200e* fore200e)
switch(fore200e->state) {
case FORE200E_STATE_COMPLETE:
- if (fore200e->stats)
- kfree(fore200e->stats);
+ kfree(fore200e->stats);
case FORE200E_STATE_IRQ:
free_irq(fore200e->irq, fore200e->atm_dev);
@@ -963,8 +962,7 @@ fore200e_tx_irq(struct fore200e* fore200e)
entry, txq->tail, entry->vc_map, entry->skb);
/* free copy of misaligned data */
- if (entry->data)
- kfree(entry->data);
+ kfree(entry->data);
/* remove DMA mapping */
fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length,
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 3022c548a13..df2c83fd549 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -412,8 +412,7 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
init_one_failure:
if (atm_dev)
atm_dev_deregister(atm_dev);
- if (he_dev)
- kfree(he_dev);
+ kfree(he_dev);
pci_disable_device(pci_dev);
return err;
}
@@ -2534,8 +2533,7 @@ he_open(struct atm_vcc *vcc)
open_failed:
if (err) {
- if (he_vcc)
- kfree(he_vcc);
+ kfree(he_vcc);
clear_bit(ATM_VF_ADDR, &vcc->flags);
}
else
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
index 85bf5c8442b..b2a7b754fd1 100644
--- a/drivers/atm/nicstar.c
+++ b/drivers/atm/nicstar.c
@@ -676,10 +676,10 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
PRINTK("nicstar%d: RSQ base at 0x%x.\n", i, (u32) card->rsq.base);
/* Initialize SCQ0, the only VBR SCQ used */
- card->scq1 = (scq_info *) NULL;
- card->scq2 = (scq_info *) NULL;
+ card->scq1 = NULL;
+ card->scq2 = NULL;
card->scq0 = get_scq(VBR_SCQSIZE, NS_VRSCD0);
- if (card->scq0 == (scq_info *) NULL)
+ if (card->scq0 == NULL)
{
printk("nicstar%d: can't get SCQ0.\n", i);
error = 12;
@@ -993,24 +993,24 @@ static scq_info *get_scq(int size, u32 scd)
int i;
if (size != VBR_SCQSIZE && size != CBR_SCQSIZE)
- return (scq_info *) NULL;
+ return NULL;
scq = (scq_info *) kmalloc(sizeof(scq_info), GFP_KERNEL);
- if (scq == (scq_info *) NULL)
- return (scq_info *) NULL;
+ if (scq == NULL)
+ return NULL;
scq->org = kmalloc(2 * size, GFP_KERNEL);
if (scq->org == NULL)
{
kfree(scq);
- return (scq_info *) NULL;
+ return NULL;
}
scq->skb = (struct sk_buff **) kmalloc(sizeof(struct sk_buff *) *
(size / NS_SCQE_SIZE), GFP_KERNEL);
- if (scq->skb == (struct sk_buff **) NULL)
+ if (scq->skb == NULL)
{
kfree(scq->org);
kfree(scq);
- return (scq_info *) NULL;
+ return NULL;
}
scq->num_entries = size / NS_SCQE_SIZE;
scq->base = (ns_scqe *) ALIGN_ADDRESS(scq->org, size);
@@ -1498,7 +1498,7 @@ static int ns_open(struct atm_vcc *vcc)
vc->cbr_scd = NS_FRSCD + frscdi * NS_FRSCD_SIZE;
scq = get_scq(CBR_SCQSIZE, vc->cbr_scd);
- if (scq == (scq_info *) NULL)
+ if (scq == NULL)
{
PRINTK("nicstar%d: can't get fixed rate SCQ.\n", card->index);
card->scd2vc[frscdi] = NULL;
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 47a800519ad..8d5e65cb975 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -902,7 +902,7 @@ static void close_tx(struct atm_vcc *vcc)
zatm_dev->tx_bw += vcc->qos.txtp.min_pcr;
dealloc_shaper(vcc->dev,zatm_vcc->shaper);
}
- if (zatm_vcc->ring) kfree(zatm_vcc->ring);
+ kfree(zatm_vcc->ring);
}
@@ -1339,12 +1339,9 @@ static int __init zatm_start(struct atm_dev *dev)
return 0;
out:
for (i = 0; i < NR_MBX; i++)
- if (zatm_dev->mbx_start[i] != 0)
- kfree((void *) zatm_dev->mbx_start[i]);
- if (zatm_dev->rx_map != NULL)
- kfree(zatm_dev->rx_map);
- if (zatm_dev->tx_map != NULL)
- kfree(zatm_dev->tx_map);
+ kfree(zatm_dev->mbx_start[i]);
+ kfree(zatm_dev->rx_map);
+ kfree(zatm_dev->tx_map);
free_irq(zatm_dev->irq, dev);
return error;
}
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index a47928a2e57..66d9c4643fc 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -1,7 +1,7 @@
# Makefile for the Linux device tree
-obj-y := core.o sys.o bus.o \
- driver.o class.o class_simple.o platform.o \
+obj-y := core.o sys.o bus.o dd.o \
+ driver.o class.o platform.o \
cpu.o firmware.o init.o map.o dmapool.o \
attribute_container.o transport_class.o
obj-y += power/
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 8d1e8bd4863..645f6269292 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -4,6 +4,8 @@ extern void bus_remove_device(struct device * dev);
extern int bus_add_driver(struct device_driver *);
extern void bus_remove_driver(struct device_driver *);
+extern void driver_detach(struct device_driver * drv);
+
static inline struct class_device *to_class_dev(struct kobject *obj)
{
return container_of(obj, struct class_device, kobj);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 3cb04bb04c2..c3fac7fd555 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -17,9 +17,6 @@
#include "base.h"
#include "power/power.h"
-#define to_dev(node) container_of(node, struct device, bus_list)
-#define to_drv(node) container_of(node, struct device_driver, kobj.entry)
-
#define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)
#define to_bus(obj) container_of(obj, struct bus_type, subsys.kset.kobj)
@@ -36,7 +33,7 @@ drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
{
struct driver_attribute * drv_attr = to_drv_attr(attr);
struct device_driver * drv = to_driver(kobj);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (drv_attr->show)
ret = drv_attr->show(drv, buf);
@@ -49,7 +46,7 @@ drv_attr_store(struct kobject * kobj, struct attribute * attr,
{
struct driver_attribute * drv_attr = to_drv_attr(attr);
struct device_driver * drv = to_driver(kobj);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (drv_attr->store)
ret = drv_attr->store(drv, buf, count);
@@ -135,50 +132,11 @@ static struct kobj_type ktype_bus = {
decl_subsys(bus, &ktype_bus, NULL);
-static int __bus_for_each_dev(struct bus_type *bus, struct device *start,
- void *data, int (*fn)(struct device *, void *))
-{
- struct list_head *head;
- struct device *dev;
- int error = 0;
-
- if (!(bus = get_bus(bus)))
- return -EINVAL;
-
- head = &bus->devices.list;
- dev = list_prepare_entry(start, head, bus_list);
- list_for_each_entry_continue(dev, head, bus_list) {
- get_device(dev);
- error = fn(dev, data);
- put_device(dev);
- if (error)
- break;
- }
- put_bus(bus);
- return error;
-}
-static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
- void * data, int (*fn)(struct device_driver *, void *))
+static struct device * next_device(struct klist_iter * i)
{
- struct list_head *head;
- struct device_driver *drv;
- int error = 0;
-
- if (!(bus = get_bus(bus)))
- return -EINVAL;
-
- head = &bus->drivers.list;
- drv = list_prepare_entry(start, head, kobj.entry);
- list_for_each_entry_continue(drv, head, kobj.entry) {
- get_driver(drv);
- error = fn(drv, data);
- put_driver(drv);
- if (error)
- break;
- }
- put_bus(bus);
- return error;
+ struct klist_node * n = klist_next(i);
+ return n ? container_of(n, struct device, knode_bus) : NULL;
}
/**
@@ -204,12 +162,27 @@ static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
int bus_for_each_dev(struct bus_type * bus, struct device * start,
void * data, int (*fn)(struct device *, void *))
{
- int ret;
+ struct klist_iter i;
+ struct device * dev;
+ int error = 0;
- down_read(&bus->subsys.rwsem);
- ret = __bus_for_each_dev(bus, start, data, fn);
- up_read(&bus->subsys.rwsem);
- return ret;
+ if (!bus)
+ return -EINVAL;
+
+ klist_iter_init_node(&bus->klist_devices, &i,
+ (start ? &start->knode_bus : NULL));
+ while ((dev = next_device(&i)) && !error)
+ error = fn(dev, data);
+ klist_iter_exit(&i);
+ return error;
+}
+
+
+
+static struct device_driver * next_driver(struct klist_iter * i)
+{
+ struct klist_node * n = klist_next(i);
+ return n ? container_of(n, struct device_driver, knode_bus) : NULL;
}
/**
@@ -235,179 +208,19 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start,
int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
void * data, int (*fn)(struct device_driver *, void *))
{
- int ret;
-
- down_read(&bus->subsys.rwsem);
- ret = __bus_for_each_drv(bus, start, data, fn);
- up_read(&bus->subsys.rwsem);
- return ret;
-}
-
-/**
- * device_bind_driver - bind a driver to one device.
- * @dev: device.
- *
- * Allow manual attachment of a driver to a device.
- * Caller must have already set @dev->driver.
- *
- * Note that this does not modify the bus reference count
- * nor take the bus's rwsem. Please verify those are accounted
- * for before calling this. (It is ok to call with no other effort
- * from a driver's probe() method.)
- */
-
-void device_bind_driver(struct device * dev)
-{
- pr_debug("bound device '%s' to driver '%s'\n",
- dev->bus_id, dev->driver->name);
- list_add_tail(&dev->driver_list, &dev->driver->devices);
- sysfs_create_link(&dev->driver->kobj, &dev->kobj,
- kobject_name(&dev->kobj));
- sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
-}
-
-
-/**
- * driver_probe_device - attempt to bind device & driver.
- * @drv: driver.
- * @dev: device.
- *
- * First, we call the bus's match function, if one present, which
- * should compare the device IDs the driver supports with the
- * device IDs of the device. Note we don't do this ourselves
- * because we don't know the format of the ID structures, nor what
- * is to be considered a match and what is not.
- *
- * If we find a match, we call @drv->probe(@dev) if it exists, and
- * call device_bind_driver() above.
- */
-int driver_probe_device(struct device_driver * drv, struct device * dev)
-{
- if (drv->bus->match && !drv->bus->match(dev, drv))
- return -ENODEV;
-
- dev->driver = drv;
- if (drv->probe) {
- int error = drv->probe(dev);
- if (error) {
- dev->driver = NULL;
- return error;
- }
- }
-
- device_bind_driver(dev);
- return 0;
-}
-
-
-/**
- * device_attach - try to attach device to a driver.
- * @dev: device.
- *
- * Walk the list of drivers that the bus has and call
- * driver_probe_device() for each pair. If a compatible
- * pair is found, break out and return.
- */
-int device_attach(struct device * dev)
-{
- struct bus_type * bus = dev->bus;
- struct list_head * entry;
- int error;
-
- if (dev->driver) {
- device_bind_driver(dev);
- return 1;
- }
-
- if (bus->match) {
- list_for_each(entry, &bus->drivers.list) {
- struct device_driver * drv = to_drv(entry);
- error = driver_probe_device(drv, dev);
- if (!error)
- /* success, driver matched */
- return 1;
- if (error != -ENODEV && error != -ENXIO)
- /* driver matched but the probe failed */
- printk(KERN_WARNING
- "%s: probe of %s failed with error %d\n",
- drv->name, dev->bus_id, error);
- }
- }
-
- return 0;
-}
-
-
-/**
- * driver_attach - try to bind driver to devices.
- * @drv: driver.
- *
- * Walk the list of devices that the bus has on it and try to
- * match the driver with each one. If driver_probe_device()
- * returns 0 and the @dev->driver is set, we've found a
- * compatible pair.
- *
- * Note that we ignore the -ENODEV error from driver_probe_device(),
- * since it's perfectly valid for a driver not to bind to any devices.
- */
-void driver_attach(struct device_driver * drv)
-{
- struct bus_type * bus = drv->bus;
- struct list_head * entry;
- int error;
-
- if (!bus->match)
- return;
-
- list_for_each(entry, &bus->devices.list) {
- struct device * dev = container_of(entry, struct device, bus_list);
- if (!dev->driver) {
- error = driver_probe_device(drv, dev);
- if (error && (error != -ENODEV))
- /* driver matched but the probe failed */
- printk(KERN_WARNING
- "%s: probe of %s failed with error %d\n",
- drv->name, dev->bus_id, error);
- }
- }
-}
-
-
-/**
- * device_release_driver - manually detach device from driver.
- * @dev: device.
- *
- * Manually detach device from driver.
- * Note that this is called without incrementing the bus
- * reference count nor taking the bus's rwsem. Be sure that
- * those are accounted for before calling this function.
- */
-
-void device_release_driver(struct device * dev)
-{
- struct device_driver * drv = dev->driver;
- if (drv) {
- sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
- sysfs_remove_link(&dev->kobj, "driver");
- list_del_init(&dev->driver_list);
- if (drv->remove)
- drv->remove(dev);
- dev->driver = NULL;
- }
-}
-
+ struct klist_iter i;
+ struct device_driver * drv;
+ int error = 0;
-/**
- * driver_detach - detach driver from all devices it controls.
- * @drv: driver.
- */
+ if (!bus)
+ return -EINVAL;
-static void driver_detach(struct device_driver * drv)
-{
- while (!list_empty(&drv->devices)) {
- struct device * dev = container_of(drv->devices.next, struct device, driver_list);
- device_release_driver(dev);
- }
+ klist_iter_init_node(&bus->klist_drivers, &i,
+ start ? &start->knode_bus : NULL);
+ while ((drv = next_driver(&i)) && !error)
+ error = fn(drv, data);
+ klist_iter_exit(&i);
+ return error;
}
static int device_add_attrs(struct bus_type * bus, struct device * dev)
@@ -456,14 +269,14 @@ int bus_add_device(struct device * dev)
int error = 0;
if (bus) {
- down_write(&dev->bus->subsys.rwsem);
pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
- list_add_tail(&dev->bus_list, &dev->bus->devices.list);
device_attach(dev);
- up_write(&dev->bus->subsys.rwsem);
- device_add_attrs(bus, dev);
- sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
- sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
+ klist_add_tail(&bus->klist_devices, &dev->knode_bus);
+ error = device_add_attrs(bus, dev);
+ if (!error) {
+ sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
+ sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
+ }
}
return error;
}
@@ -483,11 +296,9 @@ void bus_remove_device(struct device * dev)
sysfs_remove_link(&dev->kobj, "bus");
sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
device_remove_attrs(dev->bus, dev);
- down_write(&dev->bus->subsys.rwsem);
+ klist_remove(&dev->knode_bus);
pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id);
device_release_driver(dev);
- list_del_init(&dev->bus_list);
- up_write(&dev->bus->subsys.rwsem);
put_bus(dev->bus);
}
}
@@ -547,9 +358,8 @@ int bus_add_driver(struct device_driver * drv)
return error;
}
- down_write(&bus->subsys.rwsem);
driver_attach(drv);
- up_write(&bus->subsys.rwsem);
+ klist_add_tail(&bus->klist_drivers, &drv->knode_bus);
module_add_driver(drv->owner, drv);
driver_add_attrs(bus, drv);
@@ -571,10 +381,9 @@ void bus_remove_driver(struct device_driver * drv)
{
if (drv->bus) {
driver_remove_attrs(drv->bus, drv);
- down_write(&drv->bus->subsys.rwsem);
+ klist_remove(&drv->knode_bus);
pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
driver_detach(drv);
- up_write(&drv->bus->subsys.rwsem);
module_remove_driver(drv);
kobject_unregister(&drv->kobj);
put_bus(drv->bus);
@@ -587,7 +396,7 @@ static int bus_rescan_devices_helper(struct device *dev, void *data)
{
int *count = data;
- if (!dev->driver && device_attach(dev))
+ if (!dev->driver && (device_attach(dev) > 0))
(*count)++;
return 0;
@@ -607,9 +416,7 @@ int bus_rescan_devices(struct bus_type * bus)
{
int count = 0;
- down_write(&bus->subsys.rwsem);
- __bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper);
- up_write(&bus->subsys.rwsem);
+ bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper);
return count;
}
@@ -710,6 +517,9 @@ int bus_register(struct bus_type * bus)
retval = kset_register(&bus->drivers);
if (retval)
goto bus_drivers_fail;
+
+ klist_init(&bus->klist_devices);
+ klist_init(&bus->klist_drivers);
bus_add_attrs(bus);
pr_debug("bus type '%s' registered\n", bus->name);
@@ -749,12 +559,6 @@ int __init buses_init(void)
EXPORT_SYMBOL_GPL(bus_for_each_dev);
EXPORT_SYMBOL_GPL(bus_for_each_drv);
-EXPORT_SYMBOL_GPL(driver_probe_device);
-EXPORT_SYMBOL_GPL(device_bind_driver);
-EXPORT_SYMBOL_GPL(device_release_driver);
-EXPORT_SYMBOL_GPL(device_attach);
-EXPORT_SYMBOL_GPL(driver_attach);
-
EXPORT_SYMBOL_GPL(bus_add_device);
EXPORT_SYMBOL_GPL(bus_remove_device);
EXPORT_SYMBOL_GPL(bus_register);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index d2a2f8f2b4e..479c1257088 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/string.h>
#include <linux/kdev_t.h>
+#include <linux/err.h>
#include "base.h"
#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
@@ -26,7 +27,7 @@ class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
{
struct class_attribute * class_attr = to_class_attr(attr);
struct class * dc = to_class(kobj);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (class_attr->show)
ret = class_attr->show(dc, buf);
@@ -39,7 +40,7 @@ class_attr_store(struct kobject * kobj, struct attribute * attr,
{
struct class_attribute * class_attr = to_class_attr(attr);
struct class * dc = to_class(kobj);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (class_attr->store)
ret = class_attr->store(dc, buf, count);
@@ -162,6 +163,69 @@ void class_unregister(struct class * cls)
subsystem_unregister(&cls->subsys);
}
+static void class_create_release(struct class *cls)
+{
+ kfree(cls);
+}
+
+static void class_device_create_release(struct class_device *class_dev)
+{
+ kfree(class_dev);
+}
+
+/**
+ * class_create - create a struct class structure
+ * @owner: pointer to the module that is to "own" this struct class
+ * @name: pointer to a string for the name of this class.
+ *
+ * This is used to create a struct class pointer that can then be used
+ * in calls to class_device_create().
+ *
+ * Note, the pointer created here is to be destroyed when finished by
+ * making a call to class_destroy().
+ */
+struct class *class_create(struct module *owner, char *name)
+{
+ struct class *cls;
+ int retval;
+
+ cls = kmalloc(sizeof(struct class), GFP_KERNEL);
+ if (!cls) {
+ retval = -ENOMEM;
+ goto error;
+ }
+ memset(cls, 0x00, sizeof(struct class));
+
+ cls->name = name;
+ cls->owner = owner;
+ cls->class_release = class_create_release;
+ cls->release = class_device_create_release;
+
+ retval = class_register(cls);
+ if (retval)
+ goto error;
+
+ return cls;
+
+error:
+ kfree(cls);
+ return ERR_PTR(retval);
+}
+
+/**
+ * class_destroy - destroys a struct class structure
+ * @cs: pointer to the struct class that is to be destroyed
+ *
+ * Note, the pointer to be destroyed must have been created with a call
+ * to class_create().
+ */
+void class_destroy(struct class *cls)
+{
+ if ((cls == NULL) || (IS_ERR(cls)))
+ return;
+
+ class_unregister(cls);
+}
/* Class Device Stuff */
@@ -262,7 +326,7 @@ static int class_hotplug_filter(struct kset *kset, struct kobject *kobj)
return 0;
}
-static char *class_hotplug_name(struct kset *kset, struct kobject *kobj)
+static const char *class_hotplug_name(struct kset *kset, struct kobject *kobj)
{
struct class_device *class_dev = to_class_dev(kobj);
@@ -375,7 +439,6 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
{
return print_dev_t(buf, class_dev->devt);
}
-static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
void class_device_initialize(struct class_device *class_dev)
{
@@ -412,7 +475,31 @@ int class_device_add(struct class_device *class_dev)
if ((error = kobject_add(&class_dev->kobj)))
goto register_done;
- /* now take care of our own registration */
+ /* add the needed attributes to this device */
+ if (MAJOR(class_dev->devt)) {
+ struct class_device_attribute *attr;
+ attr = kmalloc(sizeof(*attr), GFP_KERNEL);
+ if (!attr) {
+ error = -ENOMEM;
+ kobject_del(&class_dev->kobj);
+ goto register_done;
+ }
+ memset(attr, sizeof(*attr), 0x00);
+ attr->attr.name = "dev";
+ attr->attr.mode = S_IRUGO;
+ attr->attr.owner = parent->owner;
+ attr->show = show_dev;
+ attr->store = NULL;
+ class_device_create_file(class_dev, attr);
+ class_dev->devt_attr = attr;
+ }
+
+ class_device_add_attrs(class_dev);
+ if (class_dev->dev)
+ sysfs_create_link(&class_dev->kobj,
+ &class_dev->dev->kobj, "device");
+
+ /* notify any interfaces this device is now here */
if (parent) {
down(&parent->sem);
list_add_tail(&class_dev->node, &parent->children);
@@ -421,16 +508,8 @@ int class_device_add(struct class_device *class_dev)
class_intf->add(class_dev);
up(&parent->sem);
}
-
- if (MAJOR(class_dev->devt))
- class_device_create_file(class_dev, &class_device_attr_dev);
-
- class_device_add_attrs(class_dev);
- if (class_dev->dev)
- sysfs_create_link(&class_dev->kobj,
- &class_dev->dev->kobj, "device");
-
kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+
register_done:
if (error && parent)
class_put(parent);
@@ -444,6 +523,58 @@ int class_device_register(struct class_device *class_dev)
return class_device_add(class_dev);
}
+/**
+ * class_device_create - creates a class device and registers it with sysfs
+ * @cs: pointer to the struct class that this device should be registered to.
+ * @dev: the dev_t for the char device to be added.
+ * @device: a pointer to a struct device that is assiociated with this class device.
+ * @fmt: string for the class device's name
+ *
+ * This function can be used by char device classes. A struct
+ * class_device will be created in sysfs, registered to the specified
+ * class. A "dev" file will be created, showing the dev_t for the
+ * device. The pointer to the struct class_device will be returned from
+ * the call. Any further sysfs files that might be required can be
+ * created using this pointer.
+ *
+ * Note: the struct class passed to this function must have previously
+ * been created with a call to class_create().
+ */
+struct class_device *class_device_create(struct class *cls, dev_t devt,
+ struct device *device, char *fmt, ...)
+{
+ va_list args;
+ struct class_device *class_dev = NULL;
+ int retval = -ENODEV;
+
+ if (cls == NULL || IS_ERR(cls))
+ goto error;
+
+ class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL);
+ if (!class_dev) {
+ retval = -ENOMEM;
+ goto error;
+ }
+ memset(class_dev, 0x00, sizeof(struct class_device));
+
+ class_dev->devt = devt;
+ class_dev->dev = device;
+ class_dev->class = cls;
+
+ va_start(args, fmt);
+ vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
+ va_end(args);
+ retval = class_device_register(class_dev);
+ if (retval)
+ goto error;
+
+ return class_dev;
+
+error:
+ kfree(class_dev);
+ return ERR_PTR(retval);
+}
+
void class_device_del(struct class_device *class_dev)
{
struct class * parent = class_dev->class;
@@ -460,6 +591,11 @@ void class_device_del(struct class_device *class_dev)
if (class_dev->dev)
sysfs_remove_link(&class_dev->kobj, "device");
+ if (class_dev->devt_attr) {
+ class_device_remove_file(class_dev, class_dev->devt_attr);
+ kfree(class_dev->devt_attr);
+ class_dev->devt_attr = NULL;
+ }
class_device_remove_attrs(class_dev);
kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
@@ -477,6 +613,32 @@ void class_device_unregister(struct class_device *class_dev)
class_device_put(class_dev);
}
+/**
+ * class_device_destroy - removes a class device that was created with class_device_create()
+ * @cls: the pointer to the struct class that this device was registered * with.
+ * @dev: the dev_t of the device that was previously registered.
+ *
+ * This call unregisters and cleans up a class device that was created with a
+ * call to class_device_create()
+ */
+void class_device_destroy(struct class *cls, dev_t devt)
+{
+ struct class_device *class_dev = NULL;
+ struct class_device *class_dev_tmp;
+
+ down(&cls->sem);
+ list_for_each_entry(class_dev_tmp, &cls->children, node) {
+ if (class_dev_tmp->devt == devt) {
+ class_dev = class_dev_tmp;
+ break;
+ }
+ }
+ up(&cls->sem);
+
+ if (class_dev)
+ class_device_unregister(class_dev);
+}
+
int class_device_rename(struct class_device *class_dev, char *new_name)
{
int error = 0;
@@ -576,6 +738,8 @@ EXPORT_SYMBOL_GPL(class_register);
EXPORT_SYMBOL_GPL(class_unregister);
EXPORT_SYMBOL_GPL(class_get);
EXPORT_SYMBOL_GPL(class_put);
+EXPORT_SYMBOL_GPL(class_create);
+EXPORT_SYMBOL_GPL(class_destroy);
EXPORT_SYMBOL_GPL(class_device_register);
EXPORT_SYMBOL_GPL(class_device_unregister);
@@ -584,6 +748,8 @@ EXPORT_SYMBOL_GPL(class_device_add);
EXPORT_SYMBOL_GPL(class_device_del);
EXPORT_SYMBOL_GPL(class_device_get);
EXPORT_SYMBOL_GPL(class_device_put);
+EXPORT_SYMBOL_GPL(class_device_create);
+EXPORT_SYMBOL_GPL(class_device_destroy);
EXPORT_SYMBOL_GPL(class_device_create_file);
EXPORT_SYMBOL_GPL(class_device_remove_file);
EXPORT_SYMBOL_GPL(class_device_create_bin_file);
diff --git a/drivers/base/class_simple.c b/drivers/base/class_simple.c
deleted file mode 100644
index 27699eb20a3..00000000000
--- a/drivers/base/class_simple.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * class_simple.c - a "simple" interface for classes for simple char devices.
- *
- * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
- * Copyright (c) 2003-2004 IBM Corp.
- *
- * This file is released under the GPLv2
- *
- */
-
-#include <linux/config.h>
-#include <linux/device.h>
-#include <linux/err.h>
-
-struct class_simple {
- struct class class;
-};
-#define to_class_simple(d) container_of(d, struct class_simple, class)
-
-struct simple_dev {
- struct list_head node;
- struct class_device class_dev;
-};
-#define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)
-
-static LIST_HEAD(simple_dev_list);
-static DEFINE_SPINLOCK(simple_dev_list_lock);
-
-static void release_simple_dev(struct class_device *class_dev)
-{
- struct simple_dev *s_dev = to_simple_dev(class_dev);
- kfree(s_dev);
-}
-
-static void class_simple_release(struct class *class)
-{
- struct class_simple *cs = to_class_simple(class);
- kfree(cs);
-}
-
-/**
- * class_simple_create - create a struct class_simple structure
- * @owner: pointer to the module that is to "own" this struct class_simple
- * @name: pointer to a string for the name of this class.
- *
- * This is used to create a struct class_simple pointer that can then be used
- * in calls to class_simple_device_add(). This is used when you do not wish to
- * create a full blown class support for a type of char devices.
- *
- * Note, the pointer created here is to be destroyed when finished by making a
- * call to class_simple_destroy().
- */
-struct class_simple *class_simple_create(struct module *owner, char *name)
-{
- struct class_simple *cs;
- int retval;
-
- cs = kmalloc(sizeof(*cs), GFP_KERNEL);
- if (!cs) {
- retval = -ENOMEM;
- goto error;
- }
- memset(cs, 0x00, sizeof(*cs));
-
- cs->class.name = name;
- cs->class.class_release = class_simple_release;
- cs->class.release = release_simple_dev;
-
- retval = class_register(&cs->class);
- if (retval)
- goto error;
-
- return cs;
-
-error:
- kfree(cs);
- return ERR_PTR(retval);
-}
-EXPORT_SYMBOL(class_simple_create);
-
-/**
- * class_simple_destroy - destroys a struct class_simple structure
- * @cs: pointer to the struct class_simple that is to be destroyed
- *
- * Note, the pointer to be destroyed must have been created with a call to
- * class_simple_create().
- */
-void class_simple_destroy(struct class_simple *cs)
-{
- if ((cs == NULL) || (IS_ERR(cs)))
- return;
-
- class_unregister(&cs->class);
-}
-EXPORT_SYMBOL(class_simple_destroy);
-
-/**
- * class_simple_device_add - adds a class device to sysfs for a character driver
- * @cs: pointer to the struct class_simple that this device should be registered to.
- * @dev: the dev_t for the device to be added.
- * @device: a pointer to a struct device that is assiociated with this class device.
- * @fmt: string for the class device's name
- *
- * This function can be used by simple char device classes that do not
- * implement their own class device registration. A struct class_device will
- * be created in sysfs, registered to the specified class. A "dev" file will
- * be created, showing the dev_t for the device. The pointer to the struct
- * class_device will be returned from the call. Any further sysfs files that
- * might be required can be created using this pointer.
- * Note: the struct class_simple passed to this function must have previously been
- * created with a call to class_simple_create().
- */
-struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev, struct device *device, const char *fmt, ...)
-{
- va_list args;
- struct simple_dev *s_dev = NULL;
- int retval;
-
- if ((cs == NULL) || (IS_ERR(cs))) {
- retval = -ENODEV;
- goto error;
- }
-
- s_dev = kmalloc(sizeof(*s_dev), GFP_KERNEL);
- if (!s_dev) {
- retval = -ENOMEM;
- goto error;
- }
- memset(s_dev, 0x00, sizeof(*s_dev));
-
- s_dev->class_dev.devt = dev;
- s_dev->class_dev.dev = device;
- s_dev->class_dev.class = &cs->class;
-
- va_start(args, fmt);
- vsnprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, fmt, args);
- va_end(args);
- retval = class_device_register(&s_dev->class_dev);
- if (retval)
- goto error;
-
- spin_lock(&simple_dev_list_lock);
- list_add(&s_dev->node, &simple_dev_list);
- spin_unlock(&simple_dev_list_lock);
-
- return &s_dev->class_dev;
-
-error:
- kfree(s_dev);
- return ERR_PTR(retval);
-}
-EXPORT_SYMBOL(class_simple_device_add);
-
-/**
- * class_simple_set_hotplug - set the hotplug callback in the embedded struct class
- * @cs: pointer to the struct class_simple to hold the pointer
- * @hotplug: function pointer to the hotplug function
- *
- * Implement and set a hotplug function to add environment variables specific to this
- * class on the hotplug event.
- */
-int class_simple_set_hotplug(struct class_simple *cs,
- int (*hotplug)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size))
-{
- if ((cs == NULL) || (IS_ERR(cs)))
- return -ENODEV;
- cs->class.hotplug = hotplug;
- return 0;
-}
-EXPORT_SYMBOL(class_simple_set_hotplug);
-
-/**
- * class_simple_device_remove - removes a class device that was created with class_simple_device_add()
- * @dev: the dev_t of the device that was previously registered.
- *
- * This call unregisters and cleans up a class device that was created with a
- * call to class_device_simple_add()
- */
-void class_simple_device_remove(dev_t dev)
-{
- struct simple_dev *s_dev = NULL;
- int found = 0;
-
- spin_lock(&simple_dev_list_lock);
- list_for_each_entry(s_dev, &simple_dev_list, node) {
- if (s_dev->class_dev.devt == dev) {
- found = 1;
- break;
- }
- }
- if (found) {
- list_del(&s_dev->node);
- spin_unlock(&simple_dev_list_lock);
- class_device_unregister(&s_dev->class_dev);
- } else {
- spin_unlock(&simple_dev_list_lock);
- }
-}
-EXPORT_SYMBOL(class_simple_device_remove);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index d21eb774449..86d79755fbf 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -36,10 +36,10 @@ dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
{
struct device_attribute * dev_attr = to_dev_attr(attr);
struct device * dev = to_dev(kobj);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (dev_attr->show)
- ret = dev_attr->show(dev, buf);
+ ret = dev_attr->show(dev, dev_attr, buf);
return ret;
}
@@ -49,10 +49,10 @@ dev_attr_store(struct kobject * kobj, struct attribute * attr,
{
struct device_attribute * dev_attr = to_dev_attr(attr);
struct device * dev = to_dev(kobj);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (dev_attr->store)
- ret = dev_attr->store(dev, buf, count);
+ ret = dev_attr->store(dev, dev_attr, buf, count);
return ret;
}
@@ -102,7 +102,7 @@ static int dev_hotplug_filter(struct kset *kset, struct kobject *kobj)
return 0;
}
-static char *dev_hotplug_name(struct kset *kset, struct kobject *kobj)
+static const char *dev_hotplug_name(struct kset *kset, struct kobject *kobj)
{
struct device *dev = to_dev(kobj);
@@ -207,11 +207,9 @@ void device_initialize(struct device *dev)
{
kobj_set_kset_s(dev, devices_subsys);
kobject_init(&dev->kobj);
- INIT_LIST_HEAD(&dev->node);
- INIT_LIST_HEAD(&dev->children);
- INIT_LIST_HEAD(&dev->driver_list);
- INIT_LIST_HEAD(&dev->bus_list);
+ klist_init(&dev->klist_children);
INIT_LIST_HEAD(&dev->dma_pools);
+ init_MUTEX(&dev->sem);
}
/**
@@ -245,26 +243,24 @@ int device_add(struct device *dev)
if ((error = kobject_add(&dev->kobj)))
goto Error;
+ kobject_hotplug(&dev->kobj, KOBJ_ADD);
if ((error = device_pm_add(dev)))
goto PMError;
if ((error = bus_add_device(dev)))
goto BusError;
- down_write(&devices_subsys.rwsem);
if (parent)
- list_add_tail(&dev->node, &parent->children);
- up_write(&devices_subsys.rwsem);
+ klist_add_tail(&parent->klist_children, &dev->knode_parent);
/* notify platform of device entry */
if (platform_notify)
platform_notify(dev);
-
- kobject_hotplug(&dev->kobj, KOBJ_ADD);
Done:
put_device(dev);
return error;
BusError:
device_pm_remove(dev);
PMError:
+ kobject_hotplug(&dev->kobj, KOBJ_REMOVE);
kobject_del(&dev->kobj);
Error:
if (parent)
@@ -336,10 +332,8 @@ void device_del(struct device * dev)
{
struct device * parent = dev->parent;
- down_write(&devices_subsys.rwsem);
if (parent)
- list_del_init(&dev->node);
- up_write(&devices_subsys.rwsem);
+ klist_remove(&dev->knode_parent);
/* Notify the platform of the removal, in case they
* need to do anything...
@@ -373,6 +367,12 @@ void device_unregister(struct device * dev)
}
+static struct device * next_device(struct klist_iter * i)
+{
+ struct klist_node * n = klist_next(i);
+ return n ? container_of(n, struct device, knode_parent) : NULL;
+}
+
/**
* device_for_each_child - device child iterator.
* @dev: parent struct device.
@@ -385,39 +385,20 @@ void device_unregister(struct device * dev)
* We check the return of @fn each time. If it returns anything
* other than 0, we break out and return that value.
*/
-int device_for_each_child(struct device * dev, void * data,
+int device_for_each_child(struct device * parent, void * data,
int (*fn)(struct device *, void *))
{
+ struct klist_iter i;
struct device * child;
int error = 0;
- down_read(&devices_subsys.rwsem);
- list_for_each_entry(child, &dev->children, node) {
- if((error = fn(child, data)))
- break;
- }
- up_read(&devices_subsys.rwsem);
+ klist_iter_init(&parent->klist_children, &i);
+ while ((child = next_device(&i)) && !error)
+ error = fn(child, data);
+ klist_iter_exit(&i);
return error;
}
-/**
- * device_find - locate device on a bus by name.
- * @name: name of the device.
- * @bus: bus to scan for the device.
- *
- * Call kset_find_obj() to iterate over list of devices on
- * a bus to find device by name. Return device if found.
- *
- * Note that kset_find_obj increments device's reference count.
- */
-struct device *device_find(const char *name, struct bus_type *bus)
-{
- struct kobject *k = kset_find_obj(&bus->devices, name);
- if (k)
- return to_dev(k);
- return NULL;
-}
-
int __init devices_init(void)
{
return subsystem_register(&devices_subsys);
@@ -433,7 +414,6 @@ EXPORT_SYMBOL_GPL(device_del);
EXPORT_SYMBOL_GPL(device_unregister);
EXPORT_SYMBOL_GPL(get_device);
EXPORT_SYMBOL_GPL(put_device);
-EXPORT_SYMBOL_GPL(device_find);
EXPORT_SYMBOL_GPL(device_create_file);
EXPORT_SYMBOL_GPL(device_remove_file);
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 6ef3069b571..b79badd0f15 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -16,6 +16,11 @@ struct sysdev_class cpu_sysdev_class = {
EXPORT_SYMBOL(cpu_sysdev_class);
#ifdef CONFIG_HOTPLUG_CPU
+int __attribute__((weak)) smp_prepare_cpu (int cpu)
+{
+ return 0;
+}
+
static ssize_t show_online(struct sys_device *dev, char *buf)
{
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
@@ -36,7 +41,11 @@ static ssize_t store_online(struct sys_device *dev, const char *buf,
kobject_hotplug(&dev->kobj, KOBJ_OFFLINE);
break;
case '1':
- ret = cpu_up(cpu->sysdev.id);
+ ret = smp_prepare_cpu(cpu->sysdev.id);
+ if (!ret)
+ ret = cpu_up(cpu->sysdev.id);
+ if (!ret)
+ kobject_hotplug(&dev->kobj, KOBJ_ONLINE);
break;
default:
ret = -EINVAL;
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
new file mode 100644
index 00000000000..6db3a789c54
--- /dev/null
+++ b/drivers/base/dd.c
@@ -0,0 +1,248 @@
+/*
+ * drivers/base/dd.c - The core device/driver interactions.
+ *
+ * This file contains the (sometimes tricky) code that controls the
+ * interactions between devices and drivers, which primarily includes
+ * driver binding and unbinding.
+ *
+ * All of this code used to exist in drivers/base/bus.c, but was
+ * relocated to here in the name of compartmentalization (since it wasn't
+ * strictly code just for the 'struct bus_type'.
+ *
+ * Copyright (c) 2002-5 Patrick Mochel
+ * Copyright (c) 2002-3 Open Source Development Labs
+ *
+ * This file is released under the GPLv2
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+
+#include "base.h"
+#include "power/power.h"
+
+#define to_drv(node) container_of(node, struct device_driver, kobj.entry)
+
+
+/**
+ * device_bind_driver - bind a driver to one device.
+ * @dev: device.
+ *
+ * Allow manual attachment of a driver to a device.
+ * Caller must have already set @dev->driver.
+ *
+ * Note that this does not modify the bus reference count
+ * nor take the bus's rwsem. Please verify those are accounted
+ * for before calling this. (It is ok to call with no other effort
+ * from a driver's probe() method.)
+ *
+ * This function must be called with @dev->sem held.
+ */
+void device_bind_driver(struct device * dev)
+{
+ pr_debug("bound device '%s' to driver '%s'\n",
+ dev->bus_id, dev->driver->name);
+ klist_add_tail(&dev->driver->klist_devices, &dev->knode_driver);
+ sysfs_create_link(&dev->driver->kobj, &dev->kobj,
+ kobject_name(&dev->kobj));
+ sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
+}
+
+/**
+ * driver_probe_device - attempt to bind device & driver.
+ * @drv: driver.
+ * @dev: device.
+ *
+ * First, we call the bus's match function, if one present, which
+ * should compare the device IDs the driver supports with the
+ * device IDs of the device. Note we don't do this ourselves
+ * because we don't know the format of the ID structures, nor what
+ * is to be considered a match and what is not.
+ *
+ *
+ * This function returns 1 if a match is found, an error if one
+ * occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.
+ *
+ * This function must be called with @dev->sem held.
+ */
+static int driver_probe_device(struct device_driver * drv, struct device * dev)
+{
+ int ret = 0;
+
+ if (drv->bus->match && !drv->bus->match(dev, drv))
+ goto Done;
+
+ pr_debug("%s: Matched Device %s with Driver %s\n",
+ drv->bus->name, dev->bus_id, drv->name);
+ dev->driver = drv;
+ if (drv->probe) {
+ ret = drv->probe(dev);
+ if (ret) {
+ dev->driver = NULL;
+ goto ProbeFailed;
+ }
+ }
+ device_bind_driver(dev);
+ ret = 1;
+ pr_debug("%s: Bound Device %s to Driver %s\n",
+ drv->bus->name, dev->bus_id, drv->name);
+ goto Done;
+
+ ProbeFailed:
+ if (ret == -ENODEV || ret == -ENXIO) {
+ /* Driver matched, but didn't support device
+ * or device not found.
+ * Not an error; keep going.
+ */
+ ret = 0;
+ } else {
+ /* driver matched but the probe failed */
+ printk(KERN_WARNING
+ "%s: probe of %s failed with error %d\n",
+ drv->name, dev->bus_id, ret);
+ }
+ Done:
+ return ret;
+}
+
+static int __device_attach(struct device_driver * drv, void * data)
+{
+ struct device * dev = data;
+ return driver_probe_device(drv, dev);
+}
+
+/**
+ * device_attach - try to attach device to a driver.
+ * @dev: device.
+ *
+ * Walk the list of drivers that the bus has and call
+ * driver_probe_device() for each pair. If a compatible
+ * pair is found, break out and return.
+ *
+ * Returns 1 if the device was bound to a driver;
+ * 0 if no matching device was found; error code otherwise.
+ */
+int device_attach(struct device * dev)
+{
+ int ret = 0;
+
+ down(&dev->sem);
+ if (dev->driver) {
+ device_bind_driver(dev);
+ ret = 1;
+ } else
+ ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
+ up(&dev->sem);
+ return ret;
+}
+
+static int __driver_attach(struct device * dev, void * data)
+{
+ struct device_driver * drv = data;
+
+ /*
+ * Lock device and try to bind to it. We drop the error
+ * here and always return 0, because we need to keep trying
+ * to bind to devices and some drivers will return an error
+ * simply if it didn't support the device.
+ *
+ * driver_probe_device() will spit a warning if there
+ * is an error.
+ */
+
+ down(&dev->sem);
+ if (!dev->driver)
+ driver_probe_device(drv, dev);
+ up(&dev->sem);
+
+
+ return 0;
+}
+
+/**
+ * driver_attach - try to bind driver to devices.
+ * @drv: driver.
+ *
+ * Walk the list of devices that the bus has on it and try to
+ * match the driver with each one. If driver_probe_device()
+ * returns 0 and the @dev->driver is set, we've found a
+ * compatible pair.
+ */
+void driver_attach(struct device_driver * drv)
+{
+ bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
+}
+
+/**
+ * device_release_driver - manually detach device from driver.
+ * @dev: device.
+ *
+ * Manually detach device from driver.
+ *
+ * __device_release_driver() must be called with @dev->sem held.
+ */
+
+static void __device_release_driver(struct device * dev)
+{
+ struct device_driver * drv;
+
+ drv = dev->driver;
+ if (drv) {
+ get_driver(drv);
+ sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
+ sysfs_remove_link(&dev->kobj, "driver");
+ klist_remove(&dev->knode_driver);
+
+ if (drv->remove)
+ drv->remove(dev);
+ dev->driver = NULL;
+ put_driver(drv);
+ }
+}
+
+void device_release_driver(struct device * dev)
+{
+ /*
+ * If anyone calls device_release_driver() recursively from
+ * within their ->remove callback for the same device, they
+ * will deadlock right here.
+ */
+ down(&dev->sem);
+ __device_release_driver(dev);
+ up(&dev->sem);
+}
+
+
+/**
+ * driver_detach - detach driver from all devices it controls.
+ * @drv: driver.
+ */
+void driver_detach(struct device_driver * drv)
+{
+ struct device * dev;
+
+ for (;;) {
+ spin_lock_irq(&drv->klist_devices.k_lock);
+ if (list_empty(&drv->klist_devices.k_list)) {
+ spin_unlock_irq(&drv->klist_devices.k_lock);
+ break;
+ }
+ dev = list_entry(drv->klist_devices.k_list.prev,
+ struct device, knode_driver.n_node);
+ get_device(dev);
+ spin_unlock_irq(&drv->klist_devices.k_lock);
+
+ down(&dev->sem);
+ if (dev->driver == drv)
+ __device_release_driver(dev);
+ up(&dev->sem);
+ put_device(dev);
+ }
+}
+
+
+EXPORT_SYMBOL_GPL(device_bind_driver);
+EXPORT_SYMBOL_GPL(device_release_driver);
+EXPORT_SYMBOL_GPL(device_attach);
+EXPORT_SYMBOL_GPL(driver_attach);
+
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
index f48833df61a..c4aebf2f522 100644
--- a/drivers/base/dmapool.c
+++ b/drivers/base/dmapool.c
@@ -41,7 +41,7 @@ struct dma_page { /* cacheable header for 'allocation' bytes */
static DECLARE_MUTEX (pools_lock);
static ssize_t
-show_pools (struct device *dev, char *buf)
+show_pools (struct device *dev, struct device_attribute *attr, char *buf)
{
unsigned temp;
unsigned size;
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 3b269f7e521..1b645886e9e 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -18,6 +18,43 @@
#define to_dev(node) container_of(node, struct device, driver_list)
#define to_drv(obj) container_of(obj, struct device_driver, kobj)
+
+static struct device * next_device(struct klist_iter * i)
+{
+ struct klist_node * n = klist_next(i);
+ return n ? container_of(n, struct device, knode_driver) : NULL;
+}
+
+/**
+ * driver_for_each_device - Iterator for devices bound to a driver.
+ * @drv: Driver we're iterating.
+ * @data: Data to pass to the callback.
+ * @fn: Function to call for each device.
+ *
+ * Iterate over the @drv's list of devices calling @fn for each one.
+ */
+
+int driver_for_each_device(struct device_driver * drv, struct device * start,
+ void * data, int (*fn)(struct device *, void *))
+{
+ struct klist_iter i;
+ struct device * dev;
+ int error = 0;
+
+ if (!drv)
+ return -EINVAL;
+
+ klist_iter_init_node(&drv->klist_devices, &i,
+ start ? &start->knode_driver : NULL);
+ while ((dev = next_device(&i)) && !error)
+ error = fn(dev, data);
+ klist_iter_exit(&i);
+ return error;
+}
+
+EXPORT_SYMBOL_GPL(driver_for_each_device);
+
+
/**
* driver_create_file - create sysfs file for driver.
* @drv: driver.
@@ -85,7 +122,7 @@ void put_driver(struct device_driver * drv)
*/
int driver_register(struct device_driver * drv)
{
- INIT_LIST_HEAD(&drv->devices);
+ klist_init(&drv->klist_devices);
init_completion(&drv->unloaded);
return bus_add_driver(drv);
}
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 583d57ec49a..904b27caf69 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -87,7 +87,7 @@ static ssize_t node_read_numastat(struct sys_device * dev, char * buf)
for (i = 0; i < MAX_NR_ZONES; i++) {
struct zone *z = &pg->node_zones[i];
for (cpu = 0; cpu < NR_CPUS; cpu++) {
- struct per_cpu_pageset *ps = &z->pageset[cpu];
+ struct per_cpu_pageset *ps = zone_pcp(z,cpu);
numa_hit += ps->numa_hit;
numa_miss += ps->numa_miss;
numa_foreign += ps->numa_foreign;
@@ -136,7 +136,7 @@ static SYSDEV_ATTR(distance, S_IRUGO, node_read_distance, NULL);
*
* Initialize and register the node device.
*/
-int __init register_node(struct node *node, int num, struct node *parent)
+int register_node(struct node *node, int num, struct node *parent)
{
int error;
@@ -153,8 +153,24 @@ int __init register_node(struct node *node, int num, struct node *parent)
return error;
}
+/**
+ * unregister_node - unregister a node device
+ * @node: node going away
+ *
+ * Unregisters a node device @node. All the devices on the node must be
+ * unregistered before calling this function.
+ */
+void unregister_node(struct node *node)
+{
+ sysdev_remove_file(&node->sysdev, &attr_cpumap);
+ sysdev_remove_file(&node->sysdev, &attr_meminfo);
+ sysdev_remove_file(&node->sysdev, &attr_numastat);
+ sysdev_remove_file(&node->sysdev, &attr_distance);
+
+ sysdev_unregister(&node->sysdev);
+}
-int __init register_node_type(void)
+static int __init register_node_type(void)
{
return sysdev_class_register(&node_class);
}
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c
index 26468971ef5..bdd96b03b88 100644
--- a/drivers/base/power/resume.c
+++ b/drivers/base/power/resume.c
@@ -22,6 +22,9 @@ extern int sysdev_resume(void);
int resume_device(struct device * dev)
{
+ int error = 0;
+
+ down(&dev->sem);
if (dev->power.pm_parent
&& dev->power.pm_parent->power.power_state) {
dev_err(dev, "PM: resume from %d, parent %s still %d\n",
@@ -31,9 +34,10 @@ int resume_device(struct device * dev)
}
if (dev->bus && dev->bus->resume) {
dev_dbg(dev,"resuming\n");
- return dev->bus->resume(dev);
+ error = dev->bus->resume(dev);
}
- return 0;
+ up(&dev->sem);
+ return error;
}
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index 0ec44ef840b..2ccee3763ac 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -39,6 +39,7 @@ int suspend_device(struct device * dev, pm_message_t state)
{
int error = 0;
+ down(&dev->sem);
if (dev->power.power_state) {
dev_dbg(dev, "PM: suspend %d-->%d\n",
dev->power.power_state, state);
@@ -58,7 +59,7 @@ int suspend_device(struct device * dev, pm_message_t state)
dev_dbg(dev, "suspending\n");
error = dev->bus->suspend(dev, state);
}
-
+ up(&dev->sem);
return error;
}
@@ -113,8 +114,19 @@ int device_suspend(pm_message_t state)
put_device(dev);
}
up(&dpm_list_sem);
- if (error)
+ if (error) {
+ /* we failed... before resuming, bring back devices from
+ * dpm_off_irq list back to main dpm_off list, we do want
+ * to call resume() on them, in case they partially suspended
+ * despite returning -EAGAIN
+ */
+ while (!list_empty(&dpm_off_irq)) {
+ struct list_head * entry = dpm_off_irq.next;
+ list_del(entry);
+ list_add(entry, &dpm_off);
+ }
dpm_resume();
+ }
up(&dpm_sem);
return error;
}
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index 6ac96349a8e..f82b3df9545 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -24,12 +24,12 @@
* low-power state.
*/
-static ssize_t state_show(struct device * dev, char * buf)
+static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf)
{
return sprintf(buf, "%u\n", dev->power.power_state);
}
-static ssize_t state_store(struct device * dev, const char * buf, size_t n)
+static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n)
{
u32 state;
char * rest;
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 9102e3756f9..f37a13de804 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -37,7 +37,7 @@ sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer)
if (sysdev_attr->show)
return sysdev_attr->show(sysdev, buffer);
- return 0;
+ return -EIO;
}
@@ -50,7 +50,7 @@ sysdev_store(struct kobject * kobj, struct attribute * attr,
if (sysdev_attr->store)
return sysdev_attr->store(sysdev, buffer, count);
- return 0;
+ return -EIO;
}
static struct sysfs_ops sysfs_ops = {
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 14aeca3e2e8..45a24309618 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -36,7 +36,7 @@ static int emsgs_head_idx, emsgs_tail_idx;
static struct semaphore emsgs_sema;
static spinlock_t emsgs_lock;
static int nblocked_emsgs_readers;
-static struct class_simple *aoe_class;
+static struct class *aoe_class;
static struct aoe_chardev chardevs[] = {
{ MINOR_ERR, "err" },
{ MINOR_DISCOVER, "discover" },
@@ -218,13 +218,13 @@ aoechr_init(void)
}
sema_init(&emsgs_sema, 0);
spin_lock_init(&emsgs_lock);
- aoe_class = class_simple_create(THIS_MODULE, "aoe");
+ aoe_class = class_create(THIS_MODULE, "aoe");
if (IS_ERR(aoe_class)) {
unregister_chrdev(AOE_MAJOR, "aoechr");
return PTR_ERR(aoe_class);
}
for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
- class_simple_device_add(aoe_class,
+ class_device_create(aoe_class,
MKDEV(AOE_MAJOR, chardevs[i].minor),
NULL, chardevs[i].name);
@@ -237,8 +237,8 @@ aoechr_exit(void)
int i;
for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
- class_simple_device_remove(MKDEV(AOE_MAJOR, chardevs[i].minor));
- class_simple_destroy(aoe_class);
+ class_device_destroy(aoe_class, MKDEV(AOE_MAJOR, chardevs[i].minor));
+ class_destroy(aoe_class);
unregister_chrdev(AOE_MAJOR, "aoechr");
}
diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c
index a9575bb58a5..3410b4d294b 100644
--- a/drivers/block/as-iosched.c
+++ b/drivers/block/as-iosched.c
@@ -1871,20 +1871,22 @@ static int as_init_queue(request_queue_t *q, elevator_t *e)
if (!arq_pool)
return -ENOMEM;
- ad = kmalloc(sizeof(*ad), GFP_KERNEL);
+ ad = kmalloc_node(sizeof(*ad), GFP_KERNEL, q->node);
if (!ad)
return -ENOMEM;
memset(ad, 0, sizeof(*ad));
ad->q = q; /* Identify what queue the data belongs to */
- ad->hash = kmalloc(sizeof(struct list_head)*AS_HASH_ENTRIES,GFP_KERNEL);
+ ad->hash = kmalloc_node(sizeof(struct list_head)*AS_HASH_ENTRIES,
+ GFP_KERNEL, q->node);
if (!ad->hash) {
kfree(ad);
return -ENOMEM;
}
- ad->arq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, arq_pool);
+ ad->arq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
+ mempool_free_slab, arq_pool, q->node);
if (!ad->arq_pool) {
kfree(ad->hash);
kfree(ad);
@@ -2044,7 +2046,7 @@ as_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
struct as_fs_entry *entry = to_as(attr);
if (!entry->show)
- return 0;
+ return -EIO;
return entry->show(e->elevator_data, page);
}
@@ -2057,7 +2059,7 @@ as_attr_store(struct kobject *kobj, struct attribute *attr,
struct as_fs_entry *entry = to_as(attr);
if (!entry->store)
- return -EINVAL;
+ return -EIO;
return entry->store(e->elevator_data, page, length);
}
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 8f7c1a1ed7f..abde27027c0 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -41,6 +41,7 @@
#include <asm/uaccess.h>
#include <asm/io.h>
+#include <linux/dma-mapping.h>
#include <linux/blkdev.h>
#include <linux/genhd.h>
#include <linux/completion.h>
@@ -126,8 +127,6 @@ static struct board_type products[] = {
#define MAX_CTLR_ORIG 8
-#define CCISS_DMA_MASK 0xFFFFFFFF /* 32 bit DMA */
-
static ctlr_info_t *hba[MAX_CTLR];
static void do_cciss_request(request_queue_t *q);
@@ -2393,11 +2392,6 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
printk(KERN_ERR "cciss: Unable to Enable PCI device\n");
return( -1);
}
- if (pci_set_dma_mask(pdev, CCISS_DMA_MASK ) != 0)
- {
- printk(KERN_ERR "cciss: Unable to set DMA mask\n");
- return(-1);
- }
subsystem_vendor_id = pdev->subsystem_vendor;
subsystem_device_id = pdev->subsystem_device;
@@ -2747,9 +2741,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
hba[i]->pdev = pdev;
/* configure PCI DMA stuff */
- if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL))
+ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK))
printk("cciss: using DAC cycles\n");
- else if (!pci_set_dma_mask(pdev, 0xffffffff))
+ else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK))
printk("cciss: not using DAC cycles\n");
else {
printk("cciss: no suitable DMA available\n");
diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c
index 0ef7a0065ec..3ac47dde64d 100644
--- a/drivers/block/cfq-iosched.c
+++ b/drivers/block/cfq-iosched.c
@@ -1202,13 +1202,16 @@ retry:
if (new_cfqq) {
cfqq = new_cfqq;
new_cfqq = NULL;
- } else if (gfp_mask & __GFP_WAIT) {
+ } else {
spin_unlock_irq(cfqd->queue->queue_lock);
new_cfqq = kmem_cache_alloc(cfq_pool, gfp_mask);
spin_lock_irq(cfqd->queue->queue_lock);
+
+ if (!new_cfqq && !(gfp_mask & __GFP_WAIT))
+ goto out;
+
goto retry;
- } else
- goto out;
+ }
memset(cfqq, 0, sizeof(*cfqq));
@@ -1772,7 +1775,7 @@ cfq_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
struct cfq_fs_entry *entry = to_cfq(attr);
if (!entry->show)
- return 0;
+ return -EIO;
return entry->show(e->elevator_data, page);
}
@@ -1785,7 +1788,7 @@ cfq_attr_store(struct kobject *kobj, struct attribute *attr,
struct cfq_fs_entry *entry = to_cfq(attr);
if (!entry->store)
- return -EINVAL;
+ return -EIO;
return entry->store(e->elevator_data, page, length);
}
diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c
index d63d34c671f..4bc2fea7327 100644
--- a/drivers/block/deadline-iosched.c
+++ b/drivers/block/deadline-iosched.c
@@ -711,18 +711,20 @@ static int deadline_init_queue(request_queue_t *q, elevator_t *e)
if (!drq_pool)
return -ENOMEM;
- dd = kmalloc(sizeof(*dd), GFP_KERNEL);
+ dd = kmalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
if (!dd)
return -ENOMEM;
memset(dd, 0, sizeof(*dd));
- dd->hash = kmalloc(sizeof(struct list_head)*DL_HASH_ENTRIES,GFP_KERNEL);
+ dd->hash = kmalloc_node(sizeof(struct list_head)*DL_HASH_ENTRIES,
+ GFP_KERNEL, q->node);
if (!dd->hash) {
kfree(dd);
return -ENOMEM;
}
- dd->drq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, drq_pool);
+ dd->drq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
+ mempool_free_slab, drq_pool, q->node);
if (!dd->drq_pool) {
kfree(dd->hash);
kfree(dd);
@@ -886,7 +888,7 @@ deadline_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
struct deadline_fs_entry *entry = to_deadline(attr);
if (!entry->show)
- return 0;
+ return -EIO;
return entry->show(e->elevator_data, page);
}
@@ -899,7 +901,7 @@ deadline_attr_store(struct kobject *kobj, struct attribute *attr,
struct deadline_fs_entry *entry = to_deadline(attr);
if (!entry->store)
- return -EINVAL;
+ return -EIO;
return entry->store(e->elevator_data, page, length);
}
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
index 6b79b431462..f831f08f839 100644
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -220,11 +220,6 @@ void elevator_exit(elevator_t *e)
kfree(e);
}
-static int elevator_global_init(void)
-{
- return 0;
-}
-
int elv_merge(request_queue_t *q, struct request **req, struct bio *bio)
{
elevator_t *e = q->elevator;
@@ -291,6 +286,13 @@ void elv_requeue_request(request_queue_t *q, struct request *rq)
}
/*
+ * the request is prepped and may have some resources allocated.
+ * allowing unprepped requests to pass this one may cause resource
+ * deadlock. turn on softbarrier.
+ */
+ rq->flags |= REQ_SOFTBARRIER;
+
+ /*
* if iosched has an explicit requeue hook, then use that. otherwise
* just put the request at the front of the queue
*/
@@ -322,7 +324,7 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
int nrq = q->rq.count[READ] + q->rq.count[WRITE]
- q->in_flight;
- if (nrq == q->unplug_thresh)
+ if (nrq >= q->unplug_thresh)
__generic_unplug_device(q);
}
} else
@@ -386,6 +388,12 @@ struct request *elv_next_request(request_queue_t *q)
if (ret == BLKPREP_OK) {
break;
} else if (ret == BLKPREP_DEFER) {
+ /*
+ * the request may have been (partially) prepped.
+ * we need to keep this request in the front to
+ * avoid resource deadlock. turn on softbarrier.
+ */
+ rq->flags |= REQ_SOFTBARRIER;
rq = NULL;
break;
} else if (ret == BLKPREP_KILL) {
@@ -692,8 +700,6 @@ ssize_t elv_iosched_show(request_queue_t *q, char *name)
return len;
}
-module_init(elevator_global_init);
-
EXPORT_SYMBOL(elv_add_request);
EXPORT_SYMBOL(__elv_add_request);
EXPORT_SYMBOL(elv_requeue_request);
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 8bbe01d4b48..47fd3659a06 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -40,7 +40,7 @@ static inline int major_to_index(int major)
#ifdef CONFIG_PROC_FS
/* get block device names in somewhat random order */
-int get_blkdev_list(char *p)
+int get_blkdev_list(char *p, int used)
{
struct blk_major_name *n;
int i, len;
@@ -49,10 +49,18 @@ int get_blkdev_list(char *p)
down(&block_subsys_sem);
for (i = 0; i < ARRAY_SIZE(major_names); i++) {
- for (n = major_names[i]; n; n = n->next)
+ for (n = major_names[i]; n; n = n->next) {
+ /*
+ * If the curent string plus the 5 extra characters
+ * in the line would run us off the page, then we're done
+ */
+ if ((len + used + strlen(n->name) + 5) >= PAGE_SIZE)
+ goto page_full;
len += sprintf(p+len, "%3d %s\n",
n->major, n->name);
+ }
}
+page_full:
up(&block_subsys_sem);
return len;
@@ -322,7 +330,7 @@ static ssize_t disk_attr_show(struct kobject *kobj, struct attribute *attr,
struct gendisk *disk = to_disk(kobj);
struct disk_attribute *disk_attr =
container_of(attr,struct disk_attribute,attr);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (disk_attr->show)
ret = disk_attr->show(disk,page);
@@ -582,10 +590,16 @@ struct seq_operations diskstats_op = {
.show = diskstats_show
};
-
struct gendisk *alloc_disk(int minors)
{
- struct gendisk *disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
+ return alloc_disk_node(minors, -1);
+}
+
+struct gendisk *alloc_disk_node(int minors, int node_id)
+{
+ struct gendisk *disk;
+
+ disk = kmalloc_node(sizeof(struct gendisk), GFP_KERNEL, node_id);
if (disk) {
memset(disk, 0, sizeof(struct gendisk));
if (!init_disk_stats(disk)) {
@@ -594,7 +608,7 @@ struct gendisk *alloc_disk(int minors)
}
if (minors > 1) {
int size = (minors - 1) * sizeof(struct hd_struct *);
- disk->part = kmalloc(size, GFP_KERNEL);
+ disk->part = kmalloc_node(size, GFP_KERNEL, node_id);
if (!disk->part) {
kfree(disk);
return NULL;
@@ -610,6 +624,7 @@ struct gendisk *alloc_disk(int minors)
}
EXPORT_SYMBOL(alloc_disk);
+EXPORT_SYMBOL(alloc_disk_node);
struct kobject *get_disk(struct gendisk *disk)
{
diff --git a/drivers/block/ioctl.c b/drivers/block/ioctl.c
index 6d7bcc9da9e..6e278474f9a 100644
--- a/drivers/block/ioctl.c
+++ b/drivers/block/ioctl.c
@@ -133,11 +133,9 @@ static int put_u64(unsigned long arg, u64 val)
return put_user(val, (u64 __user *)arg);
}
-int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
- unsigned long arg)
+static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev,
+ unsigned cmd, unsigned long arg)
{
- struct block_device *bdev = inode->i_bdev;
- struct gendisk *disk = bdev->bd_disk;
struct backing_dev_info *bdi;
int ret, n;
@@ -190,36 +188,72 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
return put_ulong(arg, bdev->bd_inode->i_size >> 9);
case BLKGETSIZE64:
return put_u64(arg, bdev->bd_inode->i_size);
+ }
+ return -ENOIOCTLCMD;
+}
+
+static int blkdev_driver_ioctl(struct inode *inode, struct file *file,
+ struct gendisk *disk, unsigned cmd, unsigned long arg)
+{
+ int ret;
+ if (disk->fops->unlocked_ioctl)
+ return disk->fops->unlocked_ioctl(file, cmd, arg);
+
+ if (disk->fops->ioctl) {
+ lock_kernel();
+ ret = disk->fops->ioctl(inode, file, cmd, arg);
+ unlock_kernel();
+ return ret;
+ }
+
+ return -ENOTTY;
+}
+
+int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
+ unsigned long arg)
+{
+ struct block_device *bdev = inode->i_bdev;
+ struct gendisk *disk = bdev->bd_disk;
+ int ret, n;
+
+ switch(cmd) {
case BLKFLSBUF:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- if (disk->fops->ioctl) {
- ret = disk->fops->ioctl(inode, file, cmd, arg);
- /* -EINVAL to handle old uncorrected drivers */
- if (ret != -EINVAL && ret != -ENOTTY)
- return ret;
- }
+
+ ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg);
+ /* -EINVAL to handle old uncorrected drivers */
+ if (ret != -EINVAL && ret != -ENOTTY)
+ return ret;
+
+ lock_kernel();
fsync_bdev(bdev);
invalidate_bdev(bdev, 0);
+ unlock_kernel();
return 0;
+
case BLKROSET:
- if (disk->fops->ioctl) {
- ret = disk->fops->ioctl(inode, file, cmd, arg);
- /* -EINVAL to handle old uncorrected drivers */
- if (ret != -EINVAL && ret != -ENOTTY)
- return ret;
- }
+ ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg);
+ /* -EINVAL to handle old uncorrected drivers */
+ if (ret != -EINVAL && ret != -ENOTTY)
+ return ret;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if (get_user(n, (int __user *)(arg)))
return -EFAULT;
+ lock_kernel();
set_device_ro(bdev, n);
+ unlock_kernel();
return 0;
- default:
- if (disk->fops->ioctl)
- return disk->fops->ioctl(inode, file, cmd, arg);
}
- return -ENOTTY;
+
+ lock_kernel();
+ ret = blkdev_locked_ioctl(file, bdev, cmd, arg);
+ unlock_kernel();
+ if (ret != -ENOIOCTLCMD)
+ return ret;
+
+ return blkdev_driver_ioctl(inode, file, disk, cmd, arg);
}
/* Most of the generic ioctls are handled in the normal fallback path.
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 11ef9d9ea13..60e64091de1 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include <linux/swap.h>
#include <linux/writeback.h>
+#include <linux/blkdev.h>
/*
* for max sense size
@@ -36,6 +37,7 @@
static void blk_unplug_work(void *data);
static void blk_unplug_timeout(unsigned long data);
+static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io);
/*
* For the allocated request tables
@@ -716,7 +718,7 @@ struct request *blk_queue_find_tag(request_queue_t *q, int tag)
{
struct blk_queue_tag *bqt = q->queue_tags;
- if (unlikely(bqt == NULL || tag >= bqt->real_max_depth))
+ if (unlikely(bqt == NULL || tag >= bqt->max_depth))
return NULL;
return bqt->tag_index[tag];
@@ -774,9 +776,9 @@ EXPORT_SYMBOL(blk_queue_free_tags);
static int
init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth)
{
- int bits, i;
struct request **tag_index;
unsigned long *tag_map;
+ int nr_ulongs;
if (depth > q->nr_requests * 2) {
depth = q->nr_requests * 2;
@@ -788,24 +790,17 @@ init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth)
if (!tag_index)
goto fail;
- bits = (depth / BLK_TAGS_PER_LONG) + 1;
- tag_map = kmalloc(bits * sizeof(unsigned long), GFP_ATOMIC);
+ nr_ulongs = ALIGN(depth, BITS_PER_LONG) / BITS_PER_LONG;
+ tag_map = kmalloc(nr_ulongs * sizeof(unsigned long), GFP_ATOMIC);
if (!tag_map)
goto fail;
memset(tag_index, 0, depth * sizeof(struct request *));
- memset(tag_map, 0, bits * sizeof(unsigned long));
+ memset(tag_map, 0, nr_ulongs * sizeof(unsigned long));
tags->max_depth = depth;
- tags->real_max_depth = bits * BITS_PER_LONG;
tags->tag_index = tag_index;
tags->tag_map = tag_map;
- /*
- * set the upper bits if the depth isn't a multiple of the word size
- */
- for (i = depth; i < bits * BLK_TAGS_PER_LONG; i++)
- __set_bit(i, tag_map);
-
return 0;
fail:
kfree(tag_index);
@@ -870,32 +865,24 @@ int blk_queue_resize_tags(request_queue_t *q, int new_depth)
struct blk_queue_tag *bqt = q->queue_tags;
struct request **tag_index;
unsigned long *tag_map;
- int bits, max_depth;
+ int max_depth, nr_ulongs;
if (!bqt)
return -ENXIO;
/*
- * don't bother sizing down
- */
- if (new_depth <= bqt->real_max_depth) {
- bqt->max_depth = new_depth;
- return 0;
- }
-
- /*
* save the old state info, so we can copy it back
*/
tag_index = bqt->tag_index;
tag_map = bqt->tag_map;
- max_depth = bqt->real_max_depth;
+ max_depth = bqt->max_depth;
if (init_tag_map(q, bqt, new_depth))
return -ENOMEM;
memcpy(bqt->tag_index, tag_index, max_depth * sizeof(struct request *));
- bits = max_depth / BLK_TAGS_PER_LONG;
- memcpy(bqt->tag_map, tag_map, bits * sizeof(unsigned long));
+ nr_ulongs = ALIGN(max_depth, BITS_PER_LONG) / BITS_PER_LONG;
+ memcpy(bqt->tag_map, tag_map, nr_ulongs * sizeof(unsigned long));
kfree(tag_index);
kfree(tag_map);
@@ -925,11 +912,16 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq)
BUG_ON(tag == -1);
- if (unlikely(tag >= bqt->real_max_depth))
+ if (unlikely(tag >= bqt->max_depth))
+ /*
+ * This can happen after tag depth has been reduced.
+ * FIXME: how about a warning or info message here?
+ */
return;
if (unlikely(!__test_and_clear_bit(tag, bqt->tag_map))) {
- printk("attempt to clear non-busy tag (%d)\n", tag);
+ printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n",
+ __FUNCTION__, tag);
return;
}
@@ -938,7 +930,8 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq)
rq->tag = -1;
if (unlikely(bqt->tag_index[tag] == NULL))
- printk("tag %d is missing\n", tag);
+ printk(KERN_ERR "%s: tag %d is missing\n",
+ __FUNCTION__, tag);
bqt->tag_index[tag] = NULL;
bqt->busy--;
@@ -967,24 +960,20 @@ EXPORT_SYMBOL(blk_queue_end_tag);
int blk_queue_start_tag(request_queue_t *q, struct request *rq)
{
struct blk_queue_tag *bqt = q->queue_tags;
- unsigned long *map = bqt->tag_map;
- int tag = 0;
+ int tag;
if (unlikely((rq->flags & REQ_QUEUED))) {
printk(KERN_ERR
- "request %p for device [%s] already tagged %d",
- rq, rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->tag);
+ "%s: request %p for device [%s] already tagged %d",
+ __FUNCTION__, rq,
+ rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->tag);
BUG();
}
- for (map = bqt->tag_map; *map == -1UL; map++) {
- tag += BLK_TAGS_PER_LONG;
-
- if (tag >= bqt->max_depth)
- return 1;
- }
+ tag = find_first_zero_bit(bqt->tag_map, bqt->max_depth);
+ if (tag >= bqt->max_depth)
+ return 1;
- tag += ffz(*map);
__set_bit(tag, bqt->tag_map);
rq->flags |= REQ_QUEUED;
@@ -1020,7 +1009,8 @@ void blk_queue_invalidate_tags(request_queue_t *q)
rq = list_entry_rq(tmp);
if (rq->tag == -1) {
- printk("bad tag found on list\n");
+ printk(KERN_ERR
+ "%s: bad tag found on list\n", __FUNCTION__);
list_del_init(&rq->queuelist);
rq->flags &= ~REQ_QUEUED;
} else
@@ -1148,7 +1138,7 @@ new_hw_segment:
}
-int blk_phys_contig_segment(request_queue_t *q, struct bio *bio,
+static int blk_phys_contig_segment(request_queue_t *q, struct bio *bio,
struct bio *nxt)
{
if (!(q->queue_flags & (1 << QUEUE_FLAG_CLUSTER)))
@@ -1169,9 +1159,7 @@ int blk_phys_contig_segment(request_queue_t *q, struct bio *bio,
return 0;
}
-EXPORT_SYMBOL(blk_phys_contig_segment);
-
-int blk_hw_contig_segment(request_queue_t *q, struct bio *bio,
+static int blk_hw_contig_segment(request_queue_t *q, struct bio *bio,
struct bio *nxt)
{
if (unlikely(!bio_flagged(bio, BIO_SEG_VALID)))
@@ -1187,8 +1175,6 @@ int blk_hw_contig_segment(request_queue_t *q, struct bio *bio,
return 1;
}
-EXPORT_SYMBOL(blk_hw_contig_segment);
-
/*
* map a request to scatterlist, return number of sg entries setup. Caller
* must make sure sg can hold rq->nr_phys_segments entries
@@ -1358,8 +1344,8 @@ static int ll_front_merge_fn(request_queue_t *q, struct request *req,
static int ll_merge_requests_fn(request_queue_t *q, struct request *req,
struct request *next)
{
- int total_phys_segments = req->nr_phys_segments +next->nr_phys_segments;
- int total_hw_segments = req->nr_hw_segments + next->nr_hw_segments;
+ int total_phys_segments;
+ int total_hw_segments;
/*
* First check if the either of the requests are re-queued
@@ -1369,7 +1355,7 @@ static int ll_merge_requests_fn(request_queue_t *q, struct request *req,
return 0;
/*
- * Will it become to large?
+ * Will it become too large?
*/
if ((req->nr_sectors + next->nr_sectors) > q->max_sectors)
return 0;
@@ -1450,7 +1436,7 @@ EXPORT_SYMBOL(blk_remove_plug);
*/
void __generic_unplug_device(request_queue_t *q)
{
- if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags))
+ if (unlikely(test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)))
return;
if (!blk_remove_plug(q))
@@ -1645,7 +1631,8 @@ static int blk_init_free_list(request_queue_t *q)
init_waitqueue_head(&rl->wait[WRITE]);
init_waitqueue_head(&rl->drain);
- rl->rq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, request_cachep);
+ rl->rq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
+ mempool_free_slab, request_cachep, q->node);
if (!rl->rq_pool)
return -ENOMEM;
@@ -1657,8 +1644,15 @@ static int __make_request(request_queue_t *, struct bio *);
request_queue_t *blk_alloc_queue(int gfp_mask)
{
- request_queue_t *q = kmem_cache_alloc(requestq_cachep, gfp_mask);
+ return blk_alloc_queue_node(gfp_mask, -1);
+}
+EXPORT_SYMBOL(blk_alloc_queue);
+request_queue_t *blk_alloc_queue_node(int gfp_mask, int node_id)
+{
+ request_queue_t *q;
+
+ q = kmem_cache_alloc_node(requestq_cachep, gfp_mask, node_id);
if (!q)
return NULL;
@@ -1671,8 +1665,7 @@ request_queue_t *blk_alloc_queue(int gfp_mask)
return q;
}
-
-EXPORT_SYMBOL(blk_alloc_queue);
+EXPORT_SYMBOL(blk_alloc_queue_node);
/**
* blk_init_queue - prepare a request queue for use with a block device
@@ -1705,13 +1698,22 @@ EXPORT_SYMBOL(blk_alloc_queue);
* blk_init_queue() must be paired with a blk_cleanup_queue() call
* when the block device is deactivated (such as at module unload).
**/
+
request_queue_t *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock)
{
- request_queue_t *q = blk_alloc_queue(GFP_KERNEL);
+ return blk_init_queue_node(rfn, lock, -1);
+}
+EXPORT_SYMBOL(blk_init_queue);
+
+request_queue_t *
+blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
+{
+ request_queue_t *q = blk_alloc_queue_node(GFP_KERNEL, node_id);
if (!q)
return NULL;
+ q->node = node_id;
if (blk_init_free_list(q))
goto out_init;
@@ -1754,12 +1756,11 @@ out_init:
kmem_cache_free(requestq_cachep, q);
return NULL;
}
-
-EXPORT_SYMBOL(blk_init_queue);
+EXPORT_SYMBOL(blk_init_queue_node);
int blk_get_queue(request_queue_t *q)
{
- if (!test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)) {
+ if (likely(!test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) {
atomic_inc(&q->refcnt);
return 0;
}
@@ -1821,7 +1822,7 @@ static inline int ioc_batching(request_queue_t *q, struct io_context *ioc)
* is the behaviour we want though - once it gets a wakeup it should be given
* a nice run.
*/
-void ioc_set_batching(request_queue_t *q, struct io_context *ioc)
+static void ioc_set_batching(request_queue_t *q, struct io_context *ioc)
{
if (!ioc || ioc_batching(q, ioc))
return;
@@ -1838,7 +1839,6 @@ static void __freed_request(request_queue_t *q, int rw)
clear_queue_congested(q, rw);
if (rl->count[rw] + 1 <= q->nr_requests) {
- smp_mb();
if (waitqueue_active(&rl->wait[rw]))
wake_up(&rl->wait[rw]);
@@ -1966,7 +1966,6 @@ static struct request *get_request_wait(request_queue_t *q, int rw)
DEFINE_WAIT(wait);
struct request *rq;
- generic_unplug_device(q);
do {
struct request_list *rl = &q->rq;
@@ -1978,6 +1977,7 @@ static struct request *get_request_wait(request_queue_t *q, int rw)
if (!rq) {
struct io_context *ioc;
+ generic_unplug_device(q);
io_schedule();
/*
@@ -2038,7 +2038,6 @@ EXPORT_SYMBOL(blk_requeue_request);
* @rq: request to be inserted
* @at_head: insert request at head or tail of queue
* @data: private data
- * @reinsert: true if request it a reinsertion of previously processed one
*
* Description:
* Many block devices need to execute commands asynchronously, so they don't
@@ -2053,8 +2052,9 @@ EXPORT_SYMBOL(blk_requeue_request);
* host that is unable to accept a particular command.
*/
void blk_insert_request(request_queue_t *q, struct request *rq,
- int at_head, void *data, int reinsert)
+ int at_head, void *data)
{
+ int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
unsigned long flags;
/*
@@ -2071,20 +2071,12 @@ void blk_insert_request(request_queue_t *q, struct request *rq,
/*
* If command is tagged, release the tag
*/
- if (reinsert)
- blk_requeue_request(q, rq);
- else {
- int where = ELEVATOR_INSERT_BACK;
-
- if (at_head)
- where = ELEVATOR_INSERT_FRONT;
+ if (blk_rq_tagged(rq))
+ blk_queue_end_tag(q, rq);
- if (blk_rq_tagged(rq))
- blk_queue_end_tag(q, rq);
+ drive_stat_acct(rq, rq->nr_sectors, 1);
+ __elv_add_request(q, rq, where, 0);
- drive_stat_acct(rq, rq->nr_sectors, 1);
- __elv_add_request(q, rq, where, 0);
- }
if (blk_queue_plugged(q))
__generic_unplug_device(q);
else
@@ -2259,45 +2251,7 @@ int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector)
EXPORT_SYMBOL(blkdev_issue_flush);
-/**
- * blkdev_scsi_issue_flush_fn - issue flush for SCSI devices
- * @q: device queue
- * @disk: gendisk
- * @error_sector: error offset
- *
- * Description:
- * Devices understanding the SCSI command set, can use this function as
- * a helper for issuing a cache flush. Note: driver is required to store
- * the error offset (in case of error flushing) in ->sector of struct
- * request.
- */
-int blkdev_scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
- sector_t *error_sector)
-{
- struct request *rq = blk_get_request(q, WRITE, __GFP_WAIT);
- int ret;
-
- rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER;
- rq->sector = 0;
- memset(rq->cmd, 0, sizeof(rq->cmd));
- rq->cmd[0] = 0x35;
- rq->cmd_len = 12;
- rq->data = NULL;
- rq->data_len = 0;
- rq->timeout = 60 * HZ;
-
- ret = blk_execute_rq(q, disk, rq);
-
- if (ret && error_sector)
- *error_sector = rq->sector;
-
- blk_put_request(rq);
- return ret;
-}
-
-EXPORT_SYMBOL(blkdev_scsi_issue_flush_fn);
-
-void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
+static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
{
int rw = rq_data_dir(rq);
@@ -2556,16 +2510,6 @@ void blk_attempt_remerge(request_queue_t *q, struct request *rq)
EXPORT_SYMBOL(blk_attempt_remerge);
-/*
- * Non-locking blk_attempt_remerge variant.
- */
-void __blk_attempt_remerge(request_queue_t *q, struct request *rq)
-{
- attempt_back_merge(q, rq);
-}
-
-EXPORT_SYMBOL(__blk_attempt_remerge);
-
static int __make_request(request_queue_t *q, struct bio *bio)
{
struct request *req, *freereq = NULL;
@@ -2589,7 +2533,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
spin_lock_prefetch(q->queue_lock);
barrier = bio_barrier(bio);
- if (barrier && (q->ordered == QUEUE_ORDERED_NONE)) {
+ if (unlikely(barrier) && (q->ordered == QUEUE_ORDERED_NONE)) {
err = -EOPNOTSUPP;
goto end_io;
}
@@ -2690,7 +2634,7 @@ get_rq:
/*
* REQ_BARRIER implies no merging, but lets make it explicit
*/
- if (barrier)
+ if (unlikely(barrier))
req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE);
req->errors = 0;
@@ -2814,7 +2758,7 @@ static inline void block_wait_queue_running(request_queue_t *q)
{
DEFINE_WAIT(wait);
- while (test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)) {
+ while (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags))) {
struct request_list *rl = &q->rq;
prepare_to_wait_exclusive(&rl->drain, &wait,
@@ -2923,7 +2867,7 @@ end_io:
goto end_io;
}
- if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))
+ if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
goto end_io;
block_wait_queue_running(q);
@@ -2976,7 +2920,7 @@ void submit_bio(int rw, struct bio *bio)
EXPORT_SYMBOL(submit_bio);
-void blk_recalc_rq_segments(struct request *rq)
+static void blk_recalc_rq_segments(struct request *rq)
{
struct bio *bio, *prevbio = NULL;
int nr_phys_segs, nr_hw_segs;
@@ -3018,7 +2962,7 @@ void blk_recalc_rq_segments(struct request *rq)
rq->nr_hw_segments = nr_hw_segs;
}
-void blk_recalc_rq_sectors(struct request *rq, int nsect)
+static void blk_recalc_rq_sectors(struct request *rq, int nsect)
{
if (blk_fs_request(rq)) {
rq->hard_sector += nsect;
@@ -3582,7 +3526,7 @@ queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
q = container_of(kobj, struct request_queue, kobj);
if (!entry->show)
- return 0;
+ return -EIO;
return entry->show(q, page);
}
@@ -3596,7 +3540,7 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
q = container_of(kobj, struct request_queue, kobj);
if (!entry->store)
- return -EINVAL;
+ return -EIO;
return entry->store(q, page, length);
}
@@ -3606,7 +3550,7 @@ static struct sysfs_ops queue_sysfs_ops = {
.store = queue_attr_store,
};
-struct kobj_type queue_ktype = {
+static struct kobj_type queue_ktype = {
.sysfs_ops = &queue_sysfs_ops,
.default_attrs = default_attrs,
};
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 6f011d0d8e9..b35e08876dd 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -472,17 +472,11 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
*/
static void loop_add_bio(struct loop_device *lo, struct bio *bio)
{
- unsigned long flags;
-
- spin_lock_irqsave(&lo->lo_lock, flags);
if (lo->lo_biotail) {
lo->lo_biotail->bi_next = bio;
lo->lo_biotail = bio;
} else
lo->lo_bio = lo->lo_biotail = bio;
- spin_unlock_irqrestore(&lo->lo_lock, flags);
-
- up(&lo->lo_bh_mutex);
}
/*
@@ -492,14 +486,12 @@ static struct bio *loop_get_bio(struct loop_device *lo)
{
struct bio *bio;
- spin_lock_irq(&lo->lo_lock);
if ((bio = lo->lo_bio)) {
if (bio == lo->lo_biotail)
lo->lo_biotail = NULL;
lo->lo_bio = bio->bi_next;
bio->bi_next = NULL;
}
- spin_unlock_irq(&lo->lo_lock);
return bio;
}
@@ -509,35 +501,28 @@ static int loop_make_request(request_queue_t *q, struct bio *old_bio)
struct loop_device *lo = q->queuedata;
int rw = bio_rw(old_bio);
- if (!lo)
- goto out;
+ if (rw == READA)
+ rw = READ;
+
+ BUG_ON(!lo || (rw != READ && rw != WRITE));
spin_lock_irq(&lo->lo_lock);
if (lo->lo_state != Lo_bound)
- goto inactive;
- atomic_inc(&lo->lo_pending);
- spin_unlock_irq(&lo->lo_lock);
-
- if (rw == WRITE) {
- if (lo->lo_flags & LO_FLAGS_READ_ONLY)
- goto err;
- } else if (rw == READA) {
- rw = READ;
- } else if (rw != READ) {
- printk(KERN_ERR "loop: unknown command (%x)\n", rw);
- goto err;
- }
+ goto out;
+ if (unlikely(rw == WRITE && (lo->lo_flags & LO_FLAGS_READ_ONLY)))
+ goto out;
+ lo->lo_pending++;
loop_add_bio(lo, old_bio);
+ spin_unlock_irq(&lo->lo_lock);
+ up(&lo->lo_bh_mutex);
return 0;
-err:
- if (atomic_dec_and_test(&lo->lo_pending))
- up(&lo->lo_bh_mutex);
+
out:
+ if (lo->lo_pending == 0)
+ up(&lo->lo_bh_mutex);
+ spin_unlock_irq(&lo->lo_lock);
bio_io_error(old_bio, old_bio->bi_size);
return 0;
-inactive:
- spin_unlock_irq(&lo->lo_lock);
- goto out;
}
/*
@@ -560,13 +545,11 @@ static void do_loop_switch(struct loop_device *, struct switch_request *);
static inline void loop_handle_bio(struct loop_device *lo, struct bio *bio)
{
- int ret;
-
if (unlikely(!bio->bi_bdev)) {
do_loop_switch(lo, bio->bi_private);
bio_put(bio);
} else {
- ret = do_bio_filebacked(lo, bio);
+ int ret = do_bio_filebacked(lo, bio);
bio_endio(bio, bio->bi_size, ret);
}
}
@@ -594,7 +577,7 @@ static int loop_thread(void *data)
set_user_nice(current, -20);
lo->lo_state = Lo_bound;
- atomic_inc(&lo->lo_pending);
+ lo->lo_pending = 1;
/*
* up sem, we are running
@@ -602,26 +585,37 @@ static int loop_thread(void *data)
up(&lo->lo_sem);
for (;;) {
- down_interruptible(&lo->lo_bh_mutex);
+ int pending;
+
/*
- * could be upped because of tear-down, not because of
- * pending work
+ * interruptible just to not contribute to load avg
*/
- if (!atomic_read(&lo->lo_pending))
+ if (down_interruptible(&lo->lo_bh_mutex))
+ continue;
+
+ spin_lock_irq(&lo->lo_lock);
+
+ /*
+ * could be upped because of tear-down, not pending work
+ */
+ if (unlikely(!lo->lo_pending)) {
+ spin_unlock_irq(&lo->lo_lock);
break;
+ }
bio = loop_get_bio(lo);
- if (!bio) {
- printk("loop: missing bio\n");
- continue;
- }
+ lo->lo_pending--;
+ pending = lo->lo_pending;
+ spin_unlock_irq(&lo->lo_lock);
+
+ BUG_ON(!bio);
loop_handle_bio(lo, bio);
/*
* upped both for pending work and tear-down, lo_pending
* will hit zero then
*/
- if (atomic_dec_and_test(&lo->lo_pending))
+ if (unlikely(!pending))
break;
}
@@ -900,7 +894,8 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
spin_lock_irq(&lo->lo_lock);
lo->lo_state = Lo_rundown;
- if (atomic_dec_and_test(&lo->lo_pending))
+ lo->lo_pending--;
+ if (!lo->lo_pending)
up(&lo->lo_bh_mutex);
spin_unlock_irq(&lo->lo_lock);
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 202a5a74ad3..fa49d62626b 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -723,7 +723,7 @@ static int pd_special_command(struct pd_unit *disk,
rq.ref_count = 1;
rq.waiting = &wait;
rq.end_io = blk_end_sync_rq;
- blk_insert_request(disk->gd->queue, &rq, 0, func, 0);
+ blk_insert_request(disk->gd->queue, &rq, 0, func);
wait_for_completion(&wait);
rq.waiting = NULL;
if (rq.errors)
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index dbeb107bb97..84d8e291ed9 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -222,7 +222,7 @@ static int pg_identify(struct pg *dev, int log);
static char pg_scratch[512]; /* scratch block buffer */
-static struct class_simple *pg_class;
+static struct class *pg_class;
/* kernel glue structures */
@@ -666,7 +666,7 @@ static int __init pg_init(void)
err = -1;
goto out;
}
- pg_class = class_simple_create(THIS_MODULE, "pg");
+ pg_class = class_create(THIS_MODULE, "pg");
if (IS_ERR(pg_class)) {
err = PTR_ERR(pg_class);
goto out_chrdev;
@@ -675,7 +675,7 @@ static int __init pg_init(void)
for (unit = 0; unit < PG_UNITS; unit++) {
struct pg *dev = &devices[unit];
if (dev->present) {
- class_simple_device_add(pg_class, MKDEV(major, unit),
+ class_device_create(pg_class, MKDEV(major, unit),
NULL, "pg%u", unit);
err = devfs_mk_cdev(MKDEV(major, unit),
S_IFCHR | S_IRUSR | S_IWUSR, "pg/%u",
@@ -688,8 +688,8 @@ static int __init pg_init(void)
goto out;
out_class:
- class_simple_device_remove(MKDEV(major, unit));
- class_simple_destroy(pg_class);
+ class_device_destroy(pg_class, MKDEV(major, unit));
+ class_destroy(pg_class);
out_chrdev:
unregister_chrdev(major, "pg");
out:
@@ -703,11 +703,11 @@ static void __exit pg_exit(void)
for (unit = 0; unit < PG_UNITS; unit++) {
struct pg *dev = &devices[unit];
if (dev->present) {
- class_simple_device_remove(MKDEV(major, unit));
+ class_device_destroy(pg_class, MKDEV(major, unit));
devfs_remove("pg/%u", unit);
}
}
- class_simple_destroy(pg_class);
+ class_destroy(pg_class);
devfs_remove("pg");
unregister_chrdev(major, name);
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 8fbd6922fe0..5fe8ee86f09 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -242,7 +242,7 @@ static struct file_operations pt_fops = {
};
/* sysfs class support */
-static struct class_simple *pt_class;
+static struct class *pt_class;
static inline int status_reg(struct pi_adapter *pi)
{
@@ -963,7 +963,7 @@ static int __init pt_init(void)
err = -1;
goto out;
}
- pt_class = class_simple_create(THIS_MODULE, "pt");
+ pt_class = class_create(THIS_MODULE, "pt");
if (IS_ERR(pt_class)) {
err = PTR_ERR(pt_class);
goto out_chrdev;
@@ -972,29 +972,29 @@ static int __init pt_init(void)
devfs_mk_dir("pt");
for (unit = 0; unit < PT_UNITS; unit++)
if (pt[unit].present) {
- class_simple_device_add(pt_class, MKDEV(major, unit),
+ class_device_create(pt_class, MKDEV(major, unit),
NULL, "pt%d", unit);
err = devfs_mk_cdev(MKDEV(major, unit),
S_IFCHR | S_IRUSR | S_IWUSR,
"pt/%d", unit);
if (err) {
- class_simple_device_remove(MKDEV(major, unit));
+ class_device_destroy(pt_class, MKDEV(major, unit));
goto out_class;
}
- class_simple_device_add(pt_class, MKDEV(major, unit + 128),
+ class_device_create(pt_class, MKDEV(major, unit + 128),
NULL, "pt%dn", unit);
err = devfs_mk_cdev(MKDEV(major, unit + 128),
S_IFCHR | S_IRUSR | S_IWUSR,
"pt/%dn", unit);
if (err) {
- class_simple_device_remove(MKDEV(major, unit + 128));
+ class_device_destroy(pt_class, MKDEV(major, unit + 128));
goto out_class;
}
}
goto out;
out_class:
- class_simple_destroy(pt_class);
+ class_destroy(pt_class);
out_chrdev:
unregister_chrdev(major, "pt");
out:
@@ -1006,12 +1006,12 @@ static void __exit pt_exit(void)
int unit;
for (unit = 0; unit < PT_UNITS; unit++)
if (pt[unit].present) {
- class_simple_device_remove(MKDEV(major, unit));
+ class_device_destroy(pt_class, MKDEV(major, unit));
devfs_remove("pt/%d", unit);
- class_simple_device_remove(MKDEV(major, unit + 128));
+ class_device_destroy(pt_class, MKDEV(major, unit + 128));
devfs_remove("pt/%dn", unit);
}
- class_simple_destroy(pt_class);
+ class_destroy(pt_class);
devfs_remove("pt");
unregister_chrdev(major, name);
for (unit = 0; unit < PT_UNITS; unit++)
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index bc56770bcc9..7b838342f0a 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -467,14 +467,12 @@ static int pkt_set_speed(struct pktcdvd_device *pd, unsigned write_speed, unsign
* Queue a bio for processing by the low-level CD device. Must be called
* from process context.
*/
-static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio, int high_prio_read)
+static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio)
{
spin_lock(&pd->iosched.lock);
if (bio_data_dir(bio) == READ) {
pkt_add_list_last(bio, &pd->iosched.read_queue,
&pd->iosched.read_queue_tail);
- if (high_prio_read)
- pd->iosched.high_prio_read = 1;
} else {
pkt_add_list_last(bio, &pd->iosched.write_queue,
&pd->iosched.write_queue_tail);
@@ -490,15 +488,16 @@ static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio, int high_p
* requirements for CDRW drives:
* - A cache flush command must be inserted before a read request if the
* previous request was a write.
- * - Switching between reading and writing is slow, so don't it more often
+ * - Switching between reading and writing is slow, so don't do it more often
* than necessary.
+ * - Optimize for throughput at the expense of latency. This means that streaming
+ * writes will never be interrupted by a read, but if the drive has to seek
+ * before the next write, switch to reading instead if there are any pending
+ * read requests.
* - Set the read speed according to current usage pattern. When only reading
* from the device, it's best to use the highest possible read speed, but
* when switching often between reading and writing, it's better to have the
* same read and write speeds.
- * - Reads originating from user space should have higher priority than reads
- * originating from pkt_gather_data, because some process is usually waiting
- * on reads of the first kind.
*/
static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
{
@@ -512,21 +511,24 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
for (;;) {
struct bio *bio;
- int reads_queued, writes_queued, high_prio_read;
+ int reads_queued, writes_queued;
spin_lock(&pd->iosched.lock);
reads_queued = (pd->iosched.read_queue != NULL);
writes_queued = (pd->iosched.write_queue != NULL);
- if (!reads_queued)
- pd->iosched.high_prio_read = 0;
- high_prio_read = pd->iosched.high_prio_read;
spin_unlock(&pd->iosched.lock);
if (!reads_queued && !writes_queued)
break;
if (pd->iosched.writing) {
- if (high_prio_read || (!writes_queued && reads_queued)) {
+ int need_write_seek = 1;
+ spin_lock(&pd->iosched.lock);
+ bio = pd->iosched.write_queue;
+ spin_unlock(&pd->iosched.lock);
+ if (bio && (bio->bi_sector == pd->iosched.last_write))
+ need_write_seek = 0;
+ if (need_write_seek && reads_queued) {
if (atomic_read(&pd->cdrw.pending_bios) > 0) {
VPRINTK("pktcdvd: write, waiting\n");
break;
@@ -559,8 +561,10 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
if (bio_data_dir(bio) == READ)
pd->iosched.successive_reads += bio->bi_size >> 10;
- else
+ else {
pd->iosched.successive_reads = 0;
+ pd->iosched.last_write = bio->bi_sector + bio_sectors(bio);
+ }
if (pd->iosched.successive_reads >= HI_SPEED_SWITCH) {
if (pd->read_speed == pd->write_speed) {
pd->read_speed = MAX_SPEED;
@@ -765,7 +769,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
atomic_inc(&pkt->io_wait);
bio->bi_rw = READ;
- pkt_queue_bio(pd, bio, 0);
+ pkt_queue_bio(pd, bio);
frames_read++;
}
@@ -1062,7 +1066,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
atomic_set(&pkt->io_wait, 1);
pkt->w_bio->bi_rw = WRITE;
- pkt_queue_bio(pd, pkt->w_bio, 0);
+ pkt_queue_bio(pd, pkt->w_bio);
}
static void pkt_finish_packet(struct packet_data *pkt, int uptodate)
@@ -1247,8 +1251,7 @@ static int kcdrwd(void *foobar)
VPRINTK("kcdrwd: wake up\n");
/* make swsusp happy with our thread */
- if (current->flags & PF_FREEZE)
- refrigerator(PF_FREEZE);
+ try_to_freeze();
list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) {
if (!pkt->sleep_time)
@@ -2120,7 +2123,7 @@ static int pkt_make_request(request_queue_t *q, struct bio *bio)
cloned_bio->bi_private = psd;
cloned_bio->bi_end_io = pkt_end_io_read_cloned;
pd->stats.secs_r += bio->bi_size >> 9;
- pkt_queue_bio(pd, cloned_bio, 1);
+ pkt_queue_bio(pd, cloned_bio);
return 0;
}
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index 797f5988c2b..5ed3a637945 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -614,7 +614,7 @@ static int carm_array_info (struct carm_host *host, unsigned int array_idx)
spin_unlock_irq(&host->lock);
DPRINTK("blk_insert_request, tag == %u\n", idx);
- blk_insert_request(host->oob_q, crq->rq, 1, crq, 0);
+ blk_insert_request(host->oob_q, crq->rq, 1, crq);
return 0;
@@ -653,7 +653,7 @@ static int carm_send_special (struct carm_host *host, carm_sspc_t func)
crq->msg_bucket = (u32) rc;
DPRINTK("blk_insert_request, tag == %u\n", idx);
- blk_insert_request(host->oob_q, crq->rq, 1, crq, 0);
+ blk_insert_request(host->oob_q, crq->rq, 1, crq);
return 0;
}
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index ce42889f98f..685f061e69b 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -8,13 +8,12 @@
* and is not licensed separately. See file COPYING for details.
*
* TODO (sorted by decreasing priority)
+ * -- Kill first_open (Al Viro fixed the block layer now)
* -- Do resets with usb_device_reset (needs a thread context, use khubd)
* -- set readonly flag for CDs, set removable flag for CF readers
* -- do inquiry and verify we got a disk and not a tape (for LUN mismatch)
- * -- support pphaneuf's SDDR-75 with two LUNs (also broken capacity...)
* -- special case some senses, e.g. 3a/0 -> no media present, reduce retries
* -- verify the 13 conditions and do bulk resets
- * -- normal pool of commands instead of cmdv[]?
* -- kill last_pipe and simply do two-state clearing on both pipes
* -- verify protocol (bulk) from USB descriptors (maybe...)
* -- highmem and sg
@@ -49,7 +48,14 @@
#define US_SC_SCSI 0x06 /* Transparent */
/*
+ * This many LUNs per USB device.
+ * Every one of them takes a host, see UB_MAX_HOSTS.
*/
+#define UB_MAX_LUNS 9
+
+/*
+ */
+
#define UB_MINORS_PER_MAJOR 8
#define UB_MAX_CDB_SIZE 16 /* Corresponds to Bulk */
@@ -65,7 +71,7 @@ struct bulk_cb_wrap {
u32 Tag; /* unique per command id */
__le32 DataTransferLength; /* size of data */
u8 Flags; /* direction in bit 0 */
- u8 Lun; /* LUN normally 0 */
+ u8 Lun; /* LUN */
u8 Length; /* of of the CDB */
u8 CDB[UB_MAX_CDB_SIZE]; /* max command */
};
@@ -168,6 +174,7 @@ struct ub_scsi_cmd {
unsigned int len; /* Requested length */
// struct scatterlist sgv[UB_MAX_REQ_SG];
+ struct ub_lun *lun;
void (*done)(struct ub_dev *, struct ub_scsi_cmd *);
void *back;
};
@@ -252,25 +259,47 @@ struct ub_scsi_cmd_queue {
};
/*
- * The UB device instance.
+ * The block device instance (one per LUN).
+ */
+struct ub_lun {
+ struct ub_dev *udev;
+ struct list_head link;
+ struct gendisk *disk;
+ int id; /* Host index */
+ int num; /* LUN number */
+ char name[16];
+
+ int changed; /* Media was changed */
+ int removable;
+ int readonly;
+ int first_open; /* Kludge. See ub_bd_open. */
+
+ /* Use Ingo's mempool if or when we have more than one command. */
+ /*
+ * Currently we never need more than one command for the whole device.
+ * However, giving every LUN a command is a cheap and automatic way
+ * to enforce fairness between them.
+ */
+ int cmda[1];
+ struct ub_scsi_cmd cmdv[1];
+
+ struct ub_capacity capacity;
+};
+
+/*
+ * The USB device instance.
*/
struct ub_dev {
spinlock_t lock;
- int id; /* Number among ub's */
atomic_t poison; /* The USB device is disconnected */
int openc; /* protected by ub_lock! */
/* kref is too implicit for our taste */
unsigned int tagcnt;
- int changed; /* Media was changed */
- int removable;
- int readonly;
- int first_open; /* Kludge. See ub_bd_open. */
- char name[8];
+ char name[12];
struct usb_device *dev;
struct usb_interface *intf;
- struct ub_capacity capacity;
- struct gendisk *disk;
+ struct list_head luns;
unsigned int send_bulk_pipe; /* cached pipe values */
unsigned int recv_bulk_pipe;
@@ -279,10 +308,6 @@ struct ub_dev {
struct tasklet_struct tasklet;
- /* XXX Use Ingo's mempool (once we have more than one) */
- int cmda[1];
- struct ub_scsi_cmd cmdv[1];
-
struct ub_scsi_cmd_queue cmd_queue;
struct ub_scsi_cmd top_rqs_cmd; /* REQUEST SENSE */
unsigned char top_sense[UB_SENSE_SIZE];
@@ -301,9 +326,9 @@ struct ub_dev {
/*
*/
static void ub_cleanup(struct ub_dev *sc);
-static int ub_bd_rq_fn_1(struct ub_dev *sc, struct request *rq);
-static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
- struct request *rq);
+static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq);
+static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
+ struct ub_scsi_cmd *cmd, struct request *rq);
static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
struct request *rq);
static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
@@ -320,8 +345,10 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
int stalled_pipe);
static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd);
-static int ub_sync_tur(struct ub_dev *sc);
-static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret);
+static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun);
+static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
+ struct ub_capacity *ret);
+static int ub_probe_lun(struct ub_dev *sc, int lnum);
/*
*/
@@ -342,6 +369,7 @@ MODULE_DEVICE_TABLE(usb, ub_usb_ids);
*/
#define UB_MAX_HOSTS 26
static char ub_hostv[UB_MAX_HOSTS];
+
static DEFINE_SPINLOCK(ub_lock); /* Locks globals and ->openc */
/*
@@ -402,10 +430,12 @@ static void ub_cmdtr_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
}
}
-static ssize_t ub_diag_show(struct device *dev, char *page)
+static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, char *page)
{
struct usb_interface *intf;
struct ub_dev *sc;
+ struct list_head *p;
+ struct ub_lun *lun;
int cnt;
unsigned long flags;
int nc, nh;
@@ -421,9 +451,15 @@ static ssize_t ub_diag_show(struct device *dev, char *page)
spin_lock_irqsave(&sc->lock, flags);
cnt += sprintf(page + cnt,
- "qlen %d qmax %d changed %d removable %d readonly %d\n",
- sc->cmd_queue.qlen, sc->cmd_queue.qmax,
- sc->changed, sc->removable, sc->readonly);
+ "qlen %d qmax %d\n",
+ sc->cmd_queue.qlen, sc->cmd_queue.qmax);
+
+ list_for_each (p, &sc->luns) {
+ lun = list_entry(p, struct ub_lun, link);
+ cnt += sprintf(page + cnt,
+ "lun %u changed %d removable %d readonly %d\n",
+ lun->num, lun->changed, lun->removable, lun->readonly);
+ }
if ((nc = sc->tr.cur + 1) == SCMD_TRACE_SZ) nc = 0;
for (j = 0; j < SCMD_TRACE_SZ; j++) {
@@ -523,53 +559,63 @@ static void ub_put(struct ub_dev *sc)
*/
static void ub_cleanup(struct ub_dev *sc)
{
+ struct list_head *p;
+ struct ub_lun *lun;
request_queue_t *q;
- /* I don't think queue can be NULL. But... Stolen from sx8.c */
- if ((q = sc->disk->queue) != NULL)
- blk_cleanup_queue(q);
+ while (!list_empty(&sc->luns)) {
+ p = sc->luns.next;
+ lun = list_entry(p, struct ub_lun, link);
+ list_del(p);
- /*
- * If we zero disk->private_data BEFORE put_disk, we have to check
- * for NULL all over the place in open, release, check_media and
- * revalidate, because the block level semaphore is well inside the
- * put_disk. But we cannot zero after the call, because *disk is gone.
- * The sd.c is blatantly racy in this area.
- */
- /* disk->private_data = NULL; */
- put_disk(sc->disk);
- sc->disk = NULL;
+ /* I don't think queue can be NULL. But... Stolen from sx8.c */
+ if ((q = lun->disk->queue) != NULL)
+ blk_cleanup_queue(q);
+ /*
+ * If we zero disk->private_data BEFORE put_disk, we have
+ * to check for NULL all over the place in open, release,
+ * check_media and revalidate, because the block level
+ * semaphore is well inside the put_disk.
+ * But we cannot zero after the call, because *disk is gone.
+ * The sd.c is blatantly racy in this area.
+ */
+ /* disk->private_data = NULL; */
+ put_disk(lun->disk);
+ lun->disk = NULL;
+
+ ub_id_put(lun->id);
+ kfree(lun);
+ }
- ub_id_put(sc->id);
kfree(sc);
}
/*
* The "command allocator".
*/
-static struct ub_scsi_cmd *ub_get_cmd(struct ub_dev *sc)
+static struct ub_scsi_cmd *ub_get_cmd(struct ub_lun *lun)
{
struct ub_scsi_cmd *ret;
- if (sc->cmda[0])
+ if (lun->cmda[0])
return NULL;
- ret = &sc->cmdv[0];
- sc->cmda[0] = 1;
+ ret = &lun->cmdv[0];
+ lun->cmda[0] = 1;
return ret;
}
-static void ub_put_cmd(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+static void ub_put_cmd(struct ub_lun *lun, struct ub_scsi_cmd *cmd)
{
- if (cmd != &sc->cmdv[0]) {
+ if (cmd != &lun->cmdv[0]) {
printk(KERN_WARNING "%s: releasing a foreign cmd %p\n",
- sc->name, cmd);
+ lun->name, cmd);
return;
}
- if (!sc->cmda[0]) {
- printk(KERN_WARNING "%s: releasing a free cmd\n", sc->name);
+ if (!lun->cmda[0]) {
+ printk(KERN_WARNING "%s: releasing a free cmd\n", lun->name);
return;
}
- sc->cmda[0] = 0;
+ lun->cmda[0] = 0;
}
/*
@@ -630,29 +676,30 @@ static struct ub_scsi_cmd *ub_cmdq_pop(struct ub_dev *sc)
static void ub_bd_rq_fn(request_queue_t *q)
{
- struct ub_dev *sc = q->queuedata;
+ struct ub_lun *lun = q->queuedata;
struct request *rq;
while ((rq = elv_next_request(q)) != NULL) {
- if (ub_bd_rq_fn_1(sc, rq) != 0) {
+ if (ub_bd_rq_fn_1(lun, rq) != 0) {
blk_stop_queue(q);
break;
}
}
}
-static int ub_bd_rq_fn_1(struct ub_dev *sc, struct request *rq)
+static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq)
{
+ struct ub_dev *sc = lun->udev;
struct ub_scsi_cmd *cmd;
int rc;
- if (atomic_read(&sc->poison) || sc->changed) {
+ if (atomic_read(&sc->poison) || lun->changed) {
blkdev_dequeue_request(rq);
ub_end_rq(rq, 0);
return 0;
}
- if ((cmd = ub_get_cmd(sc)) == NULL)
+ if ((cmd = ub_get_cmd(lun)) == NULL)
return -1;
memset(cmd, 0, sizeof(struct ub_scsi_cmd));
@@ -661,32 +708,30 @@ static int ub_bd_rq_fn_1(struct ub_dev *sc, struct request *rq)
if (blk_pc_request(rq)) {
rc = ub_cmd_build_packet(sc, cmd, rq);
} else {
- rc = ub_cmd_build_block(sc, cmd, rq);
+ rc = ub_cmd_build_block(sc, lun, cmd, rq);
}
if (rc != 0) {
- ub_put_cmd(sc, cmd);
+ ub_put_cmd(lun, cmd);
ub_end_rq(rq, 0);
- blk_start_queue(sc->disk->queue);
return 0;
}
-
cmd->state = UB_CMDST_INIT;
+ cmd->lun = lun;
cmd->done = ub_rw_cmd_done;
cmd->back = rq;
cmd->tag = sc->tagcnt++;
if ((rc = ub_submit_scsi(sc, cmd)) != 0) {
- ub_put_cmd(sc, cmd);
+ ub_put_cmd(lun, cmd);
ub_end_rq(rq, 0);
- blk_start_queue(sc->disk->queue);
return 0;
}
return 0;
}
-static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
- struct request *rq)
+static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
+ struct ub_scsi_cmd *cmd, struct request *rq)
{
int ub_dir;
#if 0 /* We use rq->buffer for now */
@@ -707,7 +752,7 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
sg = &cmd->sgv[0];
n_elem = blk_rq_map_sg(q, rq, sg);
if (n_elem <= 0) {
- ub_put_cmd(sc, cmd);
+ ub_put_cmd(lun, cmd);
ub_end_rq(rq, 0);
blk_start_queue(q);
return 0; /* request with no s/g entries? */
@@ -716,7 +761,7 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
if (n_elem != 1) { /* Paranoia */
printk(KERN_WARNING "%s: request with %d segments\n",
sc->name, n_elem);
- ub_put_cmd(sc, cmd);
+ ub_put_cmd(lun, cmd);
ub_end_rq(rq, 0);
blk_start_queue(q);
return 0;
@@ -748,8 +793,8 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
* The call to blk_queue_hardsect_size() guarantees that request
* is aligned, but it is given in terms of 512 byte units, always.
*/
- block = rq->sector >> sc->capacity.bshift;
- nblks = rq->nr_sectors >> sc->capacity.bshift;
+ block = rq->sector >> lun->capacity.bshift;
+ nblks = rq->nr_sectors >> lun->capacity.bshift;
cmd->cdb[0] = (ub_dir == UB_DIR_READ)? READ_10: WRITE_10;
/* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */
@@ -803,7 +848,8 @@ static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
{
struct request *rq = cmd->back;
- struct gendisk *disk = sc->disk;
+ struct ub_lun *lun = cmd->lun;
+ struct gendisk *disk = lun->disk;
request_queue_t *q = disk->queue;
int uptodate;
@@ -818,7 +864,7 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
else
uptodate = 0;
- ub_put_cmd(sc, cmd);
+ ub_put_cmd(lun, cmd);
ub_end_rq(rq, uptodate);
blk_start_queue(q);
}
@@ -887,7 +933,7 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
bcb->Tag = cmd->tag; /* Endianness is not important */
bcb->DataTransferLength = cpu_to_le32(cmd->len);
bcb->Flags = (cmd->dir == UB_DIR_READ) ? 0x80 : 0;
- bcb->Lun = 0; /* No multi-LUN yet */
+ bcb->Lun = (cmd->lun != NULL) ? cmd->lun->num : 0;
bcb->Length = cmd->cdb_len;
/* copy the command payload */
@@ -1002,9 +1048,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
* The control pipe clears itself - nothing to do.
* XXX Might try to reset the device here and retry.
*/
- printk(KERN_NOTICE "%s: "
- "stall on control pipe for device %u\n",
- sc->name, sc->dev->devnum);
+ printk(KERN_NOTICE "%s: stall on control pipe\n",
+ sc->name);
goto Bad_End;
}
@@ -1025,9 +1070,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
* The control pipe clears itself - nothing to do.
* XXX Might try to reset the device here and retry.
*/
- printk(KERN_NOTICE "%s: "
- "stall on control pipe for device %u\n",
- sc->name, sc->dev->devnum);
+ printk(KERN_NOTICE "%s: stall on control pipe\n",
+ sc->name);
goto Bad_End;
}
@@ -1046,9 +1090,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
if (rc != 0) {
printk(KERN_NOTICE "%s: "
- "unable to submit clear for device %u"
- " (code %d)\n",
- sc->name, sc->dev->devnum, rc);
+ "unable to submit clear (%d)\n",
+ sc->name, rc);
/*
* This is typically ENOMEM or some other such shit.
* Retrying is pointless. Just do Bad End on it...
@@ -1107,9 +1150,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
if (rc != 0) {
printk(KERN_NOTICE "%s: "
- "unable to submit clear for device %u"
- " (code %d)\n",
- sc->name, sc->dev->devnum, rc);
+ "unable to submit clear (%d)\n",
+ sc->name, rc);
/*
* This is typically ENOMEM or some other such shit.
* Retrying is pointless. Just do Bad End on it...
@@ -1140,9 +1182,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
if (rc != 0) {
printk(KERN_NOTICE "%s: "
- "unable to submit clear for device %u"
- " (code %d)\n",
- sc->name, sc->dev->devnum, rc);
+ "unable to submit clear (%d)\n",
+ sc->name, rc);
/*
* This is typically ENOMEM or some other such shit.
* Retrying is pointless. Just do Bad End on it...
@@ -1164,9 +1205,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
* encounter such a thing, try to read the CSW again.
*/
if (++cmd->stat_count >= 4) {
- printk(KERN_NOTICE "%s: "
- "unable to get CSW on device %u\n",
- sc->name, sc->dev->devnum);
+ printk(KERN_NOTICE "%s: unable to get CSW\n",
+ sc->name);
goto Bad_End;
}
__ub_state_stat(sc, cmd);
@@ -1207,10 +1247,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
*/
if (++cmd->stat_count >= 4) {
printk(KERN_NOTICE "%s: "
- "tag mismatch orig 0x%x reply 0x%x "
- "on device %u\n",
- sc->name, cmd->tag, bcs->Tag,
- sc->dev->devnum);
+ "tag mismatch orig 0x%x reply 0x%x\n",
+ sc->name, cmd->tag, bcs->Tag);
goto Bad_End;
}
__ub_state_stat(sc, cmd);
@@ -1244,8 +1282,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
} else {
printk(KERN_WARNING "%s: "
- "wrong command state %d on device %u\n",
- sc->name, cmd->state, sc->dev->devnum);
+ "wrong command state %d\n",
+ sc->name, cmd->state);
goto Bad_End;
}
return;
@@ -1288,7 +1326,6 @@ static void __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
/* XXX Clear stalls */
- printk("%s: CSW #%d submit failed (%d)\n", sc->name, cmd->tag, rc); /* P3 */
ub_complete(&sc->work_done);
ub_state_done(sc, cmd, rc);
return;
@@ -1333,6 +1370,7 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
scmd->state = UB_CMDST_INIT;
scmd->data = sc->top_sense;
scmd->len = UB_SENSE_SIZE;
+ scmd->lun = cmd->lun;
scmd->done = ub_top_sense_done;
scmd->back = cmd;
@@ -1411,14 +1449,14 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
}
if (cmd != scmd->back) {
printk(KERN_WARNING "%s: "
- "sense done for wrong command 0x%x on device %u\n",
- sc->name, cmd->tag, sc->dev->devnum);
+ "sense done for wrong command 0x%x\n",
+ sc->name, cmd->tag);
return;
}
if (cmd->state != UB_CMDST_SENSE) {
printk(KERN_WARNING "%s: "
- "sense done with bad cmd state %d on device %u\n",
- sc->name, cmd->state, sc->dev->devnum);
+ "sense done with bad cmd state %d\n",
+ sc->name, cmd->state);
return;
}
@@ -1429,68 +1467,32 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
ub_scsi_urb_compl(sc, cmd);
}
-#if 0
-/* Determine what the maximum LUN supported is */
-int usb_stor_Bulk_max_lun(struct us_data *us)
-{
- int result;
-
- /* issue the command */
- result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
- US_BULK_GET_MAX_LUN,
- USB_DIR_IN | USB_TYPE_CLASS |
- USB_RECIP_INTERFACE,
- 0, us->ifnum, us->iobuf, 1, HZ);
-
- /*
- * Some devices (i.e. Iomega Zip100) need this -- apparently
- * the bulk pipes get STALLed when the GetMaxLUN request is
- * processed. This is, in theory, harmless to all other devices
- * (regardless of if they stall or not).
- */
- if (result < 0) {
- usb_stor_clear_halt(us, us->recv_bulk_pipe);
- usb_stor_clear_halt(us, us->send_bulk_pipe);
- }
-
- US_DEBUGP("GetMaxLUN command result is %d, data is %d\n",
- result, us->iobuf[0]);
-
- /* if we have a successful request, return the result */
- if (result == 1)
- return us->iobuf[0];
-
- /* return the default -- no LUNs */
- return 0;
-}
-#endif
-
/*
* This is called from a process context.
*/
-static void ub_revalidate(struct ub_dev *sc)
+static void ub_revalidate(struct ub_dev *sc, struct ub_lun *lun)
{
- sc->readonly = 0; /* XXX Query this from the device */
+ lun->readonly = 0; /* XXX Query this from the device */
- sc->capacity.nsec = 0;
- sc->capacity.bsize = 512;
- sc->capacity.bshift = 0;
+ lun->capacity.nsec = 0;
+ lun->capacity.bsize = 512;
+ lun->capacity.bshift = 0;
- if (ub_sync_tur(sc) != 0)
+ if (ub_sync_tur(sc, lun) != 0)
return; /* Not ready */
- sc->changed = 0;
+ lun->changed = 0;
- if (ub_sync_read_cap(sc, &sc->capacity) != 0) {
+ if (ub_sync_read_cap(sc, lun, &lun->capacity) != 0) {
/*
* The retry here means something is wrong, either with the
* device, with the transport, or with our code.
* We keep this because sd.c has retries for capacity.
*/
- if (ub_sync_read_cap(sc, &sc->capacity) != 0) {
- sc->capacity.nsec = 0;
- sc->capacity.bsize = 512;
- sc->capacity.bshift = 0;
+ if (ub_sync_read_cap(sc, lun, &lun->capacity) != 0) {
+ lun->capacity.nsec = 0;
+ lun->capacity.bsize = 512;
+ lun->capacity.bshift = 0;
}
}
}
@@ -1503,12 +1505,15 @@ static void ub_revalidate(struct ub_dev *sc)
static int ub_bd_open(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct ub_lun *lun;
struct ub_dev *sc;
unsigned long flags;
int rc;
- if ((sc = disk->private_data) == NULL)
+ if ((lun = disk->private_data) == NULL)
return -ENXIO;
+ sc = lun->udev;
+
spin_lock_irqsave(&ub_lock, flags);
if (atomic_read(&sc->poison)) {
spin_unlock_irqrestore(&ub_lock, flags);
@@ -1529,15 +1534,15 @@ static int ub_bd_open(struct inode *inode, struct file *filp)
* The bottom line is, Al Viro says that we should not allow
* bdev->bd_invalidated to be set when doing add_disk no matter what.
*/
- if (sc->first_open) {
- if (sc->changed) {
- sc->first_open = 0;
+ if (lun->first_open) {
+ lun->first_open = 0;
+ if (lun->changed) {
rc = -ENOMEDIUM;
goto err_open;
}
}
- if (sc->removable || sc->readonly)
+ if (lun->removable || lun->readonly)
check_disk_change(inode->i_bdev);
/*
@@ -1545,12 +1550,12 @@ static int ub_bd_open(struct inode *inode, struct file *filp)
* under some pretty murky conditions (a failure of READ CAPACITY).
* We may need it one day.
*/
- if (sc->removable && sc->changed && !(filp->f_flags & O_NDELAY)) {
+ if (lun->removable && lun->changed && !(filp->f_flags & O_NDELAY)) {
rc = -ENOMEDIUM;
goto err_open;
}
- if (sc->readonly && (filp->f_mode & FMODE_WRITE)) {
+ if (lun->readonly && (filp->f_mode & FMODE_WRITE)) {
rc = -EROFS;
goto err_open;
}
@@ -1567,7 +1572,8 @@ err_open:
static int ub_bd_release(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
- struct ub_dev *sc = disk->private_data;
+ struct ub_lun *lun = disk->private_data;
+ struct ub_dev *sc = lun->udev;
ub_put(sc);
return 0;
@@ -1597,20 +1603,14 @@ static int ub_bd_ioctl(struct inode *inode, struct file *filp,
*/
static int ub_bd_revalidate(struct gendisk *disk)
{
- struct ub_dev *sc = disk->private_data;
-
- ub_revalidate(sc);
- /* This is pretty much a long term P3 */
- if (!atomic_read(&sc->poison)) { /* Cover sc->dev */
- printk(KERN_INFO "%s: device %u capacity nsec %ld bsize %u\n",
- sc->name, sc->dev->devnum,
- sc->capacity.nsec, sc->capacity.bsize);
- }
+ struct ub_lun *lun = disk->private_data;
+
+ ub_revalidate(lun->udev, lun);
/* XXX Support sector size switching like in sr.c */
- blk_queue_hardsect_size(disk->queue, sc->capacity.bsize);
- set_capacity(disk, sc->capacity.nsec);
- // set_disk_ro(sdkp->disk, sc->readonly);
+ blk_queue_hardsect_size(disk->queue, lun->capacity.bsize);
+ set_capacity(disk, lun->capacity.nsec);
+ // set_disk_ro(sdkp->disk, lun->readonly);
return 0;
}
@@ -1626,9 +1626,9 @@ static int ub_bd_revalidate(struct gendisk *disk)
*/
static int ub_bd_media_changed(struct gendisk *disk)
{
- struct ub_dev *sc = disk->private_data;
+ struct ub_lun *lun = disk->private_data;
- if (!sc->removable)
+ if (!lun->removable)
return 0;
/*
@@ -1640,12 +1640,12 @@ static int ub_bd_media_changed(struct gendisk *disk)
* will fail, then block layer discards the data. Since we never
* spin drives up, such devices simply cannot be used with ub anyway.
*/
- if (ub_sync_tur(sc) != 0) {
- sc->changed = 1;
+ if (ub_sync_tur(lun->udev, lun) != 0) {
+ lun->changed = 1;
return 1;
}
- return sc->changed;
+ return lun->changed;
}
static struct block_device_operations ub_bd_fops = {
@@ -1669,7 +1669,7 @@ static void ub_probe_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
/*
* Test if the device has a check condition on it, synchronously.
*/
-static int ub_sync_tur(struct ub_dev *sc)
+static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun)
{
struct ub_scsi_cmd *cmd;
enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) };
@@ -1688,6 +1688,7 @@ static int ub_sync_tur(struct ub_dev *sc)
cmd->cdb_len = 6;
cmd->dir = UB_DIR_NONE;
cmd->state = UB_CMDST_INIT;
+ cmd->lun = lun; /* This may be NULL, but that's ok */
cmd->done = ub_probe_done;
cmd->back = &compl;
@@ -1718,7 +1719,8 @@ err_alloc:
/*
* Read the SCSI capacity synchronously (for probing).
*/
-static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret)
+static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
+ struct ub_capacity *ret)
{
struct ub_scsi_cmd *cmd;
char *p;
@@ -1743,6 +1745,7 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret)
cmd->state = UB_CMDST_INIT;
cmd->data = p;
cmd->len = 8;
+ cmd->lun = lun;
cmd->done = ub_probe_done;
cmd->back = &compl;
@@ -1812,6 +1815,90 @@ static void ub_probe_timeout(unsigned long arg)
}
/*
+ * Get number of LUNs by the way of Bulk GetMaxLUN command.
+ */
+static int ub_sync_getmaxlun(struct ub_dev *sc)
+{
+ int ifnum = sc->intf->cur_altsetting->desc.bInterfaceNumber;
+ unsigned char *p;
+ enum { ALLOC_SIZE = 1 };
+ struct usb_ctrlrequest *cr;
+ struct completion compl;
+ struct timer_list timer;
+ int nluns;
+ int rc;
+
+ init_completion(&compl);
+
+ rc = -ENOMEM;
+ if ((p = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL)
+ goto err_alloc;
+ *p = 55;
+
+ cr = &sc->work_cr;
+ cr->bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+ cr->bRequest = US_BULK_GET_MAX_LUN;
+ cr->wValue = cpu_to_le16(0);
+ cr->wIndex = cpu_to_le16(ifnum);
+ cr->wLength = cpu_to_le16(1);
+
+ usb_fill_control_urb(&sc->work_urb, sc->dev, sc->recv_ctrl_pipe,
+ (unsigned char*) cr, p, 1, ub_probe_urb_complete, &compl);
+ sc->work_urb.transfer_flags = 0;
+ sc->work_urb.actual_length = 0;
+ sc->work_urb.error_count = 0;
+ sc->work_urb.status = 0;
+
+ if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
+ if (rc == -EPIPE) {
+ printk("%s: Stall at GetMaxLUN, using 1 LUN\n",
+ sc->name); /* P3 */
+ } else {
+ printk(KERN_WARNING
+ "%s: Unable to submit GetMaxLUN (%d)\n",
+ sc->name, rc);
+ }
+ goto err_submit;
+ }
+
+ init_timer(&timer);
+ timer.function = ub_probe_timeout;
+ timer.data = (unsigned long) &compl;
+ timer.expires = jiffies + UB_CTRL_TIMEOUT;
+ add_timer(&timer);
+
+ wait_for_completion(&compl);
+
+ del_timer_sync(&timer);
+ usb_kill_urb(&sc->work_urb);
+
+ if (sc->work_urb.actual_length != 1) {
+ printk("%s: GetMaxLUN returned %d bytes\n", sc->name,
+ sc->work_urb.actual_length); /* P3 */
+ nluns = 0;
+ } else {
+ if ((nluns = *p) == 55) {
+ nluns = 0;
+ } else {
+ /* GetMaxLUN returns the maximum LUN number */
+ nluns += 1;
+ if (nluns > UB_MAX_LUNS)
+ nluns = UB_MAX_LUNS;
+ }
+ printk("%s: GetMaxLUN returned %d, using %d LUNs\n", sc->name,
+ *p, nluns); /* P3 */
+ }
+
+ kfree(p);
+ return nluns;
+
+err_submit:
+ kfree(p);
+err_alloc:
+ return rc;
+}
+
+/*
* Clear initial stalls.
*/
static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe)
@@ -1897,8 +1984,8 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev,
}
if (ep_in == NULL || ep_out == NULL) {
- printk(KERN_NOTICE "%s: device %u failed endpoint check\n",
- sc->name, sc->dev->devnum);
+ printk(KERN_NOTICE "%s: failed endpoint check\n",
+ sc->name);
return -EIO;
}
@@ -1921,8 +2008,7 @@ static int ub_probe(struct usb_interface *intf,
const struct usb_device_id *dev_id)
{
struct ub_dev *sc;
- request_queue_t *q;
- struct gendisk *disk;
+ int nluns;
int rc;
int i;
@@ -1931,6 +2017,7 @@ static int ub_probe(struct usb_interface *intf,
goto err_core;
memset(sc, 0, sizeof(struct ub_dev));
spin_lock_init(&sc->lock);
+ INIT_LIST_HEAD(&sc->luns);
usb_init_urb(&sc->work_urb);
tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc);
atomic_set(&sc->poison, 0);
@@ -1942,19 +2029,16 @@ static int ub_probe(struct usb_interface *intf,
ub_init_completion(&sc->work_done);
sc->work_done.done = 1; /* A little yuk, but oh well... */
- rc = -ENOSR;
- if ((sc->id = ub_id_get()) == -1)
- goto err_id;
- snprintf(sc->name, 8, DRV_NAME "%c", sc->id + 'a');
-
sc->dev = interface_to_usbdev(intf);
sc->intf = intf;
// sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
-
usb_set_intfdata(intf, sc);
usb_get_dev(sc->dev);
// usb_get_intf(sc->intf); /* Do we need this? */
+ snprintf(sc->name, 12, DRV_NAME "(%d.%d)",
+ sc->dev->bus->busnum, sc->dev->devnum);
+
/* XXX Verify that we can handle the device (from descriptors) */
ub_get_pipes(sc, sc->dev, intf);
@@ -1992,35 +2076,88 @@ static int ub_probe(struct usb_interface *intf,
* In any case it's not our business how revaliadation is implemented.
*/
for (i = 0; i < 3; i++) { /* Retries for benh's key */
- if ((rc = ub_sync_tur(sc)) <= 0) break;
+ if ((rc = ub_sync_tur(sc, NULL)) <= 0) break;
if (rc != 0x6) break;
msleep(10);
}
- sc->removable = 1; /* XXX Query this from the device */
- sc->changed = 1; /* ub_revalidate clears only */
- sc->first_open = 1;
+ nluns = 1;
+ for (i = 0; i < 3; i++) {
+ if ((rc = ub_sync_getmaxlun(sc)) < 0) {
+ /*
+ * Some devices (i.e. Iomega Zip100) need this --
+ * apparently the bulk pipes get STALLed when the
+ * GetMaxLUN request is processed.
+ * XXX I have a ZIP-100, verify it does this.
+ */
+ if (rc == -EPIPE) {
+ ub_probe_clear_stall(sc, sc->recv_bulk_pipe);
+ ub_probe_clear_stall(sc, sc->send_bulk_pipe);
+ }
+ break;
+ }
+ if (rc != 0) {
+ nluns = rc;
+ break;
+ }
+ msleep(100);
+ }
- ub_revalidate(sc);
- /* This is pretty much a long term P3 */
- printk(KERN_INFO "%s: device %u capacity nsec %ld bsize %u\n",
- sc->name, sc->dev->devnum, sc->capacity.nsec, sc->capacity.bsize);
+ for (i = 0; i < nluns; i++) {
+ ub_probe_lun(sc, i);
+ }
+ return 0;
+
+ /* device_remove_file(&sc->intf->dev, &dev_attr_diag); */
+err_diag:
+ usb_set_intfdata(intf, NULL);
+ // usb_put_intf(sc->intf);
+ usb_put_dev(sc->dev);
+ kfree(sc);
+err_core:
+ return rc;
+}
+
+static int ub_probe_lun(struct ub_dev *sc, int lnum)
+{
+ struct ub_lun *lun;
+ request_queue_t *q;
+ struct gendisk *disk;
+ int rc;
+
+ rc = -ENOMEM;
+ if ((lun = kmalloc(sizeof(struct ub_lun), GFP_KERNEL)) == NULL)
+ goto err_alloc;
+ memset(lun, 0, sizeof(struct ub_lun));
+ lun->num = lnum;
+
+ rc = -ENOSR;
+ if ((lun->id = ub_id_get()) == -1)
+ goto err_id;
+
+ lun->udev = sc;
+ list_add(&lun->link, &sc->luns);
+
+ snprintf(lun->name, 16, DRV_NAME "%c(%d.%d.%d)",
+ lun->id + 'a', sc->dev->bus->busnum, sc->dev->devnum, lun->num);
+
+ lun->removable = 1; /* XXX Query this from the device */
+ lun->changed = 1; /* ub_revalidate clears only */
+ lun->first_open = 1;
+ ub_revalidate(sc, lun);
- /*
- * Just one disk per sc currently, but maybe more.
- */
rc = -ENOMEM;
if ((disk = alloc_disk(UB_MINORS_PER_MAJOR)) == NULL)
goto err_diskalloc;
- sc->disk = disk;
- sprintf(disk->disk_name, DRV_NAME "%c", sc->id + 'a');
- sprintf(disk->devfs_name, DEVFS_NAME "/%c", sc->id + 'a');
+ lun->disk = disk;
+ sprintf(disk->disk_name, DRV_NAME "%c", lun->id + 'a');
+ sprintf(disk->devfs_name, DEVFS_NAME "/%c", lun->id + 'a');
disk->major = UB_MAJOR;
- disk->first_minor = sc->id * UB_MINORS_PER_MAJOR;
+ disk->first_minor = lun->id * UB_MINORS_PER_MAJOR;
disk->fops = &ub_bd_fops;
- disk->private_data = sc;
- disk->driverfs_dev = &intf->dev;
+ disk->private_data = lun;
+ disk->driverfs_dev = &sc->intf->dev; /* XXX Many to one ok? */
rc = -ENOMEM;
if ((q = blk_init_queue(ub_bd_rq_fn, &sc->lock)) == NULL)
@@ -2028,28 +2165,17 @@ static int ub_probe(struct usb_interface *intf,
disk->queue = q;
- // blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask);
+ blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
blk_queue_max_hw_segments(q, UB_MAX_REQ_SG);
blk_queue_max_phys_segments(q, UB_MAX_REQ_SG);
- // blk_queue_segment_boundary(q, CARM_SG_BOUNDARY);
+ blk_queue_segment_boundary(q, 0xffffffff); /* Dubious. */
blk_queue_max_sectors(q, UB_MAX_SECTORS);
- blk_queue_hardsect_size(q, sc->capacity.bsize);
-
- /*
- * This is a serious infraction, caused by a deficiency in the
- * USB sg interface (usb_sg_wait()). We plan to remove this once
- * we get mileage on the driver and can justify a change to USB API.
- * See blk_queue_bounce_limit() to understand this part.
- *
- * XXX And I still need to be aware of the DMA mask in the HC.
- */
- q->bounce_pfn = blk_max_low_pfn;
- q->bounce_gfp = GFP_NOIO;
+ blk_queue_hardsect_size(q, lun->capacity.bsize);
- q->queuedata = sc;
+ q->queuedata = lun;
- set_capacity(disk, sc->capacity.nsec);
- if (sc->removable)
+ set_capacity(disk, lun->capacity.nsec);
+ if (lun->removable)
disk->flags |= GENHD_FL_REMOVABLE;
add_disk(disk);
@@ -2059,22 +2185,20 @@ static int ub_probe(struct usb_interface *intf,
err_blkqinit:
put_disk(disk);
err_diskalloc:
- device_remove_file(&sc->intf->dev, &dev_attr_diag);
-err_diag:
- usb_set_intfdata(intf, NULL);
- // usb_put_intf(sc->intf);
- usb_put_dev(sc->dev);
- ub_id_put(sc->id);
+ list_del(&lun->link);
+ ub_id_put(lun->id);
err_id:
- kfree(sc);
-err_core:
+ kfree(lun);
+err_alloc:
return rc;
}
static void ub_disconnect(struct usb_interface *intf)
{
struct ub_dev *sc = usb_get_intfdata(intf);
- struct gendisk *disk = sc->disk;
+ struct list_head *p;
+ struct ub_lun *lun;
+ struct gendisk *disk;
unsigned long flags;
/*
@@ -2124,14 +2248,18 @@ static void ub_disconnect(struct usb_interface *intf)
/*
* Unregister the upper layer.
*/
- if (disk->flags & GENHD_FL_UP)
- del_gendisk(disk);
- /*
- * I wish I could do:
- * set_bit(QUEUE_FLAG_DEAD, &q->queue_flags);
- * As it is, we rely on our internal poisoning and let
- * the upper levels to spin furiously failing all the I/O.
- */
+ list_for_each (p, &sc->luns) {
+ lun = list_entry(p, struct ub_lun, link);
+ disk = lun->disk;
+ if (disk->flags & GENHD_FL_UP)
+ del_gendisk(disk);
+ /*
+ * I wish I could do:
+ * set_bit(QUEUE_FLAG_DEAD, &q->queue_flags);
+ * As it is, we rely on our internal poisoning and let
+ * the upper levels to spin furiously failing all the I/O.
+ */
+ }
/*
* Taking a lock on a structure which is about to be freed
@@ -2182,8 +2310,8 @@ static int __init ub_init(void)
{
int rc;
- /* P3 */ printk("ub: sizeof ub_scsi_cmd %zu ub_dev %zu\n",
- sizeof(struct ub_scsi_cmd), sizeof(struct ub_dev));
+ /* P3 */ printk("ub: sizeof ub_scsi_cmd %zu ub_dev %zu ub_lun %zu\n",
+ sizeof(struct ub_scsi_cmd), sizeof(struct ub_dev), sizeof(struct ub_lun));
if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0)
goto err_regblkdev;
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 9075bbb56ad..f766bc22c6b 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -576,7 +576,7 @@ static void __exit hci_uart_exit(void)
#endif
/* Release tty registration of line discipline */
- if ((err = tty_register_ldisc(N_HCI, NULL)))
+ if ((err = tty_unregister_ldisc(N_HCI)))
BT_ERR("Can't unregister HCI line discipline (%d)", err);
}
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
index da80b14335a..01f03517332 100644
--- a/drivers/cdrom/cm206.c
+++ b/drivers/cdrom/cm206.c
@@ -307,7 +307,7 @@ static DEFINE_SPINLOCK(cm206_lock);
/* First, we define some polling functions. These are actually
only being used in the initialization. */
-void send_command_polled(int command)
+static void send_command_polled(int command)
{
int loop = POLLOOP;
while (!(inw(r_line_status) & ls_transmitter_buffer_empty)
@@ -318,7 +318,7 @@ void send_command_polled(int command)
outw(command, r_uart_transmit);
}
-uch receive_echo_polled(void)
+static uch receive_echo_polled(void)
{
int loop = POLLOOP;
while (!(inw(r_line_status) & ls_receive_buffer_full) && loop > 0) {
@@ -328,13 +328,13 @@ uch receive_echo_polled(void)
return ((uch) inw(r_uart_receive));
}
-uch send_receive_polled(int command)
+static uch send_receive_polled(int command)
{
send_command_polled(command);
return receive_echo_polled();
}
-inline void clear_ur(void)
+static inline void clear_ur(void)
{
if (cd->ur_r != cd->ur_w) {
debug(("Deleting bytes from fifo:"));
@@ -439,7 +439,7 @@ static irqreturn_t cm206_interrupt(int sig, void *dev_id, struct pt_regs *regs)
}
/* we have put the address of the wait queue in who */
-void cm206_timeout(unsigned long who)
+static void cm206_timeout(unsigned long who)
{
cd->timed_out = 1;
debug(("Timing out\n"));
@@ -448,7 +448,7 @@ void cm206_timeout(unsigned long who)
/* This function returns 1 if a timeout occurred, 0 if an interrupt
happened */
-int sleep_or_timeout(wait_queue_head_t * wait, int timeout)
+static int sleep_or_timeout(wait_queue_head_t * wait, int timeout)
{
cd->timed_out = 0;
init_timer(&cd->timer);
@@ -465,13 +465,7 @@ int sleep_or_timeout(wait_queue_head_t * wait, int timeout)
return 0;
}
-void cm206_delay(int nr_jiffies)
-{
- DECLARE_WAIT_QUEUE_HEAD(wait);
- sleep_or_timeout(&wait, nr_jiffies);
-}
-
-void send_command(int command)
+static void send_command(int command)
{
debug(("Sending 0x%x\n", command));
if (!(inw(r_line_status) & ls_transmitter_buffer_empty)) {
@@ -490,7 +484,7 @@ void send_command(int command)
outw(command, r_uart_transmit);
}
-uch receive_byte(int timeout)
+static uch receive_byte(int timeout)
{
uch ret;
cli();
@@ -521,23 +515,23 @@ uch receive_byte(int timeout)
return ret;
}
-inline uch receive_echo(void)
+static inline uch receive_echo(void)
{
return receive_byte(UART_TIMEOUT);
}
-inline uch send_receive(int command)
+static inline uch send_receive(int command)
{
send_command(command);
return receive_echo();
}
-inline uch wait_dsb(void)
+static inline uch wait_dsb(void)
{
return receive_byte(DSB_TIMEOUT);
}
-int type_0_command(int command, int expect_dsb)
+static int type_0_command(int command, int expect_dsb)
{
int e;
clear_ur();
@@ -552,7 +546,7 @@ int type_0_command(int command, int expect_dsb)
return 0;
}
-int type_1_command(int command, int bytes, uch * status)
+static int type_1_command(int command, int bytes, uch * status)
{ /* returns info */
int i;
if (type_0_command(command, 0))
@@ -564,7 +558,7 @@ int type_1_command(int command, int bytes, uch * status)
/* This function resets the adapter card. We'd better not do this too
* often, because it tends to generate `lost interrupts.' */
-void reset_cm260(void)
+static void reset_cm260(void)
{
outw(dc_normal | dc_initialize | READ_AHEAD, r_data_control);
udelay(10); /* 3.3 mu sec minimum */
@@ -572,7 +566,7 @@ void reset_cm260(void)
}
/* fsm: frame-sec-min from linear address; one of many */
-void fsm(int lba, uch * fsm)
+static void fsm(int lba, uch * fsm)
{
fsm[0] = lba % 75;
lba /= 75;
@@ -581,17 +575,17 @@ void fsm(int lba, uch * fsm)
fsm[2] = lba / 60;
}
-inline int fsm2lba(uch * fsm)
+static inline int fsm2lba(uch * fsm)
{
return fsm[0] + 75 * (fsm[1] - 2 + 60 * fsm[2]);
}
-inline int f_s_m2lba(uch f, uch s, uch m)
+static inline int f_s_m2lba(uch f, uch s, uch m)
{
return f + 75 * (s - 2 + 60 * m);
}
-int start_read(int start)
+static int start_read(int start)
{
uch read_sector[4] = { c_read_data, };
int i, e;
@@ -613,7 +607,7 @@ int start_read(int start)
return 0;
}
-int stop_read(void)
+static int stop_read(void)
{
int e;
type_0_command(c_stop, 0);
@@ -630,7 +624,7 @@ int stop_read(void)
routine takes care of this. Set a flag `background' in the cd
struct to indicate the process. */
-int read_background(int start, int reading)
+static int read_background(int start, int reading)
{
if (cd->background)
return -1; /* can't do twice */
@@ -658,7 +652,7 @@ void transport_data(int port, ush * dest, int count)
#define MAX_TRIES 100
-int read_sector(int start)
+static int read_sector(int start)
{
int tries = 0;
if (cd->background) {
@@ -753,7 +747,7 @@ static DECLARE_TASKLET(cm206_tasklet, cm206_tasklet_func, 0);
/* This command clears the dsb_possible_media_change flag, so we must
* retain it.
*/
-void get_drive_status(void)
+static void get_drive_status(void)
{
uch status[2];
type_1_command(c_drive_status, 2, status); /* this might be done faster */
@@ -764,7 +758,7 @@ void get_drive_status(void)
dsb_drive_not_ready | dsb_tray_not_closed));
}
-void get_disc_status(void)
+static void get_disc_status(void)
{
if (type_1_command(c_disc_status, 7, cd->disc_status)) {
debug(("get_disc_status: error\n"));
@@ -801,7 +795,7 @@ static void cm206_release(struct cdrom_device_info *cdi)
/* Empty buffer empties $sectors$ sectors of the adapter card buffer,
* and then reads a sector in kernel memory. */
-void empty_buffer(int sectors)
+static void empty_buffer(int sectors)
{
while (sectors >= 0) {
transport_data(r_fifo_output_buffer,
@@ -819,7 +813,7 @@ void empty_buffer(int sectors)
/* try_adapter. This function determines if the requested sector is
in adapter memory, or will appear there soon. Returns 0 upon
success */
-int try_adapter(int sector)
+static int try_adapter(int sector)
{
if (cd->adapter_first <= sector && sector < cd->adapter_last) {
/* sector is in adapter memory */
@@ -910,7 +904,7 @@ static void do_cm206_request(request_queue_t * q)
*/
/* seek seeks to address lba. It does wait to arrive there. */
-void seek(int lba)
+static void seek(int lba)
{
int i;
uch seek_command[4] = { c_seek, };
@@ -926,7 +920,7 @@ uch bcdbin(unsigned char bcd)
return (bcd >> 4) * 10 + (bcd & 0xf);
}
-inline uch normalize_track(uch track)
+static inline uch normalize_track(uch track)
{
if (track < 1)
return 1;
@@ -939,7 +933,7 @@ inline uch normalize_track(uch track)
* tracks seen in the process. Input $track$ must be between 1 and
* #-of-tracks+1. Note that the start of the disc must be in toc[1].fsm.
*/
-int get_toc_lba(uch track)
+static int get_toc_lba(uch track)
{
int max = 74 * 60 * 75 - 150, min = fsm2lba(cd->toc[1].fsm);
int i, lba, l, old_lba = 0;
@@ -991,7 +985,7 @@ int get_toc_lba(uch track)
return lba;
}
-void update_toc_entry(uch track)
+static void update_toc_entry(uch track)
{
track = normalize_track(track);
if (!cd->toc[track].track)
@@ -999,7 +993,7 @@ void update_toc_entry(uch track)
}
/* return 0 upon success */
-int read_toc_header(struct cdrom_tochdr *hp)
+static int read_toc_header(struct cdrom_tochdr *hp)
{
if (!FIRST_TRACK)
get_disc_status();
@@ -1016,7 +1010,7 @@ int read_toc_header(struct cdrom_tochdr *hp)
return -1;
}
-void play_from_to_msf(struct cdrom_msf *msfp)
+static void play_from_to_msf(struct cdrom_msf *msfp)
{
uch play_command[] = { c_play,
msfp->cdmsf_frame0, msfp->cdmsf_sec0, msfp->cdmsf_min0,
@@ -1032,7 +1026,7 @@ void play_from_to_msf(struct cdrom_msf *msfp)
cd->dsb = wait_dsb();
}
-void play_from_to_track(int from, int to)
+static void play_from_to_track(int from, int to)
{
uch play_command[8] = { c_play, };
int i;
@@ -1059,7 +1053,7 @@ void play_from_to_track(int from, int to)
cd->dsb = wait_dsb();
}
-int get_current_q(struct cdrom_subchnl *qp)
+static int get_current_q(struct cdrom_subchnl *qp)
{
int i;
uch *q = cd->q;
@@ -1093,14 +1087,14 @@ int get_current_q(struct cdrom_subchnl *qp)
return 0;
}
-void invalidate_toc(void)
+static void invalidate_toc(void)
{
memset(cd->toc, 0, sizeof(cd->toc));
memset(cd->disc_status, 0, sizeof(cd->disc_status));
}
/* cdrom.c guarantees that cdte_format == CDROM_MSF */
-void get_toc_entry(struct cdrom_tocentry *ep)
+static void get_toc_entry(struct cdrom_tocentry *ep)
{
uch track = normalize_track(ep->cdte_track);
update_toc_entry(track);
@@ -1117,8 +1111,8 @@ void get_toc_entry(struct cdrom_tocentry *ep)
* upon success. Memory checking has been done by cdrom_ioctl(), the
* calling function, as well as LBA/MSF sanitization.
*/
-int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
- void *arg)
+static int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
+ void *arg)
{
switch (cmd) {
case CDROMREADTOCHDR:
@@ -1189,7 +1183,7 @@ static int cm206_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
}
}
-int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr)
+static int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr)
{
if (cd != NULL) {
int r;
@@ -1204,16 +1198,9 @@ int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr)
/* The new generic cdrom support. Routines should be concise, most of
the logic should be in cdrom.c */
-/* returns number of times device is in use */
-int cm206_open_files(struct cdrom_device_info *cdi)
-{
- if (cd)
- return cd->openfiles;
- return -1;
-}
/* controls tray movement */
-int cm206_tray_move(struct cdrom_device_info *cdi, int position)
+static int cm206_tray_move(struct cdrom_device_info *cdi, int position)
{
if (position) { /* 1: eject */
type_0_command(c_open_tray, 1);
@@ -1224,7 +1211,7 @@ int cm206_tray_move(struct cdrom_device_info *cdi, int position)
}
/* gives current state of the drive */
-int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr)
+static int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr)
{
get_drive_status();
if (cd->dsb & dsb_tray_not_closed)
@@ -1237,7 +1224,7 @@ int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr)
}
/* locks or unlocks door lock==1: lock; return 0 upon success */
-int cm206_lock_door(struct cdrom_device_info *cdi, int lock)
+static int cm206_lock_door(struct cdrom_device_info *cdi, int lock)
{
uch command = (lock) ? c_lock_tray : c_unlock_tray;
type_0_command(command, 1); /* wait and get dsb */
@@ -1248,8 +1235,8 @@ int cm206_lock_door(struct cdrom_device_info *cdi, int lock)
/* Although a session start should be in LBA format, we return it in
MSF format because it is slightly easier, and the new generic ioctl
will take care of the necessary conversion. */
-int cm206_get_last_session(struct cdrom_device_info *cdi,
- struct cdrom_multisession *mssp)
+static int cm206_get_last_session(struct cdrom_device_info *cdi,
+ struct cdrom_multisession *mssp)
{
if (!FIRST_TRACK)
get_disc_status();
@@ -1268,7 +1255,7 @@ int cm206_get_last_session(struct cdrom_device_info *cdi,
return 0;
}
-int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
+static int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
{
uch upc[10];
char *ret = mcn->medium_catalog_number;
@@ -1287,7 +1274,7 @@ int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
return 0;
}
-int cm206_reset(struct cdrom_device_info *cdi)
+static int cm206_reset(struct cdrom_device_info *cdi)
{
stop_read();
reset_cm260();
@@ -1300,7 +1287,7 @@ int cm206_reset(struct cdrom_device_info *cdi)
return 0;
}
-int cm206_select_speed(struct cdrom_device_info *cdi, int speed)
+static int cm206_select_speed(struct cdrom_device_info *cdi, int speed)
{
int r;
switch (speed) {
@@ -1392,7 +1379,7 @@ static struct gendisk *cm206_gendisk;
request_region, 15 bits of one port and 6 of another make things
likely enough to accept the region on the first hit...
*/
-int __init probe_base_port(int base)
+static int __init probe_base_port(int base)
{
int b = 0x300, e = 0x370; /* this is the range of start addresses */
volatile int fool, i;
@@ -1416,7 +1403,7 @@ int __init probe_base_port(int base)
#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
/* Probe for irq# nr. If nr==0, probe for all possible irq's. */
-int __init probe_irq(int nr)
+static int __init probe_irq(int nr)
{
int irqs, irq;
outw(dc_normal | READ_AHEAD, r_data_control); /* disable irq-generation */
@@ -1558,7 +1545,7 @@ static void __init parse_options(void)
}
}
-int __cm206_init(void)
+static int __cm206_init(void)
{
parse_options();
#if !defined(AUTO_PROBE_MODULE)
@@ -1567,7 +1554,7 @@ int __cm206_init(void)
return cm206_init();
}
-void __exit cm206_exit(void)
+static void __exit cm206_exit(void)
{
del_gendisk(cm206_gendisk);
put_disk(cm206_gendisk);
diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
index f4be7bfd667..9f22e8f1f6c 100644
--- a/drivers/cdrom/sonycd535.c
+++ b/drivers/cdrom/sonycd535.c
@@ -1605,8 +1605,7 @@ out7:
put_disk(cdu_disk);
out6:
for (i = 0; i < sony_buffer_sectors; i++)
- if (sony_buffer[i])
- kfree(sony_buffer[i]);
+ kfree(sony_buffer[i]);
out5:
kfree(sony_buffer);
out4:
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index fcca26c89bb..38dd9ffbe8b 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -488,6 +488,20 @@ static int viocd_packet(struct cdrom_device_info *cdi,
& (CDC_DVD_RAM | CDC_RAM)) != 0;
}
break;
+ case GPCMD_GET_CONFIGURATION:
+ if (cgc->cmd[3] == CDF_RWRT) {
+ struct rwrt_feature_desc *rfd = (struct rwrt_feature_desc *)(cgc->buffer + sizeof(struct feature_header));
+
+ if ((buflen >=
+ (sizeof(struct feature_header) + sizeof(*rfd))) &&
+ (cdi->ops->capability & ~cdi->mask
+ & (CDC_DVD_RAM | CDC_RAM))) {
+ rfd->feature_code = cpu_to_be16(CDF_RWRT);
+ rfd->curr = 1;
+ ret = 0;
+ }
+ }
+ break;
default:
if (cgc->sense) {
/* indicate Unknown code */
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 5ed6515ae01..43d0cb19ef6 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -929,6 +929,10 @@ config SCx200_GPIO
If compiled as a module, it will be called scx200_gpio.
+config GPIO_VR41XX
+ tristate "NEC VR4100 series General-purpose I/O Unit support"
+ depends on CPU_VR41XX
+
config RAW_DRIVER
tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)"
help
@@ -936,8 +940,8 @@ config RAW_DRIVER
Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
See the raw(8) manpage for more details.
- The raw driver is deprecated and may be removed from 2.7
- kernels. Applications should simply open the device (eg /dev/hda1)
+ The raw driver is deprecated and will be removed soon.
+ Applications should simply open the device (eg /dev/hda1)
with the O_DIRECT flag.
config HPET
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index e3f5c32aac5..1aff819f383 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -80,6 +80,7 @@ obj-$(CONFIG_PPDEV) += ppdev.o
obj-$(CONFIG_NWBUTTON) += nwbutton.o
obj-$(CONFIG_NWFLASH) += nwflash.o
obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
+obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
obj-$(CONFIG_TANBAC_TB0219) += tb0219.o
obj-$(CONFIG_WATCHDOG) += watchdog/
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index ad9c11391d8..c1fe013c64f 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -278,6 +278,8 @@ void agp3_generic_cleanup(void);
#define AGP_GENERIC_SIZES_ENTRIES 11
extern struct aper_size_info_16 agp3_generic_sizes[];
+#define virt_to_gart(x) (phys_to_gart(virt_to_phys(x)))
+#define gart_to_virt(x) (phys_to_virt(gart_to_phys(x)))
extern int agp_off;
extern int agp_try_unsupported_boot;
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index 0212febda65..9c9c9c2247c 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -150,7 +150,7 @@ static void *m1541_alloc_page(struct agp_bridge_data *bridge)
pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
- virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN ));
+ virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN ));
return addr;
}
@@ -174,7 +174,7 @@ static void m1541_destroy_page(void * addr)
pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
- virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN));
+ virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN));
agp_generic_destroy_page(addr);
}
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index e62a3c2c44a..3a41672e4d6 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -43,7 +43,7 @@ static int amd_create_page_map(struct amd_page_map *page_map)
SetPageReserved(virt_to_page(page_map->real));
global_cache_flush();
- page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
+ page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
PAGE_SIZE);
if (page_map->remapped == NULL) {
ClearPageReserved(virt_to_page(page_map->real));
@@ -154,7 +154,7 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge)
agp_bridge->gatt_table_real = (u32 *)page_dir.real;
agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
- agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
+ agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
/* Get the address for the gart region.
* This is a bus address even on the alpha, b/c its
@@ -167,7 +167,7 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge)
/* Calculate the agp offset */
for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
- writel(virt_to_phys(amd_irongate_private.gatt_pages[i]->real) | 1,
+ writel(virt_to_gart(amd_irongate_private.gatt_pages[i]->real) | 1,
page_dir.remapped+GET_PAGE_DIR_OFF(addr));
readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */
}
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 399c042f68f..1407945a589 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -219,7 +219,7 @@ static struct aper_size_info_32 amd_8151_sizes[7] =
static int amd_8151_configure(void)
{
- unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real);
+ unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real);
/* Configure AGP regs in each x86-64 host bridge. */
for_each_nb() {
@@ -591,7 +591,7 @@ static void __devexit agp_amd64_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
- release_mem_region(virt_to_phys(bridge->gatt_table_real),
+ release_mem_region(virt_to_gart(bridge->gatt_table_real),
amd64_aperture_sizes[bridge->aperture_size_idx].size);
agp_remove_bridge(bridge);
agp_put_bridge(bridge);
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index a65f8827c28..e572ced9100 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -61,7 +61,7 @@ static int ati_create_page_map(ati_page_map *page_map)
SetPageReserved(virt_to_page(page_map->real));
err = map_page_into_agp(virt_to_page(page_map->real));
- page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
+ page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
PAGE_SIZE);
if (page_map->remapped == NULL || err) {
ClearPageReserved(virt_to_page(page_map->real));
@@ -343,7 +343,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge)
agp_bridge->gatt_table_real = (u32 *)page_dir.real;
agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped;
- agp_bridge->gatt_bus_addr = virt_to_bus(page_dir.real);
+ agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
/* Write out the size register */
current_size = A_SIZE_LVL2(agp_bridge->current_size);
@@ -373,7 +373,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge)
/* Calculate the agp offset */
for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
- writel(virt_to_bus(ati_generic_private.gatt_pages[i]->real) | 1,
+ writel(virt_to_gart(ati_generic_private.gatt_pages[i]->real) | 1,
page_dir.remapped+GET_PAGE_DIR_OFF(addr));
readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */
}
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 2f3dfb63bdc..4d4e602fdc7 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -148,7 +148,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
return -ENOMEM;
}
- bridge->scratch_page_real = virt_to_phys(addr);
+ bridge->scratch_page_real = virt_to_gart(addr);
bridge->scratch_page =
bridge->driver->mask_memory(bridge, bridge->scratch_page_real, 0);
}
@@ -189,7 +189,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
err_out:
if (bridge->driver->needs_scratch_page)
bridge->driver->agp_destroy_page(
- phys_to_virt(bridge->scratch_page_real));
+ gart_to_virt(bridge->scratch_page_real));
if (got_gatt)
bridge->driver->free_gatt_table(bridge);
if (got_keylist) {
@@ -214,7 +214,7 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
if (bridge->driver->agp_destroy_page &&
bridge->driver->needs_scratch_page)
bridge->driver->agp_destroy_page(
- phys_to_virt(bridge->scratch_page_real));
+ gart_to_virt(bridge->scratch_page_real));
}
/* When we remove the global variable agp_bridge from all drivers
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index 1383c3165ea..ac19fdcd21c 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -219,7 +219,7 @@ static int efficeon_create_gatt_table(struct agp_bridge_data *bridge)
efficeon_private.l1_table[index] = page;
- value = __pa(page) | pati | present | index;
+ value = virt_to_gart(page) | pati | present | index;
pci_write_config_dword(agp_bridge->dev,
EFFICEON_ATTPAGE, value);
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index c321a924e38..f0079e991bd 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -153,7 +153,7 @@ void agp_free_memory(struct agp_memory *curr)
}
if (curr->page_count != 0) {
for (i = 0; i < curr->page_count; i++) {
- curr->bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i]));
+ curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]));
}
}
agp_free_key(curr->key);
@@ -209,7 +209,7 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
agp_free_memory(new);
return NULL;
}
- new->memory[i] = virt_to_phys(addr);
+ new->memory[i] = virt_to_gart(addr);
new->page_count++;
}
new->bridge = bridge;
@@ -295,19 +295,6 @@ int agp_num_entries(void)
EXPORT_SYMBOL_GPL(agp_num_entries);
-static int check_bridge_mode(struct pci_dev *dev)
-{
- u32 agp3;
- u8 cap_ptr;
-
- cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
- pci_read_config_dword(dev, cap_ptr+AGPSTAT, &agp3);
- if (agp3 & AGPSTAT_MODE_3_0)
- return 1;
- return 0;
-}
-
-
/**
* agp_copy_info - copy bridge state information
*
@@ -328,7 +315,7 @@ int agp_copy_info(struct agp_bridge_data *bridge, struct agp_kern_info *info)
info->version.minor = bridge->version->minor;
info->chipset = SUPPORTED;
info->device = bridge->dev;
- if (check_bridge_mode(bridge->dev))
+ if (bridge->mode & AGPSTAT_MODE_3_0)
info->mode = bridge->mode & ~AGP3_RESERVED_MASK;
else
info->mode = bridge->mode & ~AGP2_RESERVED_MASK;
@@ -661,7 +648,7 @@ u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 requested_mode
bridge_agpstat &= ~AGPSTAT_FW;
/* Check to see if we are operating in 3.0 mode */
- if (check_bridge_mode(agp_bridge->dev))
+ if (agp_bridge->mode & AGPSTAT_MODE_3_0)
agp_v3_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
else
agp_v2_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
@@ -732,7 +719,7 @@ void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode)
/* Do AGP version specific frobbing. */
if (bridge->major_version >= 3) {
- if (check_bridge_mode(bridge->dev)) {
+ if (bridge->mode & AGPSTAT_MODE_3_0) {
/* If we have 3.5, we can do the isoch stuff. */
if (bridge->minor_version >= 5)
agp_3_5_enable(bridge);
@@ -806,8 +793,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
break;
}
- table = (char *) __get_free_pages(GFP_KERNEL,
- page_order);
+ table = alloc_gatt_pages(page_order);
if (table == NULL) {
i++;
@@ -838,7 +824,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
size = ((struct aper_size_info_fixed *) temp)->size;
page_order = ((struct aper_size_info_fixed *) temp)->page_order;
num_entries = ((struct aper_size_info_fixed *) temp)->num_entries;
- table = (char *) __get_free_pages(GFP_KERNEL, page_order);
+ table = alloc_gatt_pages(page_order);
}
if (table == NULL)
@@ -853,7 +839,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
agp_gatt_table = (void *)table;
bridge->driver->cache_flush();
- bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
+ bridge->gatt_table = ioremap_nocache(virt_to_gart(table),
(PAGE_SIZE * (1 << page_order)));
bridge->driver->cache_flush();
@@ -861,11 +847,11 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
ClearPageReserved(page);
- free_pages((unsigned long) table, page_order);
+ free_gatt_pages(table, page_order);
return -ENOMEM;
}
- bridge->gatt_bus_addr = virt_to_phys(bridge->gatt_table_real);
+ bridge->gatt_bus_addr = virt_to_gart(bridge->gatt_table_real);
/* AK: bogus, should encode addresses > 4GB */
for (i = 0; i < num_entries; i++) {
@@ -919,7 +905,7 @@ int agp_generic_free_gatt_table(struct agp_bridge_data *bridge)
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
ClearPageReserved(page);
- free_pages((unsigned long) bridge->gatt_table_real, page_order);
+ free_gatt_pages(bridge->gatt_table_real, page_order);
agp_gatt_table = NULL;
bridge->gatt_table = NULL;
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 6052bfa04c7..99762b6c19a 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -110,7 +110,7 @@ static int __init hp_zx1_ioc_shared(void)
hp->gart_size = HP_ZX1_GART_SIZE;
hp->gatt_entries = hp->gart_size / hp->io_page_size;
- hp->io_pdir = phys_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE));
+ hp->io_pdir = gart_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE));
hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)];
if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) {
@@ -248,7 +248,7 @@ hp_zx1_configure (void)
agp_bridge->mode = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS);
if (hp->io_pdir_owner) {
- writel(virt_to_phys(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE);
+ writel(virt_to_gart(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE);
readl(hp->ioc_regs+HP_ZX1_PDIR_BASE);
writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG);
readl(hp->ioc_regs+HP_ZX1_TCNFG);
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
index adbea896c0d..94943298c03 100644
--- a/drivers/char/agp/i460-agp.c
+++ b/drivers/char/agp/i460-agp.c
@@ -372,7 +372,7 @@ static int i460_alloc_large_page (struct lp_desc *lp)
}
memset(lp->alloced_map, 0, map_size);
- lp->paddr = virt_to_phys(lpage);
+ lp->paddr = virt_to_gart(lpage);
lp->refcount = 0;
atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
return 0;
@@ -383,7 +383,7 @@ static void i460_free_large_page (struct lp_desc *lp)
kfree(lp->alloced_map);
lp->alloced_map = NULL;
- free_pages((unsigned long) phys_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT);
+ free_pages((unsigned long) gart_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT);
atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
}
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 8c7d727432b..51266d6b4d7 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -286,7 +286,7 @@ static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
if (new == NULL)
return NULL;
- new->memory[0] = virt_to_phys(addr);
+ new->memory[0] = virt_to_gart(addr);
if (pg_count == 4) {
/* kludge to get 4 physical pages for ARGB cursor */
new->memory[1] = new->memory[0] + PAGE_SIZE;
@@ -329,10 +329,10 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
agp_free_key(curr->key);
if(curr->type == AGP_PHYS_MEMORY) {
if (curr->page_count == 4)
- i8xx_destroy_pages(phys_to_virt(curr->memory[0]));
+ i8xx_destroy_pages(gart_to_virt(curr->memory[0]));
else
agp_bridge->driver->agp_destroy_page(
- phys_to_virt(curr->memory[0]));
+ gart_to_virt(curr->memory[0]));
vfree(curr->memory);
}
kfree(curr);
@@ -418,7 +418,8 @@ static void intel_i830_init_gtt_entries(void)
case I915_GMCH_GMS_STOLEN_48M:
/* Check it's really I915G */
if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB)
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB)
gtt_entries = MB(48) - KB(size);
else
gtt_entries = 0;
@@ -426,7 +427,8 @@ static void intel_i830_init_gtt_entries(void)
case I915_GMCH_GMS_STOLEN_64M:
/* Check it's really I915G */
if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB)
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB)
gtt_entries = MB(64) - KB(size);
else
gtt_entries = 0;
@@ -1662,6 +1664,14 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
}
name = "915GM";
break;
+ case PCI_DEVICE_ID_INTEL_82945G_HB:
+ if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG)) {
+ bridge->driver = &intel_915_driver;
+ } else {
+ bridge->driver = &intel_845_driver;
+ }
+ name = "945G";
+ break;
case PCI_DEVICE_ID_INTEL_7505_0:
bridge->driver = &intel_7505_driver;
name = "E7505";
@@ -1801,6 +1811,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_7205_0),
ID(PCI_DEVICE_ID_INTEL_82915G_HB),
ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
+ ID(PCI_DEVICE_ID_INTEL_82945G_HB),
{ }
};
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index 4b3eda26797..d3aa159c9de 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -133,11 +133,14 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,
off_t j;
void *temp;
struct agp_bridge_data *bridge;
+ u64 *table;
bridge = mem->bridge;
if (!bridge)
return -EINVAL;
+ table = (u64 *)bridge->gatt_table;
+
temp = bridge->current_size;
switch (bridge->driver->size_type) {
@@ -175,7 +178,7 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,
j = pg_start;
while (j < (pg_start + mem->page_count)) {
- if (*(bridge->gatt_table + j))
+ if (table[j])
return -EBUSY;
j++;
}
@@ -186,7 +189,7 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- *(bridge->gatt_table + j) =
+ table[j] =
bridge->driver->mask_memory(bridge, mem->memory[i],
mem->type);
}
@@ -200,6 +203,7 @@ static int sgi_tioca_remove_memory(struct agp_memory *mem, off_t pg_start,
{
size_t i;
struct agp_bridge_data *bridge;
+ u64 *table;
bridge = mem->bridge;
if (!bridge)
@@ -209,8 +213,10 @@ static int sgi_tioca_remove_memory(struct agp_memory *mem, off_t pg_start,
return -EINVAL;
}
+ table = (u64 *)bridge->gatt_table;
+
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
- *(bridge->gatt_table + i) = 0;
+ table[i] = 0;
}
bridge->driver->tlb_flush(mem);
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index 10c23302dd8..a9fb12c20eb 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -51,7 +51,7 @@ static int serverworks_create_page_map(struct serverworks_page_map *page_map)
}
SetPageReserved(virt_to_page(page_map->real));
global_cache_flush();
- page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
+ page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
PAGE_SIZE);
if (page_map->remapped == NULL) {
ClearPageReserved(virt_to_page(page_map->real));
@@ -162,7 +162,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
/* Create a fake scratch directory */
for(i = 0; i < 1024; i++) {
writel(agp_bridge->scratch_page, serverworks_private.scratch_dir.remapped+i);
- writel(virt_to_phys(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
+ writel(virt_to_gart(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
}
retval = serverworks_create_gatt_pages(value->num_entries / 1024);
@@ -174,7 +174,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
agp_bridge->gatt_table_real = (u32 *)page_dir.real;
agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
- agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
+ agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
/* Get the address for the gart region.
* This is a bus address even on the alpha, b/c its
@@ -187,7 +187,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
/* Calculate the agp offset */
for(i = 0; i < value->num_entries / 1024; i++)
- writel(virt_to_phys(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
+ writel(virt_to_gart(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
return 0;
}
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index a673971f2a9..c8255312b8c 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -407,7 +407,7 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
bridge->gatt_table_real = (u32 *) table;
bridge->gatt_table = (u32 *)table;
- bridge->gatt_bus_addr = virt_to_phys(table);
+ bridge->gatt_bus_addr = virt_to_gart(table);
for (i = 0; i < num_entries; i++)
bridge->gatt_table[i] = 0;
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 1dc4259213a..2a36561eec6 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -861,13 +861,18 @@ static void change_speed(struct async_struct *info,
static void rs_put_char(struct tty_struct *tty, unsigned char ch)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct async_struct *info;
unsigned long flags;
+ if (!tty)
+ return;
+
+ info = tty->driver_data;
+
if (serial_paranoia_check(info, tty->name, "rs_put_char"))
return;
- if (!tty || !info->xmit.buf)
+ if (!info->xmit.buf)
return;
local_irq_save(flags);
@@ -910,13 +915,18 @@ static void rs_flush_chars(struct tty_struct *tty)
static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count)
{
int c, ret = 0;
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct async_struct *info;
unsigned long flags;
+ if (!tty)
+ return 0;
+
+ info = tty->driver_data;
+
if (serial_paranoia_check(info, tty->name, "rs_write"))
return 0;
- if (!tty || !info->xmit.buf || !tmp_buf)
+ if (!info->xmit.buf || !tmp_buf)
return 0;
local_save_flags(flags);
@@ -1963,10 +1973,6 @@ static _INLINE_ void show_serial_version(void)
}
-int register_serial(struct serial_struct *req);
-void unregister_serial(int line);
-
-
static struct tty_operations serial_ops = {
.open = rs_open,
.close = rs_close,
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index 6bf2e27dc23..11f9ee58112 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -599,7 +599,7 @@ static ssize_t ac_read (struct file *filp, char __user *buf, size_t count, loff_
#ifdef DEBUG
if (loopcount++ > 2) {
- printk("Looping in ac_read. loopcount %d\n", loopcount);
+ printk(KERN_DEBUG "Looping in ac_read. loopcount %d\n", loopcount);
}
#endif
}
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index 54a2914e3a3..11c6950158b 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -220,5 +220,6 @@
{0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0, 0, 0}
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
index 5b18bee6492..cd25f28e26a 100644
--- a/drivers/char/drm/radeon_irq.c
+++ b/drivers/char/drm/radeon_irq.c
@@ -123,11 +123,6 @@ static int radeon_wait_irq(drm_device_t *dev, int swi_nr)
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
- /* This is a hack to work around mysterious freezes on certain
- * systems:
- */
- radeon_acknowledge_irqs( dev_priv );
-
DRM_WAIT_ON( ret, dev_priv->swi_queue, 3 * DRM_HZ,
RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr );
diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c
index 7def6ad5179..62cda25724e 100644
--- a/drivers/char/ds1620.c
+++ b/drivers/char/ds1620.c
@@ -163,8 +163,7 @@ static void ds1620_out(int cmd, int bits, int value)
netwinder_ds1620_reset();
netwinder_unlock(&flags);
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(2);
+ msleep(20);
}
static unsigned int ds1620_in(int cmd, int bits)
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 37d6649011a..26271e3ca82 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -144,7 +144,7 @@ static struct dsp56k_device {
int tx_wsize, rx_wsize;
} dsp56k;
-static struct class_simple *dsp56k_class;
+static struct class *dsp56k_class;
static int dsp56k_reset(void)
{
@@ -510,12 +510,12 @@ static int __init dsp56k_init_driver(void)
printk("DSP56k driver: Unable to register driver\n");
return -ENODEV;
}
- dsp56k_class = class_simple_create(THIS_MODULE, "dsp56k");
+ dsp56k_class = class_create(THIS_MODULE, "dsp56k");
if (IS_ERR(dsp56k_class)) {
err = PTR_ERR(dsp56k_class);
goto out_chrdev;
}
- class_simple_device_add(dsp56k_class, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
+ class_device_create(dsp56k_class, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
err = devfs_mk_cdev(MKDEV(DSP56K_MAJOR, 0),
S_IFCHR | S_IRUSR | S_IWUSR, "dsp56k");
@@ -526,8 +526,8 @@ static int __init dsp56k_init_driver(void)
goto out;
out_class:
- class_simple_device_remove(MKDEV(DSP56K_MAJOR, 0));
- class_simple_destroy(dsp56k_class);
+ class_device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
+ class_destroy(dsp56k_class);
out_chrdev:
unregister_chrdev(DSP56K_MAJOR, "dsp56k");
out:
@@ -537,8 +537,8 @@ module_init(dsp56k_init_driver);
static void __exit dsp56k_cleanup_driver(void)
{
- class_simple_device_remove(MKDEV(DSP56K_MAJOR, 0));
- class_simple_destroy(dsp56k_class);
+ class_device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
+ class_destroy(dsp56k_class);
unregister_chrdev(DSP56K_MAJOR, "dsp56k");
devfs_remove("dsp56k");
}
diff --git a/drivers/char/ftape/compressor/zftape-compress.c b/drivers/char/ftape/compressor/zftape-compress.c
index 220a227e606..65ffc0be3df 100644
--- a/drivers/char/ftape/compressor/zftape-compress.c
+++ b/drivers/char/ftape/compressor/zftape-compress.c
@@ -1176,8 +1176,8 @@ KERN_INFO "Compressor for zftape (lzrw3 algorithm)\n");
}
#else /* !MODULE */
/* print a short no-nonsense boot message */
- printk("zftape compressor v1.00a 970514\n");
- printk("For use with " FTAPE_VERSION "\n");
+ printk(KERN_INFO "zftape compressor v1.00a 970514\n");
+ printk(KERN_INFO "For use with " FTAPE_VERSION "\n");
#endif /* MODULE */
TRACE(ft_t_info, "zft_compressor_init @ 0x%p", zft_compressor_init);
TRACE(ft_t_info, "installing compressor for zftape ...");
diff --git a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c
index dbac7e54e8e..5745b74044e 100644
--- a/drivers/char/ftape/zftape/zftape-init.c
+++ b/drivers/char/ftape/zftape/zftape-init.c
@@ -99,7 +99,7 @@ static struct file_operations zft_cdev =
.release = zft_close,
};
-static struct class_simple *zft_class;
+static struct class *zft_class;
/* Open floppy tape device
*/
@@ -329,29 +329,29 @@ KERN_INFO
"installing zftape VFS interface for ftape driver ...");
TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),);
- zft_class = class_simple_create(THIS_MODULE, "zft");
+ zft_class = class_create(THIS_MODULE, "zft");
for (i = 0; i < 4; i++) {
- class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
+ class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i),
S_IFCHR | S_IRUSR | S_IWUSR,
"qft%i", i);
- class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
+ class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 4),
S_IFCHR | S_IRUSR | S_IWUSR,
"nqft%i", i);
- class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
+ class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 16),
S_IFCHR | S_IRUSR | S_IWUSR,
"zqft%i", i);
- class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
+ class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 20),
S_IFCHR | S_IRUSR | S_IWUSR,
"nzqft%i", i);
- class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
+ class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 32),
S_IFCHR | S_IRUSR | S_IWUSR,
"rawqft%i", i);
- class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
+ class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 36),
S_IFCHR | S_IRUSR | S_IWUSR,
"nrawqft%i", i);
@@ -381,19 +381,19 @@ static void zft_exit(void)
}
for (i = 0; i < 4; i++) {
devfs_remove("qft%i", i);
- class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i));
+ class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i));
devfs_remove("nqft%i", i);
- class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 4));
+ class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4));
devfs_remove("zqft%i", i);
- class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 16));
+ class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16));
devfs_remove("nzqft%i", i);
- class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 20));
+ class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20));
devfs_remove("rawqft%i", i);
- class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 32));
+ class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32));
devfs_remove("nrawqft%i", i);
- class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 36));
+ class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36));
}
- class_simple_destroy(zft_class);
+ class_destroy(zft_class);
zft_uninit_mem(); /* release remaining memory, if any */
printk(KERN_INFO "zftape successfully unloaded.\n");
TRACE_EXIT;
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 5ec732e6ca9..762fa430fb5 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -834,7 +834,7 @@ int hpet_alloc(struct hpet_data *hdp)
printk("\n");
ns = hpetp->hp_period; /* femptoseconds, 10^-15 */
- do_div(ns, 1000000); /* convert to nanoseconds, 10^-9 */
+ ns /= 1000000; /* convert to nanoseconds, 10^-9 */
printk(KERN_INFO "hpet%d: %ldns tick, %d %d-bit timers\n",
hpetp->hp_which, ns, hpetp->hp_ntimer,
cap & HPET_COUNTER_SIZE_MASK ? 64 : 32);
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index abfbdcfd4e7..3236d240490 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -1466,7 +1466,7 @@ static inline struct hvcs_struct *from_vio_dev(struct vio_dev *viod)
}
/* The sysfs interface for the driver and devices */
-static ssize_t hvcs_partner_vtys_show(struct device *dev, char *buf)
+static ssize_t hvcs_partner_vtys_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct vio_dev *viod = to_vio_dev(dev);
struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1480,7 +1480,7 @@ static ssize_t hvcs_partner_vtys_show(struct device *dev, char *buf)
}
static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL);
-static ssize_t hvcs_partner_clcs_show(struct device *dev, char *buf)
+static ssize_t hvcs_partner_clcs_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct vio_dev *viod = to_vio_dev(dev);
struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1494,7 +1494,7 @@ static ssize_t hvcs_partner_clcs_show(struct device *dev, char *buf)
}
static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL);
-static ssize_t hvcs_current_vty_store(struct device *dev, const char * buf,
+static ssize_t hvcs_current_vty_store(struct device *dev, struct device_attribute *attr, const char * buf,
size_t count)
{
/*
@@ -1505,7 +1505,7 @@ static ssize_t hvcs_current_vty_store(struct device *dev, const char * buf,
return -EPERM;
}
-static ssize_t hvcs_current_vty_show(struct device *dev, char *buf)
+static ssize_t hvcs_current_vty_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct vio_dev *viod = to_vio_dev(dev);
struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1521,7 +1521,7 @@ static ssize_t hvcs_current_vty_show(struct device *dev, char *buf)
static DEVICE_ATTR(current_vty,
S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store);
-static ssize_t hvcs_vterm_state_store(struct device *dev, const char *buf,
+static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct vio_dev *viod = to_vio_dev(dev);
@@ -1559,7 +1559,7 @@ static ssize_t hvcs_vterm_state_store(struct device *dev, const char *buf,
return count;
}
-static ssize_t hvcs_vterm_state_show(struct device *dev, char *buf)
+static ssize_t hvcs_vterm_state_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct vio_dev *viod = to_vio_dev(dev);
struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1574,7 +1574,7 @@ static ssize_t hvcs_vterm_state_show(struct device *dev, char *buf)
static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR,
hvcs_vterm_state_show, hvcs_vterm_state_store);
-static ssize_t hvcs_index_show(struct device *dev, char *buf)
+static ssize_t hvcs_index_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct vio_dev *viod = to_vio_dev(dev);
struct hvcs_struct *hvcsd = from_vio_dev(viod);
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index a8119764028..6c4b3f986d0 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -20,13 +20,14 @@
#include <linux/types.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
-#include <linux/apm_bios.h>
+#include <linux/seq_file.h>
+#include <linux/dmi.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/i8k.h>
-#define I8K_VERSION "1.13 14/05/2002"
+#define I8K_VERSION "1.14 21/02/2005"
#define I8K_SMM_FN_STATUS 0x0025
#define I8K_SMM_POWER_STATUS 0x0069
@@ -34,7 +35,8 @@
#define I8K_SMM_GET_FAN 0x00a3
#define I8K_SMM_GET_SPEED 0x02a3
#define I8K_SMM_GET_TEMP 0x10a3
-#define I8K_SMM_GET_DELL_SIG 0xffa3
+#define I8K_SMM_GET_DELL_SIG1 0xfea3
+#define I8K_SMM_GET_DELL_SIG2 0xffa3
#define I8K_SMM_BIOS_VERSION 0x00a6
#define I8K_FAN_MULT 30
@@ -52,18 +54,7 @@
#define I8K_TEMPERATURE_BUG 1
-#define DELL_SIGNATURE "Dell Computer"
-
-static char *supported_models[] = {
- "Inspiron",
- "Latitude",
- NULL
-};
-
-static char system_vendor[48] = "?";
-static char product_name [48] = "?";
-static char bios_version [4] = "?";
-static char serial_number[16] = "?";
+static char bios_version[4];
MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops");
@@ -73,6 +64,10 @@ static int force;
module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Force loading without checking for supported models");
+static int ignore_dmi;
+module_param(ignore_dmi, bool, 0);
+MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match");
+
static int restricted;
module_param(restricted, bool, 0);
MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set");
@@ -81,69 +76,69 @@ static int power_status;
module_param(power_status, bool, 0600);
MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k");
-static ssize_t i8k_read(struct file *, char __user *, size_t, loff_t *);
+static int i8k_open_fs(struct inode *inode, struct file *file);
static int i8k_ioctl(struct inode *, struct file *, unsigned int,
unsigned long);
static struct file_operations i8k_fops = {
- .read = i8k_read,
- .ioctl = i8k_ioctl,
+ .open = i8k_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .ioctl = i8k_ioctl,
+};
+
+struct smm_regs {
+ unsigned int eax;
+ unsigned int ebx __attribute__ ((packed));
+ unsigned int ecx __attribute__ ((packed));
+ unsigned int edx __attribute__ ((packed));
+ unsigned int esi __attribute__ ((packed));
+ unsigned int edi __attribute__ ((packed));
};
-typedef struct {
- unsigned int eax;
- unsigned int ebx __attribute__ ((packed));
- unsigned int ecx __attribute__ ((packed));
- unsigned int edx __attribute__ ((packed));
- unsigned int esi __attribute__ ((packed));
- unsigned int edi __attribute__ ((packed));
-} SMMRegisters;
-
-typedef struct {
- u8 type;
- u8 length;
- u16 handle;
-} DMIHeader;
+static inline char *i8k_get_dmi_data(int field)
+{
+ return dmi_get_system_info(field) ? : "N/A";
+}
/*
* Call the System Management Mode BIOS. Code provided by Jonathan Buzzard.
*/
-static int i8k_smm(SMMRegisters *regs)
+static int i8k_smm(struct smm_regs *regs)
{
- int rc;
- int eax = regs->eax;
-
- asm("pushl %%eax\n\t" \
- "movl 0(%%eax),%%edx\n\t" \
- "push %%edx\n\t" \
- "movl 4(%%eax),%%ebx\n\t" \
- "movl 8(%%eax),%%ecx\n\t" \
- "movl 12(%%eax),%%edx\n\t" \
- "movl 16(%%eax),%%esi\n\t" \
- "movl 20(%%eax),%%edi\n\t" \
- "popl %%eax\n\t" \
- "out %%al,$0xb2\n\t" \
- "out %%al,$0x84\n\t" \
- "xchgl %%eax,(%%esp)\n\t"
- "movl %%ebx,4(%%eax)\n\t" \
- "movl %%ecx,8(%%eax)\n\t" \
- "movl %%edx,12(%%eax)\n\t" \
- "movl %%esi,16(%%eax)\n\t" \
- "movl %%edi,20(%%eax)\n\t" \
- "popl %%edx\n\t" \
- "movl %%edx,0(%%eax)\n\t" \
- "lahf\n\t" \
- "shrl $8,%%eax\n\t" \
- "andl $1,%%eax\n" \
- : "=a" (rc)
- : "a" (regs)
- : "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
-
- if ((rc != 0) || ((regs->eax & 0xffff) == 0xffff) || (regs->eax == eax)) {
- return -EINVAL;
- }
-
- return 0;
+ int rc;
+ int eax = regs->eax;
+
+ asm("pushl %%eax\n\t"
+ "movl 0(%%eax),%%edx\n\t"
+ "push %%edx\n\t"
+ "movl 4(%%eax),%%ebx\n\t"
+ "movl 8(%%eax),%%ecx\n\t"
+ "movl 12(%%eax),%%edx\n\t"
+ "movl 16(%%eax),%%esi\n\t"
+ "movl 20(%%eax),%%edi\n\t"
+ "popl %%eax\n\t"
+ "out %%al,$0xb2\n\t"
+ "out %%al,$0x84\n\t"
+ "xchgl %%eax,(%%esp)\n\t"
+ "movl %%ebx,4(%%eax)\n\t"
+ "movl %%ecx,8(%%eax)\n\t"
+ "movl %%edx,12(%%eax)\n\t"
+ "movl %%esi,16(%%eax)\n\t"
+ "movl %%edi,20(%%eax)\n\t"
+ "popl %%edx\n\t"
+ "movl %%edx,0(%%eax)\n\t"
+ "lahf\n\t"
+ "shrl $8,%%eax\n\t"
+ "andl $1,%%eax\n":"=a"(rc)
+ : "a"(regs)
+ : "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
+
+ if (rc != 0 || (regs->eax & 0xffff) == 0xffff || regs->eax == eax)
+ return -EINVAL;
+
+ return 0;
}
/*
@@ -152,24 +147,9 @@ static int i8k_smm(SMMRegisters *regs)
*/
static int i8k_get_bios_version(void)
{
- SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
- int rc;
-
- regs.eax = I8K_SMM_BIOS_VERSION;
- if ((rc=i8k_smm(&regs)) < 0) {
- return rc;
- }
-
- return regs.eax;
-}
+ struct smm_regs regs = { .eax = I8K_SMM_BIOS_VERSION, };
-/*
- * Read the machine id.
- */
-static int i8k_get_serial_number(unsigned char *buff)
-{
- strlcpy(buff, serial_number, sizeof(serial_number));
- return 0;
+ return i8k_smm(&regs) ? : regs.eax;
}
/*
@@ -177,24 +157,22 @@ static int i8k_get_serial_number(unsigned char *buff)
*/
static int i8k_get_fn_status(void)
{
- SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
- int rc;
-
- regs.eax = I8K_SMM_FN_STATUS;
- if ((rc=i8k_smm(&regs)) < 0) {
- return rc;
- }
-
- switch ((regs.eax >> I8K_FN_SHIFT) & I8K_FN_MASK) {
- case I8K_FN_UP:
- return I8K_VOL_UP;
- case I8K_FN_DOWN:
- return I8K_VOL_DOWN;
- case I8K_FN_MUTE:
- return I8K_VOL_MUTE;
- default:
- return 0;
- }
+ struct smm_regs regs = { .eax = I8K_SMM_FN_STATUS, };
+ int rc;
+
+ if ((rc = i8k_smm(&regs)) < 0)
+ return rc;
+
+ switch ((regs.eax >> I8K_FN_SHIFT) & I8K_FN_MASK) {
+ case I8K_FN_UP:
+ return I8K_VOL_UP;
+ case I8K_FN_DOWN:
+ return I8K_VOL_DOWN;
+ case I8K_FN_MUTE:
+ return I8K_VOL_MUTE;
+ default:
+ return 0;
+ }
}
/*
@@ -202,20 +180,13 @@ static int i8k_get_fn_status(void)
*/
static int i8k_get_power_status(void)
{
- SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
- int rc;
-
- regs.eax = I8K_SMM_POWER_STATUS;
- if ((rc=i8k_smm(&regs)) < 0) {
- return rc;
- }
-
- switch (regs.eax & 0xff) {
- case I8K_POWER_AC:
- return I8K_AC;
- default:
- return I8K_BATTERY;
- }
+ struct smm_regs regs = { .eax = I8K_SMM_POWER_STATUS, };
+ int rc;
+
+ if ((rc = i8k_smm(&regs)) < 0)
+ return rc;
+
+ return (regs.eax & 0xff) == I8K_POWER_AC ? I8K_AC : I8K_BATTERY;
}
/*
@@ -223,16 +194,10 @@ static int i8k_get_power_status(void)
*/
static int i8k_get_fan_status(int fan)
{
- SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
- int rc;
-
- regs.eax = I8K_SMM_GET_FAN;
- regs.ebx = fan & 0xff;
- if ((rc=i8k_smm(&regs)) < 0) {
- return rc;
- }
+ struct smm_regs regs = { .eax = I8K_SMM_GET_FAN, };
- return (regs.eax & 0xff);
+ regs.ebx = fan & 0xff;
+ return i8k_smm(&regs) ? : regs.eax & 0xff;
}
/*
@@ -240,16 +205,10 @@ static int i8k_get_fan_status(int fan)
*/
static int i8k_get_fan_speed(int fan)
{
- SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
- int rc;
+ struct smm_regs regs = { .eax = I8K_SMM_GET_SPEED, };
- regs.eax = I8K_SMM_GET_SPEED;
- regs.ebx = fan & 0xff;
- if ((rc=i8k_smm(&regs)) < 0) {
- return rc;
- }
-
- return (regs.eax & 0xffff) * I8K_FAN_MULT;
+ regs.ebx = fan & 0xff;
+ return i8k_smm(&regs) ? : (regs.eax & 0xffff) * I8K_FAN_MULT;
}
/*
@@ -257,532 +216,318 @@ static int i8k_get_fan_speed(int fan)
*/
static int i8k_set_fan(int fan, int speed)
{
- SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
- int rc;
-
- speed = (speed < 0) ? 0 : ((speed > I8K_FAN_MAX) ? I8K_FAN_MAX : speed);
+ struct smm_regs regs = { .eax = I8K_SMM_SET_FAN, };
- regs.eax = I8K_SMM_SET_FAN;
- regs.ebx = (fan & 0xff) | (speed << 8);
- if ((rc=i8k_smm(&regs)) < 0) {
- return rc;
- }
+ speed = (speed < 0) ? 0 : ((speed > I8K_FAN_MAX) ? I8K_FAN_MAX : speed);
+ regs.ebx = (fan & 0xff) | (speed << 8);
- return (i8k_get_fan_status(fan));
+ return i8k_smm(&regs) ? : i8k_get_fan_status(fan);
}
/*
* Read the cpu temperature.
*/
-static int i8k_get_cpu_temp(void)
+static int i8k_get_temp(int sensor)
{
- SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
- int rc;
- int temp;
+ struct smm_regs regs = { .eax = I8K_SMM_GET_TEMP, };
+ int rc;
+ int temp;
#ifdef I8K_TEMPERATURE_BUG
- static int prev = 0;
+ static int prev;
#endif
+ regs.ebx = sensor & 0xff;
+ if ((rc = i8k_smm(&regs)) < 0)
+ return rc;
- regs.eax = I8K_SMM_GET_TEMP;
- if ((rc=i8k_smm(&regs)) < 0) {
- return rc;
- }
- temp = regs.eax & 0xff;
+ temp = regs.eax & 0xff;
#ifdef I8K_TEMPERATURE_BUG
- /*
- * Sometimes the temperature sensor returns 0x99, which is out of range.
- * In this case we return (once) the previous cached value. For example:
- # 1003655137 00000058 00005a4b
- # 1003655138 00000099 00003a80 <--- 0x99 = 153 degrees
- # 1003655139 00000054 00005c52
- */
- if (temp > I8K_MAX_TEMP) {
- temp = prev;
- prev = I8K_MAX_TEMP;
- } else {
- prev = temp;
- }
+ /*
+ * Sometimes the temperature sensor returns 0x99, which is out of range.
+ * In this case we return (once) the previous cached value. For example:
+ # 1003655137 00000058 00005a4b
+ # 1003655138 00000099 00003a80 <--- 0x99 = 153 degrees
+ # 1003655139 00000054 00005c52
+ */
+ if (temp > I8K_MAX_TEMP) {
+ temp = prev;
+ prev = I8K_MAX_TEMP;
+ } else {
+ prev = temp;
+ }
#endif
- return temp;
+ return temp;
}
-static int i8k_get_dell_signature(void)
+static int i8k_get_dell_signature(int req_fn)
{
- SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
- int rc;
+ struct smm_regs regs = { .eax = req_fn, };
+ int rc;
- regs.eax = I8K_SMM_GET_DELL_SIG;
- if ((rc=i8k_smm(&regs)) < 0) {
- return rc;
- }
+ if ((rc = i8k_smm(&regs)) < 0)
+ return rc;
- if ((regs.eax == 1145651527) && (regs.edx == 1145392204)) {
- return 0;
- } else {
- return -1;
- }
+ return regs.eax == 1145651527 && regs.edx == 1145392204 ? 0 : -1;
}
static int i8k_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
unsigned long arg)
{
- int val;
- int speed;
- unsigned char buff[16];
- int __user *argp = (int __user *)arg;
-
- if (!argp)
- return -EINVAL;
-
- switch (cmd) {
- case I8K_BIOS_VERSION:
- val = i8k_get_bios_version();
- break;
-
- case I8K_MACHINE_ID:
- memset(buff, 0, 16);
- val = i8k_get_serial_number(buff);
- break;
-
- case I8K_FN_STATUS:
- val = i8k_get_fn_status();
- break;
-
- case I8K_POWER_STATUS:
- val = i8k_get_power_status();
- break;
-
- case I8K_GET_TEMP:
- val = i8k_get_cpu_temp();
- break;
-
- case I8K_GET_SPEED:
- if (copy_from_user(&val, argp, sizeof(int))) {
- return -EFAULT;
- }
- val = i8k_get_fan_speed(val);
- break;
-
- case I8K_GET_FAN:
- if (copy_from_user(&val, argp, sizeof(int))) {
- return -EFAULT;
- }
- val = i8k_get_fan_status(val);
- break;
+ int val = 0;
+ int speed;
+ unsigned char buff[16];
+ int __user *argp = (int __user *)arg;
- case I8K_SET_FAN:
- if (restricted && !capable(CAP_SYS_ADMIN)) {
- return -EPERM;
- }
- if (copy_from_user(&val, argp, sizeof(int))) {
- return -EFAULT;
- }
- if (copy_from_user(&speed, argp+1, sizeof(int))) {
- return -EFAULT;
- }
- val = i8k_set_fan(val, speed);
- break;
+ if (!argp)
+ return -EINVAL;
- default:
- return -EINVAL;
- }
+ switch (cmd) {
+ case I8K_BIOS_VERSION:
+ val = i8k_get_bios_version();
+ break;
- if (val < 0) {
- return val;
- }
+ case I8K_MACHINE_ID:
+ memset(buff, 0, 16);
+ strlcpy(buff, i8k_get_dmi_data(DMI_PRODUCT_SERIAL), sizeof(buff));
+ break;
- switch (cmd) {
- case I8K_BIOS_VERSION:
- if (copy_to_user(argp, &val, 4)) {
- return -EFAULT;
- }
- break;
- case I8K_MACHINE_ID:
- if (copy_to_user(argp, buff, 16)) {
- return -EFAULT;
- }
- break;
- default:
- if (copy_to_user(argp, &val, sizeof(int))) {
- return -EFAULT;
- }
- break;
- }
+ case I8K_FN_STATUS:
+ val = i8k_get_fn_status();
+ break;
- return 0;
-}
+ case I8K_POWER_STATUS:
+ val = i8k_get_power_status();
+ break;
-/*
- * Print the information for /proc/i8k.
- */
-static int i8k_get_info(char *buffer, char **start, off_t fpos, int length)
-{
- int n, fn_key, cpu_temp, ac_power;
- int left_fan, right_fan, left_speed, right_speed;
-
- cpu_temp = i8k_get_cpu_temp(); /* 11100 Ás */
- left_fan = i8k_get_fan_status(I8K_FAN_LEFT); /* 580 Ás */
- right_fan = i8k_get_fan_status(I8K_FAN_RIGHT); /* 580 Ás */
- left_speed = i8k_get_fan_speed(I8K_FAN_LEFT); /* 580 Ás */
- right_speed = i8k_get_fan_speed(I8K_FAN_RIGHT); /* 580 Ás */
- fn_key = i8k_get_fn_status(); /* 750 Ás */
- if (power_status) {
- ac_power = i8k_get_power_status(); /* 14700 Ás */
- } else {
- ac_power = -1;
- }
-
- /*
- * Info:
- *
- * 1) Format version (this will change if format changes)
- * 2) BIOS version
- * 3) BIOS machine ID
- * 4) Cpu temperature
- * 5) Left fan status
- * 6) Right fan status
- * 7) Left fan speed
- * 8) Right fan speed
- * 9) AC power
- * 10) Fn Key status
- */
- n = sprintf(buffer, "%s %s %s %d %d %d %d %d %d %d\n",
- I8K_PROC_FMT,
- bios_version,
- serial_number,
- cpu_temp,
- left_fan,
- right_fan,
- left_speed,
- right_speed,
- ac_power,
- fn_key);
-
- return n;
-}
+ case I8K_GET_TEMP:
+ val = i8k_get_temp(0);
+ break;
-static ssize_t i8k_read(struct file *f, char __user *buffer, size_t len, loff_t *fpos)
-{
- int n;
- char info[128];
+ case I8K_GET_SPEED:
+ if (copy_from_user(&val, argp, sizeof(int)))
+ return -EFAULT;
- n = i8k_get_info(info, NULL, 0, 128);
- if (n <= 0) {
- return n;
- }
+ val = i8k_get_fan_speed(val);
+ break;
- if (*fpos >= n) {
- return 0;
- }
+ case I8K_GET_FAN:
+ if (copy_from_user(&val, argp, sizeof(int)))
+ return -EFAULT;
- if ((*fpos + len) >= n) {
- len = n - *fpos;
- }
+ val = i8k_get_fan_status(val);
+ break;
- if (copy_to_user(buffer, info, len) != 0) {
- return -EFAULT;
- }
+ case I8K_SET_FAN:
+ if (restricted && !capable(CAP_SYS_ADMIN))
+ return -EPERM;
- *fpos += len;
- return len;
-}
+ if (copy_from_user(&val, argp, sizeof(int)))
+ return -EFAULT;
-static char* __init string_trim(char *s, int size)
-{
- int len;
- char *p;
+ if (copy_from_user(&speed, argp + 1, sizeof(int)))
+ return -EFAULT;
- if ((len = strlen(s)) > size) {
- len = size;
- }
+ val = i8k_set_fan(val, speed);
+ break;
- for (p=s+len-1; len && (*p==' '); len--,p--) {
- *p = '\0';
- }
+ default:
+ return -EINVAL;
+ }
- return s;
-}
+ if (val < 0)
+ return val;
-/* DMI code, stolen from arch/i386/kernel/dmi_scan.c */
+ switch (cmd) {
+ case I8K_BIOS_VERSION:
+ if (copy_to_user(argp, &val, 4))
+ return -EFAULT;
-/*
- * |<-- dmi->length -->|
- * | |
- * |dmi header s=N | string1,\0, ..., stringN,\0, ..., \0
- * | |
- * +-----------------------+
- */
-static char* __init dmi_string(DMIHeader *dmi, u8 s)
-{
- u8 *p;
+ break;
+ case I8K_MACHINE_ID:
+ if (copy_to_user(argp, buff, 16))
+ return -EFAULT;
- if (!s) {
- return "";
- }
- s--;
+ break;
+ default:
+ if (copy_to_user(argp, &val, sizeof(int)))
+ return -EFAULT;
- p = (u8 *)dmi + dmi->length;
- while (s > 0) {
- p += strlen(p);
- p++;
- s--;
- }
+ break;
+ }
- return p;
+ return 0;
}
-static void __init dmi_decode(DMIHeader *dmi)
+/*
+ * Print the information for /proc/i8k.
+ */
+static int i8k_proc_show(struct seq_file *seq, void *offset)
{
- u8 *data = (u8 *) dmi;
- char *p;
-
-#ifdef I8K_DEBUG
- int i;
- printk("%08x ", (int)data);
- for (i=0; i<data[1] && i<64; i++) {
- printk("%02x ", data[i]);
- }
- printk("\n");
-#endif
-
- switch (dmi->type) {
- case 0: /* BIOS Information */
- p = dmi_string(dmi,data[5]);
- if (*p) {
- strlcpy(bios_version, p, sizeof(bios_version));
- string_trim(bios_version, sizeof(bios_version));
- }
- break;
- case 1: /* System Information */
- p = dmi_string(dmi,data[4]);
- if (*p) {
- strlcpy(system_vendor, p, sizeof(system_vendor));
- string_trim(system_vendor, sizeof(system_vendor));
- }
- p = dmi_string(dmi,data[5]);
- if (*p) {
- strlcpy(product_name, p, sizeof(product_name));
- string_trim(product_name, sizeof(product_name));
- }
- p = dmi_string(dmi,data[7]);
- if (*p) {
- strlcpy(serial_number, p, sizeof(serial_number));
- string_trim(serial_number, sizeof(serial_number));
- }
- break;
- }
-}
+ int fn_key, cpu_temp, ac_power;
+ int left_fan, right_fan, left_speed, right_speed;
+
+ cpu_temp = i8k_get_temp(0); /* 11100 Ás */
+ left_fan = i8k_get_fan_status(I8K_FAN_LEFT); /* 580 Ás */
+ right_fan = i8k_get_fan_status(I8K_FAN_RIGHT); /* 580 Ás */
+ left_speed = i8k_get_fan_speed(I8K_FAN_LEFT); /* 580 Ás */
+ right_speed = i8k_get_fan_speed(I8K_FAN_RIGHT); /* 580 Ás */
+ fn_key = i8k_get_fn_status(); /* 750 Ás */
+ if (power_status)
+ ac_power = i8k_get_power_status(); /* 14700 Ás */
+ else
+ ac_power = -1;
-static int __init dmi_table(u32 base, int len, int num, void (*fn)(DMIHeader*))
-{
- u8 *buf;
- u8 *data;
- DMIHeader *dmi;
- int i = 1;
-
- buf = ioremap(base, len);
- if (buf == NULL) {
- return -1;
- }
- data = buf;
-
- /*
- * Stop when we see al the items the table claimed to have
- * or we run off the end of the table (also happens)
- */
- while ((i<num) && ((data-buf) < len)) {
- dmi = (DMIHeader *)data;
- /*
- * Avoid misparsing crud if the length of the last
- * record is crap
- */
- if ((data-buf+dmi->length) >= len) {
- break;
- }
- fn(dmi);
- data += dmi->length;
/*
- * Don't go off the end of the data if there is
- * stuff looking like string fill past the end
+ * Info:
+ *
+ * 1) Format version (this will change if format changes)
+ * 2) BIOS version
+ * 3) BIOS machine ID
+ * 4) Cpu temperature
+ * 5) Left fan status
+ * 6) Right fan status
+ * 7) Left fan speed
+ * 8) Right fan speed
+ * 9) AC power
+ * 10) Fn Key status
*/
- while (((data-buf) < len) && (*data || data[1])) {
- data++;
- }
- data += 2;
- i++;
- }
- iounmap(buf);
-
- return 0;
+ return seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n",
+ I8K_PROC_FMT,
+ bios_version,
+ dmi_get_system_info(DMI_PRODUCT_SERIAL) ? : "N/A",
+ cpu_temp,
+ left_fan, right_fan, left_speed, right_speed,
+ ac_power, fn_key);
}
-static int __init dmi_iterate(void (*decode)(DMIHeader *))
+static int i8k_open_fs(struct inode *inode, struct file *file)
{
- unsigned char buf[20];
- void __iomem *p = ioremap(0xe0000, 0x20000), *q;
-
- if (!p)
- return -1;
-
- for (q = p; q < p + 0x20000; q += 16) {
- memcpy_fromio(buf, q, 20);
- if (memcmp(buf, "_DMI_", 5)==0) {
- u16 num = buf[13]<<8 | buf[12];
- u16 len = buf [7]<<8 | buf [6];
- u32 base = buf[11]<<24 | buf[10]<<16 | buf[9]<<8 | buf[8];
-#ifdef I8K_DEBUG
- printk(KERN_INFO "DMI %d.%d present.\n",
- buf[14]>>4, buf[14]&0x0F);
- printk(KERN_INFO "%d structures occupying %d bytes.\n",
- buf[13]<<8 | buf[12],
- buf [7]<<8 | buf[6]);
- printk(KERN_INFO "DMI table at 0x%08X.\n",
- buf[11]<<24 | buf[10]<<16 | buf[9]<<8 | buf[8]);
-#endif
- if (dmi_table(base, len, num, decode)==0) {
- iounmap(p);
- return 0;
- }
- }
- }
- iounmap(p);
- return -1;
+ return single_open(file, i8k_proc_show, NULL);
}
-/* end of DMI code */
-
-/*
- * Get DMI information.
- */
-static int __init i8k_dmi_probe(void)
-{
- char **p;
-
- if (dmi_iterate(dmi_decode) != 0) {
- printk(KERN_INFO "i8k: unable to get DMI information\n");
- return -ENODEV;
- }
-
- if (strncmp(system_vendor,DELL_SIGNATURE,strlen(DELL_SIGNATURE)) != 0) {
- printk(KERN_INFO "i8k: not running on a Dell system\n");
- return -ENODEV;
- }
-
- for (p=supported_models; ; p++) {
- if (!*p) {
- printk(KERN_INFO "i8k: unsupported model: %s\n", product_name);
- return -ENODEV;
- }
- if (strncmp(product_name,*p,strlen(*p)) == 0) {
- break;
- }
- }
- return 0;
-}
+static struct dmi_system_id __initdata i8k_dmi_table[] = {
+ {
+ .ident = "Dell Inspiron",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron"),
+ },
+ },
+ {
+ .ident = "Dell Latitude",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
+ },
+ },
+ {
+ .ident = "Dell Inspiron 2",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron"),
+ },
+ },
+ {
+ .ident = "Dell Latitude 2",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
+ },
+ },
+ { }
+};
/*
* Probe for the presence of a supported laptop.
*/
static int __init i8k_probe(void)
{
- char buff[4];
- int version;
- int smm_found = 0;
-
- /*
- * Get DMI information
- */
- if (i8k_dmi_probe() != 0) {
- printk(KERN_INFO "i8k: vendor=%s, model=%s, version=%s\n",
- system_vendor, product_name, bios_version);
- }
-
- /*
- * Get SMM Dell signature
- */
- if (i8k_get_dell_signature() != 0) {
- printk(KERN_INFO "i8k: unable to get SMM Dell signature\n");
- } else {
- smm_found = 1;
- }
-
- /*
- * Get SMM BIOS version.
- */
- version = i8k_get_bios_version();
- if (version <= 0) {
- printk(KERN_INFO "i8k: unable to get SMM BIOS version\n");
- } else {
- smm_found = 1;
- buff[0] = (version >> 16) & 0xff;
- buff[1] = (version >> 8) & 0xff;
- buff[2] = (version) & 0xff;
- buff[3] = '\0';
+ char buff[4];
+ int version;
+
/*
- * If DMI BIOS version is unknown use SMM BIOS version.
+ * Get DMI information
*/
- if (bios_version[0] == '?') {
- strcpy(bios_version, buff);
+ if (!dmi_check_system(i8k_dmi_table)) {
+ if (!ignore_dmi && !force)
+ return -ENODEV;
+
+ printk(KERN_INFO "i8k: not running on a supported Dell system.\n");
+ printk(KERN_INFO "i8k: vendor=%s, model=%s, version=%s\n",
+ i8k_get_dmi_data(DMI_SYS_VENDOR),
+ i8k_get_dmi_data(DMI_PRODUCT_NAME),
+ i8k_get_dmi_data(DMI_BIOS_VERSION));
}
+
+ strlcpy(bios_version, i8k_get_dmi_data(DMI_BIOS_VERSION), sizeof(bios_version));
+
/*
- * Check if the two versions match.
+ * Get SMM Dell signature
*/
- if (strncmp(buff,bios_version,sizeof(bios_version)) != 0) {
- printk(KERN_INFO "i8k: BIOS version mismatch: %s != %s\n",
- buff, bios_version);
+ if (i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG1) &&
+ i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG2)) {
+ printk(KERN_ERR "i8k: unable to get SMM Dell signature\n");
+ if (!force)
+ return -ENODEV;
}
- }
- if (!smm_found && !force) {
- return -ENODEV;
- }
+ /*
+ * Get SMM BIOS version.
+ */
+ version = i8k_get_bios_version();
+ if (version <= 0) {
+ printk(KERN_WARNING "i8k: unable to get SMM BIOS version\n");
+ } else {
+ buff[0] = (version >> 16) & 0xff;
+ buff[1] = (version >> 8) & 0xff;
+ buff[2] = (version) & 0xff;
+ buff[3] = '\0';
+ /*
+ * If DMI BIOS version is unknown use SMM BIOS version.
+ */
+ if (!dmi_get_system_info(DMI_BIOS_VERSION))
+ strlcpy(bios_version, buff, sizeof(bios_version));
+
+ /*
+ * Check if the two versions match.
+ */
+ if (strncmp(buff, bios_version, sizeof(bios_version)) != 0)
+ printk(KERN_WARNING "i8k: BIOS version mismatch: %s != %s\n",
+ buff, bios_version);
+ }
- return 0;
+ return 0;
}
-#ifdef MODULE
-static
-#endif
-int __init i8k_init(void)
+static int __init i8k_init(void)
{
- struct proc_dir_entry *proc_i8k;
-
- /* Are we running on an supported laptop? */
- if (i8k_probe() != 0) {
- return -ENODEV;
- }
-
- /* Register the proc entry */
- proc_i8k = create_proc_info_entry("i8k", 0, NULL, i8k_get_info);
- if (!proc_i8k) {
- return -ENOENT;
- }
- proc_i8k->proc_fops = &i8k_fops;
- proc_i8k->owner = THIS_MODULE;
-
- printk(KERN_INFO
- "Dell laptop SMM driver v%s Massimo Dal Zotto (dz@debian.org)\n",
- I8K_VERSION);
-
- return 0;
-}
+ struct proc_dir_entry *proc_i8k;
-#ifdef MODULE
-int init_module(void)
-{
- return i8k_init();
+ /* Are we running on an supported laptop? */
+ if (i8k_probe())
+ return -ENODEV;
+
+ /* Register the proc entry */
+ proc_i8k = create_proc_entry("i8k", 0, NULL);
+ if (!proc_i8k)
+ return -ENOENT;
+
+ proc_i8k->proc_fops = &i8k_fops;
+ proc_i8k->owner = THIS_MODULE;
+
+ printk(KERN_INFO
+ "Dell laptop SMM driver v%s Massimo Dal Zotto (dz@debian.org)\n",
+ I8K_VERSION);
+
+ return 0;
}
-void cleanup_module(void)
+static void __exit i8k_exit(void)
{
- /* Remove the proc entry */
- remove_proc_entry("i8k", NULL);
-
- printk(KERN_INFO "i8k: module unloaded\n");
+ remove_proc_entry("i8k", NULL);
}
-#endif
-/* end of file */
+module_init(i8k_init);
+module_exit(i8k_exit);
diff --git a/drivers/char/ip2/i2cmd.c b/drivers/char/ip2/i2cmd.c
index fd299d6c42a..cb8f4198e9a 100644
--- a/drivers/char/ip2/i2cmd.c
+++ b/drivers/char/ip2/i2cmd.c
@@ -97,7 +97,7 @@ static UCHAR ct41[] = { 1, BYP, 0x29 }; // RESUME
//static UCHAR ct44[]={ 2, BTH, 0x2C,0 }; // MS PING
//static UCHAR ct45[]={ 1, BTH, 0x2D }; // HOTENAB
//static UCHAR ct46[]={ 1, BTH, 0x2E }; // HOTDSAB
-static UCHAR ct47[] = { 7, BTH, 0x2F,0,0,0,0,0,0 }; // UNIX FLAGS
+//static UCHAR ct47[]={ 7, BTH, 0x2F,0,0,0,0,0,0 }; // UNIX FLAGS
//static UCHAR ct48[]={ 1, BTH, 0x30 }; // DSRFLOWENAB
//static UCHAR ct49[]={ 1, BTH, 0x31 }; // DSRFLOWDSAB
//static UCHAR ct50[]={ 1, BTH, 0x32 }; // DTRFLOWENAB
@@ -162,6 +162,7 @@ static UCHAR ct89[]={ 1, BYP, 0x59 }; // DSS_NOW
// This routine sets the parameters of command 47 and returns a pointer to the
// appropriate structure.
//******************************************************************************
+#if 0
cmdSyntaxPtr
i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag)
{
@@ -175,6 +176,7 @@ i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag)
pCM->cmd[6] = (unsigned char) (lflag >> 8);
return pCM;
}
+#endif /* 0 */
//******************************************************************************
// Function: i2cmdBaudDef(which, rate)
@@ -187,7 +189,7 @@ i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag)
// This routine sets the parameters of commands 54 or 55 (according to the
// argument which), and returns a pointer to the appropriate structure.
//******************************************************************************
-cmdSyntaxPtr
+static cmdSyntaxPtr
i2cmdBaudDef(int which, unsigned short rate)
{
cmdSyntaxPtr pCM;
diff --git a/drivers/char/ip2/i2cmd.h b/drivers/char/ip2/i2cmd.h
index c41728a8571..baa4e721b75 100644
--- a/drivers/char/ip2/i2cmd.h
+++ b/drivers/char/ip2/i2cmd.h
@@ -64,16 +64,6 @@ typedef struct _cmdSyntax
// directly from user-level
#define VAR 0x10 // This command is of variable length!
-//-----------------------------------
-// External declarations for i2cmd.c
-//-----------------------------------
-// Routine to set up parameters for the "define hot-key sequence" command. Since
-// there is more than one parameter to assign, we must use a function rather
-// than a macro (used usually).
-//
-extern cmdSyntaxPtr i2cmdUnixFlags(USHORT iflag,USHORT cflag,USHORT lflag);
-extern cmdSyntaxPtr i2cmdBaudDef(int which, USHORT rate);
-
// Declarations for the global arrays used to bear the commands and their
// arguments.
//
@@ -433,6 +423,7 @@ static UCHAR cc02[];
#define CMD_HOT_ENAB (cmdSyntaxPtr)(ct45) // Enable Hot-key checking
#define CMD_HOT_DSAB (cmdSyntaxPtr)(ct46) // Disable Hot-key checking
+#if 0
// COMMAND 47: Send Protocol info via Unix flags:
// iflag = Unix tty t_iflag
// cflag = Unix tty t_cflag
@@ -441,6 +432,7 @@ static UCHAR cc02[];
// within these flags
//
#define CMD_UNIX_FLAGS(iflag,cflag,lflag) i2cmdUnixFlags(iflag,cflag,lflag)
+#endif /* 0 */
#define CMD_DSRFL_ENAB (cmdSyntaxPtr)(ct48) // Enable DSR receiver ctrl
#define CMD_DSRFL_DSAB (cmdSyntaxPtr)(ct49) // Disable DSR receiver ctrl
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
index fca9a978fb7..cf0cd58d630 100644
--- a/drivers/char/ip2main.c
+++ b/drivers/char/ip2main.c
@@ -302,7 +302,7 @@ static char rirqs[IP2_MAX_BOARDS];
static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0};
/* for sysfs class support */
-static struct class_simple *ip2_class;
+static struct class *ip2_class;
// Some functions to keep track of what irq's we have
@@ -414,9 +414,9 @@ cleanup_module(void)
iiResetDelay( i2BoardPtrTable[i] );
/* free io addresses and Tibet */
release_region( ip2config.addr[i], 8 );
- class_simple_device_remove(MKDEV(IP2_IPL_MAJOR, 4 * i));
+ class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
devfs_remove("ip2/ipl%d", i);
- class_simple_device_remove(MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
+ class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
devfs_remove("ip2/stat%d", i);
}
/* Disable and remove interrupt handler. */
@@ -425,7 +425,7 @@ cleanup_module(void)
clear_requested_irq( ip2config.irq[i]);
}
}
- class_simple_destroy(ip2_class);
+ class_destroy(ip2_class);
devfs_remove("ip2");
if ( ( err = tty_unregister_driver ( ip2_tty_driver ) ) ) {
printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err);
@@ -700,7 +700,7 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err );
} else {
/* create the sysfs class */
- ip2_class = class_simple_create(THIS_MODULE, "ip2");
+ ip2_class = class_create(THIS_MODULE, "ip2");
if (IS_ERR(ip2_class)) {
err = PTR_ERR(ip2_class);
goto out_chrdev;
@@ -722,25 +722,25 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
}
if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
- class_simple_device_add(ip2_class, MKDEV(IP2_IPL_MAJOR,
+ class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR,
4 * i), NULL, "ipl%d", i);
err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i),
S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
"ip2/ipl%d", i);
if (err) {
- class_simple_device_remove(MKDEV(IP2_IPL_MAJOR,
- 4 * i));
+ class_device_destroy(ip2_class,
+ MKDEV(IP2_IPL_MAJOR, 4 * i));
goto out_class;
}
- class_simple_device_add(ip2_class, MKDEV(IP2_IPL_MAJOR,
+ class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR,
4 * i + 1), NULL, "stat%d", i);
err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
"ip2/stat%d", i);
if (err) {
- class_simple_device_remove(MKDEV(IP2_IPL_MAJOR,
- 4 * i + 1));
+ class_device_destroy(ip2_class,
+ MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
goto out_class;
}
@@ -798,7 +798,7 @@ retry:
goto out;
out_class:
- class_simple_destroy(ip2_class);
+ class_destroy(ip2_class);
out_chrdev:
unregister_chrdev(IP2_IPL_MAJOR, "ip2");
out:
@@ -2691,16 +2691,6 @@ no_xon:
pCh->flags |= ASYNC_CHECK_CD;
}
-#ifdef XXX
-do_flags_thing: // This is a test, we don't do the flags thing
-
- if ( (cflag & CRTSCTS) ) {
- cflag |= 014000000000;
- }
- i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1,
- CMD_UNIX_FLAGS(iflag,cflag,lflag));
-#endif
-
service_it:
i2DrainOutput( pCh, 100 );
}
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 4bb9af736fb..e0a53570fea 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -45,6 +45,7 @@
#include <asm/semaphore.h>
#include <linux/init.h>
#include <linux/device.h>
+#include <linux/compat.h>
#define IPMI_DEVINTF_VERSION "v33"
@@ -500,10 +501,205 @@ static int ipmi_ioctl(struct inode *inode,
return rv;
}
+#ifdef CONFIG_COMPAT
+
+/*
+ * The following code contains code for supporting 32-bit compatible
+ * ioctls on 64-bit kernels. This allows running 32-bit apps on the
+ * 64-bit kernel
+ */
+#define COMPAT_IPMICTL_SEND_COMMAND \
+ _IOR(IPMI_IOC_MAGIC, 13, struct compat_ipmi_req)
+#define COMPAT_IPMICTL_SEND_COMMAND_SETTIME \
+ _IOR(IPMI_IOC_MAGIC, 21, struct compat_ipmi_req_settime)
+#define COMPAT_IPMICTL_RECEIVE_MSG \
+ _IOWR(IPMI_IOC_MAGIC, 12, struct compat_ipmi_recv)
+#define COMPAT_IPMICTL_RECEIVE_MSG_TRUNC \
+ _IOWR(IPMI_IOC_MAGIC, 11, struct compat_ipmi_recv)
+
+struct compat_ipmi_msg {
+ u8 netfn;
+ u8 cmd;
+ u16 data_len;
+ compat_uptr_t data;
+};
+
+struct compat_ipmi_req {
+ compat_uptr_t addr;
+ compat_uint_t addr_len;
+ compat_long_t msgid;
+ struct compat_ipmi_msg msg;
+};
+
+struct compat_ipmi_recv {
+ compat_int_t recv_type;
+ compat_uptr_t addr;
+ compat_uint_t addr_len;
+ compat_long_t msgid;
+ struct compat_ipmi_msg msg;
+};
+
+struct compat_ipmi_req_settime {
+ struct compat_ipmi_req req;
+ compat_int_t retries;
+ compat_uint_t retry_time_ms;
+};
+
+/*
+ * Define some helper functions for copying IPMI data
+ */
+static long get_compat_ipmi_msg(struct ipmi_msg *p64,
+ struct compat_ipmi_msg __user *p32)
+{
+ compat_uptr_t tmp;
+
+ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
+ __get_user(p64->netfn, &p32->netfn) ||
+ __get_user(p64->cmd, &p32->cmd) ||
+ __get_user(p64->data_len, &p32->data_len) ||
+ __get_user(tmp, &p32->data))
+ return -EFAULT;
+ p64->data = compat_ptr(tmp);
+ return 0;
+}
+
+static long put_compat_ipmi_msg(struct ipmi_msg *p64,
+ struct compat_ipmi_msg __user *p32)
+{
+ if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
+ __put_user(p64->netfn, &p32->netfn) ||
+ __put_user(p64->cmd, &p32->cmd) ||
+ __put_user(p64->data_len, &p32->data_len))
+ return -EFAULT;
+ return 0;
+}
+
+static long get_compat_ipmi_req(struct ipmi_req *p64,
+ struct compat_ipmi_req __user *p32)
+{
+
+ compat_uptr_t tmp;
+
+ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
+ __get_user(tmp, &p32->addr) ||
+ __get_user(p64->addr_len, &p32->addr_len) ||
+ __get_user(p64->msgid, &p32->msgid) ||
+ get_compat_ipmi_msg(&p64->msg, &p32->msg))
+ return -EFAULT;
+ p64->addr = compat_ptr(tmp);
+ return 0;
+}
+
+static long get_compat_ipmi_req_settime(struct ipmi_req_settime *p64,
+ struct compat_ipmi_req_settime __user *p32)
+{
+ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
+ get_compat_ipmi_req(&p64->req, &p32->req) ||
+ __get_user(p64->retries, &p32->retries) ||
+ __get_user(p64->retry_time_ms, &p32->retry_time_ms))
+ return -EFAULT;
+ return 0;
+}
+
+static long get_compat_ipmi_recv(struct ipmi_recv *p64,
+ struct compat_ipmi_recv __user *p32)
+{
+ compat_uptr_t tmp;
+
+ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
+ __get_user(p64->recv_type, &p32->recv_type) ||
+ __get_user(tmp, &p32->addr) ||
+ __get_user(p64->addr_len, &p32->addr_len) ||
+ __get_user(p64->msgid, &p32->msgid) ||
+ get_compat_ipmi_msg(&p64->msg, &p32->msg))
+ return -EFAULT;
+ p64->addr = compat_ptr(tmp);
+ return 0;
+}
+
+static long put_compat_ipmi_recv(struct ipmi_recv *p64,
+ struct compat_ipmi_recv __user *p32)
+{
+ if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
+ __put_user(p64->recv_type, &p32->recv_type) ||
+ __put_user(p64->addr_len, &p32->addr_len) ||
+ __put_user(p64->msgid, &p32->msgid) ||
+ put_compat_ipmi_msg(&p64->msg, &p32->msg))
+ return -EFAULT;
+ return 0;
+}
+
+/*
+ * Handle compatibility ioctls
+ */
+static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
+ unsigned long arg)
+{
+ int rc;
+ struct ipmi_file_private *priv = filep->private_data;
+
+ switch(cmd) {
+ case COMPAT_IPMICTL_SEND_COMMAND:
+ {
+ struct ipmi_req rp;
+
+ if (get_compat_ipmi_req(&rp, compat_ptr(arg)))
+ return -EFAULT;
+
+ return handle_send_req(priv->user, &rp,
+ priv->default_retries,
+ priv->default_retry_time_ms);
+ }
+ case COMPAT_IPMICTL_SEND_COMMAND_SETTIME:
+ {
+ struct ipmi_req_settime sp;
+
+ if (get_compat_ipmi_req_settime(&sp, compat_ptr(arg)))
+ return -EFAULT;
+
+ return handle_send_req(priv->user, &sp.req,
+ sp.retries, sp.retry_time_ms);
+ }
+ case COMPAT_IPMICTL_RECEIVE_MSG:
+ case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC:
+ {
+ struct ipmi_recv *precv64, recv64;
+
+ if (get_compat_ipmi_recv(&recv64, compat_ptr(arg)))
+ return -EFAULT;
+
+ precv64 = compat_alloc_user_space(sizeof(recv64));
+ if (copy_to_user(precv64, &recv64, sizeof(recv64)))
+ return -EFAULT;
+
+ rc = ipmi_ioctl(filep->f_dentry->d_inode, filep,
+ ((cmd == COMPAT_IPMICTL_RECEIVE_MSG)
+ ? IPMICTL_RECEIVE_MSG
+ : IPMICTL_RECEIVE_MSG_TRUNC),
+ (long) precv64);
+ if (rc != 0)
+ return rc;
+
+ if (copy_from_user(&recv64, precv64, sizeof(recv64)))
+ return -EFAULT;
+
+ if (put_compat_ipmi_recv(&recv64, compat_ptr(arg)))
+ return -EFAULT;
+
+ return rc;
+ }
+ default:
+ return ipmi_ioctl(filep->f_dentry->d_inode, filep, cmd, arg);
+ }
+}
+#endif
static struct file_operations ipmi_fops = {
.owner = THIS_MODULE,
.ioctl = ipmi_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = compat_ipmi_ioctl,
+#endif
.open = ipmi_open,
.release = ipmi_release,
.fasync = ipmi_fasync,
@@ -529,12 +725,12 @@ static void ipmi_new_smi(int if_num)
devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
"ipmidev/%d", if_num);
- class_simple_device_add(ipmi_class, dev, NULL, "ipmi%d", if_num);
+ class_device_create(ipmi_class, dev, NULL, "ipmi%d", if_num);
}
static void ipmi_smi_gone(int if_num)
{
- class_simple_device_remove(ipmi_class, MKDEV(ipmi_major, if_num));
+ class_device_destroy(ipmi_class, MKDEV(ipmi_major, if_num));
devfs_remove("ipmidev/%d", if_num);
}
@@ -555,7 +751,7 @@ static __init int init_ipmi_devintf(void)
printk(KERN_INFO "ipmi device interface version "
IPMI_DEVINTF_VERSION "\n");
- ipmi_class = class_simple_create(THIS_MODULE, "ipmi");
+ ipmi_class = class_create(THIS_MODULE, "ipmi");
if (IS_ERR(ipmi_class)) {
printk(KERN_ERR "ipmi: can't register device class\n");
return PTR_ERR(ipmi_class);
@@ -563,7 +759,7 @@ static __init int init_ipmi_devintf(void)
rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops);
if (rv < 0) {
- class_simple_destroy(ipmi_class);
+ class_destroy(ipmi_class);
printk(KERN_ERR "ipmi: can't get major %d\n", ipmi_major);
return rv;
}
@@ -577,7 +773,7 @@ static __init int init_ipmi_devintf(void)
rv = ipmi_smi_watcher_register(&smi_watcher);
if (rv) {
unregister_chrdev(ipmi_major, DEVICE_NAME);
- class_simple_destroy(ipmi_class);
+ class_destroy(ipmi_class);
printk(KERN_WARNING "ipmi: can't register smi watcher\n");
return rv;
}
@@ -588,7 +784,7 @@ module_init(init_ipmi_devintf);
static __exit void cleanup_ipmi(void)
{
- class_simple_destroy(ipmi_class);
+ class_destroy(ipmi_class);
ipmi_smi_watcher_unregister(&smi_watcher);
devfs_remove(DEVICE_NAME);
unregister_chrdev(ipmi_major, DEVICE_NAME);
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index d7fb452af7f..1813d0d198f 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -54,7 +54,9 @@ static int ipmi_init_msghandler(void);
static int initialized = 0;
-static struct proc_dir_entry *proc_ipmi_root = NULL;
+#ifdef CONFIG_PROC_FS
+struct proc_dir_entry *proc_ipmi_root = NULL;
+#endif /* CONFIG_PROC_FS */
#define MAX_EVENTS_IN_QUEUE 25
@@ -124,11 +126,13 @@ struct ipmi_channel
unsigned char protocol;
};
+#ifdef CONFIG_PROC_FS
struct ipmi_proc_entry
{
char *name;
struct ipmi_proc_entry *next;
};
+#endif
#define IPMI_IPMB_NUM_SEQ 64
#define IPMI_MAX_CHANNELS 8
@@ -156,10 +160,13 @@ struct ipmi_smi
struct ipmi_smi_handlers *handlers;
void *send_info;
+#ifdef CONFIG_PROC_FS
/* A list of proc entries for this interface. This does not
need a lock, only one thread creates it and only one thread
destroys it. */
+ spinlock_t proc_entry_lock;
struct ipmi_proc_entry *proc_entries;
+#endif
/* A table of sequence numbers for this interface. We use the
sequence numbers for IPMB messages that go out of the
@@ -641,7 +648,7 @@ int ipmi_create_user(unsigned int if_num,
return -ENOMEM;
down_read(&interfaces_sem);
- if ((if_num > MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL)
+ if ((if_num >= MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL)
{
rv = -EINVAL;
goto out_unlock;
@@ -1470,8 +1477,9 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
read_proc_t *read_proc, write_proc_t *write_proc,
void *data, struct module *owner)
{
- struct proc_dir_entry *file;
int rv = 0;
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *file;
struct ipmi_proc_entry *entry;
/* Create a list element. */
@@ -1497,10 +1505,13 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
file->write_proc = write_proc;
file->owner = owner;
+ spin_lock(&smi->proc_entry_lock);
/* Stick it on the list. */
entry->next = smi->proc_entries;
smi->proc_entries = entry;
+ spin_unlock(&smi->proc_entry_lock);
}
+#endif /* CONFIG_PROC_FS */
return rv;
}
@@ -1509,6 +1520,7 @@ static int add_proc_entries(ipmi_smi_t smi, int num)
{
int rv = 0;
+#ifdef CONFIG_PROC_FS
sprintf(smi->proc_dir_name, "%d", num);
smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root);
if (!smi->proc_dir)
@@ -1531,14 +1543,17 @@ static int add_proc_entries(ipmi_smi_t smi, int num)
rv = ipmi_smi_add_proc_entry(smi, "version",
version_file_read_proc, NULL,
smi, THIS_MODULE);
+#endif /* CONFIG_PROC_FS */
return rv;
}
static void remove_proc_entries(ipmi_smi_t smi)
{
+#ifdef CONFIG_PROC_FS
struct ipmi_proc_entry *entry;
+ spin_lock(&smi->proc_entry_lock);
while (smi->proc_entries) {
entry = smi->proc_entries;
smi->proc_entries = entry->next;
@@ -1547,7 +1562,9 @@ static void remove_proc_entries(ipmi_smi_t smi)
kfree(entry->name);
kfree(entry);
}
+ spin_unlock(&smi->proc_entry_lock);
remove_proc_entry(smi->proc_dir_name, proc_ipmi_root);
+#endif /* CONFIG_PROC_FS */
}
static int
@@ -1694,6 +1711,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
new_intf->seq_table[j].seqid = 0;
}
new_intf->curr_seq = 0;
+#ifdef CONFIG_PROC_FS
+ spin_lock_init(&(new_intf->proc_entry_lock));
+#endif
spin_lock_init(&(new_intf->waiting_msgs_lock));
INIT_LIST_HEAD(&(new_intf->waiting_msgs));
spin_lock_init(&(new_intf->events_lock));
@@ -2747,16 +2767,13 @@ static struct timer_list ipmi_timer;
the queue and this silliness can go away. */
#define IPMI_REQUEST_EV_TIME (1000 / (IPMI_TIMEOUT_TIME))
-static volatile int stop_operation = 0;
-static volatile int timer_stopped = 0;
+static atomic_t stop_operation;
static unsigned int ticks_to_req_ev = IPMI_REQUEST_EV_TIME;
static void ipmi_timeout(unsigned long data)
{
- if (stop_operation) {
- timer_stopped = 1;
+ if (atomic_read(&stop_operation))
return;
- }
ticks_to_req_ev--;
if (ticks_to_req_ev == 0) {
@@ -2766,8 +2783,7 @@ static void ipmi_timeout(unsigned long data)
ipmi_timeout_handler(IPMI_TIMEOUT_TIME);
- ipmi_timer.expires += IPMI_TIMEOUT_JIFFIES;
- add_timer(&ipmi_timer);
+ mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES);
}
@@ -3089,6 +3105,7 @@ static int ipmi_init_msghandler(void)
ipmi_interfaces[i] = NULL;
}
+#ifdef CONFIG_PROC_FS
proc_ipmi_root = proc_mkdir("ipmi", NULL);
if (!proc_ipmi_root) {
printk(KERN_ERR PFX "Unable to create IPMI proc dir");
@@ -3096,6 +3113,7 @@ static int ipmi_init_msghandler(void)
}
proc_ipmi_root->owner = THIS_MODULE;
+#endif /* CONFIG_PROC_FS */
init_timer(&ipmi_timer);
ipmi_timer.data = 0;
@@ -3130,13 +3148,12 @@ static __exit void cleanup_ipmi(void)
/* Tell the timer to stop, then wait for it to stop. This avoids
problems with race conditions removing the timer here. */
- stop_operation = 1;
- while (!timer_stopped) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- }
+ atomic_inc(&stop_operation);
+ del_timer_sync(&ipmi_timer);
+#ifdef CONFIG_PROC_FS
remove_proc_entry(proc_ipmi_root->name, &proc_root);
+#endif /* CONFIG_PROC_FS */
initialized = 0;
@@ -3177,4 +3194,5 @@ EXPORT_SYMBOL(ipmi_get_my_address);
EXPORT_SYMBOL(ipmi_set_my_LUN);
EXPORT_SYMBOL(ipmi_get_my_LUN);
EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
+EXPORT_SYMBOL(proc_ipmi_root);
EXPORT_SYMBOL(ipmi_user_set_run_to_completion);
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index cb5cdc6f14b..f951c30236c 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -31,10 +31,13 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <asm/semaphore.h>
-#include <linux/kdev_t.h>
+#include <linux/config.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/proc_fs.h>
#include <linux/string.h>
+#include <linux/completion.h>
+#include <linux/kdev_t.h>
#include <linux/ipmi.h>
#include <linux/ipmi_smi.h>
@@ -44,6 +47,18 @@
/* Where to we insert our poweroff function? */
extern void (*pm_power_off)(void);
+/* Definitions for controlling power off (if the system supports it). It
+ * conveniently matches the IPMI chassis control values. */
+#define IPMI_CHASSIS_POWER_DOWN 0 /* power down, the default. */
+#define IPMI_CHASSIS_POWER_CYCLE 0x02 /* power cycle */
+
+/* the IPMI data command */
+static int poweroff_control = IPMI_CHASSIS_POWER_DOWN;
+
+/* parameter definition to allow user to flag power cycle */
+module_param(poweroff_control, int, IPMI_CHASSIS_POWER_DOWN);
+MODULE_PARM_DESC(poweroff_control, " Set to 2 to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");
+
/* Stuff from the get device id command. */
static unsigned int mfg_id;
static unsigned int prod_id;
@@ -75,10 +90,10 @@ static struct ipmi_recv_msg halt_recv_msg =
static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data)
{
- struct semaphore *sem = recv_msg->user_msg_data;
+ struct completion *comp = recv_msg->user_msg_data;
- if (sem)
- up(sem);
+ if (comp)
+ complete(comp);
}
static struct ipmi_user_hndl ipmi_poweroff_handler =
@@ -91,27 +106,27 @@ static int ipmi_request_wait_for_response(ipmi_user_t user,
struct ipmi_addr *addr,
struct kernel_ipmi_msg *send_msg)
{
- int rv;
- struct semaphore sem;
+ int rv;
+ struct completion comp;
- sema_init (&sem, 0);
+ init_completion(&comp);
- rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, &sem,
+ rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, &comp,
&halt_smi_msg, &halt_recv_msg, 0);
if (rv)
return rv;
- down (&sem);
+ wait_for_completion(&comp);
return halt_recv_msg.msg.data[0];
}
-/* We are in run-to-completion mode, no semaphore is desired. */
+/* We are in run-to-completion mode, no completion is desired. */
static int ipmi_request_in_rc_mode(ipmi_user_t user,
struct ipmi_addr *addr,
struct kernel_ipmi_msg *send_msg)
{
- int rv;
+ int rv;
rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL,
&halt_smi_msg, &halt_recv_msg, 0);
@@ -349,26 +364,38 @@ static void ipmi_poweroff_chassis (ipmi_user_t user)
smi_addr.channel = IPMI_BMC_CHANNEL;
smi_addr.lun = 0;
- printk(KERN_INFO PFX "Powering down via IPMI chassis control command\n");
+ powercyclefailed:
+ printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n",
+ ((poweroff_control != IPMI_CHASSIS_POWER_CYCLE) ? "down" : "cycle"));
/*
* Power down
*/
send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST;
send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD;
- data[0] = 0; /* Power down */
+ data[0] = poweroff_control;
send_msg.data = data;
send_msg.data_len = sizeof(data);
rv = ipmi_request_in_rc_mode(user,
(struct ipmi_addr *) &smi_addr,
&send_msg);
if (rv) {
- printk(KERN_ERR PFX "Unable to send chassis powerdown message,"
- " IPMI error 0x%x\n", rv);
- goto out;
+ switch (poweroff_control) {
+ case IPMI_CHASSIS_POWER_CYCLE:
+ /* power cycle failed, default to power down */
+ printk(KERN_ERR PFX "Unable to send chassis power " \
+ "cycle message, IPMI error 0x%x\n", rv);
+ poweroff_control = IPMI_CHASSIS_POWER_DOWN;
+ goto powercyclefailed;
+
+ case IPMI_CHASSIS_POWER_DOWN:
+ default:
+ printk(KERN_ERR PFX "Unable to send chassis power " \
+ "down message, IPMI error 0x%x\n", rv);
+ break;
+ }
}
- out:
return;
}
@@ -430,7 +457,8 @@ static void ipmi_po_new_smi(int if_num)
if (ready)
return;
- rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL, &ipmi_user);
+ rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL,
+ &ipmi_user);
if (rv) {
printk(KERN_ERR PFX "could not create IPMI user, error %d\n",
rv);
@@ -509,21 +537,84 @@ static struct ipmi_smi_watcher smi_watcher =
};
+#ifdef CONFIG_PROC_FS
+/* displays properties to proc */
+static int proc_read_chassctrl(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+{
+ return sprintf(page, "%d\t[ 0=powerdown 2=powercycle ]\n",
+ poweroff_control);
+}
+
+/* process property writes from proc */
+static int proc_write_chassctrl(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ int rv = count;
+ unsigned int newval = 0;
+
+ sscanf(buffer, "%d", &newval);
+ switch (newval) {
+ case IPMI_CHASSIS_POWER_CYCLE:
+ printk(KERN_INFO PFX "power cycle is now enabled\n");
+ poweroff_control = newval;
+ break;
+
+ case IPMI_CHASSIS_POWER_DOWN:
+ poweroff_control = IPMI_CHASSIS_POWER_DOWN;
+ break;
+
+ default:
+ rv = -EINVAL;
+ break;
+ }
+
+ return rv;
+}
+#endif /* CONFIG_PROC_FS */
+
/*
* Startup and shutdown functions.
*/
static int ipmi_poweroff_init (void)
{
- int rv;
+ int rv;
+ struct proc_dir_entry *file;
printk ("Copyright (C) 2004 MontaVista Software -"
" IPMI Powerdown via sys_reboot version "
IPMI_POWEROFF_VERSION ".\n");
+ switch (poweroff_control) {
+ case IPMI_CHASSIS_POWER_CYCLE:
+ printk(KERN_INFO PFX "Power cycle is enabled.\n");
+ break;
+
+ case IPMI_CHASSIS_POWER_DOWN:
+ default:
+ poweroff_control = IPMI_CHASSIS_POWER_DOWN;
+ break;
+ }
+
rv = ipmi_smi_watcher_register(&smi_watcher);
- if (rv)
+ if (rv) {
printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv);
+ goto out_err;
+ }
+
+#ifdef CONFIG_PROC_FS
+ file = create_proc_entry("poweroff_control", 0, proc_ipmi_root);
+ if (!file) {
+ printk(KERN_ERR PFX "Unable to create proc power control\n");
+ } else {
+ file->nlink = 1;
+ file->read_proc = proc_read_chassctrl;
+ file->write_proc = proc_write_chassctrl;
+ file->owner = THIS_MODULE;
+ }
+#endif
+ out_err:
return rv;
}
@@ -532,6 +623,10 @@ static __exit void ipmi_poweroff_cleanup(void)
{
int rv;
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry("poweroff_control", proc_ipmi_root);
+#endif
+
ipmi_smi_watcher_unregister(&smi_watcher);
if (ready) {
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 601c7fccb4c..1bbf507adda 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -1756,7 +1756,7 @@ static void isicom_flush_buffer(struct tty_struct * tty)
}
-static int __init register_ioregion(void)
+static int __devinit register_ioregion(void)
{
int count, done=0;
for (count=0; count < BOARD_COUNT; count++ ) {
@@ -1771,7 +1771,7 @@ static int __init register_ioregion(void)
return done;
}
-static void __exit unregister_ioregion(void)
+static void unregister_ioregion(void)
{
int count;
for (count=0; count < BOARD_COUNT; count++ )
@@ -1803,7 +1803,7 @@ static struct tty_operations isicom_ops = {
.tiocmset = isicom_tiocmset,
};
-static int __init register_drivers(void)
+static int __devinit register_drivers(void)
{
int error;
@@ -1834,7 +1834,7 @@ static int __init register_drivers(void)
return 0;
}
-static void __exit unregister_drivers(void)
+static void unregister_drivers(void)
{
int error = tty_unregister_driver(isicom_normal);
if (error)
@@ -1842,7 +1842,7 @@ static void __exit unregister_drivers(void)
put_tty_driver(isicom_normal);
}
-static int __init register_isr(void)
+static int __devinit register_isr(void)
{
int count, done=0;
unsigned long irqflags;
@@ -1883,7 +1883,7 @@ static void __exit unregister_isr(void)
}
}
-static int __init isicom_init(void)
+static int __devinit isicom_init(void)
{
int card, channel, base;
struct isi_port * port;
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 21aed0e8779..52a073eee20 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -407,7 +407,6 @@ static unsigned long stli_eisamemprobeaddrs[] = {
};
static int stli_eisamempsize = sizeof(stli_eisamemprobeaddrs) / sizeof(unsigned long);
-int stli_eisaprobe = STLI_EISAPROBE;
/*
* Define the Stallion PCI vendor and device IDs.
@@ -792,7 +791,7 @@ static int stli_timeron;
/*****************************************************************************/
-static struct class_simple *istallion_class;
+static struct class *istallion_class;
#ifdef MODULE
@@ -854,10 +853,10 @@ static void __exit istallion_module_exit(void)
put_tty_driver(stli_serial);
for (i = 0; i < 4; i++) {
devfs_remove("staliomem/%d", i);
- class_simple_device_remove(MKDEV(STL_SIOMEMMAJOR, i));
+ class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, i));
}
devfs_remove("staliomem");
- class_simple_destroy(istallion_class);
+ class_destroy(istallion_class);
if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
printk("STALLION: failed to un-register serial memory device, "
"errno=%d\n", -i);
@@ -4685,7 +4684,7 @@ static int stli_initbrds(void)
#ifdef MODULE
stli_argbrds();
#endif
- if (stli_eisaprobe)
+ if (STLI_EISAPROBE)
stli_findeisabrds();
#ifdef CONFIG_PCI
stli_findpcibrds();
@@ -5242,12 +5241,12 @@ int __init stli_init(void)
"device\n");
devfs_mk_dir("staliomem");
- istallion_class = class_simple_create(THIS_MODULE, "staliomem");
+ istallion_class = class_create(THIS_MODULE, "staliomem");
for (i = 0; i < 4; i++) {
devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
S_IFCHR | S_IRUSR | S_IWUSR,
"staliomem/%d", i);
- class_simple_device_add(istallion_class, MKDEV(STL_SIOMEMMAJOR, i),
+ class_device_create(istallion_class, MKDEV(STL_SIOMEMMAJOR, i),
NULL, "staliomem%d", i);
}
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 4dee945031d..59eebe5a035 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -146,7 +146,7 @@
static struct lp_struct lp_table[LP_NO];
static unsigned int lp_count = 0;
-static struct class_simple *lp_class;
+static struct class *lp_class;
#ifdef CONFIG_LP_CONSOLE
static struct parport *console_registered; // initially NULL
@@ -804,7 +804,7 @@ static int lp_register(int nr, struct parport *port)
if (reset)
lp_reset(nr);
- class_simple_device_add(lp_class, MKDEV(LP_MAJOR, nr), NULL,
+ class_device_create(lp_class, MKDEV(LP_MAJOR, nr), NULL,
"lp%d", nr);
devfs_mk_cdev(MKDEV(LP_MAJOR, nr), S_IFCHR | S_IRUGO | S_IWUGO,
"printers/%d", nr);
@@ -907,7 +907,7 @@ static int __init lp_init (void)
}
devfs_mk_dir("printers");
- lp_class = class_simple_create(THIS_MODULE, "printer");
+ lp_class = class_create(THIS_MODULE, "printer");
if (IS_ERR(lp_class)) {
err = PTR_ERR(lp_class);
goto out_devfs;
@@ -930,7 +930,7 @@ static int __init lp_init (void)
return 0;
out_class:
- class_simple_destroy(lp_class);
+ class_destroy(lp_class);
out_devfs:
devfs_remove("printers");
unregister_chrdev(LP_MAJOR, "lp");
@@ -981,10 +981,10 @@ static void lp_cleanup_module (void)
continue;
parport_unregister_device(lp_table[offset].dev);
devfs_remove("printers/%d", offset);
- class_simple_device_remove(MKDEV(LP_MAJOR, offset));
+ class_device_destroy(lp_class, MKDEV(LP_MAJOR, offset));
}
devfs_remove("printers");
- class_simple_destroy(lp_class);
+ class_destroy(lp_class);
}
__setup("lp=", lp_setup);
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index ac9cfa9701e..115dbb35334 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -699,7 +699,7 @@ static inline int mbcs_hw_init(struct mbcs_soft *soft)
return 0;
}
-static ssize_t show_algo(struct device *dev, char *buf)
+static ssize_t show_algo(struct device *dev, struct device_attribute *attr, char *buf)
{
struct cx_dev *cx_dev = to_cx_dev(dev);
struct mbcs_soft *soft = cx_dev->soft;
@@ -715,7 +715,7 @@ static ssize_t show_algo(struct device *dev, char *buf)
(debug0 >> 32), (debug0 & 0xffffffff));
}
-static ssize_t store_algo(struct device *dev, const char *buf, size_t count)
+static ssize_t store_algo(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int n;
struct cx_dev *cx_dev = to_cx_dev(dev);
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 947cb3cef81..42187381506 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -23,7 +23,10 @@
#include <linux/devfs_fs_kernel.h>
#include <linux/ptrace.h>
#include <linux/device.h>
+#include <linux/highmem.h>
+#include <linux/crash_dump.h>
#include <linux/backing-dev.h>
+#include <linux/bootmem.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -273,6 +276,40 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
return mmap_mem(file, vma);
}
+#ifdef CONFIG_CRASH_DUMP
+/*
+ * Read memory corresponding to the old kernel.
+ */
+static ssize_t read_oldmem(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long pfn, offset;
+ size_t read = 0, csize;
+ int rc = 0;
+
+ while (count) {
+ pfn = *ppos / PAGE_SIZE;
+ if (pfn > saved_max_pfn)
+ return read;
+
+ offset = (unsigned long)(*ppos % PAGE_SIZE);
+ if (count > PAGE_SIZE - offset)
+ csize = PAGE_SIZE - offset;
+ else
+ csize = count;
+
+ rc = copy_oldmem_page(pfn, buf, csize, offset, 1);
+ if (rc < 0)
+ return rc;
+ buf += csize;
+ *ppos += csize;
+ read += csize;
+ count -= csize;
+ }
+ return read;
+}
+#endif
+
extern long vread(char *buf, char *addr, unsigned long count);
extern long vwrite(char *buf, char *addr, unsigned long count);
@@ -484,7 +521,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
return virtr + wrote;
}
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
static ssize_t read_port(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
@@ -721,6 +758,7 @@ static int open_port(struct inode * inode, struct file * filp)
#define read_full read_zero
#define open_mem open_port
#define open_kmem open_mem
+#define open_oldmem open_mem
static struct file_operations mem_fops = {
.llseek = memory_lseek,
@@ -744,7 +782,7 @@ static struct file_operations null_fops = {
.write = write_null,
};
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
static struct file_operations port_fops = {
.llseek = memory_lseek,
.read = read_port,
@@ -770,6 +808,13 @@ static struct file_operations full_fops = {
.write = write_full,
};
+#ifdef CONFIG_CRASH_DUMP
+static struct file_operations oldmem_fops = {
+ .read = read_oldmem,
+ .open = open_oldmem,
+};
+#endif
+
static ssize_t kmsg_write(struct file * file, const char __user * buf,
size_t count, loff_t *ppos)
{
@@ -804,7 +849,7 @@ static int memory_open(struct inode * inode, struct file * filp)
case 3:
filp->f_op = &null_fops;
break;
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
case 4:
filp->f_op = &port_fops;
break;
@@ -825,6 +870,11 @@ static int memory_open(struct inode * inode, struct file * filp)
case 11:
filp->f_op = &kmsg_fops;
break;
+#ifdef CONFIG_CRASH_DUMP
+ case 12:
+ filp->f_op = &oldmem_fops;
+ break;
+#endif
default:
return -ENXIO;
}
@@ -846,7 +896,7 @@ static const struct {
{1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
{2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
{3, "null", S_IRUGO | S_IWUGO, &null_fops},
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
{4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
#endif
{5, "zero", S_IRUGO | S_IWUGO, &zero_fops},
@@ -854,9 +904,12 @@ static const struct {
{8, "random", S_IRUGO | S_IWUSR, &random_fops},
{9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops},
{11,"kmsg", S_IRUGO | S_IWUSR, &kmsg_fops},
+#ifdef CONFIG_CRASH_DUMP
+ {12,"oldmem", S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops},
+#endif
};
-static struct class_simple *mem_class;
+static struct class *mem_class;
static int __init chr_dev_init(void)
{
@@ -865,10 +918,9 @@ static int __init chr_dev_init(void)
if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
printk("unable to get major %d for memory devs\n", MEM_MAJOR);
- mem_class = class_simple_create(THIS_MODULE, "mem");
+ mem_class = class_create(THIS_MODULE, "mem");
for (i = 0; i < ARRAY_SIZE(devlist); i++) {
- class_simple_device_add(mem_class,
- MKDEV(MEM_MAJOR, devlist[i].minor),
+ class_device_create(mem_class, MKDEV(MEM_MAJOR, devlist[i].minor),
NULL, devlist[i].name);
devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor),
S_IFCHR | devlist[i].mode, devlist[i].name);
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 0937544762d..31cf84d6902 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -66,8 +66,6 @@ static unsigned char misc_minors[DYNAMIC_MINORS / 8];
extern int rtc_DP8570A_init(void);
extern int rtc_MK48T08_init(void);
extern int pmu_device_init(void);
-extern int tosh_init(void);
-extern int i8k_init(void);
#ifdef CONFIG_PROC_FS
static void *misc_seq_start(struct seq_file *seq, loff_t *pos)
@@ -177,10 +175,10 @@ fail:
/*
* TODO for 2.7:
- * - add a struct class_device to struct miscdevice and make all usages of
+ * - add a struct kref to struct miscdevice and make all usages of
* them dynamic.
*/
-static struct class_simple *misc_class;
+static struct class *misc_class;
static struct file_operations misc_fops = {
.owner = THIS_MODULE,
@@ -238,8 +236,8 @@ int misc_register(struct miscdevice * misc)
}
dev = MKDEV(MISC_MAJOR, misc->minor);
- misc->class = class_simple_device_add(misc_class, dev,
- misc->dev, misc->name);
+ misc->class = class_device_create(misc_class, dev, misc->dev,
+ "%s", misc->name);
if (IS_ERR(misc->class)) {
err = PTR_ERR(misc->class);
goto out;
@@ -248,7 +246,7 @@ int misc_register(struct miscdevice * misc)
err = devfs_mk_cdev(dev, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP,
misc->devfs_name);
if (err) {
- class_simple_device_remove(dev);
+ class_device_destroy(misc_class, dev);
goto out;
}
@@ -281,7 +279,7 @@ int misc_deregister(struct miscdevice * misc)
down(&misc_sem);
list_del(&misc->list);
- class_simple_device_remove(MKDEV(MISC_MAJOR, misc->minor));
+ class_device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
devfs_remove(misc->devfs_name);
if (i < DYNAMIC_MINORS && i>0) {
misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
@@ -302,7 +300,7 @@ static int __init misc_init(void)
if (ent)
ent->proc_fops = &misc_proc_fops;
#endif
- misc_class = class_simple_create(THIS_MODULE, "misc");
+ misc_class = class_create(THIS_MODULE, "misc");
if (IS_ERR(misc_class))
return PTR_ERR(misc_class);
#ifdef CONFIG_MVME16x
@@ -314,16 +312,10 @@ static int __init misc_init(void)
#ifdef CONFIG_PMAC_PBOOK
pmu_device_init();
#endif
-#ifdef CONFIG_TOSHIBA
- tosh_init();
-#endif
-#ifdef CONFIG_I8K
- i8k_init();
-#endif
if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
printk("unable to get major %d for misc devices\n",
MISC_MAJOR);
- class_simple_destroy(misc_class);
+ class_destroy(misc_class);
return -EIO;
}
return 0;
diff --git a/drivers/char/mwave/3780i.c b/drivers/char/mwave/3780i.c
index ab00f51475d..613aed9e184 100644
--- a/drivers/char/mwave/3780i.c
+++ b/drivers/char/mwave/3780i.c
@@ -107,8 +107,8 @@ void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO,
spin_unlock_irqrestore(&dsp_lock, flags);
}
-void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
- unsigned char ucValue)
+static void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
+ unsigned char ucValue)
{
DSP_ISA_SLAVE_CONTROL rSlaveControl;
DSP_ISA_SLAVE_CONTROL rSlaveControl_Save;
@@ -141,6 +141,7 @@ void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
}
+#if 0
unsigned char dsp3780I_ReadGenCfg(unsigned short usDspBaseIO,
unsigned uIndex)
{
@@ -167,6 +168,7 @@ unsigned char dsp3780I_ReadGenCfg(unsigned short usDspBaseIO,
return ucValue;
}
+#endif /* 0 */
int dsp3780I_EnableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings,
unsigned short *pIrqMap,
diff --git a/drivers/char/mwave/3780i.h b/drivers/char/mwave/3780i.h
index 3e7d020d1bf..270431ca7da 100644
--- a/drivers/char/mwave/3780i.h
+++ b/drivers/char/mwave/3780i.h
@@ -338,10 +338,6 @@ unsigned short dsp3780I_ReadMsaCfg(unsigned short usDspBaseIO,
unsigned long ulMsaAddr);
void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO,
unsigned long ulMsaAddr, unsigned short usValue);
-void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
- unsigned char ucValue);
-unsigned char dsp3780I_ReadGenCfg(unsigned short usDspBaseIO,
- unsigned uIndex);
int dsp3780I_GetIPCSource(unsigned short usDspBaseIO,
unsigned short *pusIPCSource);
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index d37625d4774..d568991ac6b 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -472,7 +472,7 @@ struct device mwave_device;
/* Prevent code redundancy, create a macro for mwave_show_* functions. */
#define mwave_show_function(attr_name, format_string, field) \
-static ssize_t mwave_show_##attr_name(struct device *dev, char *buf) \
+static ssize_t mwave_show_##attr_name(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
DSP_3780I_CONFIG_SETTINGS *pSettings = \
&mwave_s_mdd.rBDData.rDspSettings; \
diff --git a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c
index ab650cd6efc..d6c72e0934e 100644
--- a/drivers/char/mwave/tp3780i.c
+++ b/drivers/char/mwave/tp3780i.c
@@ -242,20 +242,14 @@ int tp3780I_ClaimResources(THINKPAD_BD_DATA * pBDData)
{
int retval = 0;
DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
struct resource *pres;
-#endif
PRINTK_2(TRACE_TP3780I,
"tp3780i::tp3780I_ClaimResources entry pBDData %p\n", pBDData);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
pres = request_region(pSettings->usDspBaseIO, 16, "mwave_3780i");
if ( pres == NULL ) retval = -EIO;
-#else
- retval = check_region(pSettings->usDspBaseIO, 16);
- if (!retval) request_region(pSettings->usDspBaseIO, 16, "mwave_3780i");
-#endif
+
if (retval) {
PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_ClaimResources: Error: Could not claim I/O region starting at %x\n", pSettings->usDspBaseIO);
retval = -EIO;
@@ -292,7 +286,7 @@ int tp3780I_ReleaseResources(THINKPAD_BD_DATA * pBDData)
int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
{
DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
- BOOLEAN bDSPPoweredUp = FALSE, bDSPEnabled = FALSE, bInterruptAllocated = FALSE;
+ BOOLEAN bDSPPoweredUp = FALSE, bInterruptAllocated = FALSE;
PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_EnableDSP entry pBDData %p\n", pBDData);
@@ -397,8 +391,6 @@ int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
if (dsp3780I_EnableDSP(pSettings, s_ausThinkpadIrqToField, s_ausThinkpadDmaToField)) {
PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Error: dsp7880I_EnableDSP() failed\n");
goto exit_cleanup;
- } else {
- bDSPEnabled = TRUE;
}
EnableSRAM(pBDData);
@@ -411,8 +403,6 @@ int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
exit_cleanup:
PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Cleaning up\n");
- if (bDSPEnabled)
- dsp3780I_DisableDSP(pSettings);
if (bDSPPoweredUp)
smapi_set_DSP_power_state(FALSE);
if (bInterruptAllocated) {
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 7a245068e3e..f022f094443 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -1995,9 +1995,6 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status)
unsigned char ch, gdl;
int ignored = 0;
int cnt = 0;
- unsigned char *cp;
- char *fp;
- int count;
int recv_room;
int max = 256;
unsigned long flags;
@@ -2011,10 +2008,6 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status)
//return;
}
- cp = tty->flip.char_buf;
- fp = tty->flip.flag_buf;
- count = 0;
-
// following add by Victor Yu. 09-02-2002
if (info->IsMoxaMustChipFlag != MOXA_OTHER_UART) {
@@ -2041,12 +2034,10 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status)
}
while (gdl--) {
ch = inb(info->base + UART_RX);
- count++;
- *cp++ = ch;
- *fp++ = 0;
+ tty_insert_flip_char(tty, ch, 0);
cnt++;
/*
- if((count>=HI_WATER) && (info->stop_rx==0)){
+ if((cnt>=HI_WATER) && (info->stop_rx==0)){
mxser_stoprx(tty);
info->stop_rx=1;
break;
@@ -2061,7 +2052,7 @@ intr_old:
if (max-- < 0)
break;
/*
- if((count>=HI_WATER) && (info->stop_rx==0)){
+ if((cnt>=HI_WATER) && (info->stop_rx==0)){
mxser_stoprx(tty);
info->stop_rx=1;
break;
@@ -2078,36 +2069,33 @@ intr_old:
if (++ignored > 100)
break;
} else {
- count++;
+ char flag = 0;
if (*status & UART_LSR_SPECIAL) {
if (*status & UART_LSR_BI) {
- *fp++ = TTY_BREAK;
+ flag = TTY_BREAK;
/* added by casper 1/11/2000 */
info->icount.brk++;
-
/* */
if (info->flags & ASYNC_SAK)
do_SAK(tty);
} else if (*status & UART_LSR_PE) {
- *fp++ = TTY_PARITY;
+ flag = TTY_PARITY;
/* added by casper 1/11/2000 */
info->icount.parity++;
/* */
} else if (*status & UART_LSR_FE) {
- *fp++ = TTY_FRAME;
+ flag = TTY_FRAME;
/* added by casper 1/11/2000 */
info->icount.frame++;
/* */
} else if (*status & UART_LSR_OE) {
- *fp++ = TTY_OVERRUN;
+ flag = TTY_OVERRUN;
/* added by casper 1/11/2000 */
info->icount.overrun++;
/* */
- } else
- *fp++ = 0;
- } else
- *fp++ = 0;
- *cp++ = ch;
+ }
+ }
+ tty_insert_flip_char(tty, ch, flag);
cnt++;
if (cnt >= recv_room) {
if (!info->ldisc_stop_rx) {
@@ -2132,13 +2120,13 @@ intr_old:
// above add by Victor Yu. 09-02-2002
} while (*status & UART_LSR_DR);
- end_intr: // add by Victor Yu. 09-02-2002
+end_intr: // add by Victor Yu. 09-02-2002
mxvar_log.rxcnt[info->port] += cnt;
info->mon_data.rxcnt += cnt;
info->mon_data.up_rxcnt += cnt;
spin_unlock_irqrestore(&info->slock, flags);
-
+
tty_flip_buffer_push(tty);
}
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index b3dbff1cf96..5079beda69b 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -960,7 +960,7 @@ static char hdlc_unregister_fail[] __exitdata =
static void __exit n_hdlc_exit(void)
{
/* Release tty registration of line discipline */
- int status = tty_register_ldisc(N_HDLC, NULL);
+ int status = tty_unregister_ldisc(N_HDLC);
if (status)
printk(hdlc_unregister_fail, status);
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index 3883073ab48..2291a87e8ad 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -200,7 +200,7 @@ static void __exit r3964_exit(void)
TRACE_M ("cleanup_module()");
- status=tty_register_ldisc(N_R3964, NULL);
+ status=tty_unregister_ldisc(N_R3964);
if(status!=0)
{
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index f63a3fd7ca6..1af733d0732 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -211,12 +211,13 @@ nvram_check_checksum(void)
return rv;
}
-void
+static void
__nvram_set_checksum(void)
{
mach_set_checksum();
}
+#if 0
void
nvram_set_checksum(void)
{
@@ -226,6 +227,7 @@ nvram_set_checksum(void)
__nvram_set_checksum();
spin_unlock_irqrestore(&rtc_lock, flags);
}
+#endif /* 0 */
/*
* The are the file operation function for user access to /dev/nvram
@@ -921,6 +923,4 @@ EXPORT_SYMBOL(__nvram_write_byte);
EXPORT_SYMBOL(nvram_write_byte);
EXPORT_SYMBOL(__nvram_check_checksum);
EXPORT_SYMBOL(nvram_check_checksum);
-EXPORT_SYMBOL(__nvram_set_checksum);
-EXPORT_SYMBOL(nvram_set_checksum);
MODULE_ALIAS_MISCDEV(NVRAM_MINOR);
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 5eda075c62b..0e22880432b 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -737,7 +737,7 @@ static unsigned int pp_poll (struct file * file, poll_table * wait)
return mask;
}
-static struct class_simple *ppdev_class;
+static struct class *ppdev_class;
static struct file_operations pp_fops = {
.owner = THIS_MODULE,
@@ -752,13 +752,13 @@ static struct file_operations pp_fops = {
static void pp_attach(struct parport *port)
{
- class_simple_device_add(ppdev_class, MKDEV(PP_MAJOR, port->number),
+ class_device_create(ppdev_class, MKDEV(PP_MAJOR, port->number),
NULL, "parport%d", port->number);
}
static void pp_detach(struct parport *port)
{
- class_simple_device_remove(MKDEV(PP_MAJOR, port->number));
+ class_device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number));
}
static struct parport_driver pp_driver = {
@@ -776,7 +776,7 @@ static int __init ppdev_init (void)
PP_MAJOR);
return -EIO;
}
- ppdev_class = class_simple_create(THIS_MODULE, CHRDEV);
+ ppdev_class = class_create(THIS_MODULE, CHRDEV);
if (IS_ERR(ppdev_class)) {
err = PTR_ERR(ppdev_class);
goto out_chrdev;
@@ -798,7 +798,7 @@ out_class:
for (i = 0; i < PARPORT_MAX; i++)
devfs_remove("parports/%d", i);
devfs_remove("parports");
- class_simple_destroy(ppdev_class);
+ class_destroy(ppdev_class);
out_chrdev:
unregister_chrdev(PP_MAJOR, CHRDEV);
out:
@@ -813,7 +813,7 @@ static void __exit ppdev_cleanup (void)
devfs_remove("parports/%d", i);
parport_unregister_driver(&pp_driver);
devfs_remove("parports");
- class_simple_destroy(ppdev_class);
+ class_destroy(ppdev_class);
unregister_chrdev (PP_MAJOR, CHRDEV);
}
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index ca5f42bcaad..f13e5de0220 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -27,7 +27,7 @@ struct raw_device_data {
int inuse;
};
-static struct class_simple *raw_class;
+static struct class *raw_class;
static struct raw_device_data raw_devices[MAX_RAW_MINORS];
static DECLARE_MUTEX(raw_mutex);
static struct file_operations raw_ctl_fops; /* forward declaration */
@@ -127,8 +127,8 @@ raw_ioctl(struct inode *inode, struct file *filp,
static void bind_device(struct raw_config_request *rq)
{
- class_simple_device_remove(MKDEV(RAW_MAJOR, rq->raw_minor));
- class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor),
+ class_device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
+ class_device_create(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor),
NULL, "raw%d", rq->raw_minor);
}
@@ -200,8 +200,8 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp,
if (rq.block_major == 0 && rq.block_minor == 0) {
/* unbind */
rawdev->binding = NULL;
- class_simple_device_remove(MKDEV(RAW_MAJOR,
- rq.raw_minor));
+ class_device_destroy(raw_class,
+ MKDEV(RAW_MAJOR, rq.raw_minor));
} else {
rawdev->binding = bdget(dev);
if (rawdev->binding == NULL)
@@ -300,14 +300,14 @@ static int __init raw_init(void)
goto error;
}
- raw_class = class_simple_create(THIS_MODULE, "raw");
+ raw_class = class_create(THIS_MODULE, "raw");
if (IS_ERR(raw_class)) {
printk(KERN_ERR "Error creating raw class.\n");
cdev_del(&raw_cdev);
unregister_chrdev_region(dev, MAX_RAW_MINORS);
goto error;
}
- class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
+ class_device_create(raw_class, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
devfs_mk_cdev(MKDEV(RAW_MAJOR, 0),
S_IFCHR | S_IRUGO | S_IWUGO,
@@ -331,8 +331,8 @@ static void __exit raw_exit(void)
devfs_remove("raw/raw%d", i);
devfs_remove("raw/rawctl");
devfs_remove("raw");
- class_simple_device_remove(MKDEV(RAW_MAJOR, 0));
- class_simple_destroy(raw_class);
+ class_device_destroy(raw_class, MKDEV(RAW_MAJOR, 0));
+ class_destroy(raw_class);
cdev_del(&raw_cdev);
unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS);
}
diff --git a/drivers/char/rio/func.h b/drivers/char/rio/func.h
index e8f3860f472..01987c6dc39 100644
--- a/drivers/char/rio/func.h
+++ b/drivers/char/rio/func.h
@@ -147,7 +147,6 @@ struct rio_info * rio_info_store( int cmd, struct rio_info * p);
extern int rio_pcicopy(char *src, char *dst, int n);
extern int rio_minor (struct tty_struct *tty);
extern int rio_ismodem (struct tty_struct *tty);
-extern void rio_udelay (int usecs);
extern void rio_start_card_running (struct Host * HostP);
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index 763893e289b..7db3370f497 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -354,11 +354,6 @@ int rio_ismodem(struct tty_struct *tty)
}
-void rio_udelay (int usecs)
-{
- udelay (usecs);
-}
-
static int rio_set_real_termios (void *ptr)
{
int rv, modem;
diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c
index dca941ed10c..898a126ae3e 100644
--- a/drivers/char/rio/rioinit.c
+++ b/drivers/char/rio/rioinit.c
@@ -37,6 +37,7 @@ static char *_rioinit_c_sccs_ = "@(#)rioinit.c 1.3";
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/errno.h>
+#include <linux/delay.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/string.h>
@@ -1560,14 +1561,14 @@ uint Slot;
INTERRUPT_DISABLE | BYTE_OPERATION |
SLOW_LINKS | SLOW_AT_BUS);
WBYTE(DpRamP->DpResetTpu, 0xFF);
- rio_udelay (3);
+ udelay(3);
rio_dprintk (RIO_DEBUG_INIT, "RIOHostReset: Don't know if it worked. Try reset again\n");
WBYTE(DpRamP->DpControl, BOOT_FROM_RAM | EXTERNAL_BUS_OFF |
INTERRUPT_DISABLE | BYTE_OPERATION |
SLOW_LINKS | SLOW_AT_BUS);
WBYTE(DpRamP->DpResetTpu, 0xFF);
- rio_udelay (3);
+ udelay(3);
break;
#ifdef FUTURE_RELEASE
case RIO_EISA:
@@ -1599,7 +1600,7 @@ uint Slot;
DpRamP->DpControl = RIO_PCI_BOOT_FROM_RAM;
DpRamP->DpResetInt = 0xFF;
DpRamP->DpResetTpu = 0xFF;
- rio_udelay (100);
+ udelay(100);
/* for (i=0; i<6000; i++); */
/* suspend( 3 ); */
break;
diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c
index db655002671..78a321afdf4 100644
--- a/drivers/char/rio/riotty.c
+++ b/drivers/char/rio/riotty.c
@@ -524,16 +524,16 @@ riotclose(void *ptr)
register uint SysPort = dev;
struct ttystatics *tp; /* pointer to our ttystruct */
#endif
- struct Port *PortP =ptr; /* pointer to the port structure */
+ struct Port *PortP = ptr; /* pointer to the port structure */
int deleted = 0;
int try = -1; /* Disable the timeouts by setting them to -1 */
int repeat_this = -1; /* Congrats to those having 15 years of
uptime! (You get to break the driver.) */
- long end_time;
+ unsigned long end_time;
struct tty_struct * tty;
unsigned long flags;
int Modem;
- int rv =0;
+ int rv = 0;
rio_dprintk (RIO_DEBUG_TTY, "port close SysPort %d\n",PortP->PortNum);
@@ -620,7 +620,7 @@ riotclose(void *ptr)
if (repeat_this -- <= 0) {
rv = -EINTR;
rio_dprintk (RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
- RIOPreemptiveCmd(p, PortP, FCLOSE );
+ RIOPreemptiveCmd(p, PortP, FCLOSE);
goto close_end;
}
rio_dprintk (RIO_DEBUG_TTY, "Calling timeout to flush in closing\n");
@@ -656,14 +656,12 @@ riotclose(void *ptr)
goto close_end;
}
-
-
/* Can't call RIOShortCommand with the port locked. */
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
if (RIOShortCommand(p, PortP, CLOSE, 1, 0) == RIO_FAIL) {
- RIOPreemptiveCmd(p, PortP,FCLOSE);
- goto close_end;
+ RIOPreemptiveCmd(p, PortP, FCLOSE);
+ goto close_end;
}
if (!deleted)
@@ -698,7 +696,6 @@ riotclose(void *ptr)
*/
PortP->Config &= ~(RIO_CTSFLOW|RIO_RTSFLOW);
-
#ifdef STATS
PortP->Stat.CloseCnt++;
#endif
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 5bcbeb0cb9a..f463d6baa68 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -161,6 +161,64 @@ static Word_t upci_aiop_intr_bits[AIOP_CTL_SIZE] = {
UPCI_AIOP_INTR_BIT_3
};
+static Byte_t RData[RDATASIZE] = {
+ 0x00, 0x09, 0xf6, 0x82,
+ 0x02, 0x09, 0x86, 0xfb,
+ 0x04, 0x09, 0x00, 0x0a,
+ 0x06, 0x09, 0x01, 0x0a,
+ 0x08, 0x09, 0x8a, 0x13,
+ 0x0a, 0x09, 0xc5, 0x11,
+ 0x0c, 0x09, 0x86, 0x85,
+ 0x0e, 0x09, 0x20, 0x0a,
+ 0x10, 0x09, 0x21, 0x0a,
+ 0x12, 0x09, 0x41, 0xff,
+ 0x14, 0x09, 0x82, 0x00,
+ 0x16, 0x09, 0x82, 0x7b,
+ 0x18, 0x09, 0x8a, 0x7d,
+ 0x1a, 0x09, 0x88, 0x81,
+ 0x1c, 0x09, 0x86, 0x7a,
+ 0x1e, 0x09, 0x84, 0x81,
+ 0x20, 0x09, 0x82, 0x7c,
+ 0x22, 0x09, 0x0a, 0x0a
+};
+
+static Byte_t RRegData[RREGDATASIZE] = {
+ 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
+ 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
+ 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
+ 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
+ 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
+ 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
+ 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
+ 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
+ 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
+ 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
+ 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
+ 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
+ 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
+};
+
+static CONTROLLER_T sController[CTL_SIZE] = {
+ {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
+ {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
+ {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
+ {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
+ {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
+ {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
+ {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
+ {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}
+};
+
+static Byte_t sBitMapClrTbl[8] = {
+ 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f
+};
+
+static Byte_t sBitMapSetTbl[8] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
+};
+
+static int sClockPrescale = 0x14;
+
/*
* Line number is the ttySIx number (x), the Minor number. We
* assign them sequentially, starting at zero. The following
@@ -177,6 +235,26 @@ static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model);
static unsigned char GetLineNumber(int ctrl, int aiop, int ch);
static unsigned char SetLineNumber(int ctrl, int aiop, int ch);
static void rp_start(struct tty_struct *tty);
+static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
+ int ChanNum);
+static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode);
+static void sFlushRxFIFO(CHANNEL_T * ChP);
+static void sFlushTxFIFO(CHANNEL_T * ChP);
+static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags);
+static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags);
+static void sModemReset(CONTROLLER_T * CtlP, int chan, int on);
+static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on);
+static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data);
+static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
+ ByteIO_t * AiopIOList, int AiopIOListSize,
+ WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
+ int PeriodicOnly, int altChanRingIndicator,
+ int UPCIRingInd);
+static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
+ ByteIO_t * AiopIOList, int AiopIOListSize,
+ int IRQNum, Byte_t Frequency, int PeriodicOnly);
+static int sReadAiopID(ByteIO_t io);
+static int sReadAiopNumChan(WordIO_t io);
#ifdef MODULE
MODULE_AUTHOR("Theodore Ts'o");
@@ -1798,7 +1876,7 @@ static void rp_flush_buffer(struct tty_struct *tty)
* init's aiopic and serial port hardware.
* Inputs: i is the board number (0-n)
*/
-__init int register_PCI(int i, struct pci_dev *dev)
+static __init int register_PCI(int i, struct pci_dev *dev)
{
int num_aiops, aiop, max_num_aiops, num_chan, chan;
unsigned int aiopio[MAX_AIOPS_PER_BOARD];
@@ -2453,72 +2531,6 @@ static void rp_cleanup_module(void)
}
#endif
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-static Byte_t RData[RDATASIZE] = {
- 0x00, 0x09, 0xf6, 0x82,
- 0x02, 0x09, 0x86, 0xfb,
- 0x04, 0x09, 0x00, 0x0a,
- 0x06, 0x09, 0x01, 0x0a,
- 0x08, 0x09, 0x8a, 0x13,
- 0x0a, 0x09, 0xc5, 0x11,
- 0x0c, 0x09, 0x86, 0x85,
- 0x0e, 0x09, 0x20, 0x0a,
- 0x10, 0x09, 0x21, 0x0a,
- 0x12, 0x09, 0x41, 0xff,
- 0x14, 0x09, 0x82, 0x00,
- 0x16, 0x09, 0x82, 0x7b,
- 0x18, 0x09, 0x8a, 0x7d,
- 0x1a, 0x09, 0x88, 0x81,
- 0x1c, 0x09, 0x86, 0x7a,
- 0x1e, 0x09, 0x84, 0x81,
- 0x20, 0x09, 0x82, 0x7c,
- 0x22, 0x09, 0x0a, 0x0a
-};
-
-static Byte_t RRegData[RREGDATASIZE] = {
- 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
- 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
- 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
- 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
- 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
- 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
- 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
- 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
- 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
- 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
- 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
- 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
- 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
-};
-
-CONTROLLER_T sController[CTL_SIZE] = {
- {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
- {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
- {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
- {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
- {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
- {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
- {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
- {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}
-};
-
-Byte_t sBitMapClrTbl[8] = {
- 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f
-};
-
-Byte_t sBitMapSetTbl[8] = {
- 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
-};
-
-int sClockPrescale = 0x14;
-
/***************************************************************************
Function: sInitController
Purpose: Initialization of controller global registers and controller
@@ -2554,22 +2566,22 @@ Call: sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
FREQ_4HZ - 4 Hertz
If IRQNum is set to 0 the Frequency parameter is
overidden, it is forced to a value of FREQ_DIS.
- int PeriodicOnly: TRUE if all interrupts except the periodic
+ int PeriodicOnly: 1 if all interrupts except the periodic
interrupt are to be blocked.
- FALSE is both the periodic interrupt and
+ 0 is both the periodic interrupt and
other channel interrupts are allowed.
If IRQNum is set to 0 the PeriodicOnly parameter is
- overidden, it is forced to a value of FALSE.
+ overidden, it is forced to a value of 0.
Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
initialization failed.
Comments:
If periodic interrupts are to be disabled but AIOP interrupts
- are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
+ are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
If interrupts are to be completely disabled set IRQNum to 0.
- Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
+ Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
invalid combination.
This function performs initialization of global interrupt modes,
@@ -2589,9 +2601,9 @@ Warnings: No range checking on any of the parameters is done.
After this function all AIOPs on the controller are disabled,
they can be enabled with sEnAiop().
*/
-int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
- ByteIO_t * AiopIOList, int AiopIOListSize, int IRQNum,
- Byte_t Frequency, int PeriodicOnly)
+static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
+ ByteIO_t * AiopIOList, int AiopIOListSize,
+ int IRQNum, Byte_t Frequency, int PeriodicOnly)
{
int i;
ByteIO_t io;
@@ -2687,22 +2699,22 @@ Call: sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize,
FREQ_4HZ - 4 Hertz
If IRQNum is set to 0 the Frequency parameter is
overidden, it is forced to a value of FREQ_DIS.
- int PeriodicOnly: TRUE if all interrupts except the periodic
+ int PeriodicOnly: 1 if all interrupts except the periodic
interrupt are to be blocked.
- FALSE is both the periodic interrupt and
+ 0 is both the periodic interrupt and
other channel interrupts are allowed.
If IRQNum is set to 0 the PeriodicOnly parameter is
- overidden, it is forced to a value of FALSE.
+ overidden, it is forced to a value of 0.
Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
initialization failed.
Comments:
If periodic interrupts are to be disabled but AIOP interrupts
- are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
+ are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
If interrupts are to be completely disabled set IRQNum to 0.
- Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
+ Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
invalid combination.
This function performs initialization of global interrupt modes,
@@ -2722,11 +2734,11 @@ Warnings: No range checking on any of the parameters is done.
After this function all AIOPs on the controller are disabled,
they can be enabled with sEnAiop().
*/
-int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
- ByteIO_t * AiopIOList, int AiopIOListSize,
- WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
- int PeriodicOnly, int altChanRingIndicator,
- int UPCIRingInd)
+static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
+ ByteIO_t * AiopIOList, int AiopIOListSize,
+ WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
+ int PeriodicOnly, int altChanRingIndicator,
+ int UPCIRingInd)
{
int i;
ByteIO_t io;
@@ -2784,7 +2796,7 @@ Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X
Warnings: No context switches are allowed while executing this function.
*/
-int sReadAiopID(ByteIO_t io)
+static int sReadAiopID(ByteIO_t io)
{
Byte_t AiopID; /* ID byte from AIOP */
@@ -2810,7 +2822,7 @@ Comments: The number of channels is determined by write/reads from identical
AIOP, otherwise it is an 8 channel.
Warnings: No context switches are allowed while executing this function.
*/
-int sReadAiopNumChan(WordIO_t io)
+static int sReadAiopNumChan(WordIO_t io)
{
Word_t x;
static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 };
@@ -2834,15 +2846,15 @@ Call: sInitChan(CtlP,ChP,AiopNum,ChanNum)
CHANNEL_T *ChP; Ptr to channel structure
int AiopNum; AIOP number within controller
int ChanNum; Channel number within AIOP
-Return: int: TRUE if initialization succeeded, FALSE if it fails because channel
+Return: int: 1 if initialization succeeded, 0 if it fails because channel
number exceeds number of channels available in AIOP.
Comments: This function must be called before a channel can be used.
Warnings: No range checking on any of the parameters is done.
No context switches are allowed while executing this function.
*/
-int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
- int ChanNum)
+static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
+ int ChanNum)
{
int i;
WordIO_t AiopIO;
@@ -2853,7 +2865,7 @@ int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
int brd9600;
if (ChanNum >= CtlP->AiopNumChan[AiopNum])
- return (FALSE); /* exceeds num chans in AIOP */
+ return 0; /* exceeds num chans in AIOP */
/* Channel, AIOP, and controller identifiers */
ChP->CtlP = CtlP;
@@ -2968,7 +2980,7 @@ int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
ChP->TxPrioBuf = ChOff + _TXP_BUF;
sEnRxProcessor(ChP); /* start the Rx processor */
- return (TRUE);
+ return 1;
}
/***************************************************************************
@@ -2989,7 +3001,7 @@ Warnings: No context switches are allowed while executing this function.
After calling this function a delay of 4 uS is required to ensure
that the receive processor is no longer processing this channel.
*/
-void sStopRxProcessor(CHANNEL_T * ChP)
+static void sStopRxProcessor(CHANNEL_T * ChP)
{
Byte_t R[4];
@@ -3014,18 +3026,18 @@ Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
this function.
Warnings: No context switches are allowed while executing this function.
*/
-void sFlushRxFIFO(CHANNEL_T * ChP)
+static void sFlushRxFIFO(CHANNEL_T * ChP)
{
int i;
Byte_t Ch; /* channel number within AIOP */
- int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */
+ int RxFIFOEnabled; /* 1 if Rx FIFO enabled */
if (sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
return; /* don't need to flush */
- RxFIFOEnabled = FALSE;
+ RxFIFOEnabled = 0;
if (ChP->R[0x32] == 0x08) { /* Rx FIFO is enabled */
- RxFIFOEnabled = TRUE;
+ RxFIFOEnabled = 1;
sDisRxFIFO(ChP); /* disable it */
for (i = 0; i < 2000 / 200; i++) /* delay 2 uS to allow proc to disable FIFO */
sInB(ChP->IntChan); /* depends on bus i/o timing */
@@ -3056,18 +3068,18 @@ Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
this function.
Warnings: No context switches are allowed while executing this function.
*/
-void sFlushTxFIFO(CHANNEL_T * ChP)
+static void sFlushTxFIFO(CHANNEL_T * ChP)
{
int i;
Byte_t Ch; /* channel number within AIOP */
- int TxEnabled; /* TRUE if transmitter enabled */
+ int TxEnabled; /* 1 if transmitter enabled */
if (sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
return; /* don't need to flush */
- TxEnabled = FALSE;
+ TxEnabled = 0;
if (ChP->TxControl[3] & TX_ENABLE) {
- TxEnabled = TRUE;
+ TxEnabled = 1;
sDisTransmit(ChP); /* disable transmitter */
}
sStopRxProcessor(ChP); /* stop Rx processor */
@@ -3096,7 +3108,7 @@ Comments: The priority byte is transmitted before any data in the Tx FIFO.
Warnings: No context switches are allowed while executing this function.
*/
-int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data)
+static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data)
{
Byte_t DWBuf[4]; /* buffer for double word writes */
Word_t *WordPtr; /* must be far because Win SS != DS */
@@ -3158,7 +3170,7 @@ Comments: If an interrupt enable flag is set in Flags, that interrupt will be
enable channel interrupts. This would allow the global interrupt
status register to be used to determine which AIOPs need service.
*/
-void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags)
+static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags)
{
Byte_t Mask; /* Interrupt Mask Register */
@@ -3202,7 +3214,7 @@ Comments: If an interrupt flag is set in Flags, that interrupt will be
this channel's bit from being set in the AIOP's Interrupt Channel
Register.
*/
-void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
+static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
{
Byte_t Mask; /* Interrupt Mask Register */
@@ -3218,7 +3230,7 @@ void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
}
}
-void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode)
+static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode)
{
sOutB(ChP->CtlP->AiopIO[2], (mode & 0x18) | ChP->ChanNum);
}
@@ -3227,7 +3239,7 @@ void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode)
* Not an official SSCI function, but how to reset RocketModems.
* ISA bus version
*/
-void sModemReset(CONTROLLER_T * CtlP, int chan, int on)
+static void sModemReset(CONTROLLER_T * CtlP, int chan, int on)
{
ByteIO_t addr;
Byte_t val;
@@ -3252,7 +3264,7 @@ void sModemReset(CONTROLLER_T * CtlP, int chan, int on)
* Not an official SSCI function, but how to reset RocketModems.
* PCI bus version
*/
-void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on)
+static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on)
{
ByteIO_t addr;
diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h
index 802687290ee..3a8bcc85bc1 100644
--- a/drivers/char/rocket_int.h
+++ b/drivers/char/rocket_int.h
@@ -1130,46 +1130,6 @@ Warnings: This function writes the data byte without checking to see if
*/
#define sWriteTxByte(IO,DATA) sOutB(IO,DATA)
-int sInitController(CONTROLLER_T * CtlP,
- int CtlNum,
- ByteIO_t MudbacIO,
- ByteIO_t * AiopIOList,
- int AiopIOListSize,
- int IRQNum, Byte_t Frequency, int PeriodicOnly);
-
-int sPCIInitController(CONTROLLER_T * CtlP,
- int CtlNum,
- ByteIO_t * AiopIOList,
- int AiopIOListSize,
- WordIO_t ConfigIO,
- int IRQNum,
- Byte_t Frequency,
- int PeriodicOnly,
- int altChanRingIndicator, int UPCIRingInd);
-
-int sReadAiopID(ByteIO_t io);
-int sReadAiopNumChan(WordIO_t io);
-int sInitChan(CONTROLLER_T * CtlP,
- CHANNEL_T * ChP, int AiopNum, int ChanNum);
-Byte_t sGetRxErrStatus(CHANNEL_T * ChP);
-void sStopRxProcessor(CHANNEL_T * ChP);
-void sStopSWInFlowCtl(CHANNEL_T * ChP);
-void sFlushRxFIFO(CHANNEL_T * ChP);
-void sFlushTxFIFO(CHANNEL_T * ChP);
-int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data);
-void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags);
-void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags);
-void sModemReset(CONTROLLER_T * CtlP, int chan, int on);
-void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on);
-void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode);
-
-extern Byte_t R[RDATASIZE];
-extern CONTROLLER_T sController[CTL_SIZE];
-extern Byte_t sIRQMap[16];
-extern Byte_t sBitMapClrTbl[8];
-extern Byte_t sBitMapSetTbl[8];
-extern int sClockPrescale;
-
/*
* Begin Linux specific definitions for the Rocketport driver
*
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index e3c0b52d943..261a41bf6d0 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -357,6 +357,8 @@ static struct file_operations scdrv_fops = {
.release = scdrv_release,
};
+static struct class *snsc_class;
+
/*
* scdrv_init
*
@@ -372,7 +374,6 @@ scdrv_init(void)
char *devnamep;
struct sysctl_data_s *scd;
void *salbuf;
- struct class_simple *snsc_class;
dev_t first_dev, dev;
nasid_t event_nasid = ia64_sn_get_console_nasid();
@@ -382,7 +383,7 @@ scdrv_init(void)
__FUNCTION__);
return -ENODEV;
}
- snsc_class = class_simple_create(THIS_MODULE, SYSCTL_BASENAME);
+ snsc_class = class_create(THIS_MODULE, SYSCTL_BASENAME);
for (cnode = 0; cnode < numionodes; cnode++) {
geoid = cnodeid_get_geoid(cnode);
@@ -436,7 +437,7 @@ scdrv_init(void)
continue;
}
- class_simple_device_add(snsc_class, dev, NULL,
+ class_device_create(snsc_class, dev, NULL,
"%s", devname);
ia64_sn_irtr_intr_enable(scd->scd_nasid,
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index b8899f560b5..951545a6ef2 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -719,7 +719,7 @@ static struct file_operations stl_fsiomem = {
/*****************************************************************************/
-static struct class_simple *stallion_class;
+static struct class *stallion_class;
/*
* Loadable module initialization stuff.
@@ -777,13 +777,13 @@ static void __exit stallion_module_exit(void)
}
for (i = 0; i < 4; i++) {
devfs_remove("staliomem/%d", i);
- class_simple_device_remove(MKDEV(STL_SIOMEMMAJOR, i));
+ class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
}
devfs_remove("staliomem");
if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
printk("STALLION: failed to un-register serial memory device, "
"errno=%d\n", -i);
- class_simple_destroy(stallion_class);
+ class_destroy(stallion_class);
if (stl_tmpwritebuf != (char *) NULL)
kfree(stl_tmpwritebuf);
@@ -3090,12 +3090,12 @@ static int __init stl_init(void)
printk("STALLION: failed to register serial board device\n");
devfs_mk_dir("staliomem");
- stallion_class = class_simple_create(THIS_MODULE, "staliomem");
+ stallion_class = class_create(THIS_MODULE, "staliomem");
for (i = 0; i < 4; i++) {
devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
S_IFCHR|S_IRUSR|S_IWUSR,
"staliomem/%d", i);
- class_simple_device_add(stallion_class, MKDEV(STL_SIOMEMMAJOR, i), NULL, "staliomem%d", i);
+ class_device_create(stallion_class, MKDEV(STL_SIOMEMMAJOR, i), NULL, "staliomem%d", i);
}
stl_serial->owner = THIS_MODULE;
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index f59f7cbd525..af79805b557 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -35,6 +35,7 @@
#include <linux/spinlock.h>
#include <linux/vt_kern.h>
#include <linux/workqueue.h>
+#include <linux/kexec.h>
#include <asm/ptrace.h>
@@ -94,6 +95,21 @@ static struct sysrq_key_op sysrq_unraw_op = {
};
#endif /* CONFIG_VT */
+#ifdef CONFIG_KEXEC
+/* crashdump sysrq handler */
+static void sysrq_handle_crashdump(int key, struct pt_regs *pt_regs,
+ struct tty_struct *tty)
+{
+ crash_kexec(pt_regs);
+}
+static struct sysrq_key_op sysrq_crashdump_op = {
+ .handler = sysrq_handle_crashdump,
+ .help_msg = "Crashdump",
+ .action_msg = "Trigger a crashdump",
+ .enable_mask = SYSRQ_ENABLE_DUMP,
+};
+#endif
+
/* reboot sysrq handler */
static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
struct tty_struct *tty)
@@ -273,8 +289,12 @@ static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
it is handled specially on the sparc
and will never arrive */
/* b */ &sysrq_reboot_op,
-/* c */ NULL,
-/* d */ NULL,
+#ifdef CONFIG_KEXEC
+/* c */ &sysrq_crashdump_op,
+#else
+/* c */ NULL,
+#endif
+/* d */ NULL,
/* e */ &sysrq_term_op,
/* f */ &sysrq_moom_op,
/* g */ NULL,
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
index 0c5ba9dc906..659335d80ee 100644
--- a/drivers/char/tipar.c
+++ b/drivers/char/tipar.c
@@ -90,7 +90,7 @@ static int timeout = TIMAXTIME; /* timeout in tenth of seconds */
static unsigned int tp_count; /* tipar count */
static unsigned long opened; /* opened devices */
-static struct class_simple *tipar_class;
+static struct class *tipar_class;
/* --- macros for parport access -------------------------------------- */
@@ -436,7 +436,7 @@ tipar_register(int nr, struct parport *port)
goto out;
}
- class_simple_device_add(tipar_class, MKDEV(TIPAR_MAJOR,
+ class_device_create(tipar_class, MKDEV(TIPAR_MAJOR,
TIPAR_MINOR + nr), NULL, "par%d", nr);
/* Use devfs, tree: /dev/ticables/par/[0..2] */
err = devfs_mk_cdev(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr),
@@ -458,8 +458,8 @@ tipar_register(int nr, struct parport *port)
goto out;
out_class:
- class_simple_device_remove(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr));
- class_simple_destroy(tipar_class);
+ class_device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr));
+ class_destroy(tipar_class);
out:
return err;
}
@@ -505,7 +505,7 @@ tipar_init_module(void)
/* Use devfs with tree: /dev/ticables/par/[0..2] */
devfs_mk_dir("ticables/par");
- tipar_class = class_simple_create(THIS_MODULE, "ticables");
+ tipar_class = class_create(THIS_MODULE, "ticables");
if (IS_ERR(tipar_class)) {
err = PTR_ERR(tipar_class);
goto out_chrdev;
@@ -539,10 +539,10 @@ tipar_cleanup_module(void)
if (table[i].dev == NULL)
continue;
parport_unregister_device(table[i].dev);
- class_simple_device_remove(MKDEV(TIPAR_MAJOR, i));
+ class_device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, i));
devfs_remove("ticables/par/%d", i);
}
- class_simple_destroy(tipar_class);
+ class_destroy(tipar_class);
devfs_remove("ticables/par");
pr_info("tipar: module unloaded\n");
diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c
index 58e21fe4426..0c6f521abd0 100644
--- a/drivers/char/toshiba.c
+++ b/drivers/char/toshiba.c
@@ -73,16 +73,20 @@
#define TOSH_MINOR_DEV 181
-static int tosh_id = 0x0000;
-static int tosh_bios = 0x0000;
-static int tosh_date = 0x0000;
-static int tosh_sci = 0x0000;
-static int tosh_fan = 0;
-
-static int tosh_fn = 0;
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jonathan Buzzard <jonathan@buzzard.org.uk>");
+MODULE_DESCRIPTION("Toshiba laptop SMM driver");
+MODULE_SUPPORTED_DEVICE("toshiba");
-module_param(tosh_fn, int, 0);
+static int tosh_fn;
+module_param_named(fn, tosh_fn, int, 0);
+MODULE_PARM_DESC(fn, "User specified Fn key detection port");
+static int tosh_id;
+static int tosh_bios;
+static int tosh_date;
+static int tosh_sci;
+static int tosh_fan;
static int tosh_ioctl(struct inode *, struct file *, unsigned int,
unsigned long);
@@ -359,7 +363,7 @@ static int tosh_get_machine_id(void)
unsigned long address;
id = (0x100*(int) isa_readb(0xffffe))+((int) isa_readb(0xffffa));
-
+
/* do we have a SCTTable machine identication number on our hands */
if (id==0xfc2f) {
@@ -424,7 +428,7 @@ static int tosh_probe(void)
}
/* call the Toshiba SCI support check routine */
-
+
regs.eax = 0xf0f0;
regs.ebx = 0x0000;
regs.ecx = 0x0000;
@@ -440,7 +444,7 @@ static int tosh_probe(void)
/* if we get this far then we are running on a Toshiba (probably)! */
tosh_sci = regs.edx & 0xffff;
-
+
/* next get the machine ID of the current laptop */
tosh_id = tosh_get_machine_id();
@@ -475,16 +479,15 @@ static int tosh_probe(void)
return 0;
}
-int __init tosh_init(void)
+static int __init toshiba_init(void)
{
int retval;
/* are we running on a Toshiba laptop */
- if (tosh_probe()!=0)
- return -EIO;
+ if (tosh_probe())
+ return -ENODEV;
- printk(KERN_INFO "Toshiba System Managment Mode driver v"
- TOSH_VERSION"\n");
+ printk(KERN_INFO "Toshiba System Managment Mode driver v" TOSH_VERSION "\n");
/* set the port to use for Fn status if not specified as a parameter */
if (tosh_fn==0x00)
@@ -492,12 +495,12 @@ int __init tosh_init(void)
/* register the device file */
retval = misc_register(&tosh_device);
- if(retval < 0)
+ if (retval < 0)
return retval;
#ifdef CONFIG_PROC_FS
/* register the proc entry */
- if(create_proc_info_entry("toshiba", 0, NULL, tosh_get_info) == NULL){
+ if (create_proc_info_entry("toshiba", 0, NULL, tosh_get_info) == NULL) {
misc_deregister(&tosh_device);
return -ENOMEM;
}
@@ -506,27 +509,12 @@ int __init tosh_init(void)
return 0;
}
-#ifdef MODULE
-int init_module(void)
-{
- return tosh_init();
-}
-
-void cleanup_module(void)
+static void __exit toshiba_exit(void)
{
- /* remove the proc entry */
-
remove_proc_entry("toshiba", NULL);
-
- /* unregister the device file */
-
misc_deregister(&tosh_device);
}
-#endif
-MODULE_LICENSE("GPL");
-MODULE_PARM_DESC(tosh_fn, "User specified Fn key detection port");
-MODULE_AUTHOR("Jonathan Buzzard <jonathan@buzzard.org.uk>");
-MODULE_DESCRIPTION("Toshiba laptop SMM driver");
-MODULE_SUPPORTED_DEVICE("toshiba");
+module_init(toshiba_init);
+module_exit(toshiba_exit);
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 87235330fdb..854475c54f0 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -19,7 +19,7 @@
*
* Note, the TPM chip is not interrupt driven (only polling)
* and can have very long timeouts (minutes!). Hence the unusual
- * calls to schedule_timeout.
+ * calls to msleep.
*
*/
@@ -28,19 +28,16 @@
#include <linux/spinlock.h>
#include "tpm.h"
-#define TPM_MINOR 224 /* officially assigned */
-
-#define TPM_BUFSIZE 2048
-
-/* PCI configuration addresses */
-#define PCI_GEN_PMCON_1 0xA0
-#define PCI_GEN1_DEC 0xE4
-#define PCI_LPC_EN 0xE6
-#define PCI_GEN2_DEC 0xEC
+enum tpm_const {
+ TPM_MINOR = 224, /* officially assigned */
+ TPM_BUFSIZE = 2048,
+ TPM_NUM_DEVICES = 256,
+ TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int))
+};
static LIST_HEAD(tpm_chip_list);
static DEFINE_SPINLOCK(driver_lock);
-static int dev_mask[32];
+static int dev_mask[TPM_NUM_MASK_ENTRIES];
static void user_reader_timeout(unsigned long ptr)
{
@@ -52,92 +49,17 @@ static void user_reader_timeout(unsigned long ptr)
up(&chip->buffer_mutex);
}
-void tpm_time_expired(unsigned long ptr)
-{
- int *exp = (int *) ptr;
- *exp = 1;
-}
-
-EXPORT_SYMBOL_GPL(tpm_time_expired);
-
-/*
- * Initialize the LPC bus and enable the TPM ports
- */
-int tpm_lpc_bus_init(struct pci_dev *pci_dev, u16 base)
-{
- u32 lpcenable, tmp;
- int is_lpcm = 0;
-
- switch (pci_dev->vendor) {
- case PCI_VENDOR_ID_INTEL:
- switch (pci_dev->device) {
- case PCI_DEVICE_ID_INTEL_82801CA_12:
- case PCI_DEVICE_ID_INTEL_82801DB_12:
- is_lpcm = 1;
- break;
- }
- /* init ICH (enable LPC) */
- pci_read_config_dword(pci_dev, PCI_GEN1_DEC, &lpcenable);
- lpcenable |= 0x20000000;
- pci_write_config_dword(pci_dev, PCI_GEN1_DEC, lpcenable);
-
- if (is_lpcm) {
- pci_read_config_dword(pci_dev, PCI_GEN1_DEC,
- &lpcenable);
- if ((lpcenable & 0x20000000) == 0) {
- dev_err(&pci_dev->dev,
- "cannot enable LPC\n");
- return -ENODEV;
- }
- }
-
- /* initialize TPM registers */
- pci_read_config_dword(pci_dev, PCI_GEN2_DEC, &tmp);
-
- if (!is_lpcm)
- tmp = (tmp & 0xFFFF0000) | (base & 0xFFF0);
- else
- tmp =
- (tmp & 0xFFFF0000) | (base & 0xFFF0) |
- 0x00000001;
-
- pci_write_config_dword(pci_dev, PCI_GEN2_DEC, tmp);
-
- if (is_lpcm) {
- pci_read_config_dword(pci_dev, PCI_GEN_PMCON_1,
- &tmp);
- tmp |= 0x00000004; /* enable CLKRUN */
- pci_write_config_dword(pci_dev, PCI_GEN_PMCON_1,
- tmp);
- }
- tpm_write_index(0x0D, 0x55); /* unlock 4F */
- tpm_write_index(0x0A, 0x00); /* int disable */
- tpm_write_index(0x08, base); /* base addr lo */
- tpm_write_index(0x09, (base & 0xFF00) >> 8); /* base addr hi */
- tpm_write_index(0x0D, 0xAA); /* lock 4F */
- break;
- case PCI_VENDOR_ID_AMD:
- /* nothing yet */
- break;
- }
-
- return 0;
-}
-
-EXPORT_SYMBOL_GPL(tpm_lpc_bus_init);
-
/*
* Internal kernel interface to transmit TPM commands
*/
static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
size_t bufsiz)
{
- ssize_t len;
+ ssize_t rc;
u32 count;
- __be32 *native_size;
+ unsigned long stop;
- native_size = (__force __be32 *) (buf + 2);
- count = be32_to_cpu(*native_size);
+ count = be32_to_cpu(*((__be32 *) (buf + 2)));
if (count == 0)
return -ENODATA;
@@ -149,53 +71,49 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
down(&chip->tpm_mutex);
- if ((len = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+ if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
dev_err(&chip->pci_dev->dev,
- "tpm_transmit: tpm_send: error %zd\n", len);
- return len;
+ "tpm_transmit: tpm_send: error %zd\n", rc);
+ goto out;
}
- down(&chip->timer_manipulation_mutex);
- chip->time_expired = 0;
- init_timer(&chip->device_timer);
- chip->device_timer.function = tpm_time_expired;
- chip->device_timer.expires = jiffies + 2 * 60 * HZ;
- chip->device_timer.data = (unsigned long) &chip->time_expired;
- add_timer(&chip->device_timer);
- up(&chip->timer_manipulation_mutex);
-
+ stop = jiffies + 2 * 60 * HZ;
do {
u8 status = inb(chip->vendor->base + 1);
if ((status & chip->vendor->req_complete_mask) ==
chip->vendor->req_complete_val) {
- down(&chip->timer_manipulation_mutex);
- del_singleshot_timer_sync(&chip->device_timer);
- up(&chip->timer_manipulation_mutex);
goto out_recv;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(TPM_TIMEOUT);
+
+ if ((status == chip->vendor->req_canceled)) {
+ dev_err(&chip->pci_dev->dev, "Operation Canceled\n");
+ rc = -ECANCELED;
+ goto out;
+ }
+
+ msleep(TPM_TIMEOUT); /* CHECK */
rmb();
- } while (!chip->time_expired);
+ } while (time_before(jiffies, stop));
chip->vendor->cancel(chip);
- dev_err(&chip->pci_dev->dev, "Time expired\n");
- up(&chip->tpm_mutex);
- return -EIO;
+ dev_err(&chip->pci_dev->dev, "Operation Timed out\n");
+ rc = -ETIME;
+ goto out;
out_recv:
- len = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
- if (len < 0)
+ rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+ if (rc < 0)
dev_err(&chip->pci_dev->dev,
- "tpm_transmit: tpm_recv: error %zd\n", len);
+ "tpm_transmit: tpm_recv: error %zd\n", rc);
+out:
up(&chip->tpm_mutex);
- return len;
+ return rc;
}
#define TPM_DIGEST_SIZE 20
#define CAP_PCR_RESULT_SIZE 18
-static u8 cap_pcr[] = {
+static const u8 cap_pcr[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 22, /* length */
0, 0, 0, 101, /* TPM_ORD_GetCapability */
@@ -205,75 +123,94 @@ static u8 cap_pcr[] = {
};
#define READ_PCR_RESULT_SIZE 30
-static u8 pcrread[] = {
+static const u8 pcrread[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 14, /* length */
0, 0, 0, 21, /* TPM_ORD_PcrRead */
0, 0, 0, 0 /* PCR index */
};
-static ssize_t show_pcrs(struct device *dev, char *buf)
+ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
u8 data[READ_PCR_RESULT_SIZE];
ssize_t len;
- int i, j, index, num_pcrs;
+ int i, j, num_pcrs;
+ __be32 index;
char *str = buf;
struct tpm_chip *chip =
- pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+ pci_get_drvdata(to_pci_dev(dev));
if (chip == NULL)
return -ENODEV;
memcpy(data, cap_pcr, sizeof(cap_pcr));
if ((len = tpm_transmit(chip, data, sizeof(data)))
- < CAP_PCR_RESULT_SIZE)
- return len;
+ < CAP_PCR_RESULT_SIZE) {
+ dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred "
+ "attempting to determine the number of PCRS\n",
+ be32_to_cpu(*((__be32 *) (data + 6))));
+ return 0;
+ }
- num_pcrs = be32_to_cpu(*((__force __be32 *) (data + 14)));
+ num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
for (i = 0; i < num_pcrs; i++) {
memcpy(data, pcrread, sizeof(pcrread));
index = cpu_to_be32(i);
memcpy(data + 10, &index, 4);
if ((len = tpm_transmit(chip, data, sizeof(data)))
- < READ_PCR_RESULT_SIZE)
- return len;
+ < READ_PCR_RESULT_SIZE){
+ dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred"
+ " attempting to read PCR %d of %d\n",
+ be32_to_cpu(*((__be32 *) (data + 6))), i, num_pcrs);
+ goto out;
+ }
str += sprintf(str, "PCR-%02d: ", i);
for (j = 0; j < TPM_DIGEST_SIZE; j++)
str += sprintf(str, "%02X ", *(data + 10 + j));
str += sprintf(str, "\n");
}
+out:
return str - buf;
}
-
-static DEVICE_ATTR(pcrs, S_IRUGO, show_pcrs, NULL);
+EXPORT_SYMBOL_GPL(tpm_show_pcrs);
#define READ_PUBEK_RESULT_SIZE 314
-static u8 readpubek[] = {
+static const u8 readpubek[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 30, /* length */
0, 0, 0, 124, /* TPM_ORD_ReadPubek */
};
-static ssize_t show_pubek(struct device *dev, char *buf)
+ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
- u8 data[READ_PUBEK_RESULT_SIZE];
+ u8 *data;
ssize_t len;
- __be32 *native_val;
- int i;
+ int i, rc;
char *str = buf;
struct tpm_chip *chip =
- pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+ pci_get_drvdata(to_pci_dev(dev));
if (chip == NULL)
return -ENODEV;
+ data = kmalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
memcpy(data, readpubek, sizeof(readpubek));
memset(data + sizeof(readpubek), 0, 20); /* zero nonce */
- if ((len = tpm_transmit(chip, data, sizeof(data))) <
- READ_PUBEK_RESULT_SIZE)
- return len;
+ if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
+ READ_PUBEK_RESULT_SIZE) {
+ dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred "
+ "attempting to read the PUBEK\n",
+ be32_to_cpu(*((__be32 *) (data + 6))));
+ rc = 0;
+ goto out;
+ }
/*
ignore header 10 bytes
@@ -286,8 +223,6 @@ static ssize_t show_pubek(struct device *dev, char *buf)
ignore checksum 20 bytes
*/
- native_val = (__force __be32 *) (data + 34);
-
str +=
sprintf(str,
"Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
@@ -298,21 +233,23 @@ static ssize_t show_pubek(struct device *dev, char *buf)
data[15], data[16], data[17], data[22], data[23],
data[24], data[25], data[26], data[27], data[28],
data[29], data[30], data[31], data[32], data[33],
- be32_to_cpu(*native_val)
- );
+ be32_to_cpu(*((__be32 *) (data + 34))));
for (i = 0; i < 256; i++) {
- str += sprintf(str, "%02X ", data[i + 39]);
+ str += sprintf(str, "%02X ", data[i + 38]);
if ((i + 1) % 16 == 0)
str += sprintf(str, "\n");
}
- return str - buf;
+ rc = str - buf;
+out:
+ kfree(data);
+ return rc;
}
-static DEVICE_ATTR(pubek, S_IRUGO, show_pubek, NULL);
+EXPORT_SYMBOL_GPL(tpm_show_pubek);
#define CAP_VER_RESULT_SIZE 18
-static u8 cap_version[] = {
+static const u8 cap_version[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 18, /* length */
0, 0, 0, 101, /* TPM_ORD_GetCapability */
@@ -321,7 +258,7 @@ static u8 cap_version[] = {
};
#define CAP_MANUFACTURER_RESULT_SIZE 18
-static u8 cap_manufacturer[] = {
+static const u8 cap_manufacturer[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 22, /* length */
0, 0, 0, 101, /* TPM_ORD_GetCapability */
@@ -330,14 +267,15 @@ static u8 cap_manufacturer[] = {
0, 0, 1, 3
};
-static ssize_t show_caps(struct device *dev, char *buf)
+ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
- u8 data[READ_PUBEK_RESULT_SIZE];
+ u8 data[sizeof(cap_manufacturer)];
ssize_t len;
char *str = buf;
struct tpm_chip *chip =
- pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+ pci_get_drvdata(to_pci_dev(dev));
if (chip == NULL)
return -ENODEV;
@@ -348,7 +286,7 @@ static ssize_t show_caps(struct device *dev, char *buf)
return len;
str += sprintf(str, "Manufacturer: 0x%x\n",
- be32_to_cpu(*(data + 14)));
+ be32_to_cpu(*((__be32 *) (data + 14))));
memcpy(data, cap_version, sizeof(cap_version));
@@ -363,8 +301,20 @@ static ssize_t show_caps(struct device *dev, char *buf)
return str - buf;
}
+EXPORT_SYMBOL_GPL(tpm_show_caps);
+
+ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return 0;
+
+ chip->vendor->cancel(chip);
+ return count;
+}
+EXPORT_SYMBOL_GPL(tpm_store_cancel);
-static DEVICE_ATTR(caps, S_IRUGO, show_caps, NULL);
/*
* Device file system interface to the TPM
@@ -422,24 +372,15 @@ EXPORT_SYMBOL_GPL(tpm_open);
int tpm_release(struct inode *inode, struct file *file)
{
struct tpm_chip *chip = file->private_data;
-
- file->private_data = NULL;
spin_lock(&driver_lock);
+ file->private_data = NULL;
chip->num_opens--;
- spin_unlock(&driver_lock);
-
- down(&chip->timer_manipulation_mutex);
- if (timer_pending(&chip->user_read_timer))
- del_singleshot_timer_sync(&chip->user_read_timer);
- else if (timer_pending(&chip->device_timer))
- del_singleshot_timer_sync(&chip->device_timer);
- up(&chip->timer_manipulation_mutex);
-
- kfree(chip->data_buffer);
+ del_singleshot_timer_sync(&chip->user_read_timer);
atomic_set(&chip->data_pending, 0);
-
pci_dev_put(chip->pci_dev);
+ kfree(chip->data_buffer);
+ spin_unlock(&driver_lock);
return 0;
}
@@ -453,10 +394,8 @@ ssize_t tpm_write(struct file * file, const char __user * buf,
/* cannot perform a write until the read has cleared
either via tpm_read or a user_read_timer timeout */
- while (atomic_read(&chip->data_pending) != 0) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(TPM_TIMEOUT);
- }
+ while (atomic_read(&chip->data_pending) != 0)
+ msleep(TPM_TIMEOUT);
down(&chip->buffer_mutex);
@@ -476,13 +415,7 @@ ssize_t tpm_write(struct file * file, const char __user * buf,
up(&chip->buffer_mutex);
/* Set a timeout by which the reader must come claim the result */
- down(&chip->timer_manipulation_mutex);
- init_timer(&chip->user_read_timer);
- chip->user_read_timer.function = user_reader_timeout;
- chip->user_read_timer.data = (unsigned long) chip;
- chip->user_read_timer.expires = jiffies + (60 * HZ);
- add_timer(&chip->user_read_timer);
- up(&chip->timer_manipulation_mutex);
+ mod_timer(&chip->user_read_timer, jiffies + (60 * HZ));
return in_size;
}
@@ -493,29 +426,19 @@ ssize_t tpm_read(struct file * file, char __user * buf,
size_t size, loff_t * off)
{
struct tpm_chip *chip = file->private_data;
- int ret_size = -ENODATA;
+ int ret_size;
- if (atomic_read(&chip->data_pending) != 0) { /* Result available */
- down(&chip->timer_manipulation_mutex);
- del_singleshot_timer_sync(&chip->user_read_timer);
- up(&chip->timer_manipulation_mutex);
+ del_singleshot_timer_sync(&chip->user_read_timer);
+ ret_size = atomic_read(&chip->data_pending);
+ atomic_set(&chip->data_pending, 0);
+ if (ret_size > 0) { /* relay data */
+ if (size < ret_size)
+ ret_size = size;
down(&chip->buffer_mutex);
-
- ret_size = atomic_read(&chip->data_pending);
- atomic_set(&chip->data_pending, 0);
-
- if (ret_size == 0) /* timeout just occurred */
- ret_size = -ETIME;
- else if (ret_size > 0) { /* relay data */
- if (size < ret_size)
- ret_size = size;
-
- if (copy_to_user((void __user *) buf,
- chip->data_buffer, ret_size)) {
- ret_size = -EFAULT;
- }
- }
+ if (copy_to_user
+ ((void __user *) buf, chip->data_buffer, ret_size))
+ ret_size = -EFAULT;
up(&chip->buffer_mutex);
}
@@ -541,14 +464,13 @@ void __devexit tpm_remove(struct pci_dev *pci_dev)
pci_set_drvdata(pci_dev, NULL);
misc_deregister(&chip->vendor->miscdev);
+ kfree(&chip->vendor->miscdev.name);
- device_remove_file(&pci_dev->dev, &dev_attr_pubek);
- device_remove_file(&pci_dev->dev, &dev_attr_pcrs);
- device_remove_file(&pci_dev->dev, &dev_attr_caps);
+ sysfs_remove_group(&pci_dev->dev.kobj, chip->vendor->attr_group);
pci_disable_device(pci_dev);
- dev_mask[chip->dev_num / 32] &= !(1 << (chip->dev_num % 32));
+ dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
kfree(chip);
@@ -590,10 +512,6 @@ int tpm_pm_resume(struct pci_dev *pci_dev)
if (chip == NULL)
return -ENODEV;
- spin_lock(&driver_lock);
- tpm_lpc_bus_init(pci_dev, chip->vendor->base);
- spin_unlock(&driver_lock);
-
return 0;
}
@@ -609,7 +527,9 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume);
int tpm_register_hardware(struct pci_dev *pci_dev,
struct tpm_vendor_specific *entry)
{
- char devname[7];
+#define DEVNAME_SIZE 7
+
+ char *devname;
struct tpm_chip *chip;
int i, j;
@@ -622,17 +542,21 @@ int tpm_register_hardware(struct pci_dev *pci_dev,
init_MUTEX(&chip->buffer_mutex);
init_MUTEX(&chip->tpm_mutex);
- init_MUTEX(&chip->timer_manipulation_mutex);
INIT_LIST_HEAD(&chip->list);
+ init_timer(&chip->user_read_timer);
+ chip->user_read_timer.function = user_reader_timeout;
+ chip->user_read_timer.data = (unsigned long) chip;
+
chip->vendor = entry;
chip->dev_num = -1;
- for (i = 0; i < 32; i++)
- for (j = 0; j < 8; j++)
+ for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++)
+ for (j = 0; j < 8 * sizeof(int); j++)
if ((dev_mask[i] & (1 << j)) == 0) {
- chip->dev_num = i * 32 + j;
+ chip->dev_num =
+ i * TPM_NUM_MASK_ENTRIES + j;
dev_mask[i] |= 1 << j;
goto dev_num_search_complete;
}
@@ -648,7 +572,8 @@ dev_num_search_complete:
else
chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
- snprintf(devname, sizeof(devname), "%s%d", "tpm", chip->dev_num);
+ devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
+ scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
chip->vendor->miscdev.name = devname;
chip->vendor->miscdev.dev = &(pci_dev->dev);
@@ -665,31 +590,20 @@ dev_num_search_complete:
return -ENODEV;
}
+ spin_lock(&driver_lock);
+
pci_set_drvdata(pci_dev, chip);
list_add(&chip->list, &tpm_chip_list);
- device_create_file(&pci_dev->dev, &dev_attr_pubek);
- device_create_file(&pci_dev->dev, &dev_attr_pcrs);
- device_create_file(&pci_dev->dev, &dev_attr_caps);
-
- return 0;
-}
+ spin_unlock(&driver_lock);
-EXPORT_SYMBOL_GPL(tpm_register_hardware);
+ sysfs_create_group(&pci_dev->dev.kobj, chip->vendor->attr_group);
-static int __init init_tpm(void)
-{
return 0;
}
-static void __exit cleanup_tpm(void)
-{
-
-}
-
-module_init(init_tpm);
-module_exit(cleanup_tpm);
+EXPORT_SYMBOL_GPL(tpm_register_hardware);
MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
MODULE_DESCRIPTION("TPM Driver");
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index de0c796fce8..373b41f6b46 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -25,23 +25,38 @@
#include <linux/fs.h>
#include <linux/miscdevice.h>
-#define TPM_TIMEOUT msecs_to_jiffies(5)
+enum tpm_timeout {
+ TPM_TIMEOUT = 5, /* msecs */
+};
/* TPM addresses */
-#define TPM_ADDR 0x4E
-#define TPM_DATA 0x4F
+enum tpm_addr {
+ TPM_SUPERIO_ADDR = 0x2E,
+ TPM_ADDR = 0x4E,
+};
+
+extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr,
+ const char *, size_t);
struct tpm_chip;
struct tpm_vendor_specific {
u8 req_complete_mask;
u8 req_complete_val;
+ u8 req_canceled;
u16 base; /* TPM base address */
int (*recv) (struct tpm_chip *, u8 *, size_t);
int (*send) (struct tpm_chip *, u8 *, size_t);
void (*cancel) (struct tpm_chip *);
struct miscdevice miscdev;
+ struct attribute_group *attr_group;
};
struct tpm_chip {
@@ -58,29 +73,24 @@ struct tpm_chip {
struct timer_list user_read_timer; /* user needs to claim result */
struct semaphore tpm_mutex; /* tpm is processing */
- struct timer_list device_timer; /* tpm is processing */
- struct semaphore timer_manipulation_mutex;
struct tpm_vendor_specific *vendor;
struct list_head list;
};
-static inline int tpm_read_index(int index)
+static inline int tpm_read_index(int base, int index)
{
- outb(index, TPM_ADDR);
- return inb(TPM_DATA) & 0xFF;
+ outb(index, base);
+ return inb(base+1) & 0xFF;
}
-static inline void tpm_write_index(int index, int value)
+static inline void tpm_write_index(int base, int index, int value)
{
- outb(index, TPM_ADDR);
- outb(value & 0xFF, TPM_DATA);
+ outb(index, base);
+ outb(value & 0xFF, base+1);
}
-extern void tpm_time_expired(unsigned long);
-extern int tpm_lpc_bus_init(struct pci_dev *, u16);
-
extern int tpm_register_hardware(struct pci_dev *,
struct tpm_vendor_specific *);
extern int tpm_open(struct inode *, struct file *);
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index f9333e729b6..cc2cc77fd17 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -22,17 +22,23 @@
#include "tpm.h"
/* Atmel definitions */
-#define TPM_ATML_BASE 0x400
+enum tpm_atmel_addr {
+ TPM_ATMEL_BASE_ADDR_LO = 0x08,
+ TPM_ATMEL_BASE_ADDR_HI = 0x09
+};
/* write status bits */
-#define ATML_STATUS_ABORT 0x01
-#define ATML_STATUS_LASTBYTE 0x04
-
+enum tpm_atmel_write_status {
+ ATML_STATUS_ABORT = 0x01,
+ ATML_STATUS_LASTBYTE = 0x04
+};
/* read status bits */
-#define ATML_STATUS_BUSY 0x01
-#define ATML_STATUS_DATA_AVAIL 0x02
-#define ATML_STATUS_REWRITE 0x04
-
+enum tpm_atmel_read_status {
+ ATML_STATUS_BUSY = 0x01,
+ ATML_STATUS_DATA_AVAIL = 0x02,
+ ATML_STATUS_REWRITE = 0x04,
+ ATML_STATUS_READY = 0x08
+};
static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
{
@@ -121,13 +127,29 @@ static struct file_operations atmel_ops = {
.release = tpm_release,
};
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR |S_IWGRP, NULL, tpm_store_cancel);
+
+static struct attribute* atmel_attrs[] = {
+ &dev_attr_pubek.attr,
+ &dev_attr_pcrs.attr,
+ &dev_attr_caps.attr,
+ &dev_attr_cancel.attr,
+ 0,
+};
+
+static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs };
+
static struct tpm_vendor_specific tpm_atmel = {
.recv = tpm_atml_recv,
.send = tpm_atml_send,
.cancel = tpm_atml_cancel,
.req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
.req_complete_val = ATML_STATUS_DATA_AVAIL,
- .base = TPM_ATML_BASE,
+ .req_canceled = ATML_STATUS_READY,
+ .attr_group = &atmel_attr_grp,
.miscdev = { .fops = &atmel_ops, },
};
@@ -136,27 +158,29 @@ static int __devinit tpm_atml_init(struct pci_dev *pci_dev,
{
u8 version[4];
int rc = 0;
+ int lo, hi;
if (pci_enable_device(pci_dev))
return -EIO;
- if (tpm_lpc_bus_init(pci_dev, TPM_ATML_BASE)) {
- rc = -ENODEV;
- goto out_err;
- }
+ lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
+ hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
+
+ tpm_atmel.base = (hi<<8)|lo;
+ dev_dbg( &pci_dev->dev, "Operating with base: 0x%x\n", tpm_atmel.base);
/* verify that it is an Atmel part */
- if (tpm_read_index(4) != 'A' || tpm_read_index(5) != 'T'
- || tpm_read_index(6) != 'M' || tpm_read_index(7) != 'L') {
+ if (tpm_read_index(TPM_ADDR, 4) != 'A' || tpm_read_index(TPM_ADDR, 5) != 'T'
+ || tpm_read_index(TPM_ADDR, 6) != 'M' || tpm_read_index(TPM_ADDR, 7) != 'L') {
rc = -ENODEV;
goto out_err;
}
/* query chip for its version number */
- if ((version[0] = tpm_read_index(0x00)) != 0xFF) {
- version[1] = tpm_read_index(0x01);
- version[2] = tpm_read_index(0x02);
- version[3] = tpm_read_index(0x03);
+ if ((version[0] = tpm_read_index(TPM_ADDR, 0x00)) != 0xFF) {
+ version[1] = tpm_read_index(TPM_ADDR, 0x01);
+ version[2] = tpm_read_index(TPM_ADDR, 0x02);
+ version[3] = tpm_read_index(TPM_ADDR, 0x03);
} else {
dev_info(&pci_dev->dev, "version query failed\n");
rc = -ENODEV;
@@ -183,6 +207,7 @@ static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
{PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
+ {PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6LPC)},
{0,}
};
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index 9cce833a092..b4127348c06 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -22,43 +22,52 @@
#include "tpm.h"
/* National definitions */
-#define TPM_NSC_BASE 0x360
-#define TPM_NSC_IRQ 0x07
+enum tpm_nsc_addr{
+ TPM_NSC_IRQ = 0x07,
+ TPM_NSC_BASE0_HI = 0x60,
+ TPM_NSC_BASE0_LO = 0x61,
+ TPM_NSC_BASE1_HI = 0x62,
+ TPM_NSC_BASE1_LO = 0x63
+};
-#define NSC_LDN_INDEX 0x07
-#define NSC_SID_INDEX 0x20
-#define NSC_LDC_INDEX 0x30
-#define NSC_DIO_INDEX 0x60
-#define NSC_CIO_INDEX 0x62
-#define NSC_IRQ_INDEX 0x70
-#define NSC_ITS_INDEX 0x71
+enum tpm_nsc_index {
+ NSC_LDN_INDEX = 0x07,
+ NSC_SID_INDEX = 0x20,
+ NSC_LDC_INDEX = 0x30,
+ NSC_DIO_INDEX = 0x60,
+ NSC_CIO_INDEX = 0x62,
+ NSC_IRQ_INDEX = 0x70,
+ NSC_ITS_INDEX = 0x71
+};
-#define NSC_STATUS 0x01
-#define NSC_COMMAND 0x01
-#define NSC_DATA 0x00
+enum tpm_nsc_status_loc {
+ NSC_STATUS = 0x01,
+ NSC_COMMAND = 0x01,
+ NSC_DATA = 0x00
+};
/* status bits */
-#define NSC_STATUS_OBF 0x01 /* output buffer full */
-#define NSC_STATUS_IBF 0x02 /* input buffer full */
-#define NSC_STATUS_F0 0x04 /* F0 */
-#define NSC_STATUS_A2 0x08 /* A2 */
-#define NSC_STATUS_RDY 0x10 /* ready to receive command */
-#define NSC_STATUS_IBR 0x20 /* ready to receive data */
+enum tpm_nsc_status {
+ NSC_STATUS_OBF = 0x01, /* output buffer full */
+ NSC_STATUS_IBF = 0x02, /* input buffer full */
+ NSC_STATUS_F0 = 0x04, /* F0 */
+ NSC_STATUS_A2 = 0x08, /* A2 */
+ NSC_STATUS_RDY = 0x10, /* ready to receive command */
+ NSC_STATUS_IBR = 0x20 /* ready to receive data */
+};
/* command bits */
-#define NSC_COMMAND_NORMAL 0x01 /* normal mode */
-#define NSC_COMMAND_EOC 0x03
-#define NSC_COMMAND_CANCEL 0x22
-
+enum tpm_nsc_cmd_mode {
+ NSC_COMMAND_NORMAL = 0x01, /* normal mode */
+ NSC_COMMAND_EOC = 0x03,
+ NSC_COMMAND_CANCEL = 0x22
+};
/*
* Wait for a certain status to appear
*/
static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
{
- int expired = 0;
- struct timer_list status_timer =
- TIMER_INITIALIZER(tpm_time_expired, jiffies + 10 * HZ,
- (unsigned long) &expired);
+ unsigned long stop;
/* status immediately available check */
*data = inb(chip->vendor->base + NSC_STATUS);
@@ -66,17 +75,14 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
return 0;
/* wait for status */
- add_timer(&status_timer);
+ stop = jiffies + 10 * HZ;
do {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(TPM_TIMEOUT);
+ msleep(TPM_TIMEOUT);
*data = inb(chip->vendor->base + 1);
- if ((*data & mask) == val) {
- del_singleshot_timer_sync(&status_timer);
+ if ((*data & mask) == val)
return 0;
- }
}
- while (!expired);
+ while (time_before(jiffies, stop));
return -EBUSY;
}
@@ -84,10 +90,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
static int nsc_wait_for_ready(struct tpm_chip *chip)
{
int status;
- int expired = 0;
- struct timer_list status_timer =
- TIMER_INITIALIZER(tpm_time_expired, jiffies + 100,
- (unsigned long) &expired);
+ unsigned long stop;
/* status immediately available check */
status = inb(chip->vendor->base + NSC_STATUS);
@@ -97,19 +100,16 @@ static int nsc_wait_for_ready(struct tpm_chip *chip)
return 0;
/* wait for status */
- add_timer(&status_timer);
+ stop = jiffies + 100;
do {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(TPM_TIMEOUT);
+ msleep(TPM_TIMEOUT);
status = inb(chip->vendor->base + NSC_STATUS);
if (status & NSC_STATUS_OBF)
status = inb(chip->vendor->base + NSC_DATA);
- if (status & NSC_STATUS_RDY) {
- del_singleshot_timer_sync(&status_timer);
+ if (status & NSC_STATUS_RDY)
return 0;
- }
}
- while (!expired);
+ while (time_before(jiffies, stop));
dev_info(&chip->pci_dev->dev, "wait for ready failed\n");
return -EBUSY;
@@ -150,7 +150,8 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
*p = inb(chip->vendor->base + NSC_DATA);
}
- if ((data & NSC_STATUS_F0) == 0) {
+ if ((data & NSC_STATUS_F0) == 0 &&
+ (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0)) {
dev_err(&chip->pci_dev->dev, "F0 not set\n");
return -EIO;
}
@@ -228,100 +229,95 @@ static struct file_operations nsc_ops = {
.release = tpm_release,
};
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR|S_IWGRP, NULL, tpm_store_cancel);
+
+static struct attribute * nsc_attrs[] = {
+ &dev_attr_pubek.attr,
+ &dev_attr_pcrs.attr,
+ &dev_attr_caps.attr,
+ &dev_attr_cancel.attr,
+ 0,
+};
+
+static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs };
+
static struct tpm_vendor_specific tpm_nsc = {
.recv = tpm_nsc_recv,
.send = tpm_nsc_send,
.cancel = tpm_nsc_cancel,
.req_complete_mask = NSC_STATUS_OBF,
.req_complete_val = NSC_STATUS_OBF,
- .base = TPM_NSC_BASE,
+ .req_canceled = NSC_STATUS_RDY,
+ .attr_group = &nsc_attr_grp,
.miscdev = { .fops = &nsc_ops, },
-
};
static int __devinit tpm_nsc_init(struct pci_dev *pci_dev,
const struct pci_device_id *pci_id)
{
int rc = 0;
+ int lo, hi;
+ int nscAddrBase = TPM_ADDR;
+
if (pci_enable_device(pci_dev))
return -EIO;
- if (tpm_lpc_bus_init(pci_dev, TPM_NSC_BASE)) {
- rc = -ENODEV;
- goto out_err;
- }
+ /* select PM channel 1 */
+ tpm_write_index(nscAddrBase,NSC_LDN_INDEX, 0x12);
/* verify that it is a National part (SID) */
- if (tpm_read_index(NSC_SID_INDEX) != 0xEF) {
- rc = -ENODEV;
- goto out_err;
+ if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
+ nscAddrBase = (tpm_read_index(TPM_SUPERIO_ADDR, 0x2C)<<8)|
+ (tpm_read_index(TPM_SUPERIO_ADDR, 0x2B)&0xFE);
+ if (tpm_read_index(nscAddrBase, NSC_SID_INDEX) != 0xF6) {
+ rc = -ENODEV;
+ goto out_err;
+ }
}
+ hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
+ lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO);
+ tpm_nsc.base = (hi<<8) | lo;
+
dev_dbg(&pci_dev->dev, "NSC TPM detected\n");
dev_dbg(&pci_dev->dev,
"NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n",
- tpm_read_index(0x07), tpm_read_index(0x20),
- tpm_read_index(0x27));
+ tpm_read_index(nscAddrBase,0x07), tpm_read_index(nscAddrBase,0x20),
+ tpm_read_index(nscAddrBase,0x27));
dev_dbg(&pci_dev->dev,
"NSC SIOCF1 0x%x SIOCF5 0x%x SIOCF6 0x%x SIOCF8 0x%x\n",
- tpm_read_index(0x21), tpm_read_index(0x25),
- tpm_read_index(0x26), tpm_read_index(0x28));
+ tpm_read_index(nscAddrBase,0x21), tpm_read_index(nscAddrBase,0x25),
+ tpm_read_index(nscAddrBase,0x26), tpm_read_index(nscAddrBase,0x28));
dev_dbg(&pci_dev->dev, "NSC IO Base0 0x%x\n",
- (tpm_read_index(0x60) << 8) | tpm_read_index(0x61));
+ (tpm_read_index(nscAddrBase,0x60) << 8) | tpm_read_index(nscAddrBase,0x61));
dev_dbg(&pci_dev->dev, "NSC IO Base1 0x%x\n",
- (tpm_read_index(0x62) << 8) | tpm_read_index(0x63));
+ (tpm_read_index(nscAddrBase,0x62) << 8) | tpm_read_index(nscAddrBase,0x63));
dev_dbg(&pci_dev->dev, "NSC Interrupt number and wakeup 0x%x\n",
- tpm_read_index(0x70));
+ tpm_read_index(nscAddrBase,0x70));
dev_dbg(&pci_dev->dev, "NSC IRQ type select 0x%x\n",
- tpm_read_index(0x71));
+ tpm_read_index(nscAddrBase,0x71));
dev_dbg(&pci_dev->dev,
"NSC DMA channel select0 0x%x, select1 0x%x\n",
- tpm_read_index(0x74), tpm_read_index(0x75));
+ tpm_read_index(nscAddrBase,0x74), tpm_read_index(nscAddrBase,0x75));
dev_dbg(&pci_dev->dev,
"NSC Config "
"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
- tpm_read_index(0xF0), tpm_read_index(0xF1),
- tpm_read_index(0xF2), tpm_read_index(0xF3),
- tpm_read_index(0xF4), tpm_read_index(0xF5),
- tpm_read_index(0xF6), tpm_read_index(0xF7),
- tpm_read_index(0xF8), tpm_read_index(0xF9));
+ tpm_read_index(nscAddrBase,0xF0), tpm_read_index(nscAddrBase,0xF1),
+ tpm_read_index(nscAddrBase,0xF2), tpm_read_index(nscAddrBase,0xF3),
+ tpm_read_index(nscAddrBase,0xF4), tpm_read_index(nscAddrBase,0xF5),
+ tpm_read_index(nscAddrBase,0xF6), tpm_read_index(nscAddrBase,0xF7),
+ tpm_read_index(nscAddrBase,0xF8), tpm_read_index(nscAddrBase,0xF9));
dev_info(&pci_dev->dev,
- "NSC PC21100 TPM revision %d\n",
- tpm_read_index(0x27) & 0x1F);
-
- if (tpm_read_index(NSC_LDC_INDEX) == 0)
- dev_info(&pci_dev->dev, ": NSC TPM not active\n");
-
- /* select PM channel 1 */
- tpm_write_index(NSC_LDN_INDEX, 0x12);
- tpm_read_index(NSC_LDN_INDEX);
-
- /* disable the DPM module */
- tpm_write_index(NSC_LDC_INDEX, 0);
- tpm_read_index(NSC_LDC_INDEX);
-
- /* set the data register base addresses */
- tpm_write_index(NSC_DIO_INDEX, TPM_NSC_BASE >> 8);
- tpm_write_index(NSC_DIO_INDEX + 1, TPM_NSC_BASE);
- tpm_read_index(NSC_DIO_INDEX);
- tpm_read_index(NSC_DIO_INDEX + 1);
-
- /* set the command register base addresses */
- tpm_write_index(NSC_CIO_INDEX, (TPM_NSC_BASE + 1) >> 8);
- tpm_write_index(NSC_CIO_INDEX + 1, (TPM_NSC_BASE + 1));
- tpm_read_index(NSC_DIO_INDEX);
- tpm_read_index(NSC_DIO_INDEX + 1);
-
- /* set the interrupt number to be used for the host interface */
- tpm_write_index(NSC_IRQ_INDEX, TPM_NSC_IRQ);
- tpm_write_index(NSC_ITS_INDEX, 0x00);
- tpm_read_index(NSC_IRQ_INDEX);
+ "NSC TPM revision %d\n",
+ tpm_read_index(nscAddrBase, 0x27) & 0x1F);
/* enable the DPM module */
- tpm_write_index(NSC_LDC_INDEX, 0x01);
- tpm_read_index(NSC_LDC_INDEX);
+ tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
if ((rc = tpm_register_hardware(pci_dev, &tpm_nsc)) < 0)
goto out_err;
@@ -339,6 +335,9 @@ static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0)},
{PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
{0,}
};
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 26e5e19ed85..6e4be3bb2d8 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -94,6 +94,7 @@
#include <linux/idr.h>
#include <linux/wait.h>
#include <linux/bitops.h>
+#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -251,7 +252,7 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
static DEFINE_SPINLOCK(tty_ldisc_lock);
static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
-static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */
+static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */
int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
{
@@ -262,24 +263,35 @@ int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
return -EINVAL;
spin_lock_irqsave(&tty_ldisc_lock, flags);
- if (new_ldisc) {
- tty_ldiscs[disc] = *new_ldisc;
- tty_ldiscs[disc].num = disc;
- tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
- tty_ldiscs[disc].refcount = 0;
- } else {
- if(tty_ldiscs[disc].refcount)
- ret = -EBUSY;
- else
- tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED;
- }
+ tty_ldiscs[disc] = *new_ldisc;
+ tty_ldiscs[disc].num = disc;
+ tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
+ tty_ldiscs[disc].refcount = 0;
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
return ret;
}
-
EXPORT_SYMBOL(tty_register_ldisc);
+int tty_unregister_ldisc(int disc)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (disc < N_TTY || disc >= NR_LDISCS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ if (tty_ldiscs[disc].refcount)
+ ret = -EBUSY;
+ else
+ tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED;
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(tty_unregister_ldisc);
+
struct tty_ldisc *tty_ldisc_get(int disc)
{
unsigned long flags;
@@ -2169,12 +2181,11 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
return tty_set_ldisc(tty, ldisc);
}
-static int send_break(struct tty_struct *tty, int duration)
+static int send_break(struct tty_struct *tty, unsigned int duration)
{
tty->driver->break_ctl(tty, -1);
if (!signal_pending(current)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(duration);
+ msleep_interruptible(duration);
}
tty->driver->break_ctl(tty, 0);
if (signal_pending(current))
@@ -2355,10 +2366,10 @@ int tty_ioctl(struct inode * inode, struct file * file,
* all by anyone?
*/
if (!arg)
- return send_break(tty, HZ/4);
+ return send_break(tty, 250);
return 0;
case TCSBRKP: /* support for POSIX tcsendbreak() */
- return send_break(tty, arg ? arg*(HZ/10) : HZ/4);
+ return send_break(tty, arg ? arg*100 : 250);
case TIOCMGET:
return tty_tiocmget(tty, file, p);
@@ -2654,7 +2665,7 @@ static void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
tty->driver->write(tty, &ch, 1);
}
-static struct class_simple *tty_class;
+static struct class *tty_class;
/**
* tty_register_device - register a tty device
@@ -2687,7 +2698,7 @@ void tty_register_device(struct tty_driver *driver, unsigned index,
pty_line_name(driver, index, name);
else
tty_line_name(driver, index, name);
- class_simple_device_add(tty_class, dev, device, name);
+ class_device_create(tty_class, dev, device, name);
}
/**
@@ -2701,7 +2712,7 @@ void tty_register_device(struct tty_driver *driver, unsigned index,
void tty_unregister_device(struct tty_driver *driver, unsigned index)
{
devfs_remove("%s%d", driver->devfs_name, index + driver->name_base);
- class_simple_device_remove(MKDEV(driver->major, driver->minor_start) + index);
+ class_device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index);
}
EXPORT_SYMBOL(tty_register_device);
@@ -2918,7 +2929,7 @@ extern int vty_init(void);
static int __init tty_class_init(void)
{
- tty_class = class_simple_create(THIS_MODULE, "tty");
+ tty_class = class_create(THIS_MODULE, "tty");
if (IS_ERR(tty_class))
return PTR_ERR(tty_class);
return 0;
@@ -2947,14 +2958,14 @@ static int __init tty_init(void)
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
panic("Couldn't register /dev/tty driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty");
- class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
+ class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
cdev_init(&console_cdev, &console_fops);
if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
panic("Couldn't register /dev/console driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console");
- class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
+ class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
#ifdef CONFIG_UNIX98_PTYS
cdev_init(&ptmx_cdev, &ptmx_fops);
@@ -2962,7 +2973,7 @@ static int __init tty_init(void)
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
panic("Couldn't register /dev/ptmx driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx");
- class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
+ class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
#endif
#ifdef CONFIG_VT
@@ -2971,7 +2982,7 @@ static int __init tty_init(void)
register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
panic("Couldn't register /dev/tty0 driver\n");
devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0");
- class_simple_device_add(tty_class, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
+ class_device_create(tty_class, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
vty_init();
#endif
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index 7abe405b865..79c2928a881 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -474,7 +474,7 @@ static struct file_operations vcs_fops = {
.open = vcs_open,
};
-static struct class_simple *vc_class;
+static struct class *vc_class;
void vcs_make_devfs(struct tty_struct *tty)
{
@@ -484,26 +484,26 @@ void vcs_make_devfs(struct tty_struct *tty)
devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 129),
S_IFCHR|S_IRUSR|S_IWUSR,
"vcc/a%u", tty->index + 1);
- class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, tty->index + 1), NULL, "vcs%u", tty->index + 1);
- class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, tty->index + 129), NULL, "vcsa%u", tty->index + 1);
+ class_device_create(vc_class, MKDEV(VCS_MAJOR, tty->index + 1), NULL, "vcs%u", tty->index + 1);
+ class_device_create(vc_class, MKDEV(VCS_MAJOR, tty->index + 129), NULL, "vcsa%u", tty->index + 1);
}
void vcs_remove_devfs(struct tty_struct *tty)
{
devfs_remove("vcc/%u", tty->index + 1);
devfs_remove("vcc/a%u", tty->index + 1);
- class_simple_device_remove(MKDEV(VCS_MAJOR, tty->index + 1));
- class_simple_device_remove(MKDEV(VCS_MAJOR, tty->index + 129));
+ class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1));
+ class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129));
}
int __init vcs_init(void)
{
if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops))
panic("unable to get major %d for vcs device", VCS_MAJOR);
- vc_class = class_simple_create(THIS_MODULE, "vc");
+ vc_class = class_create(THIS_MODULE, "vc");
devfs_mk_cdev(MKDEV(VCS_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/0");
devfs_mk_cdev(MKDEV(VCS_MAJOR, 128), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/a0");
- class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
- class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
+ class_device_create(vc_class, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
+ class_device_create(vc_class, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
return 0;
}
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index aea3cbf5219..4764b4f9555 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -237,7 +237,7 @@ static dma_addr_t viotape_unitinfo_token;
static struct mtget viomtget[VIOTAPE_MAX_TAPE];
-static struct class_simple *tape_class;
+static struct class *tape_class;
static struct device *tape_device[VIOTAPE_MAX_TAPE];
@@ -956,9 +956,9 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
state[i].cur_part = 0;
for (j = 0; j < MAX_PARTITIONS; ++j)
state[i].part_stat_rwi[j] = VIOT_IDLE;
- class_simple_device_add(tape_class, MKDEV(VIOTAPE_MAJOR, i), NULL,
+ class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i), NULL,
"iseries!vt%d", i);
- class_simple_device_add(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80),
+ class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80),
NULL, "iseries!nvt%d", i);
devfs_mk_cdev(MKDEV(VIOTAPE_MAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR,
"iseries/vt%d", i);
@@ -980,8 +980,8 @@ static int viotape_remove(struct vio_dev *vdev)
devfs_remove("iseries/nvt%d", i);
devfs_remove("iseries/vt%d", i);
devfs_unregister_tape(state[i].dev_handle);
- class_simple_device_remove(MKDEV(VIOTAPE_MAJOR, i | 0x80));
- class_simple_device_remove(MKDEV(VIOTAPE_MAJOR, i));
+ class_device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80));
+ class_device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i));
return 0;
}
@@ -1045,7 +1045,7 @@ int __init viotap_init(void)
goto clear_handler;
}
- tape_class = class_simple_create(THIS_MODULE, "tape");
+ tape_class = class_create(THIS_MODULE, "tape");
if (IS_ERR(tape_class)) {
printk(VIOTAPE_KERN_WARN "Unable to allocat class\n");
ret = PTR_ERR(tape_class);
@@ -1070,7 +1070,7 @@ int __init viotap_init(void)
return 0;
unreg_class:
- class_simple_destroy(tape_class);
+ class_destroy(tape_class);
unreg_chrdev:
unregister_chrdev(VIOTAPE_MAJOR, "viotape");
clear_handler:
@@ -1110,7 +1110,7 @@ static void __exit viotap_exit(void)
remove_proc_entry("iSeries/viotape", NULL);
vio_unregister_driver(&viotape_driver);
- class_simple_destroy(tape_class);
+ class_destroy(tape_class);
ret = unregister_chrdev(VIOTAPE_MAJOR, "viotape");
if (ret < 0)
printk(VIOTAPE_KERN_WARN "Error unregistering device: %d\n",
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c
new file mode 100644
index 00000000000..683278bc524
--- /dev/null
+++ b/drivers/char/vr41xx_giu.c
@@ -0,0 +1,743 @@
+/*
+ * Driver for NEC VR4100 series General-purpose I/O Unit.
+ *
+ * Copyright (C) 2002 MontaVista Software Inc.
+ * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/cpu.h>
+#include <asm/io.h>
+#include <asm/vr41xx/giu.h>
+#include <asm/vr41xx/vr41xx.h>
+
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
+MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
+MODULE_LICENSE("GPL");
+
+static int major; /* default is dynamic major device number */
+module_param(major, int, 0);
+MODULE_PARM_DESC(major, "Major device number");
+
+#define GIU_TYPE1_START 0x0b000100UL
+#define GIU_TYPE1_SIZE 0x20UL
+
+#define GIU_TYPE2_START 0x0f000140UL
+#define GIU_TYPE2_SIZE 0x20UL
+
+#define GIU_TYPE3_START 0x0f000140UL
+#define GIU_TYPE3_SIZE 0x28UL
+
+#define GIU_PULLUPDOWN_START 0x0b0002e0UL
+#define GIU_PULLUPDOWN_SIZE 0x04UL
+
+#define GIUIOSELL 0x00
+#define GIUIOSELH 0x02
+#define GIUPIODL 0x04
+#define GIUPIODH 0x06
+#define GIUINTSTATL 0x08
+#define GIUINTSTATH 0x0a
+#define GIUINTENL 0x0c
+#define GIUINTENH 0x0e
+#define GIUINTTYPL 0x10
+#define GIUINTTYPH 0x12
+#define GIUINTALSELL 0x14
+#define GIUINTALSELH 0x16
+#define GIUINTHTSELL 0x18
+#define GIUINTHTSELH 0x1a
+#define GIUPODATL 0x1c
+#define GIUPODATEN 0x1c
+#define GIUPODATH 0x1e
+ #define PIOEN0 0x0100
+ #define PIOEN1 0x0200
+#define GIUPODAT 0x1e
+#define GIUFEDGEINHL 0x20
+#define GIUFEDGEINHH 0x22
+#define GIUREDGEINHL 0x24
+#define GIUREDGEINHH 0x26
+
+#define GIUUSEUPDN 0x1e0
+#define GIUTERMUPDN 0x1e2
+
+#define GPIO_HAS_PULLUPDOWN_IO 0x0001
+#define GPIO_HAS_OUTPUT_ENABLE 0x0002
+#define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100
+
+static spinlock_t giu_lock;
+static struct resource *giu_resource1;
+static struct resource *giu_resource2;
+static unsigned long giu_flags;
+static unsigned int giu_nr_pins;
+
+static void __iomem *giu_base;
+
+#define giu_read(offset) readw(giu_base + (offset))
+#define giu_write(offset, value) writew((value), giu_base + (offset))
+
+#define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE)
+#define GIUINT_HIGH_OFFSET 16
+#define GIUINT_HIGH_MAX 32
+
+static inline uint16_t giu_set(uint16_t offset, uint16_t set)
+{
+ uint16_t data;
+
+ data = giu_read(offset);
+ data |= set;
+ giu_write(offset, data);
+
+ return data;
+}
+
+static inline uint16_t giu_clear(uint16_t offset, uint16_t clear)
+{
+ uint16_t data;
+
+ data = giu_read(offset);
+ data &= ~clear;
+ giu_write(offset, data);
+
+ return data;
+}
+
+static unsigned int startup_giuint_low_irq(unsigned int irq)
+{
+ unsigned int pin;
+
+ pin = GPIO_PIN_OF_IRQ(irq);
+ giu_write(GIUINTSTATL, 1 << pin);
+ giu_set(GIUINTENL, 1 << pin);
+
+ return 0;
+}
+
+static void shutdown_giuint_low_irq(unsigned int irq)
+{
+ giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+}
+
+static void enable_giuint_low_irq(unsigned int irq)
+{
+ giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+}
+
+#define disable_giuint_low_irq shutdown_giuint_low_irq
+
+static void ack_giuint_low_irq(unsigned int irq)
+{
+ unsigned int pin;
+
+ pin = GPIO_PIN_OF_IRQ(irq);
+ giu_clear(GIUINTENL, 1 << pin);
+ giu_write(GIUINTSTATL, 1 << pin);
+}
+
+static void end_giuint_low_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+}
+
+static struct hw_interrupt_type giuint_low_irq_type = {
+ .typename = "GIUINTL",
+ .startup = startup_giuint_low_irq,