aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRoland Dreier <rolandd@cisco.com>2005-10-28 15:50:51 -0700
committerRoland Dreier <rolandd@cisco.com>2005-10-28 15:50:51 -0700
commita4da0628efd788eb199dd9df225e296035ec2539 (patch)
tree1e611030c993e1480dc2f07f26976d2d33002b0d /drivers
parent70a30e16a8a9d22396a4d1e96af86e43594df584 (diff)
parent20731945ae743034353a88c307920d1f16cf8ac8 (diff)
downloadlinux-a4da0628efd788eb199dd9df225e296035ec2539.tar.gz
Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/attribute_container.c2
-rw-r--r--drivers/base/base.h12
-rw-r--r--drivers/base/class.c150
-rw-r--r--drivers/base/core.c21
-rw-r--r--drivers/base/cpu.c1
-rw-r--r--drivers/base/driver.c3
-rw-r--r--drivers/base/firmware.c3
-rw-r--r--drivers/base/init.c10
-rw-r--r--drivers/base/platform.c22
-rw-r--r--drivers/base/power/sysfs.c73
-rw-r--r--drivers/block/aoe/aoe.h2
-rw-r--r--drivers/block/aoe/aoechr.c2
-rw-r--r--drivers/block/aoe/aoecmd.c15
-rw-r--r--drivers/block/as-iosched.c327
-rw-r--r--drivers/block/cfq-iosched.c372
-rw-r--r--drivers/block/deadline-iosched.c125
-rw-r--r--drivers/block/elevator.c345
-rw-r--r--drivers/block/genhd.c25
-rw-r--r--drivers/block/ll_rw_blk.c193
-rw-r--r--drivers/block/loop.c2
-rw-r--r--drivers/block/noop-iosched.c48
-rw-r--r--drivers/block/paride/pg.c2
-rw-r--r--drivers/block/paride/pt.c4
-rw-r--r--drivers/block/rd.c2
-rw-r--r--drivers/block/sx8.c51
-rw-r--r--drivers/bluetooth/Kconfig8
-rw-r--r--drivers/bluetooth/bpa10x.c3
-rw-r--r--drivers/bluetooth/hci_bcsp.c160
-rw-r--r--drivers/bluetooth/hci_bcsp.h70
-rw-r--r--drivers/bluetooth/hci_h4.c101
-rw-r--r--drivers/bluetooth/hci_h4.h44
-rw-r--r--drivers/bluetooth/hci_ldisc.c134
-rw-r--r--drivers/bluetooth/hci_uart.h84
-rw-r--r--drivers/char/drm/radeon_cp.c11
-rw-r--r--drivers/char/dsp56k.c2
-rw-r--r--drivers/char/ftape/zftape/zftape-init.c12
-rw-r--r--drivers/char/ip2main.c10
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c2
-rw-r--r--drivers/char/istallion.c3
-rw-r--r--drivers/char/lp.c2
-rw-r--r--drivers/char/mem.c3
-rw-r--r--drivers/char/misc.c2
-rw-r--r--drivers/char/n_tty.c2
-rw-r--r--drivers/char/nvram.c110
-rw-r--r--drivers/char/ppdev.c2
-rw-r--r--drivers/char/raw.c4
-rw-r--r--drivers/char/s3c2410-rtc.c20
-rw-r--r--drivers/char/snsc.c2
-rw-r--r--drivers/char/sonypi.c106
-rw-r--r--drivers/char/stallion.c4
-rw-r--r--drivers/char/tipar.c2
-rw-r--r--drivers/char/tty_io.c10
-rw-r--r--drivers/char/vc_screen.c10
-rw-r--r--drivers/char/viotape.c4
-rw-r--r--drivers/char/watchdog/s3c2410_wdt.c30
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c6
-rw-r--r--drivers/hwmon/adm1021.c5
-rw-r--r--drivers/hwmon/adm1025.c3
-rw-r--r--drivers/hwmon/adm1026.c22
-rw-r--r--drivers/hwmon/adm1031.c3
-rw-r--r--drivers/hwmon/adm9240.c429
-rw-r--r--drivers/hwmon/asb100.c11
-rw-r--r--drivers/hwmon/atxp1.c5
-rw-r--r--drivers/hwmon/ds1621.c9
-rw-r--r--drivers/hwmon/fscher.c3
-rw-r--r--drivers/hwmon/fscpos.c5
-rw-r--r--drivers/hwmon/gl518sm.c3
-rw-r--r--drivers/hwmon/gl520sm.c3
-rw-r--r--drivers/hwmon/hdaps.c6
-rw-r--r--drivers/hwmon/hwmon.c2
-rw-r--r--drivers/hwmon/it87.c56
-rw-r--r--drivers/hwmon/lm63.c3
-rw-r--r--drivers/hwmon/lm75.c3
-rw-r--r--drivers/hwmon/lm77.c3
-rw-r--r--drivers/hwmon/lm78.c6
-rw-r--r--drivers/hwmon/lm80.c5
-rw-r--r--drivers/hwmon/lm83.c3
-rw-r--r--drivers/hwmon/lm85.c15
-rw-r--r--drivers/hwmon/lm87.c3
-rw-r--r--drivers/hwmon/lm90.c181
-rw-r--r--drivers/hwmon/lm92.c3
-rw-r--r--drivers/hwmon/max1619.c3
-rw-r--r--drivers/hwmon/pc87360.c3
-rw-r--r--drivers/hwmon/sis5595.c3
-rw-r--r--drivers/hwmon/smsc47b397.c10
-rw-r--r--drivers/hwmon/smsc47m1.c10
-rw-r--r--drivers/hwmon/via686a.c28
-rw-r--r--drivers/hwmon/w83627ehf.c16
-rw-r--r--drivers/hwmon/w83627hf.c32
-rw-r--r--drivers/hwmon/w83781d.c11
-rw-r--r--drivers/hwmon/w83792d.c7
-rw-r--r--drivers/hwmon/w83l785ts.c42
-rw-r--r--drivers/i2c/algos/i2c-algo-pca.c2
-rw-r--r--drivers/i2c/algos/i2c-algo-sibyte.c2
-rw-r--r--drivers/i2c/busses/Kconfig3
-rw-r--r--drivers/i2c/busses/i2c-ali1535.c7
-rw-r--r--drivers/i2c/busses/i2c-ali1563.c7
-rw-r--r--drivers/i2c/busses/i2c-ali15x3.c10
-rw-r--r--drivers/i2c/busses/i2c-amd756-s4882.c4
-rw-r--r--drivers/i2c/busses/i2c-amd756.c8
-rw-r--r--drivers/i2c/busses/i2c-amd8111.c16
-rw-r--r--drivers/i2c/busses/i2c-elektor.c138
-rw-r--r--drivers/i2c/busses/i2c-hydra.c1
-rw-r--r--drivers/i2c/busses/i2c-i801.c61
-rw-r--r--drivers/i2c/busses/i2c-i810.c2
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c3
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c9
-rw-r--r--drivers/i2c/busses/i2c-isa.c1
-rw-r--r--drivers/i2c/busses/i2c-ixp2000.c8
-rw-r--r--drivers/i2c/busses/i2c-ixp4xx.c8
-rw-r--r--drivers/i2c/busses/i2c-keywest.c5
-rw-r--r--drivers/i2c/busses/i2c-mpc.c4
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c6
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c16
-rw-r--r--drivers/i2c/busses/i2c-parport.c11
-rw-r--r--drivers/i2c/busses/i2c-piix4.c13
-rw-r--r--drivers/i2c/busses/i2c-pmac-smu.c3
-rw-r--r--drivers/i2c/busses/i2c-prosavage.c10
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c10
-rw-r--r--drivers/i2c/busses/i2c-savage4.c1
-rw-r--r--drivers/i2c/busses/i2c-sis5595.c10
-rw-r--r--drivers/i2c/busses/i2c-sis630.c9
-rw-r--r--drivers/i2c/busses/i2c-sis96x.c8
-rw-r--r--drivers/i2c/busses/i2c-via.c7
-rw-r--r--drivers/i2c/busses/i2c-viapro.c271
-rw-r--r--drivers/i2c/busses/i2c-voodoo3.c1
-rw-r--r--drivers/i2c/busses/scx200_acb.c3
-rw-r--r--drivers/i2c/chips/Kconfig9
-rw-r--r--drivers/i2c/chips/Makefile1
-rw-r--r--drivers/i2c/chips/ds1337.c3
-rw-r--r--drivers/i2c/chips/ds1374.c7
-rw-r--r--drivers/i2c/chips/eeprom.c9
-rw-r--r--drivers/i2c/chips/isp1301_omap.c1
-rw-r--r--drivers/i2c/chips/m41t00.c4
-rw-r--r--drivers/i2c/chips/max6875.c6
-rw-r--r--drivers/i2c/chips/pca9539.c3
-rw-r--r--drivers/i2c/chips/pcf8574.c5
-rw-r--r--drivers/i2c/chips/pcf8591.c5
-rw-r--r--drivers/i2c/chips/rtc8564.c5
-rw-r--r--drivers/i2c/chips/tps65010.c3
-rw-r--r--drivers/i2c/chips/x1205.c698
-rw-r--r--drivers/i2c/i2c-core.c198
-rw-r--r--drivers/i2c/i2c-dev.c17
-rw-r--r--drivers/ide/ide-tape.c38
-rw-r--r--drivers/ieee1394/dv1394.c2
-rw-r--r--drivers/ieee1394/eth1394.c2
-rw-r--r--drivers/ieee1394/nodemgr.c4
-rw-r--r--drivers/ieee1394/raw1394.c2
-rw-r--r--drivers/ieee1394/video1394.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.h2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.h2
-rw-r--r--drivers/input/evdev.c16
-rw-r--r--drivers/input/input.c445
-rw-r--r--drivers/input/joydev.c16
-rw-r--r--drivers/input/joystick/adi.c93
-rw-r--r--drivers/input/joystick/amijoy.c85
-rw-r--r--drivers/input/joystick/analog.c96
-rw-r--r--drivers/input/joystick/cobra.c66
-rw-r--r--drivers/input/joystick/db9.c292
-rw-r--r--drivers/input/joystick/gamecon.c396
-rw-r--r--drivers/input/joystick/gf2k.c69
-rw-r--r--drivers/input/joystick/grip.c77
-rw-r--r--drivers/input/joystick/grip_mp.c149
-rw-r--r--drivers/input/joystick/guillemot.c51
-rw-r--r--drivers/input/joystick/iforce/iforce-main.c106
-rw-r--r--drivers/input/joystick/iforce/iforce-packets.c5
-rw-r--r--drivers/input/joystick/iforce/iforce-serio.c10
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c22
-rw-r--r--drivers/input/joystick/iforce/iforce.h2
-rw-r--r--drivers/input/joystick/interact.c53
-rw-r--r--drivers/input/joystick/magellan.c71
-rw-r--r--drivers/input/joystick/sidewinder.c70
-rw-r--r--drivers/input/joystick/spaceball.c82
-rw-r--r--drivers/input/joystick/spaceorb.c78
-rw-r--r--drivers/input/joystick/stinger.c75
-rw-r--r--drivers/input/joystick/tmdc.c324
-rw-r--r--drivers/input/joystick/turbografx.c215
-rw-r--r--drivers/input/joystick/twidjoy.c120
-rw-r--r--drivers/input/joystick/warrior.c83
-rw-r--r--drivers/input/keyboard/amikbd.c59
-rw-r--r--drivers/input/keyboard/atkbd.c188
-rw-r--r--drivers/input/keyboard/corgikbd.c96
-rw-r--r--drivers/input/keyboard/hil_kbd.c28
-rw-r--r--drivers/input/keyboard/hilkbd.c8
-rw-r--r--drivers/input/keyboard/lkkbd.c128
-rw-r--r--drivers/input/keyboard/maple_keyb.c72
-rw-r--r--drivers/input/keyboard/newtonkbd.c83
-rw-r--r--drivers/input/keyboard/spitzkbd.c119
-rw-r--r--drivers/input/keyboard/sunkbd.c117
-rw-r--r--drivers/input/keyboard/xtkbd.c80
-rw-r--r--drivers/input/misc/m68kspkr.c36
-rw-r--r--drivers/input/misc/pcspkr.c30
-rw-r--r--drivers/input/misc/sparcspkr.c47
-rw-r--r--drivers/input/mouse/alps.c63
-rw-r--r--drivers/input/mouse/alps.h2
-rw-r--r--drivers/input/mouse/amimouse.c49
-rw-r--r--drivers/input/mouse/hil_ptr.c33
-rw-r--r--drivers/input/mouse/inport.c96
-rw-r--r--drivers/input/mouse/lifebook.c16
-rw-r--r--drivers/input/mouse/logibm.c88
-rw-r--r--drivers/input/mouse/logips2pp.c20
-rw-r--r--drivers/input/mouse/maplemouse.c10
-rw-r--r--drivers/input/mouse/pc110pad.c64
-rw-r--r--drivers/input/mouse/psmouse-base.c99
-rw-r--r--drivers/input/mouse/psmouse.h2
-rw-r--r--drivers/input/mouse/rpcmouse.c43
-rw-r--r--drivers/input/mouse/sermouse.c82
-rw-r--r--drivers/input/mouse/synaptics.c6
-rw-r--r--drivers/input/mouse/vsxxxaa.c84
-rw-r--r--drivers/input/mousedev.c25
-rw-r--r--drivers/input/serio/gscps2.c17
-rw-r--r--drivers/input/serio/hil_mlc.c14
-rw-r--r--drivers/input/serio/hp_sdc.c8
-rw-r--r--drivers/input/serio/i8042.c13
-rw-r--r--drivers/input/touchscreen/corgi_ts.c127
-rw-r--r--drivers/input/touchscreen/elo.c89
-rw-r--r--drivers/input/touchscreen/gunze.c66
-rw-r--r--drivers/input/touchscreen/h3600_ts_input.c149
-rw-r--r--drivers/input/touchscreen/hp680_ts_input.c50
-rw-r--r--drivers/input/touchscreen/mk712.c80
-rw-r--r--drivers/input/touchscreen/mtouch.c64
-rw-r--r--drivers/input/tsdev.c19
-rw-r--r--drivers/isdn/capi/capi.c2
-rw-r--r--drivers/macintosh/adb.c2
-rw-r--r--drivers/macintosh/adbhid.c222
-rw-r--r--drivers/macintosh/mac_hid.c40
-rw-r--r--drivers/md/bitmap.c2
-rw-r--r--drivers/md/dm-crypt.c2
-rw-r--r--drivers/md/md.c10
-rw-r--r--drivers/media/common/ir-common.c1
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c108
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c2
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-remote.c50
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb.h3
-rw-r--r--drivers/media/dvb/ttpci/av7110_ir.c37
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c24
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c51
-rw-r--r--drivers/media/video/bttvp.h2
-rw-r--r--drivers/media/video/cx88/cx88-input.c58
-rw-r--r--drivers/media/video/ir-kbd-gpio.c52
-rw-r--r--drivers/media/video/ir-kbd-i2c.c33
-rw-r--r--drivers/media/video/msp3400.c8
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c39
-rw-r--r--drivers/media/video/saa7134/saa7134.h2
-rw-r--r--drivers/media/video/tda9887.c4
-rw-r--r--drivers/media/video/tuner-core.c4
-rw-r--r--drivers/message/i2o/core.h3
-rw-r--r--drivers/message/i2o/device.c272
-rw-r--r--drivers/message/i2o/driver.c3
-rw-r--r--drivers/message/i2o/iop.c32
-rw-r--r--drivers/mfd/mcp-sa11x0.c20
-rw-r--r--drivers/mfd/ucb1x00-ts.c43
-rw-r--r--drivers/mmc/mmci.c1
-rw-r--r--drivers/mmc/pxamci.c8
-rw-r--r--drivers/mmc/wbsd.c4
-rw-r--r--drivers/mtd/maps/sa1100-flash.c9
-rw-r--r--drivers/mtd/mtdchar.c4
-rw-r--r--drivers/net/8139cp.c5
-rw-r--r--drivers/net/8139too.c5
-rw-r--r--drivers/net/Kconfig25
-rw-r--r--drivers/net/Makefile4
-rw-r--r--drivers/net/arm/am79c961a.c1
-rw-r--r--drivers/net/au1000_eth.c13
-rw-r--r--drivers/net/b44.c136
-rw-r--r--drivers/net/b44.h2
-rw-r--r--drivers/net/bonding/bond_main.c57
-rw-r--r--drivers/net/cassini.c4
-rw-r--r--drivers/net/cs89x0.c14
-rw-r--r--drivers/net/cs89x0.h2
-rw-r--r--drivers/net/declance.c37
-rw-r--r--drivers/net/dm9000.c8
-rw-r--r--drivers/net/e100.c4
-rw-r--r--drivers/net/e1000/e1000.h74
-rw-r--r--drivers/net/e1000/e1000_ethtool.c95
-rw-r--r--drivers/net/e1000/e1000_hw.c220
-rw-r--r--drivers/net/e1000/e1000_hw.h96
-rw-r--r--drivers/net/e1000/e1000_main.c1078
-rw-r--r--drivers/net/e1000/e1000_param.c10
-rw-r--r--drivers/net/epic100.c4
-rw-r--r--drivers/net/forcedeth.c310
-rw-r--r--drivers/net/gianfar.c412
-rw-r--r--drivers/net/gianfar.h30
-rw-r--r--drivers/net/gianfar_ethtool.c100
-rw-r--r--drivers/net/gianfar_mii.c219
-rw-r--r--drivers/net/gianfar_mii.h45
-rw-r--r--drivers/net/gianfar_phy.c661
-rw-r--r--drivers/net/gianfar_phy.h213
-rw-r--r--drivers/net/hamradio/Kconfig1
-rw-r--r--drivers/net/hamradio/bpqether.c9
-rw-r--r--drivers/net/hamradio/mkiss.c182
-rw-r--r--drivers/net/hamradio/mkiss.h62
-rw-r--r--drivers/net/hp100.c48
-rw-r--r--drivers/net/irda/Kconfig10
-rw-r--r--drivers/net/irda/Makefile1
-rw-r--r--drivers/net/irda/pxaficp_ir.c871
-rw-r--r--drivers/net/irda/sa1100_ir.c8
-rw-r--r--drivers/net/irda/smsc-ircc2.c12
-rw-r--r--drivers/net/irda/stir4200.c7
-rw-r--r--drivers/net/ixgb/ixgb_ethtool.c8
-rw-r--r--drivers/net/ixgb/ixgb_main.c3
-rw-r--r--drivers/net/lance.c4
-rw-r--r--drivers/net/lasi_82596.c30
-rw-r--r--drivers/net/lne390.c2
-rw-r--r--drivers/net/mii.c15
-rw-r--r--drivers/net/mipsnet.c371
-rw-r--r--drivers/net/mipsnet.h127
-rw-r--r--drivers/net/myri_sbus.c2
-rw-r--r--drivers/net/myri_sbus.h2
-rw-r--r--drivers/net/ne.c15
-rw-r--r--drivers/net/ne2k-pci.c2
-rw-r--r--drivers/net/ns83820.c3
-rw-r--r--drivers/net/pcnet32.c278
-rw-r--r--drivers/net/phy/Kconfig8
-rw-r--r--drivers/net/phy/mdio_bus.c20
-rw-r--r--drivers/net/phy/phy.c8
-rw-r--r--drivers/net/phy/phy_device.c3
-rw-r--r--drivers/net/ppp_generic.c2
-rw-r--r--drivers/net/r8169.c2
-rw-r--r--drivers/net/rionet.c574
-rw-r--r--drivers/net/s2io-regs.h11
-rw-r--r--drivers/net/s2io.c791
-rw-r--r--drivers/net/s2io.h50
-rw-r--r--drivers/net/sb1250-mac.c1384
-rw-r--r--drivers/net/sgiseeq.c37
-rw-r--r--drivers/net/skge.c2
-rw-r--r--drivers/net/smc91x.c8
-rw-r--r--drivers/net/sunbmac.c3
-rw-r--r--drivers/net/sunbmac.h2
-rw-r--r--drivers/net/sundance.c49
-rw-r--r--drivers/net/tokenring/ibmtr.c9
-rw-r--r--drivers/net/tokenring/olympic.c2
-rw-r--r--drivers/net/tokenring/tms380tr.c3
-rw-r--r--drivers/net/tulip/de2104x.c5
-rw-r--r--drivers/net/typhoon.c7
-rw-r--r--drivers/net/via-rhine.c38
-rw-r--r--drivers/net/wan/cosa.c8
-rw-r--r--drivers/net/wan/cycx_drv.c7
-rw-r--r--drivers/net/wan/cycx_main.c2
-rw-r--r--drivers/net/wan/cycx_x25.c5
-rw-r--r--drivers/net/wan/dscc4.c23
-rw-r--r--drivers/net/wan/farsync.c27
-rw-r--r--drivers/net/wan/hdlc_fr.c2
-rw-r--r--drivers/net/wan/lmc/lmc_debug.c10
-rw-r--r--drivers/net/wan/lmc/lmc_media.c8
-rw-r--r--drivers/net/wan/pc300.h16
-rw-r--r--drivers/net/wan/pc300_drv.c87
-rw-r--r--drivers/net/wan/pc300_tty.c18
-rw-r--r--drivers/net/wan/sdla.c20
-rw-r--r--drivers/net/wan/sdla_fr.c4
-rw-r--r--drivers/net/wan/sdla_x25.c8
-rw-r--r--drivers/net/wan/sdladrv.c16
-rw-r--r--drivers/net/wan/syncppp.c10
-rw-r--r--drivers/net/wireless/airo.c37
-rw-r--r--drivers/net/wireless/airport.c19
-rw-r--r--drivers/net/wireless/atmel.c24
-rw-r--r--drivers/net/wireless/hermes.c11
-rw-r--r--drivers/net/wireless/hermes.h111
-rw-r--r--drivers/net/wireless/hostap/hostap.c6
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_rx.c43
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_tx.c28
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c80
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.h6
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c50
-rw-r--r--drivers/net/wireless/hostap/hostap_hw.c22
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c23
-rw-r--r--drivers/net/wireless/hostap/hostap_pci.c21
-rw-r--r--drivers/net/wireless/hostap/hostap_plx.c11
-rw-r--r--drivers/net/wireless/hostap/hostap_wlan.h2
-rw-r--r--drivers/net/wireless/ipw2100.c24
-rw-r--r--drivers/net/wireless/ipw2100.h2
-rw-r--r--drivers/net/wireless/ipw2200.c27
-rw-r--r--drivers/net/wireless/ipw2200.h4
-rw-r--r--drivers/net/wireless/netwave_cs.c185
-rw-r--r--drivers/net/wireless/orinoco.c235
-rw-r--r--drivers/net/wireless/orinoco.h16
-rw-r--r--drivers/net/wireless/orinoco_cs.c110
-rw-r--r--drivers/net/wireless/orinoco_nortel.c20
-rw-r--r--drivers/net/wireless/orinoco_pci.c18
-rw-r--r--drivers/net/wireless/orinoco_plx.c18
-rw-r--r--drivers/net/wireless/orinoco_tmd.c18
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c10
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.c10
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.h2
-rw-r--r--drivers/net/wireless/prism54/islpci_mgt.c5
-rw-r--r--drivers/net/wireless/ray_cs.c46
-rw-r--r--drivers/net/wireless/spectrum_cs.c79
-rw-r--r--drivers/net/wireless/wavelan.c8
-rw-r--r--drivers/net/wireless/wavelan.p.h4
-rw-r--r--drivers/net/wireless/wavelan_cs.c8
-rw-r--r--drivers/net/wireless/wavelan_cs.p.h4
-rw-r--r--drivers/net/wireless/wl3501.h2
-rw-r--r--drivers/parisc/asp.c6
-rw-r--r--drivers/parisc/ccio-dma.c144
-rw-r--r--drivers/parisc/ccio-rm-dma.c2
-rw-r--r--drivers/parisc/dino.c42
-rw-r--r--drivers/parisc/eisa.c4
-rw-r--r--drivers/parisc/gsc.c11
-rw-r--r--drivers/parisc/hppb.c10
-rw-r--r--drivers/parisc/iosapic.c2
-rw-r--r--drivers/parisc/lasi.c4
-rw-r--r--drivers/parisc/lba_pci.c14
-rw-r--r--drivers/parisc/led.c225
-rw-r--r--drivers/parisc/pdc_stable.c2
-rw-r--r--drivers/parisc/sba_iommu.c166
-rw-r--r--drivers/parisc/superio.c3
-rw-r--r--drivers/parisc/wax.c2
-rw-r--r--drivers/parport/parport_gsc.c5
-rw-r--r--drivers/pci/pcie/portdrv_core.c4
-rw-r--r--drivers/pci/quirks.c101
-rw-r--r--drivers/pcmcia/au1000_generic.c21
-rw-r--r--drivers/pcmcia/ds.c6
-rw-r--r--drivers/pcmcia/hd64465_ss.c20
-rw-r--r--drivers/pcmcia/i82365.c20
-rw-r--r--drivers/pcmcia/m32r_cfc.c21
-rw-r--r--drivers/pcmcia/m32r_pcc.c21
-rw-r--r--drivers/pcmcia/omap_cf.c18
-rw-r--r--drivers/pcmcia/pxa2xx_base.c26
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c6
-rw-r--r--drivers/pcmcia/sa1100_generic.c20
-rw-r--r--drivers/pcmcia/sa1111_generic.c2
-rw-r--r--drivers/pcmcia/socket_sysfs.c6
-rw-r--r--drivers/pcmcia/tcic.c20
-rw-r--r--drivers/pcmcia/vrc4171_card.c24
-rw-r--r--drivers/pcmcia/yenta_socket.c42
-rw-r--r--drivers/s390/char/tape_class.c1
-rw-r--r--drivers/s390/char/vmlogrdr.c1
-rw-r--r--drivers/s390/net/fsm.c2
-rw-r--r--drivers/s390/net/fsm.h2
-rw-r--r--drivers/s390/net/qeth.h45
-rw-r--r--drivers/s390/net/qeth_fs.h12
-rw-r--r--drivers/s390/net/qeth_main.c419
-rw-r--r--drivers/s390/net/qeth_mpc.c6
-rw-r--r--drivers/s390/net/qeth_mpc.h15
-rw-r--r--drivers/s390/net/qeth_sys.c28
-rw-r--r--drivers/scsi/Kconfig22
-rw-r--r--drivers/scsi/Makefile2
-rw-r--r--drivers/scsi/ahci.c41
-rw-r--r--drivers/scsi/ata_piix.c4
-rw-r--r--drivers/scsi/ch.c2
-rw-r--r--drivers/scsi/eata.c2
-rw-r--r--drivers/scsi/hosts.c3
-rw-r--r--drivers/scsi/lasi700.c6
-rw-r--r--drivers/scsi/libata-core.c874
-rw-r--r--drivers/scsi/libata-scsi.c730
-rw-r--r--drivers/scsi/libata.h19
-rw-r--r--drivers/scsi/lpfc/lpfc_mem.c2
-rw-r--r--drivers/scsi/osst.c8
-rw-r--r--drivers/scsi/pdc_adma.c739
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h4
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c3
-rw-r--r--drivers/scsi/qla2xxx/qla_rscn.c2
-rw-r--r--drivers/scsi/sata_mv.c1145
-rw-r--r--drivers/scsi/sata_nv.c8
-rw-r--r--drivers/scsi/sata_promise.c26
-rw-r--r--drivers/scsi/sata_qstor.c8
-rw-r--r--drivers/scsi/sata_sil.c6
-rw-r--r--drivers/scsi/sata_sil24.c875
-rw-r--r--drivers/scsi/sata_sis.c4
-rw-r--r--drivers/scsi/sata_svw.c4
-rw-r--r--drivers/scsi/sata_sx4.c29
-rw-r--r--drivers/scsi/sata_uli.c4
-rw-r--r--drivers/scsi/sata_via.c4
-rw-r--r--drivers/scsi/sata_vsc.c14
-rw-r--r--drivers/scsi/scsi.c8
-rw-r--r--drivers/scsi/scsi_ioctl.c3
-rw-r--r--drivers/scsi/scsi_lib.c2
-rw-r--r--drivers/scsi/sg.c12
-rw-r--r--drivers/scsi/st.c8
-rw-r--r--drivers/scsi/zalon.c4
-rw-r--r--drivers/serial/8250.c10
-rw-r--r--drivers/serial/8250_gsc.c6
-rw-r--r--drivers/serial/8250_pci.c26
-rw-r--r--drivers/serial/amba-pl010.c1
-rw-r--r--drivers/serial/amba-pl011.c1
-rw-r--r--drivers/serial/clps711x.c9
-rw-r--r--drivers/serial/imx.c8
-rw-r--r--drivers/serial/mpc52xx_uart.c8
-rw-r--r--drivers/serial/mux.c11
-rw-r--r--drivers/serial/pxa.c29
-rw-r--r--drivers/serial/s3c2410.c9
-rw-r--r--drivers/serial/sa1100.c8
-rw-r--r--drivers/serial/vr41xx_siu.c10
-rw-r--r--drivers/usb/core/buffer.c2
-rw-r--r--drivers/usb/core/devio.c2
-rw-r--r--drivers/usb/core/file.c4
-rw-r--r--drivers/usb/core/hcd.c5
-rw-r--r--drivers/usb/core/hcd.h8
-rw-r--r--drivers/usb/core/hub.c16
-rw-r--r--drivers/usb/core/message.c2
-rw-r--r--drivers/usb/core/urb.c4
-rw-r--r--drivers/usb/core/usb.c2
-rw-r--r--drivers/usb/gadget/dummy_hcd.c30
-rw-r--r--drivers/usb/gadget/ether.c22
-rw-r--r--drivers/usb/gadget/goku_udc.c6
-rw-r--r--drivers/usb/gadget/lh7a40x_udc.c12
-rw-r--r--drivers/usb/gadget/net2280.c6
-rw-r--r--drivers/usb/gadget/omap_udc.c15
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.c25
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.h8
-rw-r--r--drivers/usb/gadget/serial.c16
-rw-r--r--drivers/usb/gadget/zero.c8
-rw-r--r--drivers/usb/host/ehci-hcd.c2
-rw-r--r--drivers/usb/host/ehci-mem.c6
-rw-r--r--drivers/usb/host/ehci-q.c6
-rw-r--r--drivers/usb/host/ehci-sched.c14
-rw-r--r--drivers/usb/host/isp116x-hcd.c16
-rw-r--r--drivers/usb/host/ohci-hcd.c2
-rw-r--r--drivers/usb/host/ohci-mem.c4
-rw-r--r--drivers/usb/host/ohci-omap.c10
-rw-r--r--drivers/usb/host/ohci-pxa27x.c4
-rw-r--r--drivers/usb/host/sl811-hcd.c12
-rw-r--r--drivers/usb/host/uhci-q.c2
-rw-r--r--drivers/usb/input/acecad.c76
-rw-r--r--drivers/usb/input/aiptek.c209
-rw-r--r--drivers/usb/input/appletouch.c130
-rw-r--r--drivers/usb/input/ati_remote.c173
-rw-r--r--drivers/usb/input/hid-core.c51
-rw-r--r--drivers/usb/input/hid-input.c56
-rw-r--r--drivers/usb/input/hid-lgff.c17
-rw-r--r--drivers/usb/input/hid-tmff.c11
-rw-r--r--drivers/usb/input/hid.h2
-rw-r--r--drivers/usb/input/itmtouch.c70
-rw-r--r--drivers/usb/input/kbtab.c82
-rw-r--r--drivers/usb/input/keyspan_remote.c210
-rw-r--r--drivers/usb/input/mtouchusb.c111
-rw-r--r--drivers/usb/input/pid.c12
-rw-r--r--drivers/usb/input/powermate.c136
-rw-r--r--drivers/usb/input/touchkitusb.c116
-rw-r--r--drivers/usb/input/usbkbd.c105
-rw-r--r--drivers/usb/input/usbmouse.c93
-rw-r--r--drivers/usb/input/wacom.c142
-rw-r--r--drivers/usb/input/xpad.c95
-rw-r--r--drivers/usb/input/yealink.c66
-rw-r--r--drivers/usb/media/konicawc.c89
-rw-r--r--drivers/usb/misc/uss720.c6
-rw-r--r--drivers/usb/net/asix.c2
-rw-r--r--drivers/usb/net/gl620a.c2
-rw-r--r--drivers/usb/net/kaweth.c6
-rw-r--r--drivers/usb/net/net1080.c2
-rw-r--r--drivers/usb/net/rndis_host.c2
-rw-r--r--drivers/usb/net/usbnet.c2
-rw-r--r--drivers/usb/net/usbnet.h2
-rw-r--r--drivers/usb/net/zaurus.c2
-rw-r--r--drivers/usb/net/zd1201.c2
-rw-r--r--drivers/usb/storage/onetouch.c99
-rw-r--r--drivers/video/amba-clcd.c1
-rw-r--r--drivers/video/backlight/corgi_bl.c10
-rw-r--r--drivers/video/console/Kconfig8
-rw-r--r--drivers/video/console/sticore.c126
-rw-r--r--drivers/video/fbmem.c2
-rw-r--r--drivers/video/fbsysfs.c8
-rw-r--r--drivers/video/imxfb.c10
-rw-r--r--drivers/video/pxafb.c10
-rw-r--r--drivers/video/s1d13xxxfb.c7
-rw-r--r--drivers/video/s3c2410fb.c27
-rw-r--r--drivers/video/sa1100fb.c10
-rw-r--r--drivers/video/w100fb.c46
560 files changed, 19412 insertions, 12547 deletions
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index 6b2eb6f39b4dea..2a7d7ae83e1eaf 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -19,6 +19,8 @@
#include <linux/list.h>
#include <linux/module.h>
+#include "base.h"
+
/* This is a private structure used to tie the classdev and the
* container .. it should never be visible outside this file */
struct internal_container {
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 783752b68a9a32..e3b548d46cff82 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -1,3 +1,15 @@
+
+/* initialisation functions */
+
+extern int devices_init(void);
+extern int buses_init(void);
+extern int classes_init(void);
+extern int firmware_init(void);
+extern int platform_bus_init(void);
+extern int system_bus_init(void);
+extern int cpu_dev_init(void);
+extern int attribute_container_init(void);
+
extern int bus_add_device(struct device * dev);
extern void bus_remove_device(struct device * dev);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index ce23dc8c18c590..c3e569730afe70 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -99,7 +99,8 @@ struct class * class_get(struct class * cls)
void class_put(struct class * cls)
{
- subsys_put(&cls->subsys);
+ if (cls)
+ subsys_put(&cls->subsys);
}
@@ -165,14 +166,25 @@ void class_unregister(struct class * cls)
static void class_create_release(struct class *cls)
{
+ pr_debug("%s called for %s\n", __FUNCTION__, cls->name);
kfree(cls);
}
static void class_device_create_release(struct class_device *class_dev)
{
+ pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
kfree(class_dev);
}
+/* needed to allow these devices to have parent class devices */
+static int class_device_create_hotplug(struct class_device *class_dev,
+ char **envp, int num_envp,
+ char *buffer, int buffer_size)
+{
+ pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
+ return 0;
+}
+
/**
* class_create - create a struct class structure
* @owner: pointer to the module that is to "own" this struct class
@@ -301,10 +313,12 @@ static void class_dev_release(struct kobject * kobj)
kfree(cd->devt_attr);
cd->devt_attr = NULL;
- if (cls->release)
+ if (cd->release)
+ cd->release(cd);
+ else if (cls->release)
cls->release(cd);
else {
- printk(KERN_ERR "Device class '%s' does not have a release() function, "
+ printk(KERN_ERR "Class Device '%s' does not have a release() function, "
"it is broken and must be fixed.\n",
cd->class_id);
WARN_ON(1);
@@ -382,14 +396,18 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
buffer = &buffer[length];
buffer_size -= length;
- if (class_dev->class->hotplug) {
- /* have the bus specific function add its stuff */
- retval = class_dev->class->hotplug (class_dev, envp, num_envp,
- buffer, buffer_size);
- if (retval) {
- pr_debug ("%s - hotplug() returned %d\n",
- __FUNCTION__, retval);
- }
+ if (class_dev->hotplug) {
+ /* have the class device specific function add its stuff */
+ retval = class_dev->hotplug(class_dev, envp, num_envp,
+ buffer, buffer_size);
+ if (retval)
+ pr_debug("class_dev->hotplug() returned %d\n", retval);
+ } else if (class_dev->class->hotplug) {
+ /* have the class specific function add its stuff */
+ retval = class_dev->class->hotplug(class_dev, envp, num_envp,
+ buffer, buffer_size);
+ if (retval)
+ pr_debug("class->hotplug() returned %d\n", retval);
}
return retval;
@@ -442,6 +460,13 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
return print_dev_t(buf, class_dev->devt);
}
+static ssize_t store_uevent(struct class_device *class_dev,
+ const char *buf, size_t count)
+{
+ kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+ return count;
+}
+
void class_device_initialize(struct class_device *class_dev)
{
kobj_set_kset_s(class_dev, class_obj_subsys);
@@ -469,34 +494,45 @@ static char *make_class_name(struct class_device *class_dev)
int class_device_add(struct class_device *class_dev)
{
- struct class * parent = NULL;
- struct class_interface * class_intf;
+ struct class *parent_class = NULL;
+ struct class_device *parent_class_dev = NULL;
+ struct class_interface *class_intf;
char *class_name = NULL;
- int error;
+ int error = -EINVAL;
class_dev = class_device_get(class_dev);
if (!class_dev)
return -EINVAL;
- if (!strlen(class_dev->class_id)) {
- error = -EINVAL;
+ if (!strlen(class_dev->class_id))
goto register_done;
- }
- parent = class_get(class_dev->class);
+ parent_class = class_get(class_dev->class);
+ if (!parent_class)
+ goto register_done;
+ parent_class_dev = class_device_get(class_dev->parent);
pr_debug("CLASS: registering class device: ID = '%s'\n",
class_dev->class_id);
/* first, register with generic layer. */
kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
- if (parent)
- class_dev->kobj.parent = &parent->subsys.kset.kobj;
+ if (parent_class_dev)
+ class_dev->kobj.parent = &parent_class_dev->kobj;
+ else
+ class_dev->kobj.parent = &parent_class->subsys.kset.kobj;
- if ((error = kobject_add(&class_dev->kobj)))
+ error = kobject_add(&class_dev->kobj);
+ if (error)
goto register_done;
/* add the needed attributes to this device */
+ class_dev->uevent_attr.attr.name = "uevent";
+ class_dev->uevent_attr.attr.mode = S_IWUSR;
+ class_dev->uevent_attr.attr.owner = parent_class->owner;
+ class_dev->uevent_attr.store = store_uevent;
+ class_device_create_file(class_dev, &class_dev->uevent_attr);
+
if (MAJOR(class_dev->devt)) {
struct class_device_attribute *attr;
attr = kzalloc(sizeof(*attr), GFP_KERNEL);
@@ -505,12 +541,10 @@ int class_device_add(struct class_device *class_dev)
kobject_del(&class_dev->kobj);
goto register_done;
}
-
attr->attr.name = "dev";
attr->attr.mode = S_IRUGO;
- attr->attr.owner = parent->owner;
+ attr->attr.owner = parent_class->owner;
attr->show = show_dev;
- attr->store = NULL;
class_device_create_file(class_dev, attr);
class_dev->devt_attr = attr;
}
@@ -524,20 +558,23 @@ int class_device_add(struct class_device *class_dev)
class_name);
}
+ kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+
/* notify any interfaces this device is now here */
- if (parent) {
- down(&parent->sem);
- list_add_tail(&class_dev->node, &parent->children);
- list_for_each_entry(class_intf, &parent->interfaces, node)
+ if (parent_class) {
+ down(&parent_class->sem);
+ list_add_tail(&class_dev->node, &parent_class->children);
+ list_for_each_entry(class_intf, &parent_class->interfaces, node)
if (class_intf->add)
- class_intf->add(class_dev);
- up(&parent->sem);
+ class_intf->add(class_dev, class_intf);
+ up(&parent_class->sem);
}
- kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
register_done:
- if (error && parent)
- class_put(parent);
+ if (error) {
+ class_put(parent_class);
+ class_device_put(parent_class_dev);
+ }
class_device_put(class_dev);
kfree(class_name);
return error;
@@ -552,21 +589,28 @@ int class_device_register(struct class_device *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.
+ * @parent: pointer to the parent struct class_device of this new device, if any.
* @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.
+ * class.
+ * A "dev" file will be created, showing the dev_t for the device, if
+ * the dev_t is not 0,0.
+ * If a pointer to a parent struct class_device is passed in, the newly
+ * created struct class_device will be a child of that device in sysfs.
+ * 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 class_device *class_device_create(struct class *cls,
+ struct class_device *parent,
+ dev_t devt,
struct device *device, char *fmt, ...)
{
va_list args;
@@ -585,6 +629,9 @@ struct class_device *class_device_create(struct class *cls, dev_t devt,
class_dev->devt = devt;
class_dev->dev = device;
class_dev->class = cls;
+ class_dev->parent = parent;
+ class_dev->release = class_device_create_release;
+ class_dev->hotplug = class_device_create_hotplug;
va_start(args, fmt);
vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
@@ -602,17 +649,18 @@ error:
void class_device_del(struct class_device *class_dev)
{
- struct class * parent = class_dev->class;
- struct class_interface * class_intf;
+ struct class *parent_class = class_dev->class;
+ struct class_device *parent_device = class_dev->parent;
+ struct class_interface *class_intf;
char *class_name = NULL;
- if (parent) {
- down(&parent->sem);
+ if (parent_class) {
+ down(&parent_class->sem);
list_del_init(&class_dev->node);
- list_for_each_entry(class_intf, &parent->interfaces, node)
+ list_for_each_entry(class_intf, &parent_class->interfaces, node)
if (class_intf->remove)
- class_intf->remove(class_dev);
- up(&parent->sem);
+ class_intf->remove(class_dev, class_intf);
+ up(&parent_class->sem);
}
if (class_dev->dev) {
@@ -620,6 +668,7 @@ void class_device_del(struct class_device *class_dev)
sysfs_remove_link(&class_dev->kobj, "device");
sysfs_remove_link(&class_dev->dev->kobj, class_name);
}
+ class_device_remove_file(class_dev, &class_dev->uevent_attr);
if (class_dev->devt_attr)
class_device_remove_file(class_dev, class_dev->devt_attr);
class_device_remove_attrs(class_dev);
@@ -627,8 +676,8 @@ void class_device_del(struct class_device *class_dev)
kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
kobject_del(&class_dev->kobj);
- if (parent)
- class_put(parent);
+ class_device_put(parent_device);
+ class_put(parent_class);
kfree(class_name);
}
@@ -708,7 +757,8 @@ struct class_device * class_device_get(struct class_device *class_dev)
void class_device_put(struct class_device *class_dev)
{
- kobject_put(&class_dev->kobj);
+ if (class_dev)
+ kobject_put(&class_dev->kobj);
}
@@ -728,7 +778,7 @@ int class_interface_register(struct class_interface *class_intf)
list_add_tail(&class_intf->node, &parent->interfaces);
if (class_intf->add) {
list_for_each_entry(class_dev, &parent->children, node)
- class_intf->add(class_dev);
+ class_intf->add(class_dev, class_intf);
}
up(&parent->sem);
@@ -747,7 +797,7 @@ void class_interface_unregister(struct class_interface *class_intf)
list_del_init(&class_intf->node);
if (class_intf->remove) {
list_for_each_entry(class_dev, &parent->children, node)
- class_intf->remove(class_dev);
+ class_intf->remove(class_dev, class_intf);
}
up(&parent->sem);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 6ab73f5c799aa4..8615b42b517a6f 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -154,6 +154,13 @@ static struct kset_hotplug_ops device_hotplug_ops = {
.hotplug = dev_hotplug,
};
+static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ kobject_hotplug(&dev->kobj, KOBJ_ADD);
+ return count;
+}
+
/**
* device_subsys - structure to be registered with kobject core.
*/
@@ -225,6 +232,7 @@ void device_initialize(struct device *dev)
klist_children_put);
INIT_LIST_HEAD(&dev->dma_pools);
init_MUTEX(&dev->sem);
+ device_init_wakeup(dev, 0);
}
/**
@@ -258,6 +266,14 @@ int device_add(struct device *dev)
if ((error = kobject_add(&dev->kobj)))
goto Error;
+
+ dev->uevent_attr.attr.name = "uevent";
+ dev->uevent_attr.attr.mode = S_IWUSR;
+ if (dev->driver)
+ dev->uevent_attr.attr.owner = dev->driver->owner;
+ dev->uevent_attr.store = store_uevent;
+ device_create_file(dev, &dev->uevent_attr);
+
kobject_hotplug(&dev->kobj, KOBJ_ADD);
if ((error = device_pm_add(dev)))
goto PMError;
@@ -349,6 +365,7 @@ void device_del(struct device * dev)
if (parent)
klist_del(&dev->knode_parent);
+ device_remove_file(dev, &dev->uevent_attr);
/* Notify the platform of the removal, in case they
* need to do anything...
@@ -390,11 +407,11 @@ static struct device * next_device(struct klist_iter * i)
/**
* device_for_each_child - device child iterator.
- * @dev: parent struct device.
+ * @parent: parent struct device.
* @data: data for the callback.
* @fn: function to be called for each device.
*
- * Iterate over @dev's child devices, and call @fn for each,
+ * Iterate over @parent's child devices, and call @fn for each,
* passing it @data.
*
* We check the return of @fn each time. If it returns anything
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index b79badd0f1588d..081c927b1ed8b6 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -9,6 +9,7 @@
#include <linux/topology.h>
#include <linux/device.h>
+#include "base.h"
struct sysdev_class cpu_sysdev_class = {
set_kset_name("cpu"),
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index ef3fe513e39855..161f3a390d9065 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -28,6 +28,7 @@ static struct device * next_device(struct klist_iter * i)
/**
* driver_for_each_device - Iterator for devices bound to a driver.
* @drv: Driver we're iterating.
+ * @start: Device to begin with
* @data: Data to pass to the callback.
* @fn: Function to call for each device.
*
@@ -57,7 +58,7 @@ EXPORT_SYMBOL_GPL(driver_for_each_device);
/**
* driver_find_device - device iterator for locating a particular device.
- * @driver: The device's driver
+ * @drv: The device's driver
* @start: Device to begin with
* @data: Data to pass to match function
* @match: Callback function to check device
diff --git a/drivers/base/firmware.c b/drivers/base/firmware.c
index 88ab044932f2a1..cb1b98ae0d5830 100644
--- a/drivers/base/firmware.c
+++ b/drivers/base/firmware.c
@@ -11,6 +11,9 @@
#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/device.h>
+
+#include "base.h"
static decl_subsys(firmware, NULL, NULL);
diff --git a/drivers/base/init.c b/drivers/base/init.c
index a76ae5a221f3e5..84e604e25c4f4d 100644
--- a/drivers/base/init.c
+++ b/drivers/base/init.c
@@ -10,14 +10,8 @@
#include <linux/device.h>
#include <linux/init.h>
-extern int devices_init(void);
-extern int buses_init(void);
-extern int classes_init(void);
-extern int firmware_init(void);
-extern int platform_bus_init(void);
-extern int system_bus_init(void);
-extern int cpu_dev_init(void);
-extern int attribute_container_init(void);
+#include "base.h"
+
/**
* driver_init - initialize driver model.
*
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 361e204209ebb3..75ce8711bca5d7 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -17,6 +17,8 @@
#include <linux/bootmem.h>
#include <linux/err.h>
+#include "base.h"
+
struct device platform_bus = {
.bus_id = "platform",
};
@@ -279,13 +281,9 @@ static int platform_suspend(struct device * dev, pm_message_t state)
{
int ret = 0;
- if (dev->driver && dev->driver->suspend) {
- ret = dev->driver->suspend(dev, state, SUSPEND_DISABLE);
- if (ret == 0)
- ret = dev->driver->suspend(dev, state, SUSPEND_SAVE_STATE);
- if (ret == 0)
- ret = dev->driver->suspend(dev, state, SUSPEND_POWER_DOWN);
- }
+ if (dev->driver && dev->driver->suspend)
+ ret = dev->driver->suspend(dev, state);
+
return ret;
}
@@ -293,13 +291,9 @@ static int platform_resume(struct device * dev)
{
int ret = 0;
- if (dev->driver && dev->driver->resume) {
- ret = dev->driver->resume(dev, RESUME_POWER_ON);
- if (ret == 0)
- ret = dev->driver->resume(dev, RESUME_RESTORE_STATE);
- if (ret == 0)
- ret = dev->driver->resume(dev, RESUME_ENABLE);
- }
+ if (dev->driver && dev->driver->resume)
+ ret = dev->driver->resume(dev);
+
return ret;
}
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index 8d04fb435c176e..89c57875f3e53c 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -48,8 +48,81 @@ static ssize_t state_store(struct device * dev, struct device_attribute *attr, c
static DEVICE_ATTR(state, 0644, state_show, state_store);
+/*
+ * wakeup - Report/change current wakeup option for device
+ *
+ * Some devices support "wakeup" events, which are hardware signals
+ * used to activate devices from suspended or low power states. Such
+ * devices have one of three values for the sysfs power/wakeup file:
+ *
+ * + "enabled\n" to issue the events;
+ * + "disabled\n" not to do so; or
+ * + "\n" for temporary or permanent inability to issue wakeup.
+ *
+ * (For example, unconfigured USB devices can't issue wakeups.)
+ *
+ * Familiar examples of devices that can issue wakeup events include
+ * keyboards and mice (both PS2 and USB styles), power buttons, modems,
+ * "Wake-On-LAN" Ethernet links, GPIO lines, and more. Some events
+ * will wake the entire system from a suspend state; others may just
+ * wake up the device (if the system as a whole is already active).
+ * Some wakeup events use normal IRQ lines; other use special out
+ * of band signaling.
+ *
+ * It is the responsibility of device drivers to enable (or disable)
+ * wakeup signaling as part of changing device power states, respecting
+ * the policy choices provided through the driver model.
+ *
+ * Devices may not be able to generate wakeup events from all power
+ * states. Also, the events may be ignored in some configurations;
+ * for example, they might need help from other devices that aren't
+ * active, or which may have wakeup disabled. Some drivers rely on
+ * wakeup events internally (unless they are disabled), keeping
+ * their hardware in low power modes whenever they're unused. This
+ * saves runtime power, without requiring system-wide sleep states.
+ */
+
+static const char enabled[] = "enabled";
+static const char disabled[] = "disabled";
+
+static ssize_t
+wake_show(struct device * dev, struct device_attribute *attr, char * buf)
+{
+ return sprintf(buf, "%s\n", device_can_wakeup(dev)
+ ? (device_may_wakeup(dev) ? enabled : disabled)
+ : "");
+}
+
+static ssize_t
+wake_store(struct device * dev, struct device_attribute *attr,
+ const char * buf, size_t n)
+{
+ char *cp;
+ int len = n;
+
+ if (!device_can_wakeup(dev))
+ return -EINVAL;
+
+ cp = memchr(buf, '\n', n);
+ if (cp)
+ len = cp - buf;
+ if (len == sizeof enabled - 1
+ && strncmp(buf, enabled, sizeof enabled - 1) == 0)
+ device_set_wakeup_enable(dev, 1);
+ else if (len == sizeof disabled - 1
+ && strncmp(buf, disabled, sizeof disabled - 1) == 0)
+ device_set_wakeup_enable(dev, 0);
+ else
+ return -EINVAL;
+ return n;
+}
+
+static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
+
+
static struct attribute * power_attrs[] = {
&dev_attr_state.attr,
+ &dev_attr_wakeup.attr,
NULL,
};
static struct attribute_group pm_attr_group = {
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index 0e9e586e9ba362..881c48d941b734 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -1,5 +1,5 @@
/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
-#define VERSION "12"
+#define VERSION "14"
#define AOE_MAJOR 152
#define DEVICE_NAME "aoe"
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 45a243096187af..41ae0ede619a84 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -224,7 +224,7 @@ aoechr_init(void)
return PTR_ERR(aoe_class);
}
for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
- class_device_create(aoe_class,
+ class_device_create(aoe_class, NULL,
MKDEV(AOE_MAJOR, chardevs[i].minor),
NULL, chardevs[i].name);
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index b5be4b7d7b5b3a..5c9c7c1a3d4cfd 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -8,6 +8,7 @@
#include <linux/blkdev.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
+#include <asm/unaligned.h>
#include "aoe.h"
#define TIMERTICK (HZ / 10)
@@ -311,16 +312,16 @@ ataid_complete(struct aoedev *d, unsigned char *id)
u16 n;
/* word 83: command set supported */
- n = le16_to_cpup((__le16 *) &id[83<<1]);
+ n = le16_to_cpu(get_unaligned((__le16 *) &id[83<<1]));
/* word 86: command set/feature enabled */
- n |= le16_to_cpup((__le16 *) &id[86<<1]);
+ n |= le16_to_cpu(get_unaligned((__le16 *) &id[86<<1]));
if (n & (1<<10)) { /* bit 10: LBA 48 */
d->flags |= DEVFL_EXT;
/* word 100: number lba48 sectors */
- ssize = le64_to_cpup((__le64 *) &id[100<<1]);
+ ssize = le64_to_cpu(get_unaligned((__le64 *) &id[100<<1]));
/* set as in ide-disk.c:init_idedisk_capacity */
d->geo.cylinders = ssize;
@@ -331,12 +332,12 @@ ataid_complete(struct aoedev *d, unsigned char *id)
d->flags &= ~DEVFL_EXT;
/* number lba28 sectors */
- ssize = le32_to_cpup((__le32 *) &id[60<<1]);
+ ssize = le32_to_cpu(get_unaligned((__le32 *) &id[60<<1]));
/* NOTE: obsolete in ATA 6 */
- d->geo.cylinders = le16_to_cpup((__le16 *) &id[54<<1]);
- d->geo.heads = le16_to_cpup((__le16 *) &id[55<<1]);
- d->geo.sectors = le16_to_cpup((__le16 *) &id[56<<1]);
+ d->geo.cylinders = le16_to_cpu(get_unaligned((__le16 *) &id[54<<1]));
+ d->geo.heads = le16_to_cpu(get_unaligned((__le16 *) &id[55<<1]));
+ d->geo.sectors = le16_to_cpu(get_unaligned((__le16 *) &id[56<<1]));
}
d->ssize = ssize;
d->geo.start = 0;
diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c
index 95c0a3690b0ffc..4081c36c8c19eb 100644
--- a/drivers/block/as-iosched.c
+++ b/drivers/block/as-iosched.c
@@ -98,7 +98,6 @@ struct as_data {
struct as_rq *next_arq[2]; /* next in sort order */
sector_t last_sector[2]; /* last REQ_SYNC & REQ_ASYNC sectors */
- struct list_head *dispatch; /* driver dispatch queue */
struct list_head *hash; /* request hash */
unsigned long exit_prob; /* probability a task will exit while
@@ -239,6 +238,25 @@ static struct io_context *as_get_io_context(void)
return ioc;
}
+static void as_put_io_context(struct as_rq *arq)
+{
+ struct as_io_context *aic;
+
+ if (unlikely(!arq->io_context))
+ return;
+
+ aic = arq->io_context->aic;
+
+ if (arq->is_sync == REQ_SYNC && aic) {
+ spin_lock(&aic->lock);
+ set_bit(AS_TASK_IORUNNING, &aic->state);
+ aic->last_end_request = jiffies;
+ spin_unlock(&aic->lock);
+ }
+
+ put_io_context(arq->io_context);
+}
+
/*
* the back merge hash support functions
*/
@@ -261,14 +279,6 @@ static inline void as_del_arq_hash(struct as_rq *arq)
__as_del_arq_hash(arq);
}
-static void as_remove_merge_hints(request_queue_t *q, struct as_rq *arq)
-{
- as_del_arq_hash(arq);
-
- if (q->last_merge == arq->request)
- q->last_merge = NULL;
-}
-
static void as_add_arq_hash(struct as_data *ad, struct as_rq *arq)
{
struct request *rq = arq->request;
@@ -312,7 +322,7 @@ static struct request *as_find_arq_hash(struct as_data *ad, sector_t offset)
BUG_ON(!arq->on_hash);
if (!rq_mergeable(__rq)) {
- as_remove_merge_hints(ad->q, arq);
+ as_del_arq_hash(arq);
continue;
}
@@ -950,23 +960,12 @@ static void as_completed_request(request_queue_t *q, struct request *rq)
WARN_ON(!list_empty(&rq->queuelist));
- if (arq->state == AS_RQ_PRESCHED) {
- WARN_ON(arq->io_context);
- goto out;
- }
-
- if (arq->state == AS_RQ_MERGED)
- goto out_ioc;
-
if (arq->state != AS_RQ_REMOVED) {
printk("arq->state %d\n", arq->state);
WARN_ON(1);
goto out;
}
- if (!blk_fs_request(rq))
- goto out;
-
if (ad->changed_batch && ad->nr_dispatched == 1) {
kblockd_schedule_work(&ad->antic_work);
ad->changed_batch = 0;
@@ -1001,21 +1000,7 @@ static void as_completed_request(request_queue_t *q, struct request *rq)
}
}
-out_ioc:
- if (!arq->io_context)
- goto out;
-
- if (arq->is_sync == REQ_SYNC) {
- struct as_io_context *aic = arq->io_context->aic;
- if (aic) {
- spin_lock(&aic->lock);
- set_bit(AS_TASK_IORUNNING, &aic->state);
- aic->last_end_request = jiffies;
- spin_unlock(&aic->lock);
- }
- }
-
- put_io_context(arq->io_context);
+ as_put_io_context(arq);
out:
arq->state = AS_RQ_POSTSCHED;
}
@@ -1047,73 +1032,11 @@ static void as_remove_queued_request(request_queue_t *q, struct request *rq)
ad->next_arq[data_dir] = as_find_next_arq(ad, arq);
list_del_init(&arq->fifo);
- as_remove_merge_hints(q, arq);
+ as_del_arq_hash(arq);
as_del_arq_rb(ad, arq);
}
/*
- * as_remove_dispatched_request is called to remove a request which has gone
- * to the dispatch list.
- */
-static void as_remove_dispatched_request(request_queue_t *q, struct request *rq)
-{
- struct as_rq *arq = RQ_DATA(rq);
- struct as_io_context *aic;
-
- if (!arq) {
- WARN_ON(1);
- return;
- }
-
- WARN_ON(arq->state != AS_RQ_DISPATCHED);
- WARN_ON(ON_RB(&arq->rb_node));
- if (arq->io_context && arq->io_context->aic) {
- aic = arq->io_context->aic;
- if (aic) {
- WARN_ON(!atomic_read(&aic->nr_dispatched));
- atomic_dec(&aic->nr_dispatched);
- }
- }
-}
-
-/*
- * as_remove_request is called when a driver has finished with a request.
- * This should be only called for dispatched requests, but for some reason
- * a POWER4 box running hwscan it does not.
- */
-static void as_remove_request(request_queue_t *q, struct request *rq)
-{
- struct as_rq *arq = RQ_DATA(rq);
-
- if (unlikely(arq->state == AS_RQ_NEW))
- goto out;
-
- if (ON_RB(&arq->rb_node)) {
- if (arq->state != AS_RQ_QUEUED) {
- printk("arq->state %d\n", arq->state);
- WARN_ON(1);
- goto out;
- }
- /*
- * We'll lose the aliased request(s) here. I don't think this
- * will ever happen, but if it does, hopefully someone will
- * report it.
- */
- WARN_ON(!list_empty(&rq->queuelist));
- as_remove_queued_request(q, rq);
- } else {
- if (arq->state != AS_RQ_DISPATCHED) {
- printk("arq->state %d\n", arq->state);
- WARN_ON(1);
- goto out;
- }
- as_remove_dispatched_request(q, rq);
- }
-out:
- arq->state = AS_RQ_REMOVED;
-}
-
-/*
* as_fifo_expired returns 0 if there are no expired reads on the fifo,
* 1 otherwise. It is ratelimited so that we only perform the check once per
* `fifo_expire' interval. Otherwise a large number of expired requests
@@ -1165,7 +1088,6 @@ static inline int as_batch_expired(struct as_data *ad)
static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
{
struct request *rq = arq->request;
- struct list_head *insert;
const int data_dir = arq->is_sync;
BUG_ON(!ON_RB(&arq->rb_node));
@@ -1198,13 +1120,13 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
/*
* take it off the sort and fifo list, add to dispatch queue
*/
- insert = ad->dispatch->prev;
-
while (!list_empty(&rq->queuelist)) {
struct request *__rq = list_entry_rq(rq->queuelist.next);
struct as_rq *__arq = RQ_DATA(__rq);
- list_move_tail(&__rq->queuelist, ad->dispatch);
+ list_del(&__rq->queuelist);
+
+ elv_dispatch_add_tail(ad->q, __rq);
if (__arq->io_context && __arq->io_context->aic)
atomic_inc(&__arq->io_context->aic->nr_dispatched);
@@ -1218,7 +1140,8 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
as_remove_queued_request(ad->q, rq);
WARN_ON(arq->state != AS_RQ_QUEUED);
- list_add(&rq->queuelist, insert);
+ elv_dispatch_sort(ad->q, rq);
+
arq->state = AS_RQ_DISPATCHED;
if (arq->io_context && arq->io_context->aic)
atomic_inc(&arq->io_context->aic->nr_dispatched);
@@ -1230,12 +1153,42 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
* read/write expire, batch expire, etc, and moves it to the dispatch
* queue. Returns 1 if a request was found, 0 otherwise.
*/
-static int as_dispatch_request(struct as_data *ad)
+static int as_dispatch_request(request_queue_t *q, int force)
{
+ struct as_data *ad = q->elevator->elevator_data;
struct as_rq *arq;
const int reads = !list_empty(&ad->fifo_list[REQ_SYNC]);
const int writes = !list_empty(&ad->fifo_list[REQ_ASYNC]);
+ if (unlikely(force)) {
+ /*
+ * Forced dispatch, accounting is useless. Reset
+ * accounting states and dump fifo_lists. Note that
+ * batch_data_dir is reset to REQ_SYNC to avoid
+ * screwing write batch accounting as write batch
+ * accounting occurs on W->R transition.
+ */
+ int dispatched = 0;
+
+ ad->batch_data_dir = REQ_SYNC;
+ ad->changed_batch = 0;
+ ad->new_batch = 0;
+
+ while (ad->next_arq[REQ_SYNC]) {
+ as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]);
+ dispatched++;
+ }
+ ad->last_check_fifo[REQ_SYNC] = jiffies;
+
+ while (ad->next_arq[REQ_ASYNC]) {
+ as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]);
+ dispatched++;
+ }
+ ad->last_check_fifo[REQ_ASYNC] = jiffies;
+
+ return dispatched;
+ }
+
/* Signal that the write batch was uncontended, so we can't time it */
if (ad->batch_data_dir == REQ_ASYNC && !reads) {
if (ad->current_write_count == 0 || !writes)
@@ -1359,20 +1312,6 @@ fifo_expired:
return 1;
}
-static struct request *as_next_request(request_queue_t *q)
-{
- struct as_data *ad = q->elevator->elevator_data;
- struct request *rq = NULL;
-
- /*
- * if there are still requests on the dispatch queue, grab the first
- */
- if (!list_empty(ad->dispatch) || as_dispatch_request(ad))
- rq = list_entry_rq(ad->dispatch->next);
-
- return rq;
-}
-
/*
* Add arq to a list behind alias
*/
@@ -1404,17 +1343,25 @@ as_add_aliased_request(struct as_data *ad, struct as_rq *arq, struct as_rq *alia
/*
* Don't want to have to handle merges.
*/
- as_remove_merge_hints(ad->q, arq);
+ as_del_arq_hash(arq);
}
/*
* add arq to rbtree and fifo
*/
-static void as_add_request(struct as_data *ad, struct as_rq *arq)
+static void as_add_request(request_queue_t *q, struct request *rq)
{
+ struct as_data *ad = q->elevator->elevator_data;
+ struct as_rq *arq = RQ_DATA(rq);
struct as_rq *alias;
int data_dir;
+ if (arq->state != AS_RQ_PRESCHED) {
+ printk("arq->state: %d\n", arq->state);
+ WARN_ON(1);
+ }
+ arq->state = AS_RQ_NEW;
+
if (rq_data_dir(arq->request) == READ
|| current->flags&PF_SYNCWRITE)
arq->is_sync = 1;
@@ -1437,12 +1384,8 @@ static void as_add_request(struct as_data *ad, struct as_rq *arq)
arq->expires = jiffies + ad->fifo_expire[data_dir];
list_add_tail(&arq->fifo, &ad->fifo_list[data_dir]);
- if (rq_mergeable(arq->request)) {
+ if (rq_mergeable(arq->request))
as_add_arq_hash(ad, arq);
-
- if (!ad->q->last_merge)
- ad->q->last_merge = arq->request;
- }
as_update_arq(ad, arq); /* keep state machine up to date */
} else {
@@ -1463,96 +1406,24 @@ static void as_add_request(struct as_data *ad, struct as_rq *arq)
arq->state = AS_RQ_QUEUED;
}
-static void as_deactivate_request(request_queue_t *q, struct request *rq)
+static void as_activate_request(request_queue_t *q, struct request *rq)
{
- struct as_data *ad = q->elevator->elevator_data;
struct as_rq *arq = RQ_DATA(rq);
- if (arq) {
- if (arq->state == AS_RQ_REMOVED) {
- arq->state = AS_RQ_DISPATCHED;
- if (arq->io_context && arq->io_context->aic)
- atomic_inc(&arq->io_context->aic->nr_dispatched);
- }
- } else
- WARN_ON(blk_fs_request(rq)
- && (!(rq->flags & (REQ_HARDBARRIER|REQ_SOFTBARRIER))) );
-
- /* Stop anticipating - let this request get through */
- as_antic_stop(ad);
-}
-
-/*
- * requeue the request. The request has not been completed, nor is it a
- * new request, so don't touch accounting.
- */
-static void as_requeue_request(request_queue_t *q, struct request *rq)
-{
- as_deactivate_request(q, rq);
- list_add(&rq->queuelist, &q->queue_head);
-}
-
-/*
- * Account a request that is inserted directly onto the dispatch queue.
- * arq->io_context->aic->nr_dispatched should not need to be incremented
- * because only new requests should come through here: requeues go through
- * our explicit requeue handler.
- */
-static void as_account_queued_request(struct as_data *ad, struct request *rq)
-{
- if (blk_fs_request(rq)) {
- struct as_rq *arq = RQ_DATA(rq);
- arq->state = AS_RQ_DISPATCHED;
- ad->nr_dispatched++;
- }
+ WARN_ON(arq->state != AS_RQ_DISPATCHED);
+ arq->state = AS_RQ_REMOVED;
+ if (arq->io_context && arq->io_context->aic)
+ atomic_dec(&arq->io_context->aic->nr_dispatched);
}
-static void
-as_insert_request(request_queue_t *q, struct request *rq, int where)
+static void as_deactivate_request(request_queue_t *q, struct request *rq)
{
- struct as_data *ad = q->elevator->elevator_data;
struct as_rq *arq = RQ_DATA(rq);
- if (arq) {
- if (arq->state != AS_RQ_PRESCHED) {
- printk("arq->state: %d\n", arq->state);
- WARN_ON(1);
- }
- arq->state = AS_RQ_NEW;
- }
-
- /* barriers must flush the reorder queue */
- if (unlikely(rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)
- && where == ELEVATOR_INSERT_SORT)) {
- WARN_ON(1);
- where = ELEVATOR_INSERT_BACK;
- }
-
- switch (where) {
- case ELEVATOR_INSERT_BACK:
- while (ad->next_arq[REQ_SYNC])
- as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]);
-
- while (ad->next_arq[REQ_ASYNC])
- as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]);
-
- list_add_tail(&rq->queuelist, ad->dispatch);
- as_account_queued_request(ad, rq);
- as_antic_stop(ad);
- break;
- case ELEVATOR_INSERT_FRONT:
- list_add(&rq->queuelist, ad->dispatch);
- as_account_queued_request(ad, rq);
- as_antic_stop(ad);
- break;
- case ELEVATOR_INSERT_SORT:
- BUG_ON(!blk_fs_request(rq));
- as_add_request(ad, arq);
- break;
- default:
- BUG();
- return;
- }
+ WARN_ON(arq->state != AS_RQ_REMOVED);
+ arq->state = AS_RQ_DISPATCHED;
+ if (arq->io_context && arq->io_context->aic)
+ atomic_inc(&arq->io_context->aic->nr_dispatched);
}
/*
@@ -1565,12 +1436,8 @@ static int as_queue_empty(request_queue_t *q)
{
struct as_data *ad = q->elevator->elevator_data;
- if (!list_empty(&ad->fifo_list[REQ_ASYNC])
- || !list_empty(&ad->fifo_list[REQ_SYNC])
- || !list_empty(ad->dispatch))
- return 0;
-
- return 1;
+ return list_empty(&ad->fifo_list[REQ_ASYNC])
+ && list_empty(&ad->fifo_list[REQ_SYNC]);
}
static struct request *
@@ -1608,15 +1475,6 @@ as_merge(request_queue_t *q, struct request **req, struct bio *bio)
int ret;
/*
- * try last_merge to avoid going to hash
- */
- ret = elv_try_last_merge(q, bio);
- if (ret != ELEVATOR_NO_MERGE) {
- __rq = q->last_merge;
- goto out_insert;
- }
-
- /*
* see if the merge hash can satisfy a back merge
*/
__rq = as_find_arq_hash(ad, bio->bi_sector);
@@ -1644,9 +1502,6 @@ as_merge(request_queue_t *q, struct request **req, struct bio *bio)
return ELEVATOR_NO_MERGE;
out:
- if (rq_mergeable(__rq))
- q->last_merge = __rq;
-out_insert:
if (ret) {
if (rq_mergeable(__rq))
as_hot_arq_hash(ad, RQ_DATA(__rq));
@@ -1693,9 +1548,6 @@ static void as_merged_request(request_queue_t *q, struct request *req)
* behind the disk head. We currently don't bother adjusting.
*/
}
-
- if (arq->on_hash)
- q->last_merge = req;
}
static void
@@ -1763,6 +1615,7 @@ as_merged_requests(request_queue_t *q, struct request *req,
* kill knowledge of next, this one is a goner
*/
as_remove_queued_request(q, next);
+ as_put_io_context(anext);
anext->state = AS_RQ_MERGED;
}
@@ -1782,7 +1635,7 @@ static void as_work_handler(void *data)
unsigned long flags;
spin_lock_irqsave(q->queue_lock, flags);
- if (as_next_request(q))
+ if (!as_queue_empty(q))
q->request_fn(q);
spin_unlock_irqrestore(q->queue_lock, flags);
}
@@ -1797,7 +1650,9 @@ static void as_put_request(request_queue_t *q, struct request *rq)
return;
}
- if (arq->state != AS_RQ_POSTSCHED && arq->state != AS_RQ_PRESCHED) {
+ if (unlikely(arq->state != AS_RQ_POSTSCHED &&
+ arq->state != AS_RQ_PRESCHED &&
+ arq->state != AS_RQ_MERGED)) {
printk("arq->state %d\n", arq->state);
WARN_ON(1);
}
@@ -1807,7 +1662,7 @@ static void as_put_request(request_queue_t *q, struct request *rq)
}
static int as_set_request(request_queue_t *q, struct request *rq,
- struct bio *bio, int gfp_mask)
+ struct bio *bio, gfp_t gfp_mask)
{
struct as_data *ad = q->elevator->elevator_data;
struct as_rq *arq = mempool_alloc(ad->arq_pool, gfp_mask);
@@ -1907,7 +1762,6 @@ static int as_init_queue(request_queue_t *q, elevator_t *e)
INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]);
ad->sort_list[REQ_SYNC] = RB_ROOT;
ad->sort_list[REQ_ASYNC] = RB_ROOT;
- ad->dispatch = &q->queue_head;
ad->fifo_expire[REQ_SYNC] = default_read_expire;
ad->fifo_expire[REQ_ASYNC] = default_write_expire;
ad->antic_expire = default_antic_expire;
@@ -2072,10 +1926,9 @@ static struct elevator_type iosched_as = {
.elevator_merge_fn = as_merge,
.elevator_merged_fn = as_merged_request,
.elevator_merge_req_fn = as_merged_requests,
- .elevator_next_req_fn = as_next_request,
- .elevator_add_req_fn = as_insert_request,
- .elevator_remove_req_fn = as_remove_request,
- .elevator_requeue_req_fn = as_requeue_request,
+ .elevator_dispatch_fn = as_dispatch_request,
+ .elevator_add_req_fn = as_add_request,
+ .elevator_activate_req_fn = as_activate_request,
.elevator_deactivate_req_fn = as_deactivate_request,
.elevator_queue_empty_fn = as_queue_empty,
.elevator_completed_req_fn = as_completed_request,
diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c
index cd056e7e64ec15..94690e4d41e096 100644
--- a/drivers/block/cfq-iosched.c
+++ b/drivers/block/cfq-iosched.c
@@ -84,7 +84,6 @@ static int cfq_max_depth = 2;
(node)->rb_left = NULL; \
} while (0)
#define RB_CLEAR_ROOT(root) ((root)->rb_node = NULL)
-#define ON_RB(node) ((node)->rb_color != RB_NONE)
#define rb_entry_crq(node) rb_entry((node), struct cfq_rq, rb_node)
#define rq_rb_key(rq) (rq)->sector
@@ -271,10 +270,7 @@ CFQ_CFQQ_FNS(expired);
#undef CFQ_CFQQ_FNS
enum cfq_rq_state_flags {
- CFQ_CRQ_FLAG_in_flight = 0,
- CFQ_CRQ_FLAG_in_driver,
- CFQ_CRQ_FLAG_is_sync,
- CFQ_CRQ_FLAG_requeued,
+ CFQ_CRQ_FLAG_is_sync = 0,
};
#define CFQ_CRQ_FNS(name) \
@@ -291,14 +287,11 @@ static inline int cfq_crq_##name(const struct cfq_rq *crq) \
return (crq->crq_flags & (1 << CFQ_CRQ_FLAG_##name)) != 0; \
}
-CFQ_CRQ_FNS(in_flight);
-CFQ_CRQ_FNS(in_driver);
CFQ_CRQ_FNS(is_sync);
-CFQ_CRQ_FNS(requeued);
#undef CFQ_CRQ_FNS
static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short);
-static void cfq_dispatch_sort(request_queue_t *, struct cfq_rq *);
+static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *);
static void cfq_put_cfqd(struct cfq_data *cfqd);
#define process_sync(tsk) ((tsk)->flags & PF_SYNCWRITE)
@@ -311,14 +304,6 @@ static inline void cfq_del_crq_hash(struct cfq_rq *crq)
hlist_del_init(&crq->hash);
}
-static void cfq_remove_merge_hints(request_queue_t *q, struct cfq_rq *crq)
-{
- cfq_del_crq_hash(crq);
-
- if (q->last_merge == crq->request)
- q->last_merge = NULL;
-}
-
static inline void cfq_add_crq_hash(struct cfq_data *cfqd, struct cfq_rq *crq)
{
const int hash_idx = CFQ_MHASH_FN(rq_hash_key(crq->request));
@@ -347,18 +332,13 @@ static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset)
return NULL;
}
-static inline int cfq_pending_requests(struct cfq_data *cfqd)
-{
- return !list_empty(&cfqd->queue->queue_head) || cfqd->busy_queues;
-}
-
/*
* scheduler run of queue, if there are requests pending and no one in the
* driver that will restart queueing
*/
static inline void cfq_schedule_dispatch(struct cfq_data *cfqd)
{
- if (!cfqd->rq_in_driver && cfq_pending_requests(cfqd))
+ if (!cfqd->rq_in_driver && cfqd->busy_queues)
kblockd_schedule_work(&cfqd->unplug_work);
}
@@ -366,7 +346,7 @@ static int cfq_queue_empty(request_queue_t *q)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
- return !cfq_pending_requests(cfqd);
+ return !cfqd->busy_queues;
}
/*
@@ -386,11 +366,6 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2)
if (crq2 == NULL)
return crq1;
- if (cfq_crq_requeued(crq1) && !cfq_crq_requeued(crq2))
- return crq1;
- else if (cfq_crq_requeued(crq2) && !cfq_crq_requeued(crq1))
- return crq2;
-
if (cfq_crq_is_sync(crq1) && !cfq_crq_is_sync(crq2))
return crq1;
else if (cfq_crq_is_sync(crq2) && !cfq_crq_is_sync(crq1))
@@ -461,10 +436,7 @@ cfq_find_next_crq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
struct cfq_rq *crq_next = NULL, *crq_prev = NULL;
struct rb_node *rbnext, *rbprev;
- rbnext = NULL;
- if (ON_RB(&last->rb_node))
- rbnext = rb_next(&last->rb_node);
- if (!rbnext) {
+ if (!(rbnext = rb_next(&last->rb_node))) {
rbnext = rb_first(&cfqq->sort_list);
if (rbnext == &last->rb_node)
rbnext = NULL;
@@ -545,13 +517,13 @@ static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
* the pending list according to last request service
*/
static inline void
-cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq, int requeue)
+cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
{
BUG_ON(cfq_cfqq_on_rr(cfqq));
cfq_mark_cfqq_on_rr(cfqq);
cfqd->busy_queues++;
- cfq_resort_rr_list(cfqq, requeue);
+ cfq_resort_rr_list(cfqq, 0);
}
static inline void
@@ -571,22 +543,19 @@ cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
static inline void cfq_del_crq_rb(struct cfq_rq *crq)
{
struct cfq_queue *cfqq = crq->cfq_queue;
+ struct cfq_data *cfqd = cfqq->cfqd;
+ const int sync = cfq_crq_is_sync(crq);
- if (ON_RB(&crq->rb_node)) {
- struct cfq_data *cfqd = cfqq->cfqd;
- const int sync = cfq_crq_is_sync(crq);
+ BUG_ON(!cfqq->queued[sync]);
+ cfqq->queued[sync]--;
- BUG_ON(!cfqq->queued[sync]);
- cfqq->queued[sync]--;
+ cfq_update_next_crq(crq);
- cfq_update_next_crq(crq);
+ rb_erase(&crq->rb_node, &cfqq->sort_list);
+ RB_CLEAR_COLOR(&crq->rb_node);
- rb_erase(&crq->rb_node, &cfqq->sort_list);
- RB_CLEAR_COLOR(&crq->rb_node);
-
- if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list))
- cfq_del_cfqq_rr(cfqd, cfqq);
- }
+ if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list))
+ cfq_del_cfqq_rr(cfqd, cfqq);
}
static struct cfq_rq *
@@ -627,12 +596,12 @@ static void cfq_add_crq_rb(struct cfq_rq *crq)
* if that happens, put the alias on the dispatch list
*/
while ((__alias = __cfq_add_crq_rb(crq)) != NULL)
- cfq_dispatch_sort(cfqd->queue, __alias);
+ cfq_dispatch_insert(cfqd->queue, __alias);
rb_insert_color(&crq->rb_node, &cfqq->sort_list);
if (!cfq_cfqq_on_rr(cfqq))
- cfq_add_cfqq_rr(cfqd, cfqq, cfq_crq_requeued(crq));
+ cfq_add_cfqq_rr(cfqd, cfqq);
/*
* check if this request is a better next-serve candidate
@@ -643,10 +612,8 @@ static void cfq_add_crq_rb(struct cfq_rq *crq)
static inline void
cfq_reposition_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq)
{
- if (ON_RB(&crq->rb_node)) {
- rb_erase(&crq->rb_node, &cfqq->sort_list);
- cfqq->queued[cfq_crq_is_sync(crq)]--;
- }
+ rb_erase(&crq->rb_node, &cfqq->sort_list);
+ cfqq->queued[cfq_crq_is_sync(crq)]--;
cfq_add_crq_rb(crq);
}
@@ -676,49 +643,28 @@ out:
return NULL;
}
-static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
+static void cfq_activate_request(request_queue_t *q, struct request *rq)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
- struct cfq_rq *crq = RQ_DATA(rq);
-
- if (crq) {
- struct cfq_queue *cfqq = crq->cfq_queue;
-
- if (cfq_crq_in_driver(crq)) {
- cfq_clear_crq_in_driver(crq);
- WARN_ON(!cfqd->rq_in_driver);
- cfqd->rq_in_driver--;
- }
- if (cfq_crq_in_flight(crq)) {
- const int sync = cfq_crq_is_sync(crq);
- cfq_clear_crq_in_flight(crq);
- WARN_ON(!cfqq->on_dispatch[sync]);
- cfqq->on_dispatch[sync]--;
- }
- cfq_mark_crq_requeued(crq);
- }
+ cfqd->rq_in_driver++;
}
-/*
- * make sure the service time gets corrected on reissue of this request
- */
-static void cfq_requeue_request(request_queue_t *q, struct request *rq)
+static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
{
- cfq_deactivate_request(q, rq);
- list_add(&rq->queuelist, &q->queue_head);
+ struct cfq_data *cfqd = q->elevator->elevator_data;
+
+ WARN_ON(!cfqd->rq_in_driver);
+ cfqd->rq_in_driver--;
}
-static void cfq_remove_request(request_queue_t *q, struct request *rq)
+static void cfq_remove_request(struct request *rq)
{
struct cfq_rq *crq = RQ_DATA(rq);
- if (crq) {
- list_del_init(&rq->queuelist);
- cfq_del_crq_rb(crq);
- cfq_remove_merge_hints(q, crq);
-
- }
+ list_del_init(&rq->queuelist);
+ cfq_del_crq_rb(crq);
+ cfq_del_crq_hash(crq);
}
static int
@@ -728,12 +674,6 @@ cfq_merge(request_queue_t *q, struct request **req, struct bio *bio)
struct request *__rq;
int ret;
- ret = elv_try_last_merge(q, bio);
- if (ret != ELEVATOR_NO_MERGE) {
- __rq = q->last_merge;
- goto out_insert;
- }
-
__rq = cfq_find_rq_hash(cfqd, bio->bi_sector);
if (__rq && elv_rq_merge_ok(__rq, bio)) {
ret = ELEVATOR_BACK_MERGE;
@@ -748,8 +688,6 @@ cfq_merge(request_queue_t *q, struct request **req, struct bio *bio)
return ELEVATOR_NO_MERGE;
out:
- q->last_merge = __rq;
-out_insert:
*req = __rq;
return ret;
}
@@ -762,14 +700,12 @@ static void cfq_merged_request(request_queue_t *q, struct request *req)
cfq_del_crq_hash(crq);
cfq_add_crq_hash(cfqd, crq);
- if (ON_RB(&crq->rb_node) && (rq_rb_key(req) != crq->rb_key)) {
+ if (rq_rb_key(req) != crq->rb_key) {
struct cfq_queue *cfqq = crq->cfq_queue;
cfq_update_next_crq(crq);
cfq_reposition_crq_rb(cfqq, crq);
}
-
- q->last_merge = req;
}
static void
@@ -785,7 +721,7 @@ cfq_merged_requests(request_queue_t *q, struct request *rq,
time_before(next->start_time, rq->start_time))
list_move(&rq->queuelist, &next->queuelist);
- cfq_remove_request(q, next);
+ cfq_remove_request(next);
}
static inline void
@@ -992,53 +928,15 @@ static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
return 1;
}
-/*
- * we dispatch cfqd->cfq_quantum requests in total from the rr_list queues,
- * this function sector sorts the selected request to minimize seeks. we start
- * at cfqd->last_sector, not 0.
- */
-static void cfq_dispatch_sort(request_queue_t *q, struct cfq_rq *crq)
+static void cfq_dispatch_insert(request_queue_t *q, struct cfq_rq *crq)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
struct cfq_queue *cfqq = crq->cfq_queue;
- struct list_head *head = &q->queue_head, *entry = head;
- struct request *__rq;
- sector_t last;
-
- list_del(&crq->request->queuelist);
-
- last = cfqd->last_sector;
- list_for_each_entry_reverse(__rq, head, queuelist) {
- struct cfq_rq *__crq = RQ_DATA(__rq);
-
- if (blk_barrier_rq(__rq))
- break;
- if (!blk_fs_request(__rq))
- break;
- if (cfq_crq_requeued(__crq))
- break;
-
- if (__rq->sector <= crq->request->sector)
- break;
- if (__rq->sector > last && crq->request->sector < last) {
- last = crq->request->sector + crq->request->nr_sectors;
- break;
- }
- entry = &__rq->queuelist;
- }
-
- cfqd->last_sector = last;
cfqq->next_crq = cfq_find_next_crq(cfqd, cfqq, crq);
-
- cfq_del_crq_rb(crq);
- cfq_remove_merge_hints(q, crq);
-
- cfq_mark_crq_in_flight(crq);
- cfq_clear_crq_requeued(crq);
-
+ cfq_remove_request(crq->request);
cfqq->on_dispatch[cfq_crq_is_sync(crq)]++;
- list_add_tail(&crq->request->queuelist, entry);
+ elv_dispatch_sort(q, crq->request);
}
/*
@@ -1159,7 +1057,7 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
/*
* finally, insert request into driver dispatch list
*/
- cfq_dispatch_sort(cfqd->queue, crq);
+ cfq_dispatch_insert(cfqd->queue, crq);
cfqd->dispatch_slice++;
dispatched++;
@@ -1194,7 +1092,7 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
}
static int
-cfq_dispatch_requests(request_queue_t *q, int max_dispatch, int force)
+cfq_dispatch_requests(request_queue_t *q, int force)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
struct cfq_queue *cfqq;
@@ -1204,12 +1102,25 @@ cfq_dispatch_requests(request_queue_t *q, int max_dispatch, int force)
cfqq = cfq_select_queue(cfqd, force);
if (cfqq) {
+ int max_dispatch;
+
+ /*
+ * if idle window is disabled, allow queue buildup
+ */
+ if (!cfq_cfqq_idle_window(cfqq) &&
+ cfqd->rq_in_driver >= cfqd->cfq_max_depth)
+ return 0;
+
cfq_clear_cfqq_must_dispatch(cfqq);
cfq_clear_cfqq_wait_request(cfqq);
del_timer(&cfqd->idle_slice_timer);
- if (cfq_class_idle(cfqq))
- max_dispatch = 1;
+ if (!force) {
+ max_dispatch = cfqd->cfq_quantum;
+ if (cfq_class_idle(cfqq))
+ max_dispatch = 1;
+ } else
+ max_dispatch = INT_MAX;
return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
}
@@ -1217,93 +1128,6 @@ cfq_dispatch_requests(request_queue_t *q, int max_dispatch, int force)
return 0;
}
-static inline void cfq_account_dispatch(struct cfq_rq *crq)
-{
- struct cfq_queue *cfqq = crq->cfq_queue;
- struct cfq_data *cfqd = cfqq->cfqd;
-
- if (unlikely(!blk_fs_request(crq->request)))
- return;
-
- /*
- * accounted bit is necessary since some drivers will call
- * elv_next_request() many times for the same request (eg ide)
- */
- if (cfq_crq_in_driver(crq))
- return;
-
- cfq_mark_crq_in_driver(crq);
- cfqd->rq_in_driver++;
-}
-
-static inline void
-cfq_account_completion(struct cfq_queue *cfqq, struct cfq_rq *crq)
-{
- struct cfq_data *cfqd = cfqq->cfqd;
- unsigned long now;
-
- if (!cfq_crq_in_driver(crq))
- return;
-
- now = jiffies;
-
- WARN_ON(!cfqd->rq_in_driver);
- cfqd->rq_in_driver--;
-
- if (!cfq_class_idle(cfqq))
- cfqd->last_end_request = now;
-
- if (!cfq_cfqq_dispatched(cfqq)) {
- if (cfq_cfqq_on_rr(cfqq)) {
- cfqq->service_last = now;
- cfq_resort_rr_list(cfqq, 0);
- }
- if (cfq_cfqq_expired(cfqq)) {
- __cfq_slice_expired(cfqd, cfqq, 0);
- cfq_schedule_dispatch(cfqd);
- }
- }
-
- if (cfq_crq_is_sync(crq))
- crq->io_context->last_end_request = now;
-}
-
-static struct request *cfq_next_request(request_queue_t *q)
-{
- struct cfq_data *cfqd = q->elevator->elevator_data;
- struct request *rq;
-
- if (!list_empty(&q->queue_head)) {
- struct cfq_rq *crq;
-dispatch:
- rq = list_entry_rq(q->queue_head.next);
-
- crq = RQ_DATA(rq);
- if (crq) {
- struct cfq_queue *cfqq = crq->cfq_queue;
-
- /*
- * if idle window is disabled, allow queue buildup
- */
- if (!cfq_crq_in_driver(crq) &&
- !cfq_cfqq_idle_window(cfqq) &&
- !blk_barrier_rq(rq) &&
- cfqd->rq_in_driver >= cfqd->cfq_max_depth)
- return NULL;
-
- cfq_remove_merge_hints(q, crq);
- cfq_account_dispatch(crq);
- }
-
- return rq;
- }
-
- if (cfq_dispatch_requests(q, cfqd->cfq_quantum, 0))
- goto dispatch;
-
- return NULL;
-}
-
/*
* task holds one reference to the queue, dropped when task exits. each crq
* in-flight on this queue also holds a reference, dropped when crq is freed.
@@ -1422,7 +1246,7 @@ static void cfq_exit_io_context(struct cfq_io_context *cic)
}
static struct cfq_io_context *
-cfq_alloc_io_context(struct cfq_data *cfqd, int gfp_mask)
+cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
{
struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask);
@@ -1517,7 +1341,7 @@ static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio)
static struct cfq_queue *
cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio,
- int gfp_mask)
+ gfp_t gfp_mask)
{
const int hashval = hash_long(key, CFQ_QHASH_SHIFT);
struct cfq_queue *cfqq, *new_cfqq = NULL;
@@ -1578,7 +1402,7 @@ out:
* cfqq, so we don't need to worry about it disappearing
*/
static struct cfq_io_context *
-cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, int gfp_mask)
+cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
{
struct io_context *ioc = NULL;
struct cfq_io_context *cic;
@@ -1816,8 +1640,9 @@ cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
}
}
-static void cfq_enqueue(struct cfq_data *cfqd, struct request *rq)
+static void cfq_insert_request(request_queue_t *q, struct request *rq)
{
+ struct cfq_data *cfqd = q->elevator->elevator_data;
struct cfq_rq *crq = RQ_DATA(rq);
struct cfq_queue *cfqq = crq->cfq_queue;
@@ -1827,66 +1652,43 @@ static void cfq_enqueue(struct cfq_data *cfqd, struct request *rq)
list_add_tail(&rq->queuelist, &cfqq->fifo);
- if (rq_mergeable(rq)) {
+ if (rq_mergeable(rq))
cfq_add_crq_hash(cfqd, crq);
- if (!cfqd->queue->last_merge)
- cfqd->queue->last_merge = rq;
- }
-
cfq_crq_enqueued(cfqd, cfqq, crq);
}
-static void
-cfq_insert_request(request_queue_t *q, struct request *rq, int where)
-{
- struct cfq_data *cfqd = q->elevator->elevator_data;
-
- switch (where) {
- case ELEVATOR_INSERT_BACK:
- while (cfq_dispatch_requests(q, INT_MAX, 1))
- ;
- list_add_tail(&rq->queuelist, &q->queue_head);
- /*
- * If we were idling with pending requests on
- * inactive cfqqs, force dispatching will
- * remove the idle timer and the queue won't
- * be kicked by __make_request() afterward.
- * Kick it here.
- */
- cfq_schedule_dispatch(cfqd);
- break;
- case ELEVATOR_INSERT_FRONT:
- list_add(&rq->queuelist, &q->queue_head);
- break;
- case ELEVATOR_INSERT_SORT:
- BUG_ON(!blk_fs_request(rq));
- cfq_enqueue(cfqd, rq);
- break;
- default:
- printk("%s: bad insert point %d\n", __FUNCTION__,where);
- return;
- }
-}
-
static void cfq_completed_request(request_queue_t *q, struct request *rq)
{
struct cfq_rq *crq = RQ_DATA(rq);
- struct cfq_queue *cfqq;
+ struct cfq_queue *cfqq = crq->cfq_queue;
+ struct cfq_data *cfqd = cfqq->cfqd;
+ const int sync = cfq_crq_is_sync(crq);
+ unsigned long now;
- if (unlikely(!blk_fs_request(rq)))
- return;
+ now = jiffies;
- cfqq = crq->cfq_queue;
+ WARN_ON(!cfqd->rq_in_driver);
+ WARN_ON(!cfqq->on_dispatch[sync]);
+ cfqd->rq_in_driver--;
+ cfqq->on_dispatch[sync]--;
- if (cfq_crq_in_flight(crq)) {
- const int sync = cfq_crq_is_sync(crq);
+ if (!cfq_class_idle(cfqq))
+ cfqd->last_end_request = now;
- WARN_ON(!cfqq->on_dispatch[sync]);
- cfqq->on_dispatch[sync]--;
+ if (!cfq_cfqq_dispatched(cfqq)) {
+ if (cfq_cfqq_on_rr(cfqq)) {
+ cfqq->service_last = now;
+ cfq_resort_rr_list(cfqq, 0);
+ }
+ if (cfq_cfqq_expired(cfqq)) {
+ __cfq_slice_expired(cfqd, cfqq, 0);
+ cfq_schedule_dispatch(cfqd);
+ }
}
- cfq_account_completion(cfqq, crq);
+ if (cfq_crq_is_sync(crq))
+ crq->io_context->last_end_request = now;
}
static struct request *
@@ -2075,7 +1877,7 @@ static void cfq_put_request(request_queue_t *q, struct request *rq)
*/
static int
cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
- int gfp_mask)
+ gfp_t gfp_mask)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
struct task_struct *tsk = current;
@@ -2118,9 +1920,6 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
INIT_HLIST_NODE(&crq->hash);
crq->cfq_queue = cfqq;
crq->io_context = cic;
- cfq_clear_crq_in_flight(crq);
- cfq_clear_crq_in_driver(crq);
- cfq_clear_crq_requeued(crq);
if (rw == READ || process_sync(tsk))
cfq_mark_crq_is_sync(crq);
@@ -2201,7 +2000,7 @@ static void cfq_idle_slice_timer(unsigned long data)
* only expire and reinvoke request handler, if there are
* other queues with pending requests
*/
- if (!cfq_pending_requests(cfqd)) {
+ if (!cfqd->busy_queues) {
cfqd->idle_slice_timer.expires = min(now + cfqd->cfq_slice_idle, cfqq->slice_end);
add_timer(&cfqd->idle_slice_timer);
goto out_cont;
@@ -2576,10 +2375,9 @@ static struct elevator_type iosched_cfq = {
.elevator_merge_fn = cfq_merge,
.elevator_merged_fn = cfq_merged_request,
.elevator_merge_req_fn = cfq_merged_requests,
- .elevator_next_req_fn = cfq_next_request,
+ .elevator_dispatch_fn = cfq_dispatch_requests,
.elevator_add_req_fn = cfq_insert_request,
- .elevator_remove_req_fn = cfq_remove_request,
- .elevator_requeue_req_fn = cfq_requeue_request,
+ .elevator_activate_req_fn = cfq_activate_request,
.elevator_deactivate_req_fn = cfq_deactivate_request,
.elevator_queue_empty_fn = cfq_queue_empty,
.elevator_completed_req_fn = cfq_completed_request,
diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c
index 52a3ae5289a09a..7929471d7df7ef 100644
--- a/drivers/block/deadline-iosched.c
+++ b/drivers/block/deadline-iosched.c
@@ -50,7 +50,6 @@ struct deadline_data {
* next in sort order. read, write or both are NULL
*/
struct deadline_rq *next_drq[2];
- struct list_head *dispatch; /* driver dispatch queue */
struct list_head *hash; /* request hash */
unsigned int batching; /* number of sequential requests made */
sector_t last_sector; /* head position */
@@ -113,15 +112,6 @@ static inline void deadline_del_drq_hash(struct deadline_rq *drq)
__deadline_del_drq_hash(drq);
}
-static void
-deadline_remove_merge_hints(request_queue_t *q, struct deadline_rq *drq)
-{
- deadline_del_drq_hash(drq);
-
- if (q->last_merge == drq->request)
- q->last_merge = NULL;
-}
-
static inline void
deadline_add_drq_hash(struct deadline_data *dd, struct deadline_rq *drq)
{
@@ -239,10 +229,9 @@ deadline_del_drq_rb(struct deadline_data *dd, struct deadline_rq *drq)
dd->next_drq[data_dir] = rb_entry_drq(rbnext);
}
- if (ON_RB(&drq->rb_node)) {
- rb_erase(&drq->rb_node, DRQ_RB_ROOT(dd, drq));
- RB_CLEAR(&drq->rb_node);
- }
+ BUG_ON(!ON_RB(&drq->rb_node));
+ rb_erase(&drq->rb_node, DRQ_RB_ROOT(dd, drq));
+ RB_CLEAR(&drq->rb_node);
}
static struct request *
@@ -286,7 +275,7 @@ deadline_find_first_drq(struct deadline_data *dd, int data_dir)
/*
* add drq to rbtree and fifo
*/
-static inline void
+static void
deadline_add_request(struct request_queue *q, struct request *rq)
{
struct deadline_data *dd = q->elevator->elevator_data;
@@ -301,12 +290,8 @@ deadline_add_request(struct request_queue *q, struct request *rq)
drq->expires = jiffies + dd->fifo_expire[data_dir];
list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]);
- if (rq_mergeable(rq)) {
+ if (rq_mergeable(rq))
deadline_add_drq_hash(dd, drq);
-
- if (!q->last_merge)
- q->last_merge = rq;
- }
}
/*
@@ -315,14 +300,11 @@ deadline_add_request(struct request_queue *q, struct request *rq)
static void deadline_remove_request(request_queue_t *q, struct request *rq)
{
struct deadline_rq *drq = RQ_DATA(rq);
+ struct deadline_data *dd = q->elevator->elevator_data;
- if (drq) {
- struct deadline_data *dd = q->elevator->elevator_data;
-
- list_del_init(&drq->fifo);
- deadline_remove_merge_hints(q, drq);
- deadline_del_drq_rb(dd, drq);
- }
+ list_del_init(&drq->fifo);
+ deadline_del_drq_rb(dd, drq);
+ deadline_del_drq_hash(drq);
}
static int
@@ -333,15 +315,6 @@ deadline_merge(request_queue_t *q, struct request **req, struct bio *bio)
int ret;
/*
- * try last_merge to avoid going to hash
- */
- ret = elv_try_last_merge(q, bio);
- if (ret != ELEVATOR_NO_MERGE) {
- __rq = q->last_merge;
- goto out_insert;
- }
-
- /*
* see if the merge hash can satisfy a back merge
*/
__rq = deadline_find_drq_hash(dd, bio->bi_sector);
@@ -373,8 +346,6 @@ deadline_merge(request_queue_t *q, struct request **req, struct bio *bio)
return ELEVATOR_NO_MERGE;
out:
- q->last_merge = __rq;
-out_insert:
if (ret)
deadline_hot_drq_hash(dd, RQ_DATA(__rq));
*req = __rq;
@@ -399,8 +370,6 @@ static void deadline_merged_request(request_queue_t *q, struct request *req)
deadline_del_drq_rb(dd, drq);
deadline_add_drq_rb(dd, drq);
}
-
- q->last_merge = req;
}
static void
@@ -452,7 +421,7 @@ deadline_move_to_dispatch(struct deadline_data *dd, struct deadline_rq *drq)
request_queue_t *q = drq->request->q;
deadline_remove_request(q, drq->request);
- list_add_tail(&drq->request->queuelist, dd->dispatch);
+ elv_dispatch_add_tail(q, drq->request);
}
/*
@@ -502,8 +471,9 @@ static inline int deadline_check_fifo(struct deadline_data *dd, int ddir)
* deadline_dispatch_requests selects the best request according to
* read/write expire, fifo_batch, etc
*/
-static int deadline_dispatch_requests(struct deadline_data *dd)
+static int deadline_dispatch_requests(request_queue_t *q, int force)
{
+ struct deadline_data *dd = q->elevator->elevator_data;
const int reads = !list_empty(&dd->fifo_list[READ]);
const int writes = !list_empty(&dd->fifo_list[WRITE]);
struct deadline_rq *drq;
@@ -597,65 +567,12 @@ dispatch_request:
return 1;
}
-static struct request *deadline_next_request(request_queue_t *q)
-{
- struct deadline_data *dd = q->elevator->elevator_data;
- struct request *rq;
-
- /*
- * if there are still requests on the dispatch queue, grab the first one
- */
- if (!list_empty(dd->dispatch)) {
-dispatch:
- rq = list_entry_rq(dd->dispatch->next);
- return rq;
- }
-
- if (deadline_dispatch_requests(dd))
- goto dispatch;
-
- return NULL;
-}
-
-static void
-deadline_insert_request(request_queue_t *q, struct request *rq, int where)
-{
- struct deadline_data *dd = q->elevator->elevator_data;
-
- /* barriers must flush the reorder queue */
- if (unlikely(rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)
- && where == ELEVATOR_INSERT_SORT))
- where = ELEVATOR_INSERT_BACK;
-
- switch (where) {
- case ELEVATOR_INSERT_BACK:
- while (deadline_dispatch_requests(dd))
- ;
- list_add_tail(&rq->queuelist, dd->dispatch);
- break;
- case ELEVATOR_INSERT_FRONT:
- list_add(&rq->queuelist, dd->dispatch);
- break;
- case ELEVATOR_INSERT_SORT:
- BUG_ON(!blk_fs_request(rq));
- deadline_add_request(q, rq);
- break;
- default:
- printk("%s: bad insert point %d\n", __FUNCTION__,where);
- return;
- }
-}
-
static int deadline_queue_empty(request_queue_t *q)
{
struct deadline_data *dd = q->elevator->elevator_data;
- if (!list_empty(&dd->fifo_list[WRITE])
- || !list_empty(&dd->fifo_list[READ])
- || !list_empty(dd->dispatch))
- return 0;
-
- return 1;
+ return list_empty(&dd->fifo_list[WRITE])
+ && list_empty(&dd->fifo_list[READ]);
}
static struct request *
@@ -733,7 +650,6 @@ static int deadline_init_queue(request_queue_t *q, elevator_t *e)
INIT_LIST_HEAD(&dd->fifo_list[WRITE]);
dd->sort_list[READ] = RB_ROOT;
dd->sort_list[WRITE] = RB_ROOT;
- dd->dispatch = &q->queue_head;
dd->fifo_expire[READ] = read_expire;
dd->fifo_expire[WRITE] = write_expire;
dd->writes_starved = writes_starved;
@@ -748,15 +664,13 @@ static void deadline_put_request(request_queue_t *q, struct request *rq)
struct deadline_data *dd = q->elevator->elevator_data;
struct deadline_rq *drq = RQ_DATA(rq);
- if (drq) {
- mempool_free(drq, dd->drq_pool);
- rq->elevator_private = NULL;
- }
+ mempool_free(drq, dd->drq_pool);
+ rq->elevator_private = NULL;
}
static int
deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
- int gfp_mask)
+ gfp_t gfp_mask)
{
struct deadline_data *dd = q->elevator->elevator_data;
struct deadline_rq *drq;
@@ -917,9 +831,8 @@ static struct elevator_type iosched_deadline = {
.elevator_merge_fn = deadline_merge,
.elevator_merged_fn = deadline_merged_request,
.elevator_merge_req_fn = deadline_merged_requests,
- .elevator_next_req_fn = deadline_next_request,
- .elevator_add_req_fn = deadline_insert_request,
- .elevator_remove_req_fn = deadline_remove_request,
+ .elevator_dispatch_fn = deadline_dispatch_requests,
+ .elevator_add_req_fn = deadline_add_request,
.elevator_queue_empty_fn = deadline_queue_empty,
.elevator_former_req_fn = deadline_former_request,
.elevator_latter_req_fn = deadline_latter_request,
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
index 98f0126a2deb32..55621d5c577403 100644
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -34,6 +34,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/compiler.h>
+#include <linux/delay.h>
#include <asm/uaccess.h>
@@ -83,21 +84,11 @@ inline int elv_try_merge(struct request *__rq, struct bio *bio)
}
EXPORT_SYMBOL(elv_try_merge);
-inline int elv_try_last_merge(request_queue_t *q, struct bio *bio)
-{
- if (q->last_merge)
- return elv_try_merge(q->last_merge, bio);
-
- return ELEVATOR_NO_MERGE;
-}
-EXPORT_SYMBOL(elv_try_last_merge);
-
static struct elevator_type *elevator_find(const char *name)
{
struct elevator_type *e = NULL;
struct list_head *entry;
- spin_lock_irq(&elv_list_lock);
list_for_each(entry, &elv_list) {
struct elevator_type *__e;
@@ -108,7 +99,6 @@ static struct elevator_type *elevator_find(const char *name)
break;
}
}
- spin_unlock_irq(&elv_list_lock);
return e;
}
@@ -120,12 +110,15 @@ static void elevator_put(struct elevator_type *e)
static struct elevator_type *elevator_get(const char *name)
{
- struct elevator_type *e = elevator_find(name);
+ struct elevator_type *e;
- if (!e)
- return NULL;
- if (!try_module_get(e->elevator_owner))
- return NULL;
+ spin_lock_irq(&elv_list_lock);
+
+ e = elevator_find(name);
+ if (e && !try_module_get(e->elevator_owner))
+ e = NULL;
+
+ spin_unlock_irq(&elv_list_lock);
return e;
}
@@ -139,8 +132,6 @@ static int elevator_attach(request_queue_t *q, struct elevator_type *e,
eq->ops = &e->ops;
eq->elevator_type = e;
- INIT_LIST_HEAD(&q->queue_head);
- q->last_merge = NULL;
q->elevator = eq;
if (eq->ops->elevator_init_fn)
@@ -153,11 +144,15 @@ static char chosen_elevator[16];
static void elevator_setup_default(void)
{
+ struct elevator_type *e;
+
/*
* check if default is set and exists
*/
- if (chosen_elevator[0] && elevator_find(chosen_elevator))
+ if (chosen_elevator[0] && (e = elevator_get(chosen_elevator))) {
+ elevator_put(e);
return;
+ }
#if defined(CONFIG_IOSCHED_AS)
strcpy(chosen_elevator, "anticipatory");
@@ -186,6 +181,11 @@ int elevator_init(request_queue_t *q, char *name)
struct elevator_queue *eq;
int ret = 0;
+ INIT_LIST_HEAD(&q->queue_head);
+ q->last_merge = NULL;
+ q->end_sector = 0;
+ q->boundary_rq = NULL;
+
elevator_setup_default();
if (!name)
@@ -220,9 +220,52 @@ void elevator_exit(elevator_t *e)
kfree(e);
}
+/*
+ * Insert rq into dispatch queue of q. Queue lock must be held on
+ * entry. If sort != 0, rq is sort-inserted; otherwise, rq will be
+ * appended to the dispatch queue. To be used by specific elevators.
+ */
+void elv_dispatch_sort(request_queue_t *q, struct request *rq)
+{
+ sector_t boundary;
+ struct list_head *entry;
+
+ if (q->last_merge == rq)
+ q->last_merge = NULL;
+
+ boundary = q->end_sector;
+
+ list_for_each_prev(entry, &q->queue_head) {
+ struct request *pos = list_entry_rq(entry);
+
+ if (pos->flags & (REQ_SOFTBARRIER|REQ_HARDBARRIER|REQ_STARTED))
+ break;
+ if (rq->sector >= boundary) {
+ if (pos->sector < boundary)
+ continue;
+ } else {
+ if (pos->sector >= boundary)
+ break;
+ }
+ if (rq->sector >= pos->sector)
+ break;
+ }
+
+ list_add(&rq->queuelist, entry);
+}
+
int elv_merge(request_queue_t *q, struct request **req, struct bio *bio)
{
elevator_t *e = q->elevator;
+ int ret;
+
+ if (q->last_merge) {
+ ret = elv_try_merge(q->last_merge, bio);
+ if (ret != ELEVATOR_NO_MERGE) {
+ *req = q->last_merge;
+ return ret;
+ }
+ }
if (e->ops->elevator_merge_fn)
return e->ops->elevator_merge_fn(q, req, bio);
@@ -236,6 +279,8 @@ void elv_merged_request(request_queue_t *q, struct request *rq)
if (e->ops->elevator_merged_fn)
e->ops->elevator_merged_fn(q, rq);
+
+ q->last_merge = rq;
}
void elv_merge_requests(request_queue_t *q, struct request *rq,
@@ -243,20 +288,13 @@ void elv_merge_requests(request_queue_t *q, struct request *rq,
{
elevator_t *e = q->elevator;
- if (q->last_merge == next)
- q->last_merge = NULL;
-
if (e->ops->elevator_merge_req_fn)
e->ops->elevator_merge_req_fn(q, rq, next);
+
+ q->last_merge = rq;
}
-/*
- * For careful internal use by the block layer. Essentially the same as
- * a requeue in that it tells the io scheduler that this request is not
- * active in the driver or hardware anymore, but we don't want the request
- * added back to the scheduler. Function is not exported.
- */
-void elv_deactivate_request(request_queue_t *q, struct request *rq)
+void elv_requeue_request(request_queue_t *q, struct request *rq)
{
elevator_t *e = q->elevator;
@@ -264,19 +302,14 @@ void elv_deactivate_request(request_queue_t *q, struct request *rq)
* it already went through dequeue, we need to decrement the
* in_flight count again
*/
- if (blk_account_rq(rq))
+ if (blk_account_rq(rq)) {
q->in_flight--;
+ if (blk_sorted_rq(rq) && e->ops->elevator_deactivate_req_fn)
+ e->ops->elevator_deactivate_req_fn(q, rq);
+ }
rq->flags &= ~REQ_STARTED;
- if (e->ops->elevator_deactivate_req_fn)
- e->ops->elevator_deactivate_req_fn(q, rq);
-}
-
-void elv_requeue_request(request_queue_t *q, struct request *rq)
-{
- elv_deactivate_request(q, rq);
-
/*
* if this is the flush, requeue the original instead and drop the flush
*/
@@ -285,31 +318,27 @@ void elv_requeue_request(request_queue_t *q, struct request *rq)
rq = rq->end_io_data;
}
- /*
- * 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
- */
- if (q->elevator->ops->elevator_requeue_req_fn)
- q->elevator->ops->elevator_requeue_req_fn(q, rq);
- else
- __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
+ __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
}
void __elv_add_request(request_queue_t *q, struct request *rq, int where,
int plug)
{
- /*
- * barriers implicitly indicate back insertion
- */
- if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER) &&
- where == ELEVATOR_INSERT_SORT)
+ if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) {
+ /*
+ * barriers implicitly indicate back insertion
+ */
+ if (where == ELEVATOR_INSERT_SORT)
+ where = ELEVATOR_INSERT_BACK;
+
+ /*
+ * this request is scheduling boundary, update end_sector
+ */
+ if (blk_fs_request(rq)) {
+ q->end_sector = rq_end_sector(rq);
+ q->boundary_rq = rq;
+ }
+ } else if (!(rq->flags & REQ_ELVPRIV) && where == ELEVATOR_INSERT_SORT)
where = ELEVATOR_INSERT_BACK;
if (plug)
@@ -317,23 +346,54 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
rq->q = q;
- if (!test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)) {
- q->elevator->ops->elevator_add_req_fn(q, rq, where);
+ switch (where) {
+ case ELEVATOR_INSERT_FRONT:
+ rq->flags |= REQ_SOFTBARRIER;
- if (blk_queue_plugged(q)) {
- int nrq = q->rq.count[READ] + q->rq.count[WRITE]
- - q->in_flight;
+ list_add(&rq->queuelist, &q->queue_head);
+ break;
- if (nrq >= q->unplug_thresh)
- __generic_unplug_device(q);
- }
- } else
+ case ELEVATOR_INSERT_BACK:
+ rq->flags |= REQ_SOFTBARRIER;
+
+ while (q->elevator->ops->elevator_dispatch_fn(q, 1))
+ ;
+ list_add_tail(&rq->queuelist, &q->queue_head);
/*
- * if drain is set, store the request "locally". when the drain
- * is finished, the requests will be handed ordered to the io
- * scheduler
+ * We kick the queue here for the following reasons.
+ * - The elevator might have returned NULL previously
+ * to delay requests and returned them now. As the
+ * queue wasn't empty before this request, ll_rw_blk
+ * won't run the queue on return, resulting in hang.
+ * - Usually, back inserted requests won't be merged
+ * with anything. There's no point in delaying queue
+ * processing.
*/
- list_add_tail(&rq->queuelist, &q->drain_list);
+ blk_remove_plug(q);
+ q->request_fn(q);
+ break;
+
+ case ELEVATOR_INSERT_SORT:
+ BUG_ON(!blk_fs_request(rq));
+ rq->flags |= REQ_SORTED;
+ q->elevator->ops->elevator_add_req_fn(q, rq);
+ if (q->last_merge == NULL && rq_mergeable(rq))
+ q->last_merge = rq;
+ break;
+
+ default:
+ printk(KERN_ERR "%s: bad insertion point %d\n",
+ __FUNCTION__, where);
+ BUG();
+ }
+
+ if (blk_queue_plugged(q)) {
+ int nrq = q->rq.count[READ] + q->rq.count[WRITE]
+ - q->in_flight;
+
+ if (nrq >= q->unplug_thresh)
+ __generic_unplug_device(q);
+ }
}
void elv_add_request(request_queue_t *q, struct request *rq, int where,
@@ -348,13 +408,19 @@ void elv_add_request(request_queue_t *q, struct request *rq, int where,
static inline struct request *__elv_next_request(request_queue_t *q)
{
- struct request *rq = q->elevator->ops->elevator_next_req_fn(q);
+ struct request *rq;
+
+ if (unlikely(list_empty(&q->queue_head) &&
+ !q->elevator->ops->elevator_dispatch_fn(q, 0)))
+ return NULL;
+
+ rq = list_entry_rq(q->queue_head.next);
/*
* if this is a barrier write and the device has to issue a
* flush sequence to support it, check how far we are
*/
- if (rq && blk_fs_request(rq) && blk_barrier_rq(rq)) {
+ if (blk_fs_request(rq) && blk_barrier_rq(rq)) {
BUG_ON(q->ordered == QUEUE_ORDERED_NONE);
if (q->ordered == QUEUE_ORDERED_FLUSH &&
@@ -371,15 +437,30 @@ struct request *elv_next_request(request_queue_t *q)
int ret;
while ((rq = __elv_next_request(q)) != NULL) {
- /*
- * just mark as started even if we don't start it, a request
- * that has been delayed should not be passed by new incoming
- * requests
- */
- rq->flags |= REQ_STARTED;
+ if (!(rq->flags & REQ_STARTED)) {
+ elevator_t *e = q->elevator;
- if (rq == q->last_merge)
- q->last_merge = NULL;
+ /*
+ * This is the first time the device driver
+ * sees this request (possibly after
+ * requeueing). Notify IO scheduler.
+ */
+ if (blk_sorted_rq(rq) &&
+ e->ops->elevator_activate_req_fn)
+ e->ops->elevator_activate_req_fn(q, rq);
+
+ /*
+ * just mark as started even if we don't start
+ * it, a request that has been delayed should
+ * not be passed by new incoming requests
+ */
+ rq->flags |= REQ_STARTED;
+ }
+
+ if (!q->boundary_rq || q->boundary_rq == rq) {
+ q->end_sector = rq_end_sector(rq);
+ q->boundary_rq = NULL;
+ }
if ((rq->flags & REQ_DONTPREP) || !q->prep_rq_fn)
break;
@@ -391,9 +472,9 @@ struct request *elv_next_request(request_queue_t *q)
/*
* the request may have been (partially) prepped.
* we need to keep this request in the front to
- * avoid resource deadlock. turn on softbarrier.
+ * avoid resource deadlock. REQ_STARTED will
+ * prevent other fs requests from passing this one.
*/
- rq->flags |= REQ_SOFTBARRIER;
rq = NULL;
break;
} else if (ret == BLKPREP_KILL) {
@@ -416,42 +497,32 @@ struct request *elv_next_request(request_queue_t *q)
return rq;
}
-void elv_remove_request(request_queue_t *q, struct request *rq)
+void elv_dequeue_request(request_queue_t *q, struct request *rq)
{
- elevator_t *e = q->elevator;
+ BUG_ON(list_empty(&rq->queuelist));
+
+ list_del_init(&rq->queuelist);
/*
* the time frame between a request being removed from the lists
* and to it is freed is accounted as io that is in progress at
- * the driver side. note that we only account requests that the
- * driver has seen (REQ_STARTED set), to avoid false accounting
- * for request-request merges
+ * the driver side.
*/
if (blk_account_rq(rq))
q->in_flight++;
-
- /*
- * the main clearing point for q->last_merge is on retrieval of
- * request by driver (it calls elv_next_request()), but it _can_
- * also happen here if a request is added to the queue but later
- * deleted without ever being given to driver (merged with another
- * request).
- */
- if (rq == q->last_merge)
- q->last_merge = NULL;
-
- if (e->ops->elevator_remove_req_fn)
- e->ops->elevator_remove_req_fn(q, rq);
}
int elv_queue_empty(request_queue_t *q)
{
elevator_t *e = q->elevator;
+ if (!list_empty(&q->queue_head))
+ return 0;
+
if (e->ops->elevator_queue_empty_fn)
return e->ops->elevator_queue_empty_fn(q);
- return list_empty(&q->queue_head);
+ return 1;
}
struct request *elv_latter_request(request_queue_t *q, struct request *rq)
@@ -487,7 +558,7 @@ struct request *elv_former_request(request_queue_t *q, struct request *rq)
}
int elv_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
- int gfp_mask)
+ gfp_t gfp_mask)
{
elevator_t *e = q->elevator;
@@ -523,11 +594,11 @@ void elv_completed_request(request_queue_t *q, struct request *rq)
/*
* request is released from the driver, io must be done
*/
- if (blk_account_rq(rq))
+ if (blk_account_rq(rq)) {
q->in_flight--;
-
- if (e->ops->elevator_completed_req_fn)
- e->ops->elevator_completed_req_fn(q, rq);
+ if (blk_sorted_rq(rq) && e->ops->elevator_completed_req_fn)
+ e->ops->elevator_completed_req_fn(q, rq);
+ }
}
int elv_register_queue(struct request_queue *q)
@@ -555,10 +626,9 @@ void elv_unregister_queue(struct request_queue *q)
int elv_register(struct elevator_type *e)
{
+ spin_lock_irq(&elv_list_lock);
if (elevator_find(e->elevator_name))
BUG();
-
- spin_lock_irq(&elv_list_lock);
list_add_tail(&e->list, &elv_list);
spin_unlock_irq(&elv_list_lock);
@@ -582,25 +652,36 @@ EXPORT_SYMBOL_GPL(elv_unregister);
* switch to new_e io scheduler. be careful not to introduce deadlocks -
* we don't free the old io scheduler, before we have allocated what we
* need for the new one. this way we have a chance of going back to the old
- * one, if the new one fails init for some reason. we also do an intermediate
- * switch to noop to ensure safety with stack-allocated requests, since they
- * don't originate from the block layer allocator. noop is safe here, because
- * it never needs to touch the elevator itself for completion events. DRAIN
- * flags will make sure we don't touch it for additions either.
+ * one, if the new one fails init for some reason.
*/
static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
{
- elevator_t *e = kmalloc(sizeof(elevator_t), GFP_KERNEL);
- struct elevator_type *noop_elevator = NULL;
- elevator_t *old_elevator;
+ elevator_t *old_elevator, *e;
+ /*
+ * Allocate new elevator
+ */
+ e = kmalloc(sizeof(elevator_t), GFP_KERNEL);
if (!e)
goto error;
/*
- * first step, drain requests from the block freelist
+ * Turn on BYPASS and drain all requests w/ elevator private data
*/
- blk_wait_queue_drained(q, 0);
+ spin_lock_irq(q->queue_lock);
+
+ set_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
+
+ while (q->elevator->ops->elevator_dispatch_fn(q, 1))
+ ;
+
+ while (q->rq.elvpriv) {
+ spin_unlock_irq(q->queue_lock);
+ msleep(10);
+ spin_lock_irq(q->queue_lock);
+ }
+
+ spin_unlock_irq(q->queue_lock);
/*
* unregister old elevator data
@@ -609,18 +690,6 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
old_elevator = q->elevator;
/*
- * next step, switch to noop since it uses no private rq structures
- * and doesn't allocate any memory for anything. then wait for any
- * non-fs requests in-flight
- */
- noop_elevator = elevator_get("noop");
- spin_lock_irq(q->queue_lock);
- elevator_attach(q, noop_elevator, e);
- spin_unlock_irq(q->queue_lock);
-
- blk_wait_queue_drained(q, 1);
-
- /*
* attach and start new elevator
*/
if (elevator_attach(q, new_e, e))
@@ -630,11 +699,10 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
goto fail_register;
/*
- * finally exit old elevator and start queue again
+ * finally exit old elevator and turn off BYPASS.
*/
elevator_exit(old_elevator);
- blk_finish_queue_drain(q);
- elevator_put(noop_elevator);
+ clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
return;
fail_register:
@@ -643,13 +711,13 @@ fail_register:
* one again (along with re-adding the sysfs dir)
*/
elevator_exit(e);
+ e = NULL;
fail:
q->elevator = old_elevator;
elv_register_queue(q);
- blk_finish_queue_drain(q);
+ clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
+ kfree(e);
error:
- if (noop_elevator)
- elevator_put(noop_elevator);
elevator_put(new_e);
printk(KERN_ERR "elevator: switch to %s failed\n",new_e->elevator_name);
}
@@ -701,11 +769,12 @@ ssize_t elv_iosched_show(request_queue_t *q, char *name)
return len;
}
+EXPORT_SYMBOL(elv_dispatch_sort);
EXPORT_SYMBOL(elv_add_request);
EXPORT_SYMBOL(__elv_add_request);
EXPORT_SYMBOL(elv_requeue_request);
EXPORT_SYMBOL(elv_next_request);
-EXPORT_SYMBOL(elv_remove_request);
+EXPORT_SYMBOL(elv_dequeue_request);
EXPORT_SYMBOL(elv_queue_empty);
EXPORT_SYMBOL(elv_completed_request);
EXPORT_SYMBOL(elevator_exit);
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index d42840cc0d1dfc..486ce1fdeb8c88 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -337,10 +337,30 @@ static ssize_t disk_attr_show(struct kobject *kobj, struct attribute *attr,
return ret;
}
+static ssize_t disk_attr_store(struct kobject * kobj, struct attribute * attr,
+ const char *page, size_t count)
+{
+ struct gendisk *disk = to_disk(kobj);
+ struct disk_attribute *disk_attr =
+ container_of(attr,struct disk_attribute,attr);
+ ssize_t ret = 0;
+
+ if (disk_attr->store)
+ ret = disk_attr->store(disk, page, count);
+ return ret;
+}
+
static struct sysfs_ops disk_sysfs_ops = {
.show = &disk_attr_show,
+ .store = &disk_attr_store,
};
+static ssize_t disk_uevent_store(struct gendisk * disk,
+ const char *buf, size_t count)
+{
+ kobject_hotplug(&disk->kobj, KOBJ_ADD);
+ return count;
+}
static ssize_t disk_dev_read(struct gendisk * disk, char *page)
{
dev_t base = MKDEV(disk->major, disk->first_minor);
@@ -382,6 +402,10 @@ static ssize_t disk_stats_read(struct gendisk * disk, char *page)
jiffies_to_msecs(disk_stat_read(disk, io_ticks)),
jiffies_to_msecs(disk_stat_read(disk, time_in_queue)));
}
+static struct disk_attribute disk_attr_uevent = {
+ .attr = {.name = "uevent", .mode = S_IWUSR },
+ .store = disk_uevent_store
+};
static struct disk_attribute disk_attr_dev = {
.attr = {.name = "dev", .mode = S_IRUGO },
.show = disk_dev_read
@@ -404,6 +428,7 @@ static struct disk_attribute disk_attr_stat = {
};
static struct attribute * default_attrs[] = {
+ &disk_attr_uevent.attr,
&disk_attr_dev.attr,
&disk_attr_range.attr,
&disk_attr_removable.attr,
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index baedac522945a4..0af73512b9a8c3 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -263,8 +263,6 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
blk_queue_activity_fn(q, NULL, NULL);
-
- INIT_LIST_HEAD(&q->drain_list);
}
EXPORT_SYMBOL(blk_queue_make_request);
@@ -353,6 +351,8 @@ static void blk_pre_flush_end_io(struct request *flush_rq)
struct request *rq = flush_rq->end_io_data;
request_queue_t *q = rq->q;
+ elv_completed_request(q, flush_rq);
+
rq->flags |= REQ_BAR_PREFLUSH;
if (!flush_rq->errors)
@@ -369,6 +369,8 @@ static void blk_post_flush_end_io(struct request *flush_rq)
struct request *rq = flush_rq->end_io_data;
request_queue_t *q = rq->q;
+ elv_completed_request(q, flush_rq);
+
rq->flags |= REQ_BAR_POSTFLUSH;
q->end_flush_fn(q, flush_rq);
@@ -408,8 +410,6 @@ struct request *blk_start_pre_flush(request_queue_t *q, struct request *rq)
if (!list_empty(&rq->queuelist))
blkdev_dequeue_request(rq);
- elv_deactivate_request(q, rq);
-
flush_rq->end_io_data = rq;
flush_rq->end_io = blk_pre_flush_end_io;
@@ -1040,6 +1040,7 @@ EXPORT_SYMBOL(blk_queue_invalidate_tags);
static char *rq_flags[] = {
"REQ_RW",
"REQ_FAILFAST",
+ "REQ_SORTED",
"REQ_SOFTBARRIER",
"REQ_HARDBARRIER",
"REQ_CMD",
@@ -1047,6 +1048,7 @@ static char *rq_flags[] = {
"REQ_STARTED",
"REQ_DONTPREP",
"REQ_QUEUED",
+ "REQ_ELVPRIV",
"REQ_PC",
"REQ_BLOCK_PC",
"REQ_SENSE",
@@ -1637,9 +1639,9 @@ static int blk_init_free_list(request_queue_t *q)
rl->count[READ] = rl->count[WRITE] = 0;
rl->starved[READ] = rl->starved[WRITE] = 0;
+ rl->elvpriv = 0;
init_waitqueue_head(&rl->wait[READ]);
init_waitqueue_head(&rl->wait[WRITE]);
- init_waitqueue_head(&rl->drain);
rl->rq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
mempool_free_slab, request_cachep, q->node);
@@ -1652,13 +1654,13 @@ static int blk_init_free_list(request_queue_t *q)
static int __make_request(request_queue_t *, struct bio *);
-request_queue_t *blk_alloc_queue(int gfp_mask)
+request_queue_t *blk_alloc_queue(gfp_t 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 *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
{
request_queue_t *q;
@@ -1782,12 +1784,14 @@ EXPORT_SYMBOL(blk_get_queue);
static inline void blk_free_request(request_queue_t *q, struct request *rq)
{
- elv_put_request(q, rq);
+ if (rq->flags & REQ_ELVPRIV)
+ elv_put_request(q, rq);
mempool_free(rq, q->rq.rq_pool);
}
static inline struct request *
-blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, int gfp_mask)
+blk_alloc_request(request_queue_t *q, int rw, struct bio *bio,
+ int priv, gfp_t gfp_mask)
{
struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask);
@@ -1800,11 +1804,15 @@ blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, int gfp_mask)
*/
rq->flags = rw;
- if (!elv_set_request(q, rq, bio, gfp_mask))
- return rq;
+ if (priv) {
+ if (unlikely(elv_set_request(q, rq, bio, gfp_mask))) {
+ mempool_free(rq, q->rq.rq_pool);
+ return NULL;
+ }
+ rq->flags |= REQ_ELVPRIV;
+ }
- mempool_free(rq, q->rq.rq_pool);
- return NULL;
+ return rq;
}
/*
@@ -1860,22 +1868,18 @@ static void __freed_request(request_queue_t *q, int rw)
* A request has just been released. Account for it, update the full and
* congestion status, wake up any waiters. Called under q->queue_lock.
*/
-static void freed_request(request_queue_t *q, int rw)
+static void freed_request(request_queue_t *q, int rw, int priv)
{
struct request_list *rl = &q->rq;
rl->count[rw]--;
+ if (priv)
+ rl->elvpriv--;
__freed_request(q, rw);
if (unlikely(rl->starved[rw ^ 1]))
__freed_request(q, rw ^ 1);
-
- if (!rl->count[READ] && !rl->count[WRITE]) {
- smp_mb();
- if (unlikely(waitqueue_active(&rl->drain)))
- wake_up(&rl->drain);
- }
}
#define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist)
@@ -1885,14 +1889,12 @@ static void freed_request(request_queue_t *q, int rw)
* Returns !NULL on success, with queue_lock *not held*.
*/
static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
- int gfp_mask)
+ gfp_t gfp_mask)
{
struct request *rq = NULL;
struct request_list *rl = &q->rq;
struct io_context *ioc = current_io_context(GFP_ATOMIC);
-
- if (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)))
- goto out;
+ int priv;
if (rl->count[rw]+1 >= q->nr_requests) {
/*
@@ -1937,9 +1939,14 @@ get_rq:
rl->starved[rw] = 0;
if (rl->count[rw] >= queue_congestion_on_threshold(q))
set_queue_congested(q, rw);
+
+ priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
+ if (priv)
+ rl->elvpriv++;
+
spin_unlock_irq(q->queue_lock);
- rq = blk_alloc_request(q, rw, bio, gfp_mask);
+ rq = blk_alloc_request(q, rw, bio, priv, gfp_mask);
if (!rq) {
/*
* Allocation failed presumably due to memory. Undo anything
@@ -1949,7 +1956,7 @@ get_rq:
* wait queue, but this is pretty rare.
*/
spin_lock_irq(q->queue_lock);
- freed_request(q, rw);
+ freed_request(q, rw, priv);
/*
* in the very unlikely event that allocation failed and no
@@ -2019,7 +2026,7 @@ static struct request *get_request_wait(request_queue_t *q, int rw,
return rq;
}
-struct request *blk_get_request(request_queue_t *q, int rw, int gfp_mask)
+struct request *blk_get_request(request_queue_t *q, int rw, gfp_t gfp_mask)
{
struct request *rq;
@@ -2251,7 +2258,7 @@ EXPORT_SYMBOL(blk_rq_unmap_user);
* @gfp_mask: memory allocation flags
*/
int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf,
- unsigned int len, unsigned int gfp_mask)
+ unsigned int len, gfp_t gfp_mask)
{
struct bio *bio;
@@ -2433,13 +2440,15 @@ void disk_round_stats(struct gendisk *disk)
{
unsigned long now = jiffies;
- __disk_stat_add(disk, time_in_queue,
- disk->in_flight * (now - disk->stamp));
- disk->stamp = now;
+ if (now == disk->stamp)
+ return;
- if (disk->in_flight)
- __disk_stat_add(disk, io_ticks, (now - disk->stamp_idle));
- disk->stamp_idle = now;
+ if (disk->in_flight) {
+ __disk_stat_add(disk, time_in_queue,
+ disk->in_flight * (now - disk->stamp));
+ __disk_stat_add(disk, io_ticks, (now - disk->stamp));
+ }
+ disk->stamp = now;
}
/*
@@ -2454,6 +2463,8 @@ static void __blk_put_request(request_queue_t *q, struct request *req)
if (unlikely(--req->ref_count))
return;
+ elv_completed_request(q, req);
+
req->rq_status = RQ_INACTIVE;
req->rl = NULL;
@@ -2463,26 +2474,25 @@ static void __blk_put_request(request_queue_t *q, struct request *req)
*/
if (rl) {
int rw = rq_data_dir(req);
-
- elv_completed_request(q, req);
+ int priv = req->flags & REQ_ELVPRIV;
BUG_ON(!list_empty(&req->queuelist));
blk_free_request(q, req);
- freed_request(q, rw);
+ freed_request(q, rw, priv);
}
}
void blk_put_request(struct request *req)
{
+ unsigned long flags;
+ request_queue_t *q = req->q;
+
/*
- * if req->rl isn't set, this request didnt originate from the
- * block layer, so it's safe to just disregard it
+ * Gee, IDE calls in w/ NULL q. Fix IDE and remove the
+ * following if (q) test.
*/
- if (req->rl) {
- unsigned long flags;
- request_queue_t *q = req->q;
-
+ if (q) {
spin_lock_irqsave(q->queue_lock, flags);
__blk_put_request(q, req);
spin_unlock_irqrestore(q->queue_lock, flags);
@@ -2797,97 +2807,6 @@ static inline void blk_partition_remap(struct bio *bio)
}
}
-void blk_finish_queue_drain(request_queue_t *q)
-{
- struct request_list *rl = &q->rq;
- struct request *rq;
- int requeued = 0;
-
- spin_lock_irq(q->queue_lock);
- clear_bit(QUEUE_FLAG_DRAIN, &q->queue_flags);
-
- while (!list_empty(&q->drain_list)) {
- rq = list_entry_rq(q->drain_list.next);
-
- list_del_init(&rq->queuelist);
- elv_requeue_request(q, rq);
- requeued++;
- }
-
- if (requeued)
- q->request_fn(q);
-
- spin_unlock_irq(q->queue_lock);
-
- wake_up(&rl->wait[0]);
- wake_up(&rl->wait[1]);
- wake_up(&rl->drain);
-}
-
-static int wait_drain(request_queue_t *q, struct request_list *rl, int dispatch)
-{
- int wait = rl->count[READ] + rl->count[WRITE];
-
- if (dispatch)
- wait += !list_empty(&q->queue_head);
-
- return wait;
-}
-
-/*
- * We rely on the fact that only requests allocated through blk_alloc_request()
- * have io scheduler private data structures associated with them. Any other
- * type of request (allocated on stack or through kmalloc()) should not go
- * to the io scheduler core, but be attached to the queue head instead.
- */
-void blk_wait_queue_drained(request_queue_t *q, int wait_dispatch)
-{
- struct request_list *rl = &q->rq;
- DEFINE_WAIT(wait);
-
- spin_lock_irq(q->queue_lock);
- set_bit(QUEUE_FLAG_DRAIN, &q->queue_flags);
-
- while (wait_drain(q, rl, wait_dispatch)) {
- prepare_to_wait(&rl->drain, &wait, TASK_UNINTERRUPTIBLE);
-
- if (wait_drain(q, rl, wait_dispatch)) {
- __generic_unplug_device(q);
- spin_unlock_irq(q->queue_lock);
- io_schedule();
- spin_lock_irq(q->queue_lock);
- }
-
- finish_wait(&rl->drain, &wait);
- }
-
- spin_unlock_irq(q->queue_lock);
-}
-
-/*
- * block waiting for the io scheduler being started again.
- */
-static inline void block_wait_queue_running(request_queue_t *q)
-{
- DEFINE_WAIT(wait);
-
- while (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags))) {
- struct request_list *rl = &q->rq;
-
- prepare_to_wait_exclusive(&rl->drain, &wait,
- TASK_UNINTERRUPTIBLE);
-
- /*
- * re-check the condition. avoids using prepare_to_wait()
- * in the fast path (queue is running)
- */
- if (test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags))
- io_schedule();
-
- finish_wait(&rl->drain, &wait);
- }
-}
-
static void handle_bad_sector(struct bio *bio)
{
char b[BDEVNAME_SIZE];
@@ -2983,8 +2902,6 @@ end_io:
if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
goto end_io;
- block_wait_queue_running(q);
-
/*
* If this device has partitions, remap block n
* of partition p to block n+start(p) of the disk.
@@ -3393,7 +3310,7 @@ void exit_io_context(void)
* but since the current task itself holds a reference, the context can be
* used in general code, so long as it stays within `current` context.
*/
-struct io_context *current_io_context(int gfp_flags)
+struct io_context *current_io_context(gfp_t gfp_flags)
{
struct task_struct *tsk = current;
struct io_context *ret;
@@ -3424,7 +3341,7 @@ EXPORT_SYMBOL(current_io_context);
*
* This is always called in the context of the task which submitted the I/O.
*/
-struct io_context *get_io_context(int gfp_flags)
+struct io_context *get_io_context(gfp_t gfp_flags)
{
struct io_context *ret;
ret = current_io_context(gfp_flags);
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index b35e08876dd4b7..96c664af8d069f 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -881,7 +881,7 @@ loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer,
static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
{
struct file *filp = lo->lo_backing_file;
- int gfp = lo->old_gfp_mask;
+ gfp_t gfp = lo->old_gfp_mask;
if (lo->lo_state != Lo_bound)
return -ENXIO;
diff --git a/drivers/block/noop-iosched.c b/drivers/block/noop-iosched.c
index b1730b62c37e47..f56b8edb06e42b 100644
--- a/drivers/block/noop-iosched.c
+++ b/drivers/block/noop-iosched.c
@@ -7,57 +7,19 @@
#include <linux/module.h>
#include <linux/init.h>
-/*
- * See if we can find a request that this buffer can be coalesced with.
- */
-static int elevator_noop_merge(request_queue_t *q, struct request **req,
- struct bio *bio)
-{
- int ret;
-
- ret = elv_try_last_merge(q, bio);
- if (ret != ELEVATOR_NO_MERGE)
- *req = q->last_merge;
-
- return ret;
-}
-
-static void elevator_noop_merge_requests(request_queue_t *q, struct request *req,
- struct request *next)
-{
- list_del_init(&next->queuelist);
-}
-
-static void elevator_noop_add_request(request_queue_t *q, struct request *rq,
- int where)
+static void elevator_noop_add_request(request_queue_t *q, struct request *rq)
{
- if (where == ELEVATOR_INSERT_FRONT)
- list_add(&rq->queuelist, &q->queue_head);
- else
- list_add_tail(&rq->queuelist, &q->queue_head);
-
- /*
- * new merges must not precede this barrier
- */
- if (rq->flags & REQ_HARDBARRIER)
- q->last_merge = NULL;
- else if (!q->last_merge)
- q->last_merge = rq;
+ elv_dispatch_add_tail(q, rq);
}
-static struct request *elevator_noop_next_request(request_queue_t *q)
+static int elevator_noop_dispatch(request_queue_t *q, int force)
{
- if (!list_empty(&q->queue_head))
- return list_entry_rq(q->queue_head.next);
-
- return NULL;
+ return 0;
}
static struct elevator_type elevator_noop = {
.ops = {
- .elevator_merge_fn = elevator_noop_merge,
- .elevator_merge_req_fn = elevator_noop_merge_requests,
- .elevator_next_req_fn = elevator_noop_next_request,
+ .elevator_dispatch_fn = elevator_noop_dispatch,
.elevator_add_req_fn = elevator_noop_add_request,
},
.elevator_name = "noop",
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index b3982395f22b4d..82f2d6d2eeefef 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -674,7 +674,7 @@ static int __init pg_init(void)
for (unit = 0; unit < PG_UNITS; unit++) {
struct pg *dev = &devices[unit];
if (dev->present) {
- class_device_create(pg_class, MKDEV(major, unit),
+ class_device_create(pg_class, NULL, MKDEV(major, unit),
NULL, "pg%u", unit);
err = devfs_mk_cdev(MKDEV(major, unit),
S_IFCHR | S_IRUSR | S_IWUSR, "pg/%u",
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index d8d35233cf495d..686c955734523f 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -971,7 +971,7 @@ static int __init pt_init(void)
devfs_mk_dir("pt");
for (unit = 0; unit < PT_UNITS; unit++)
if (pt[unit].present) {
- class_device_create(pt_class, MKDEV(major, unit),
+ class_device_create(pt_class, NULL, MKDEV(major, unit),
NULL, "pt%d", unit);
err = devfs_mk_cdev(MKDEV(major, unit),
S_IFCHR | S_IRUSR | S_IWUSR,
@@ -980,7 +980,7 @@ static int __init pt_init(void)
class_device_destroy(pt_class, MKDEV(major, unit));
goto out_class;
}
- class_device_create(pt_class, MKDEV(major, unit + 128),
+ class_device_create(pt_class, NULL, MKDEV(major, unit + 128),
NULL, "pt%dn", unit);
err = devfs_mk_cdev(MKDEV(major, unit + 128),
S_IFCHR | S_IRUSR | S_IWUSR,
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 145c1fbffe0135..68c60a5bcdabaf 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -348,7 +348,7 @@ static int rd_open(struct inode *inode, struct file *filp)
struct block_device *bdev = inode->i_bdev;
struct address_space *mapping;
unsigned bsize;
- int gfp_mask;
+ gfp_t gfp_mask;
inode = igrab(bdev->bd_inode);
rd_bdev[unit] = bdev;
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index d57007b92f77ba..1ded3b43345923 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -1,7 +1,7 @@
/*
* sx8.c: Driver for Promise SATA SX8 looks-like-I2O hardware
*
- * Copyright 2004 Red Hat, Inc.
+ * Copyright 2004-2005 Red Hat, Inc.
*
* Author/maintainer: Jeff Garzik <jgarzik@pobox.com>
*
@@ -31,10 +31,6 @@
#include <asm/semaphore.h>
#include <asm/uaccess.h>
-MODULE_AUTHOR("Jeff Garzik");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Promise SATA SX8 block driver");
-
#if 0
#define CARM_DEBUG
#define CARM_VERBOSE_DEBUG
@@ -45,9 +41,35 @@ MODULE_DESCRIPTION("Promise SATA SX8 block driver");
#undef CARM_NDEBUG
#define DRV_NAME "sx8"
-#define DRV_VERSION "0.8"
+#define DRV_VERSION "1.0"
#define PFX DRV_NAME ": "
+MODULE_AUTHOR("Jeff Garzik");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Promise SATA SX8 block driver");
+MODULE_VERSION(DRV_VERSION);
+
+/*
+ * SX8 hardware has a single message queue for all ATA ports.
+ * When this driver was written, the hardware (firmware?) would
+ * corrupt data eventually, if more than one request was outstanding.
+ * As one can imagine, having 8 ports bottlenecking on a single
+ * command hurts performance.
+ *
+ * Based on user reports, later versions of the hardware (firmware?)
+ * seem to be able to survive with more than one command queued.
+ *
+ * Therefore, we default to the safe option -- 1 command -- but
+ * allow the user to increase this.
+ *
+ * SX8 should be able to support up to ~60 queued commands (CARM_MAX_REQ),
+ * but problems seem to occur when you exceed ~30, even on newer hardware.
+ */
+static int max_queue = 1;
+module_param(max_queue, int, 0444);
+MODULE_PARM_DESC(max_queue, "Maximum number of queued commands. (min==1, max==30, safe==1)");
+
+
#define NEXT_RESP(idx) ((idx + 1) % RMSG_Q_LEN)
/* 0xf is just arbitrary, non-zero noise; this is sorta like poisoning */
@@ -90,12 +112,10 @@ enum {
/* command message queue limits */
CARM_MAX_REQ = 64, /* max command msgs per host */
- CARM_MAX_Q = 1, /* one command at a time */
CARM_MSG_LOW_WATER = (CARM_MAX_REQ / 4), /* refill mark */
/* S/G limits, host-wide and per-request */
CARM_MAX_REQ_SG = 32, /* max s/g entries per request */
- CARM_SG_BOUNDARY = 0xffffUL, /* s/g segment boundary */
CARM_MAX_HOST_SG = 600, /* max s/g entries per host */
CARM_SG_LOW_WATER = (CARM_MAX_HOST_SG / 4), /* re-fill mark */
@@ -181,6 +201,10 @@ enum {
FL_DYN_MAJOR = (1 << 17),
};
+enum {
+ CARM_SG_BOUNDARY = 0xffffUL, /* s/g segment boundary */
+};
+
enum scatter_gather_types {
SGT_32BIT = 0,
SGT_64BIT = 1,
@@ -218,7 +242,6 @@ static const char *state_name[] = {
struct carm_port {
unsigned int port_no;
- unsigned int n_queued;
struct gendisk *disk;
struct carm_host *host;
@@ -448,7 +471,7 @@ static inline int carm_lookup_bucket(u32 msg_size)
for (i = 0; i < ARRAY_SIZE(msg_sizes); i++)
if (msg_size <= msg_sizes[i])
return i;
-
+
return -ENOENT;
}
@@ -509,7 +532,7 @@ static struct carm_request *carm_get_request(struct carm_host *host)
if (host->hw_sg_used >= (CARM_MAX_HOST_SG - CARM_MAX_REQ_SG))
return NULL;
- for (i = 0; i < CARM_MAX_Q; i++)
+ for (i = 0; i < max_queue; i++)
if ((host->msg_alloc & (1ULL << i)) == 0) {
struct carm_request *crq = &host->req[i];
crq->port = NULL;
@@ -521,14 +544,14 @@ static struct carm_request *carm_get_request(struct carm_host *host)
assert(host->n_msgs <= CARM_MAX_REQ);
return crq;
}
-
+
DPRINTK("no request available, returning NULL\n");
return NULL;
}
static int carm_put_request(struct carm_host *host, struct carm_request *crq)
{
- assert(crq->tag < CARM_MAX_Q);
+ assert(crq->tag < max_queue);
if (unlikely((host->msg_alloc & (1ULL << crq->tag)) == 0))
return -EINVAL; /* tried to clear a tag that was not active */
@@ -791,7 +814,7 @@ static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq,
int is_ok)
{
carm_end_request_queued(host, crq, is_ok);
- if (CARM_MAX_Q == 1)
+ if (max_queue == 1)
carm_round_robin(host);
else if ((host->n_msgs <= CARM_MSG_LOW_WATER) &&
(host->hw_sg_used <= CARM_SG_LOW_WATER)) {
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 543f93e0f23f68..b9fbe6e7f9ae6e 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -55,14 +55,6 @@ config BT_HCIUART_BCSP
Say Y here to compile support for HCI BCSP protocol.
-config BT_HCIUART_BCSP_TXCRC
- bool "Transmit CRC with every BCSP packet"
- depends on BT_HCIUART_BCSP
- help
- If you say Y here, a 16-bit CRC checksum will be transmitted along with
- every BCSP (BlueCore Serial Protocol) packet sent to the Bluetooth chip.
- This increases reliability, but slightly reduces efficiency.
-
config BT_HCIBCM203X
tristate "HCI BCM203x USB driver"
depends on USB
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index 4fa85234d8b5e1..0db0400519c95e 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -550,6 +550,9 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
if (ignore)
return -ENODEV;
+ if (intf->cur_altsetting->desc.bInterfaceNumber > 0)
+ return -ENODEV;
+
data = kmalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
BT_ERR("Can't allocate data structure");
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index 0ee324e1265de3..0a4761415ac39b 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -1,35 +1,27 @@
-/*
- BlueCore Serial Protocol (BCSP) for Linux Bluetooth stack (BlueZ).
- Copyright 2002 by Fabrizio Gennari <fabrizio.gennari@philips.com>
-
- Based on
- hci_h4.c by Maxim Krasnyansky <maxk@qualcomm.com>
- ABCSP by Carl Orsborn <cjo@csr.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2 as
- published by the Free Software Foundation;
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
- SOFTWARE IS DISCLAIMED.
-*/
-
/*
- * $Id: hci_bcsp.c,v 1.2 2002/09/26 05:05:14 maxk Exp $
+ *
+ * Bluetooth HCI UART driver
+ *
+ * Copyright (C) 2002-2003 Fabrizio Gennari <fabrizio.gennari@philips.com>
+ * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * 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
+ *
*/
-#define VERSION "0.2"
-
#include <linux/config.h>
#include <linux/module.h>
@@ -52,16 +44,56 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
+
#include "hci_uart.h"
-#include "hci_bcsp.h"
#ifndef CONFIG_BT_HCIUART_DEBUG
#undef BT_DBG
#define BT_DBG( A... )
#endif
+#define VERSION "0.3"
+
+static int txcrc = 1;
static int hciextn = 1;
+#define BCSP_TXWINSIZE 4
+
+#define BCSP_ACK_PKT 0x05
+#define BCSP_LE_PKT 0x06
+
+struct bcsp_struct {
+ struct sk_buff_head unack; /* Unack'ed packets queue */
+ struct sk_buff_head rel; /* Reliable packets queue */
+ struct sk_buff_head unrel; /* Unreliable packets queue */
+
+ unsigned long rx_count;
+ struct sk_buff *rx_skb;
+ u8 rxseq_txack; /* rxseq == txack. */
+ u8 rxack; /* Last packet sent by us that the peer ack'ed */
+ struct timer_list tbcsp;
+
+ enum {
+ BCSP_W4_PKT_DELIMITER,
+ BCSP_W4_PKT_START,
+ BCSP_W4_BCSP_HDR,
+ BCSP_W4_DATA,
+ BCSP_W4_CRC
+ } rx_state;
+
+ enum {
+ BCSP_ESCSTATE_NOESC,
+ BCSP_ESCSTATE_ESC
+ } rx_esc_state;
+
+ u8 use_crc;
+ u16 message_crc;
+ u8 txack_req; /* Do we need to send ack's to the peer? */
+
+ /* Reliable packet sequence number - used to assign seq to each rel pkt. */
+ u8 msgq_txseq;
+};
+
/* ---- BCSP CRC calculation ---- */
/* Table for calculating CRC for polynomial 0x1021, LSB processed first,
@@ -111,6 +143,7 @@ static u16 bcsp_crc_reverse(u16 crc)
rev |= (crc & 1);
crc = crc >> 1;
}
+
return (rev);
}
@@ -119,6 +152,7 @@ static u16 bcsp_crc_reverse(u16 crc)
static void bcsp_slip_msgdelim(struct sk_buff *skb)
{
const char pkt_delim = 0xc0;
+
memcpy(skb_put(skb, 1), &pkt_delim, 1);
}
@@ -173,11 +207,8 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
{
struct sk_buff *nskb;
u8 hdr[4], chan;
- int rel, i;
-
-#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
u16 BCSP_CRC_INIT(bcsp_txmsg_crc);
-#endif
+ int rel, i;
switch (pkt_type) {
case HCI_ACLDATA_PKT:
@@ -240,9 +271,9 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
BT_DBG("Sending packet with seqno %u", bcsp->msgq_txseq);
bcsp->msgq_txseq = ++(bcsp->msgq_txseq) & 0x07;
}
-#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
- hdr[0] |= 0x40;
-#endif
+
+ if (bcsp->use_crc)
+ hdr[0] |= 0x40;
hdr[1] = ((len << 4) & 0xff) | chan;
hdr[2] = len >> 4;
@@ -251,25 +282,25 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
/* Put BCSP header */
for (i = 0; i < 4; i++) {
bcsp_slip_one_byte(nskb, hdr[i]);
-#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
- bcsp_crc_update(&bcsp_txmsg_crc, hdr[i]);
-#endif
+
+ if (bcsp->use_crc)
+ bcsp_crc_update(&bcsp_txmsg_crc, hdr[i]);
}
/* Put payload */
for (i = 0; i < len; i++) {
bcsp_slip_one_byte(nskb, data[i]);
-#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
- bcsp_crc_update(&bcsp_txmsg_crc, data[i]);
-#endif
+
+ if (bcsp->use_crc)
+ bcsp_crc_update(&bcsp_txmsg_crc, data[i]);
}
-#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
/* Put CRC */
- bcsp_txmsg_crc = bcsp_crc_reverse(bcsp_txmsg_crc);
- bcsp_slip_one_byte(nskb, (u8) ((bcsp_txmsg_crc >> 8) & 0x00ff));
- bcsp_slip_one_byte(nskb, (u8) (bcsp_txmsg_crc & 0x00ff));
-#endif
+ if (bcsp->use_crc) {
+ bcsp_txmsg_crc = bcsp_crc_reverse(bcsp_txmsg_crc);
+ bcsp_slip_one_byte(nskb, (u8) ((bcsp_txmsg_crc >> 8) & 0x00ff));
+ bcsp_slip_one_byte(nskb, (u8) (bcsp_txmsg_crc & 0x00ff));
+ }
bcsp_slip_msgdelim(nskb);
return nskb;
@@ -317,7 +348,6 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
spin_unlock_irqrestore(&bcsp->unack.lock, flags);
-
/* We could not send a reliable packet, either because there are
none or because there are too many unack'ed pkts. Did we receive
any packets we have not acknowledged yet ? */
@@ -363,7 +393,7 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp)
BT_ERR("Peer acked invalid packet");
BT_DBG("Removing %u pkts out of %u, up to seqno %u",
- pkts_to_be_removed, bcsp->unack.qlen, (seqno - 1) & 0x07);
+ pkts_to_be_removed, bcsp->unack.qlen, (seqno - 1) & 0x07);
for (i = 0, skb = ((struct sk_buff *) &bcsp->unack)->next; i < pkts_to_be_removed
&& skb != (struct sk_buff *) &bcsp->unack; i++) {
@@ -374,8 +404,10 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp)
kfree_skb(skb);
skb = nskb;
}
+
if (bcsp->unack.qlen == 0)
del_timer(&bcsp->tbcsp);
+
spin_unlock_irqrestore(&bcsp->unack.lock, flags);
if (i != pkts_to_be_removed)
@@ -530,6 +562,7 @@ static inline void bcsp_complete_rx_pkt(struct hci_uart *hu)
hci_recv_frame(bcsp->rx_skb);
}
+
bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
bcsp->rx_skb = NULL;
}
@@ -598,8 +631,8 @@ static int bcsp_recv(struct hci_uart *hu, void *data, int count)
BT_ERR ("Checksum failed: computed %04x received %04x",
bcsp_crc_reverse(bcsp->message_crc),
- (bcsp->rx_skb-> data[bcsp->rx_skb->len - 2] << 8) +
- bcsp->rx_skb->data[bcsp->rx_skb->len - 1]);
+ (bcsp->rx_skb-> data[bcsp->rx_skb->len - 2] << 8) +
+ bcsp->rx_skb->data[bcsp->rx_skb->len - 1]);
kfree_skb(bcsp->rx_skb);
bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
@@ -633,7 +666,7 @@ static int bcsp_recv(struct hci_uart *hu, void *data, int count)
bcsp->rx_count = 4;
bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC;
BCSP_CRC_INIT(bcsp->message_crc);
-
+
/* Do not increment ptr or decrement count
* Allocate packet. Max len of a BCSP pkt=
* 0xFFF (payload) +4 (header) +2 (crc) */
@@ -698,6 +731,9 @@ static int bcsp_open(struct hci_uart *hu)
bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
+ if (txcrc)
+ bcsp->use_crc = 1;
+
return 0;
}
@@ -718,18 +754,19 @@ static int bcsp_close(struct hci_uart *hu)
}
static struct hci_uart_proto bcsp = {
- .id = HCI_UART_BCSP,
- .open = bcsp_open,
- .close = bcsp_close,
- .enqueue = bcsp_enqueue,
- .dequeue = bcsp_dequeue,
- .recv = bcsp_recv,
- .flush = bcsp_flush
+ .id = HCI_UART_BCSP,
+ .open = bcsp_open,
+ .close = bcsp_close,
+ .enqueue = bcsp_enqueue,
+ .dequeue = bcsp_dequeue,
+ .recv = bcsp_recv,
+ .flush = bcsp_flush
};
int bcsp_init(void)
{
int err = hci_uart_register_proto(&bcsp);
+
if (!err)
BT_INFO("HCI BCSP protocol initialized");
else
@@ -743,5 +780,8 @@ int bcsp_deinit(void)
return hci_uart_unregister_proto(&bcsp);
}
+module_param(txcrc, bool, 0644);
+MODULE_PARM_DESC(txcrc, "Transmit CRC with every BCSP packet");
+
module_param(hciextn, bool, 0644);
MODULE_PARM_DESC(hciextn, "Convert HCI Extensions into BCSP packets");
diff --git a/drivers/bluetooth/hci_bcsp.h b/drivers/bluetooth/hci_bcsp.h
deleted file mode 100644
index a2b3bb92274bf5..00000000000000
--- a/drivers/bluetooth/hci_bcsp.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- BlueCore Serial Protocol (BCSP) for Linux Bluetooth stack (BlueZ).
- Copyright 2002 by Fabrizio Gennari <fabrizio.gennari@philips.com>
-
- Based on
- hci_h4.c by Maxim Krasnyansky <maxk@qualcomm.com>
- ABCSP by Carl Orsborn <cjo@csr.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2 as
- published by the Free Software Foundation;
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
- SOFTWARE IS DISCLAIMED.
-*/
-
-/*
- * $Id: hci_bcsp.h,v 1.2 2002/09/26 05:05:14 maxk Exp $
- */
-
-#ifndef __HCI_BCSP_H__
-#define __HCI_BCSP_H__
-
-#define BCSP_TXWINSIZE 4
-
-#define BCSP_ACK_PKT 0x05
-#define BCSP_LE_PKT 0x06
-
-struct bcsp_struct {
- struct sk_buff_head unack; /* Unack'ed packets queue */
- struct sk_buff_head rel; /* Reliable packets queue */
- struct sk_buff_head unrel; /* Unreliable packets queue */
-
- unsigned long rx_count;
- struct sk_buff *rx_skb;
- u8 rxseq_txack; /* rxseq == txack. */
- u8 rxack; /* Last packet sent by us that the peer ack'ed */
- struct timer_list tbcsp;
-
- enum {
- BCSP_W4_PKT_DELIMITER,
- BCSP_W4_PKT_START,
- BCSP_W4_BCSP_HDR,
- BCSP_W4_DATA,
- BCSP_W4_CRC
- } rx_state;
-
- enum {
- BCSP_ESCSTATE_NOESC,
- BCSP_ESCSTATE_ESC
- } rx_esc_state;
-
- u16 message_crc;
- u8 txack_req; /* Do we need to send ack's to the peer? */
-
- /* Reliable packet sequence number - used to assign seq to each rel pkt. */
- u8 msgq_txseq;
-};
-
-#endif /* __HCI_BCSP_H__ */
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
index cf8a22d58d960f..12e369a66fc24b 100644
--- a/drivers/bluetooth/hci_h4.c
+++ b/drivers/bluetooth/hci_h4.c
@@ -1,33 +1,27 @@
-/*
- BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
-
- Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2 as
- published by the Free Software Foundation;
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
- SOFTWARE IS DISCLAIMED.
-*/
-
/*
- * Bluetooth HCI UART(H4) protocol.
*
- * $Id: hci_h4.c,v 1.3 2002/09/09 01:17:32 maxk Exp $
+ * Bluetooth HCI UART driver
+ *
+ * Copyright (C) 2000-2001 Qualcomm Incorporated
+ * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
+ * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * 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
+ *
*/
-#define VERSION "1.2"
#include <linux/config.h>
#include <linux/module.h>
@@ -51,24 +45,41 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
+
#include "hci_uart.h"
-#include "hci_h4.h"
#ifndef CONFIG_BT_HCIUART_DEBUG
#undef BT_DBG
#define BT_DBG( A... )
#endif
+#define VERSION "1.2"
+
+struct h4_struct {
+ unsigned long rx_state;
+ unsigned long rx_count;
+ struct sk_buff *rx_skb;
+ struct sk_buff_head txq;
+};
+
+/* H4 receiver States */
+#define H4_W4_PACKET_TYPE 0
+#define H4_W4_EVENT_HDR 1
+#define H4_W4_ACL_HDR 2
+#define H4_W4_SCO_HDR 3
+#define H4_W4_DATA 4
+
/* Initialize protocol */
static int h4_open(struct hci_uart *hu)
{
struct h4_struct *h4;
-
+
BT_DBG("hu %p", hu);
-
+
h4 = kmalloc(sizeof(*h4), GFP_ATOMIC);
if (!h4)
return -ENOMEM;
+
memset(h4, 0, sizeof(*h4));
skb_queue_head_init(&h4->txq);
@@ -83,7 +94,9 @@ static int h4_flush(struct hci_uart *hu)
struct h4_struct *h4 = hu->priv;
BT_DBG("hu %p", hu);
+
skb_queue_purge(&h4->txq);
+
return 0;
}
@@ -91,16 +104,19 @@ static int h4_flush(struct hci_uart *hu)
static int h4_close(struct hci_uart *hu)
{
struct h4_struct *h4 = hu->priv;
+
hu->priv = NULL;
BT_DBG("hu %p", hu);
skb_queue_purge(&h4->txq);
+
if (h4->rx_skb)
kfree_skb(h4->rx_skb);
hu->priv = NULL;
kfree(h4);
+
return 0;
}
@@ -114,6 +130,7 @@ static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
skb_queue_tail(&h4->txq, skb);
+
return 0;
}
@@ -122,6 +139,7 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
register int room = skb_tailroom(h4->rx_skb);
BT_DBG("len %d room %d", len, room);
+
if (!len) {
hci_recv_frame(h4->rx_skb);
} else if (len > room) {
@@ -136,6 +154,7 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
h4->rx_state = H4_W4_PACKET_TYPE;
h4->rx_skb = NULL;
h4->rx_count = 0;
+
return 0;
}
@@ -228,6 +247,7 @@ static int h4_recv(struct hci_uart *hu, void *data, int count)
ptr++; count--;
continue;
};
+
ptr++; count--;
/* Allocate packet */
@@ -238,9 +258,11 @@ static int h4_recv(struct hci_uart *hu, void *data, int count)
h4->rx_count = 0;
return 0;
}
+
h4->rx_skb->dev = (void *) hu->hdev;
bt_cb(h4->rx_skb)->pkt_type = type;
}
+
return count;
}
@@ -251,23 +273,24 @@ static struct sk_buff *h4_dequeue(struct hci_uart *hu)
}
static struct hci_uart_proto h4p = {
- .id = HCI_UART_H4,
- .open = h4_open,
- .close = h4_close,
- .recv = h4_recv,
- .enqueue = h4_enqueue,
- .dequeue = h4_dequeue,
- .flush = h4_flush,
+ .id = HCI_UART_H4,
+ .open = h4_open,
+ .close = h4_close,
+ .recv = h4_recv,
+ .enqueue = h4_enqueue,
+ .dequeue = h4_dequeue,
+ .flush = h4_flush,
};
-
+
int h4_init(void)
{
int err = hci_uart_register_proto(&h4p);
+
if (!err)
BT_INFO("HCI H4 protocol initialized");
else
BT_ERR("HCI H4 protocol registration failed");
-
+
return err;
}
diff --git a/drivers/bluetooth/hci_h4.h b/drivers/bluetooth/hci_h4.h
deleted file mode 100644
index b95ff54bfd47c8..00000000000000
--- a/drivers/bluetooth/hci_h4.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
-
- Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2 as
- published by the Free Software Foundation;
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
- SOFTWARE IS DISCLAIMED.
-*/
-
-/*
- * $Id: hci_h4.h,v 1.2 2002/09/09 01:17:32 maxk Exp $
- */
-
-#ifdef __KERNEL__
-struct h4_struct {
- unsigned long rx_state;
- unsigned long rx_count;
- struct sk_buff *rx_skb;
- struct sk_buff_head txq;
-};
-
-/* H4 receiver States */
-#define H4_W4_PACKET_TYPE 0
-#define H4_W4_EVENT_HDR 1
-#define H4_W4_ACL_HDR 2
-#define H4_W4_SCO_HDR 3
-#define H4_W4_DATA 4
-
-#endif /* __KERNEL__ */
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index aed80cc2289028..4a775f6ea39071 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -1,33 +1,27 @@
-/*
- BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
-
- Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2 as
- published by the Free Software Foundation;
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
- SOFTWARE IS DISCLAIMED.
-*/
-
/*
- * Bluetooth HCI UART driver.
*
- * $Id: hci_ldisc.c,v 1.5 2002/10/02 18:37:20 maxk Exp $
+ * Bluetooth HCI UART driver
+ *
+ * Copyright (C) 2000-2001 Qualcomm Incorporated
+ * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
+ * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * 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
+ *
*/
-#define VERSION "2.1"
#include <linux/config.h>
#include <linux/module.h>
@@ -59,6 +53,8 @@
#define BT_DBG( A... )
#endif
+#define VERSION "2.2"
+
static int reset = 0;
static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO];
@@ -72,6 +68,7 @@ int hci_uart_register_proto(struct hci_uart_proto *p)
return -EEXIST;
hup[p->id] = p;
+
return 0;
}
@@ -84,6 +81,7 @@ int hci_uart_unregister_proto(struct hci_uart_proto *p)
return -EINVAL;
hup[p->id] = NULL;
+
return 0;
}
@@ -91,13 +89,14 @@ static struct hci_uart_proto *hci_uart_get_proto(unsigned int id)
{
if (id >= HCI_UART_MAX_PROTO)
return NULL;
+
return hup[id];
}
static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type)
{
struct hci_dev *hdev = hu->hdev;
-
+
/* Update HCI stat counters */
switch (pkt_type) {
case HCI_COMMAND_PKT:
@@ -117,10 +116,12 @@ static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type)
static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
{
struct sk_buff *skb = hu->tx_skb;
+
if (!skb)
skb = hu->proto->dequeue(hu);
else
hu->tx_skb = NULL;
+
return skb;
}
@@ -129,7 +130,7 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
struct tty_struct *tty = hu->tty;
struct hci_dev *hdev = hu->hdev;
struct sk_buff *skb;
-
+
if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) {
set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
return 0;
@@ -142,7 +143,7 @@ restart:
while ((skb = hci_uart_dequeue(hu))) {
int len;
-
+
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
len = tty->driver->write(tty, skb->data, skb->len);
hdev->stat.byte_tx += len;
@@ -152,11 +153,11 @@ restart:
hu->tx_skb = skb;
break;
}
-
+
hci_uart_tx_complete(hu, bt_cb(skb)->pkt_type);
kfree_skb(skb);
- }
-
+ }
+
if (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state))
goto restart;
@@ -173,6 +174,7 @@ static int hci_uart_open(struct hci_dev *hdev)
/* Nothing to do for UART driver */
set_bit(HCI_RUNNING, &hdev->flags);
+
return 0;
}
@@ -234,6 +236,7 @@ static int hci_uart_send_frame(struct sk_buff *skb)
hu->proto->enqueue(hu, skb);
hci_uart_tx_wakeup(hu);
+
return 0;
}
@@ -241,7 +244,8 @@ static void hci_uart_destruct(struct hci_dev *hdev)
{
struct hci_uart *hu;
- if (!hdev) return;
+ if (!hdev)
+ return;
BT_DBG("%s", hdev->name);
@@ -272,6 +276,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
BT_ERR("Can't allocate controll structure");
return -ENFILE;
}
+
memset(hu, 0, sizeof(struct hci_uart));
tty->disc_data = hu;
@@ -280,8 +285,10 @@ static int hci_uart_tty_open(struct tty_struct *tty)
spin_lock_init(&hu->rx_lock);
/* Flush any pending characters in the driver and line discipline. */
+
/* FIXME: why is this needed. Note don't use ldisc_ref here as the
open path is before the ldisc is referencable */
+
if (tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer(tty);
@@ -372,13 +379,13 @@ static int hci_uart_tty_room (struct tty_struct *tty)
static void hci_uart_tty_receive(struct tty_struct *tty, const __u8 *data, char *flags, int count)
{
struct hci_uart *hu = (void *)tty->disc_data;
-
+
if (!hu || tty != hu->tty)
return;
if (!test_bit(HCI_UART_PROTO_SET, &hu->flags))
return;
-
+
spin_lock(&hu->rx_lock);
hu->proto->recv(hu, (void *) data, count);
hu->hdev->stat.byte_rx += count;
@@ -429,8 +436,8 @@ static int hci_uart_register_dev(struct hci_uart *hu)
static int hci_uart_set_proto(struct hci_uart *hu, int id)
{
struct hci_uart_proto *p;
- int err;
-
+ int err;
+
p = hci_uart_get_proto(id);
if (!p)
return -EPROTONOSUPPORT;
@@ -446,6 +453,7 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
p->close(hu);
return err;
}
+
return 0;
}
@@ -463,7 +471,7 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
* Return Value: Command dependent
*/
static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
struct hci_uart *hu = (void *)tty->disc_data;
int err = 0;
@@ -483,14 +491,14 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
return err;
}
tty->low_latency = 1;
- } else
+ } else
return -EBUSY;
case HCIUARTGETPROTO:
if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
return hu->proto->id;
return -EUNATCH;
-
+
default:
err = n_tty_ioctl(tty, file, cmd, arg);
break;
@@ -502,28 +510,24 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
/*
* We don't provide read/write/poll interface for user space.
*/
-static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file, unsigned char __user *buf, size_t nr)
+static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file,
+ unsigned char __user *buf, size_t nr)
{
return 0;
}
-static ssize_t hci_uart_tty_write(struct tty_struct *tty, struct file *file, const unsigned char *data, size_t count)
+
+static ssize_t hci_uart_tty_write(struct tty_struct *tty, struct file *file,
+ const unsigned char *data, size_t count)
{
return 0;
}
-static unsigned int hci_uart_tty_poll(struct tty_struct *tty, struct file *filp, poll_table *wait)
+
+static unsigned int hci_uart_tty_poll(struct tty_struct *tty,
+ struct file *filp, poll_table *wait)
{
return 0;
}
-#ifdef CONFIG_BT_HCIUART_H4
-int h4_init(void);
-int h4_deinit(void);
-#endif
-#ifdef CONFIG_BT_HCIUART_BCSP
-int bcsp_init(void);
-int bcsp_deinit(void);
-#endif
-
static int __init hci_uart_init(void)
{
static struct tty_ldisc hci_uart_ldisc;
@@ -534,18 +538,18 @@ static int __init hci_uart_init(void)
/* Register the tty discipline */
memset(&hci_uart_ldisc, 0, sizeof (hci_uart_ldisc));
- hci_uart_ldisc.magic = TTY_LDISC_MAGIC;
- hci_uart_ldisc.name = "n_hci";
- hci_uart_ldisc.open = hci_uart_tty_open;
- hci_uart_ldisc.close = hci_uart_tty_close;
- hci_uart_ldisc.read = hci_uart_tty_read;
- hci_uart_ldisc.write = hci_uart_tty_write;
- hci_uart_ldisc.ioctl = hci_uart_tty_ioctl;
- hci_uart_ldisc.poll = hci_uart_tty_poll;
- hci_uart_ldisc.receive_room= hci_uart_tty_room;
- hci_uart_ldisc.receive_buf = hci_uart_tty_receive;
- hci_uart_ldisc.write_wakeup= hci_uart_tty_wakeup;
- hci_uart_ldisc.owner = THIS_MODULE;
+ hci_uart_ldisc.magic = TTY_LDISC_MAGIC;
+ hci_uart_ldisc.name = "n_hci";
+ hci_uart_ldisc.open = hci_uart_tty_open;
+ hci_uart_ldisc.close = hci_uart_tty_close;
+ hci_uart_ldisc.read = hci_uart_tty_read;
+ hci_uart_ldisc.write = hci_uart_tty_write;
+ hci_uart_ldisc.ioctl = hci_uart_tty_ioctl;
+ hci_uart_ldisc.poll = hci_uart_tty_poll;
+ hci_uart_ldisc.receive_room = hci_uart_tty_room;
+ hci_uart_ldisc.receive_buf = hci_uart_tty_receive;
+ hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup;
+ hci_uart_ldisc.owner = THIS_MODULE;
if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) {
BT_ERR("HCI line discipline registration failed. (%d)", err);
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index 0a57d72790ec1a..b250e6789dee68 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -1,32 +1,29 @@
-/*
- BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
-
- Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2 as
- published by the Free Software Foundation;
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
- SOFTWARE IS DISCLAIMED.
-*/
-
/*
- * $Id: hci_uart.h,v 1.2 2002/09/09 01:17:32 maxk Exp $
+ *
+ * Bluetooth HCI UART driver
+ *
+ * Copyright (C) 2000-2001 Qualcomm Incorporated
+ * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
+ * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * 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
+ *
*/
-#ifndef N_HCI
+#ifndef N_HCI
#define N_HCI 15
#endif
@@ -42,7 +39,6 @@
#define HCI_UART_3WIRE 2
#define HCI_UART_H4DS 3
-#ifdef __KERNEL__
struct hci_uart;
struct hci_uart_proto {
@@ -56,27 +52,35 @@ struct hci_uart_proto {
};
struct hci_uart {
- struct tty_struct *tty;
- struct hci_dev *hdev;
- unsigned long flags;
+ struct tty_struct *tty;
+ struct hci_dev *hdev;
+ unsigned long flags;
- struct hci_uart_proto *proto;
- void *priv;
-
- struct sk_buff *tx_skb;
- unsigned long tx_state;
- spinlock_t rx_lock;
+ struct hci_uart_proto *proto;
+ void *priv;
+
+ struct sk_buff *tx_skb;
+ unsigned long tx_state;
+ spinlock_t rx_lock;
};
/* HCI_UART flag bits */
-#define HCI_UART_PROTO_SET 0
+#define HCI_UART_PROTO_SET 0
/* TX states */
-#define HCI_UART_SENDING 1
-#define HCI_UART_TX_WAKEUP 2
+#define HCI_UART_SENDING 1
+#define HCI_UART_TX_WAKEUP 2
int hci_uart_register_proto(struct hci_uart_proto *p);
int hci_uart_unregister_proto(struct hci_uart_proto *p);
int hci_uart_tx_wakeup(struct hci_uart *hu);
-#endif /* __KERNEL__ */
+#ifdef CONFIG_BT_HCIUART_H4
+int h4_init(void);
+int h4_deinit(void);
+#endif
+
+#ifdef CONFIG_BT_HCIUART_BCSP
+int bcsp_init(void);
+int bcsp_deinit(void);
+#endif
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index 6d9080a3ca7e97..12ef13ff04ca1a 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -1133,10 +1133,10 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev,
ring_start = (dev_priv->cp_ring->offset
- dev->agp->base
+ dev_priv->gart_vm_start);
- } else
+ } else
#endif
ring_start = (dev_priv->cp_ring->offset
- - dev->sg->handle
+ - (unsigned long)dev->sg->virtual
+ dev_priv->gart_vm_start);
RADEON_WRITE( RADEON_CP_RB_BASE, ring_start );
@@ -1164,7 +1164,8 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev,
drm_sg_mem_t *entry = dev->sg;
unsigned long tmp_ofs, page_ofs;
- tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
+ tmp_ofs = dev_priv->ring_rptr->offset -
+ (unsigned long)dev->sg->virtual;
page_ofs = tmp_ofs >> PAGE_SHIFT;
RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
@@ -1491,8 +1492,8 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
else
#endif
dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
- - dev->sg->handle
- + dev_priv->gart_vm_start);
+ - (unsigned long)dev->sg->virtual
+ + dev_priv->gart_vm_start);
DRM_DEBUG( "dev_priv->gart_size %d\n",
dev_priv->gart_size );
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 26271e3ca82371..8693835cb2d51f 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -515,7 +515,7 @@ static int __init dsp56k_init_driver(void)
err = PTR_ERR(dsp56k_class);
goto out_chrdev;
}
- class_device_create(dsp56k_class, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
+ class_device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
err = devfs_mk_cdev(MKDEV(DSP56K_MAJOR, 0),
S_IFCHR | S_IRUSR | S_IWUSR, "dsp56k");
diff --git a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c
index 5745b74044ec1b..821357ce7e0e86 100644
--- a/drivers/char/ftape/zftape/zftape-init.c
+++ b/drivers/char/ftape/zftape/zftape-init.c
@@ -331,27 +331,27 @@ KERN_INFO
zft_class = class_create(THIS_MODULE, "zft");
for (i = 0; i < 4; i++) {
- class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
+ class_device_create(zft_class, NULL, 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_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
+ class_device_create(zft_class, NULL, 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_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
+ class_device_create(zft_class, NULL, 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_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
+ class_device_create(zft_class, NULL, 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_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
+ class_device_create(zft_class, NULL, 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_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
+ class_device_create(zft_class, NULL, 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);
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
index 9e4e26aef94ea8..d815d197dc3e33 100644
--- a/drivers/char/ip2main.c
+++ b/drivers/char/ip2main.c
@@ -721,8 +721,9 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
}
if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
- class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR,
- 4 * i), NULL, "ipl%d", i);
+ class_device_create(ip2_class, NULL,
+ 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);
@@ -732,8 +733,9 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
goto out_class;
}
- class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR,
- 4 * i + 1), NULL, "stat%d", i);
+ class_device_create(ip2_class, NULL,
+ 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);
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index a09ff10806874d..7c0684deea06a8 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -798,7 +798,7 @@ static void ipmi_new_smi(int if_num)
devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
"ipmidev/%d", if_num);
- class_device_create(ipmi_class, dev, NULL, "ipmi%d", if_num);
+ class_device_create(ipmi_class, NULL, dev, NULL, "ipmi%d", if_num);
}
static void ipmi_smi_gone(int if_num)
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 9c19e5435a11fa..e3ddbdb85a2f3d 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -5246,7 +5246,8 @@ int __init stli_init(void)
devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
S_IFCHR | S_IRUSR | S_IWUSR,
"staliomem/%d", i);
- class_device_create(istallion_class, MKDEV(STL_SIOMEMMAJOR, i),
+ class_device_create(istallion_class, NULL,
+ MKDEV(STL_SIOMEMMAJOR, i),
NULL, "staliomem%d", i);
}
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 2afb9038dbc575..e572605252935c 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -805,7 +805,7 @@ static int lp_register(int nr, struct parport *port)
if (reset)
lp_reset(nr);
- class_device_create(lp_class, MKDEV(LP_MAJOR, nr), NULL,
+ class_device_create(lp_class, NULL, MKDEV(LP_MAJOR, nr), NULL,
"lp%d", nr);
devfs_mk_cdev(MKDEV(LP_MAJOR, nr), S_IFCHR | S_IRUGO | S_IWUGO,
"printers/%d", nr);
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index f182752fe918b9..38be4b0dbd1cc0 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -920,7 +920,8 @@ static int __init chr_dev_init(void)
mem_class = class_create(THIS_MODULE, "mem");
for (i = 0; i < ARRAY_SIZE(devlist); i++) {
- class_device_create(mem_class, MKDEV(MEM_MAJOR, devlist[i].minor),
+ class_device_create(mem_class, NULL,
+ 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 0c8375165e29af..3e4c0414a01a21 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -234,7 +234,7 @@ int misc_register(struct miscdevice * misc)
}
dev = MKDEV(MISC_MAJOR, misc->minor);
- misc->class = class_device_create(misc_class, dev, misc->dev,
+ misc->class = class_device_create(misc_class, NULL, dev, misc->dev,
"%s", misc->name);
if (IS_ERR(misc->class)) {
err = PTR_ERR(misc->class);
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index c9bdf544ed2cd1..c556f4d3ccd7cd 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -62,7 +62,7 @@
static inline unsigned char *alloc_buf(void)
{
- unsigned int prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+ gfp_t prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
if (PAGE_SIZE != N_TTY_BUF_SIZE)
return kmalloc(N_TTY_BUF_SIZE, prio);
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 1af733d07321a8..9e24bbd4090cc7 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -32,9 +32,11 @@
* added changelog
* 1.2 Erik Gilling: Cobalt Networks support
* Tim Hockin: general cleanup, Cobalt support
+ * 1.3 Jon Ringle: Comdial MP1000 support
+ *
*/
-#define NVRAM_VERSION "1.2"
+#define NVRAM_VERSION "1.3"
#include <linux/module.h>
#include <linux/config.h>
@@ -45,6 +47,7 @@
#define PC 1
#define ATARI 2
#define COBALT 3
+#define MP1000 4
/* select machine configuration */
#if defined(CONFIG_ATARI)
@@ -54,6 +57,9 @@
# if defined(CONFIG_COBALT)
# include <linux/cobalt-nvram.h>
# define MACH COBALT
+# elif defined(CONFIG_MACH_MP1000)
+# undef MACH
+# define MACH MP1000
# else
# define MACH PC
# endif
@@ -112,6 +118,23 @@
#endif
+#if MACH == MP1000
+
+/* RTC in a MP1000 */
+#define CHECK_DRIVER_INIT() 1
+
+#define MP1000_CKS_RANGE_START 0
+#define MP1000_CKS_RANGE_END 111
+#define MP1000_CKS_LOC 112
+
+#define NVRAM_BYTES (128-NVRAM_FIRST_BYTE)
+
+#define mach_check_checksum mp1000_check_checksum
+#define mach_set_checksum mp1000_set_checksum
+#define mach_proc_infos mp1000_proc_infos
+
+#endif
+
/* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with
* rtc_lock held. Due to the index-port/data-port design of the RTC, we
* don't want two different things trying to get to it at once. (e.g. the
@@ -915,6 +938,91 @@ atari_proc_infos(unsigned char *nvram, char *buffer, int *len,
#endif /* MACH == ATARI */
+#if MACH == MP1000
+
+static int
+mp1000_check_checksum(void)
+{
+ int i;
+ unsigned short sum = 0;
+ unsigned short expect;
+
+ for (i = MP1000_CKS_RANGE_START; i <= MP1000_CKS_RANGE_END; ++i)
+ sum += __nvram_read_byte(i);
+
+ expect = __nvram_read_byte(MP1000_CKS_LOC+1)<<8 |
+ __nvram_read_byte(MP1000_CKS_LOC);
+ return ((sum & 0xffff) == expect);
+}
+
+static void
+mp1000_set_checksum(void)
+{
+ int i;
+ unsigned short sum = 0;
+
+ for (i = MP1000_CKS_RANGE_START; i <= MP1000_CKS_RANGE_END; ++i)
+ sum += __nvram_read_byte(i);
+ __nvram_write_byte(sum >> 8, MP1000_CKS_LOC + 1);
+ __nvram_write_byte(sum & 0xff, MP1000_CKS_LOC);
+}
+
+#ifdef CONFIG_PROC_FS
+
+#define SERVER_N_LEN 32
+#define PATH_N_LEN 32
+#define FILE_N_LEN 32
+#define NVRAM_MAGIC_SIG 0xdead
+
+typedef struct NvRamImage
+{
+ unsigned short int magic;
+ unsigned short int mode;
+ char fname[FILE_N_LEN];
+ char path[PATH_N_LEN];
+ char server[SERVER_N_LEN];
+ char pad[12];
+} NvRam;
+
+static int
+mp1000_proc_infos(unsigned char *nvram, char *buffer, int *len,
+ off_t *begin, off_t offset, int size)
+{
+ int checksum;
+ NvRam* nv = (NvRam*)nvram;
+
+ spin_lock_irq(&rtc_lock);
+ checksum = __nvram_check_checksum();
+ spin_unlock_irq(&rtc_lock);
+
+ PRINT_PROC("Checksum status: %svalid\n", checksum ? "" : "not ");
+
+ switch( nv->mode )
+ {
+ case 0 :
+ PRINT_PROC( "\tMode 0, tftp prompt\n" );
+ break;
+ case 1 :
+ PRINT_PROC( "\tMode 1, booting from disk\n" );
+ break;
+ case 2 :
+ PRINT_PROC( "\tMode 2, Alternate boot from disk /boot/%s\n", nv->fname );
+ break;
+ case 3 :
+ PRINT_PROC( "\tMode 3, Booting from net:\n" );
+ PRINT_PROC( "\t\t%s:%s%s\n",nv->server, nv->path, nv->fname );
+ break;
+ default:
+ PRINT_PROC( "\tInconsistant nvram?\n" );
+ break;
+ }
+
+ return 1;
+}
+#endif
+
+#endif /* MACH == MP1000 */
+
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(__nvram_read_byte);
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 0e22880432bca3..306ee0f091a4eb 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -752,7 +752,7 @@ static struct file_operations pp_fops = {
static void pp_attach(struct parport *port)
{
- class_device_create(ppdev_class, MKDEV(PP_MAJOR, port->number),
+ class_device_create(ppdev_class, NULL, MKDEV(PP_MAJOR, port->number),
NULL, "parport%d", port->number);
}
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index f13e5de02207b8..30e4cbe16bb003 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -128,7 +128,7 @@ raw_ioctl(struct inode *inode, struct file *filp,
static void bind_device(struct raw_config_request *rq)
{
class_device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
- class_device_create(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor),
+ class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
NULL, "raw%d", rq->raw_minor);
}
@@ -307,7 +307,7 @@ static int __init raw_init(void)
unregister_chrdev_region(dev, MAX_RAW_MINORS);
goto error;
}
- class_device_create(raw_class, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
+ class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
devfs_mk_cdev(MKDEV(RAW_MAJOR, 0),
S_IFCHR | S_IRUGO | S_IWUGO,
diff --git a/drivers/char/s3c2410-rtc.c b/drivers/char/s3c2410-rtc.c
index e1a90d9a875671..887b8b2d788278 100644
--- a/drivers/char/s3c2410-rtc.c
+++ b/drivers/char/s3c2410-rtc.c
@@ -519,30 +519,28 @@ static struct timespec s3c2410_rtc_delta;
static int ticnt_save;
-static int s3c2410_rtc_suspend(struct device *dev, pm_message_t state, u32 level)
+static int s3c2410_rtc_suspend(struct device *dev, pm_message_t state)
{
struct rtc_time tm;
struct timespec time;
time.tv_nsec = 0;
- if (level == SUSPEND_POWER_DOWN) {
- /* save TICNT for anyone using periodic interrupts */
+ /* save TICNT for anyone using periodic interrupts */
- ticnt_save = readb(S3C2410_TICNT);
+ ticnt_save = readb(S3C2410_TICNT);
- /* calculate time delta for suspend */
+ /* calculate time delta for suspend */
- s3c2410_rtc_gettime(&tm);
- rtc_tm_to_time(&tm, &time.tv_sec);
- save_time_delta(&s3c2410_rtc_delta, &time);
- s3c2410_rtc_enable(dev, 0);
- }
+ s3c2410_rtc_gettime(&tm);
+ rtc_tm_to_time(&tm, &time.tv_sec);
+ save_time_delta(&s3c2410_rtc_delta, &time);
+ s3c2410_rtc_enable(dev, 0);
return 0;
}
-static int s3c2410_rtc_resume(struct device *dev, u32 level)
+static int s3c2410_rtc_resume(struct device *dev)
{
struct rtc_time tm;
struct timespec time;
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index 261a41bf6d02ed..1758a83327e54b 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -437,7 +437,7 @@ scdrv_init(void)
continue;
}
- class_device_create(snsc_class, dev, NULL,
+ class_device_create(snsc_class, NULL, dev, NULL,
"%s", devname);
ia64_sn_irtr_intr_enable(scd->scd_nasid,
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 36ae9ad2598cc7..f86c15587238e3 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -424,10 +424,6 @@ static struct sonypi_eventtypes {
#define SONYPI_BUF_SIZE 128
-/* The name of the devices for the input device drivers */
-#define SONYPI_JOG_INPUTNAME "Sony Vaio Jogdial"
-#define SONYPI_KEY_INPUTNAME "Sony Vaio Keys"
-
/* Correspondance table between sonypi events and input layer events */
static struct {
int sonypiev;
@@ -490,8 +486,8 @@ static struct sonypi_device {
struct fasync_struct *fifo_async;
int open_count;
int model;
- struct input_dev input_jog_dev;
- struct input_dev input_key_dev;
+ struct input_dev *input_jog_dev;
+ struct input_dev *input_key_dev;
struct work_struct input_work;
struct kfifo *input_fifo;
spinlock_t input_fifo_lock;
@@ -779,8 +775,8 @@ static void input_keyrelease(void *data)
static void sonypi_report_input_event(u8 event)
{
- struct input_dev *jog_dev = &sonypi_device.input_jog_dev;
- struct input_dev *key_dev = &sonypi_device.input_key_dev;
+ struct input_dev *jog_dev = sonypi_device.input_jog_dev;
+ struct input_dev *key_dev = sonypi_device.input_key_dev;
struct sonypi_keypress kp = { NULL };
int i;
@@ -1171,19 +1167,17 @@ static int sonypi_disable(void)
#ifdef CONFIG_PM
static int old_camera_power;
-static int sonypi_suspend(struct device *dev, pm_message_t state, u32 level)
+static int sonypi_suspend(struct device *dev, pm_message_t state)
{
- if (level == SUSPEND_DISABLE) {
- old_camera_power = sonypi_device.camera_power;
- sonypi_disable();
- }
+ old_camera_power = sonypi_device.camera_power;
+ sonypi_disable();
+
return 0;
}
-static int sonypi_resume(struct device *dev, u32 level)
+static int sonypi_resume(struct device *dev)
{
- if (level == RESUME_ENABLE)
- sonypi_enable(old_camera_power);
+ sonypi_enable(old_camera_power);
return 0;
}
#endif
@@ -1203,6 +1197,47 @@ static struct device_driver sonypi_driver = {
.shutdown = sonypi_shutdown,
};
+static int __devinit sonypi_create_input_devices(void)
+{
+ struct input_dev *jog_dev;
+ struct input_dev *key_dev;
+ int i;
+
+ sonypi_device.input_jog_dev = jog_dev = input_allocate_device();
+ if (!jog_dev)
+ return -ENOMEM;
+
+ jog_dev->name = "Sony Vaio Jogdial";
+ jog_dev->id.bustype = BUS_ISA;
+ jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
+
+ jog_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ jog_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_MIDDLE);
+ jog_dev->relbit[0] = BIT(REL_WHEEL);
+
+ sonypi_device.input_key_dev = key_dev = input_allocate_device();
+ if (!key_dev) {
+ input_free_device(jog_dev);
+ sonypi_device.input_jog_dev = NULL;
+ return -ENOMEM;
+ }
+
+ key_dev->name = "Sony Vaio Keys";
+ key_dev->id.bustype = BUS_ISA;
+ key_dev->id.vendor = PCI_VENDOR_ID_SONY;
+
+ /* Initialize the Input Drivers: special keys */
+ key_dev->evbit[0] = BIT(EV_KEY);
+ for (i = 0; sonypi_inputkeys[i].sonypiev; i++)
+ if (sonypi_inputkeys[i].inputev)
+ set_bit(sonypi_inputkeys[i].inputev, key_dev->keybit);
+
+ input_register_device(jog_dev);
+ input_register_device(key_dev);
+
+ return 0;
+}
+
static int __devinit sonypi_probe(void)
{
int i, ret;
@@ -1298,34 +1333,10 @@ static int __devinit sonypi_probe(void)
}
if (useinput) {
- /* Initialize the Input Drivers: jogdial */
- int i;
- sonypi_device.input_jog_dev.evbit[0] =
- BIT(EV_KEY) | BIT(EV_REL);
- sonypi_device.input_jog_dev.keybit[LONG(BTN_MOUSE)] =
- BIT(BTN_MIDDLE);
- sonypi_device.input_jog_dev.relbit[0] = BIT(REL_WHEEL);
- sonypi_device.input_jog_dev.name = SONYPI_JOG_INPUTNAME;
- sonypi_device.input_jog_dev.id.bustype = BUS_ISA;
- sonypi_device.input_jog_dev.id.vendor = PCI_VENDOR_ID_SONY;
-
- input_register_device(&sonypi_device.input_jog_dev);
- printk(KERN_INFO "%s input method installed.\n",
- sonypi_device.input_jog_dev.name);
-
- /* Initialize the Input Drivers: special keys */
- sonypi_device.input_key_dev.evbit[0] = BIT(EV_KEY);
- for (i = 0; sonypi_inputkeys[i].sonypiev; i++)
- if (sonypi_inputkeys[i].inputev)
- set_bit(sonypi_inputkeys[i].inputev,
- sonypi_device.input_key_dev.keybit);
- sonypi_device.input_key_dev.name = SONYPI_KEY_INPUTNAME;
- sonypi_device.input_key_dev.id.bustype = BUS_ISA;
- sonypi_device.input_key_dev.id.vendor = PCI_VENDOR_ID_SONY;
- input_register_device(&sonypi_device.input_key_dev);
- printk(KERN_INFO "%s input method installed.\n",
- sonypi_device.input_key_dev.name);
+ ret = sonypi_create_input_devices();
+ if (ret)
+ goto out_inputdevices;
spin_lock_init(&sonypi_device.input_fifo_lock);
sonypi_device.input_fifo =
@@ -1375,8 +1386,9 @@ static int __devinit sonypi_probe(void)
out_platformdev:
kfifo_free(sonypi_device.input_fifo);
out_infifo:
- input_unregister_device(&sonypi_device.input_key_dev);
- input_unregister_device(&sonypi_device.input_jog_dev);
+ input_unregister_device(sonypi_device.input_key_dev);
+ input_unregister_device(sonypi_device.input_jog_dev);
+out_inputdevices:
free_irq(sonypi_device.irq, sonypi_irq);
out_reqirq:
release_region(sonypi_device.ioport1, sonypi_device.region_size);
@@ -1402,8 +1414,8 @@ static void __devexit sonypi_remove(void)
platform_device_unregister(sonypi_device.pdev);
if (useinput) {
- input_unregister_device(&sonypi_device.input_key_dev);
- input_unregister_device(&sonypi_device.input_jog_dev);
+ input_unregister_device(sonypi_device.input_key_dev);
+ input_unregister_device(sonypi_device.input_jog_dev);
kfifo_free(sonypi_device.input_fifo);
}
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 951545a6ef2d3f..1c686414e0a1f6 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -3095,7 +3095,9 @@ static int __init stl_init(void)
devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
S_IFCHR|S_IRUSR|S_IWUSR,
"staliomem/%d", i);
- class_device_create(stallion_class, MKDEV(STL_SIOMEMMAJOR, i), NULL, "staliomem%d", i);
+ class_device_create(stallion_class, NULL,
+ MKDEV(STL_SIOMEMMAJOR, i), NULL,
+ "staliomem%d", i);
}
stl_serial->owner = THIS_MODULE;
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
index ec78d2f161f753..41a94bc79f67f4 100644
--- a/drivers/char/tipar.c
+++ b/drivers/char/tipar.c
@@ -436,7 +436,7 @@ tipar_register(int nr, struct parport *port)
goto out;
}
- class_device_create(tipar_class, MKDEV(TIPAR_MAJOR,
+ class_device_create(tipar_class, NULL, 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),
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index e5953f3433f3ea..f5649a3377431f 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -2728,7 +2728,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_device_create(tty_class, dev, device, name);
+ class_device_create(tty_class, NULL, dev, device, "%s", name);
}
/**
@@ -2983,14 +2983,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_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
+ class_device_create(tty_class, NULL, 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_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
+ class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
#ifdef CONFIG_UNIX98_PTYS
cdev_init(&ptmx_cdev, &ptmx_fops);
@@ -2998,7 +2998,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_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
+ class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
#endif
#ifdef CONFIG_VT
@@ -3007,7 +3007,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_device_create(tty_class, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
+ class_device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
vty_init();
#endif
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index 79c2928a8817d1..f66c7ad6fd3877 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -484,8 +484,10 @@ 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_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);
+ class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
+ NULL, "vcs%u", tty->index + 1);
+ class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
+ NULL, "vcsa%u", tty->index + 1);
}
void vcs_remove_devfs(struct tty_struct *tty)
{
@@ -503,7 +505,7 @@ int __init vcs_init(void)
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_device_create(vc_class, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
- class_device_create(vc_class, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
+ class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
+ class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
return 0;
}
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 0aff45fac2e6c9..a5e104f428f844 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -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_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i), NULL,
+ class_device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), NULL,
"iseries!vt%d", i);
- class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80),
+ class_device_create(tape_class, NULL, 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);
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index 3625b2601b4257..b732020acadb19 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -464,32 +464,28 @@ static void s3c2410wdt_shutdown(struct device *dev)
static unsigned long wtcon_save;
static unsigned long wtdat_save;
-static int s3c2410wdt_suspend(struct device *dev, pm_message_t state, u32 level)
+static int s3c2410wdt_suspend(struct device *dev, pm_message_t state)
{
- if (level == SUSPEND_POWER_DOWN) {
- /* Save watchdog state, and turn it off. */
- wtcon_save = readl(wdt_base + S3C2410_WTCON);
- wtdat_save = readl(wdt_base + S3C2410_WTDAT);
+ /* Save watchdog state, and turn it off. */
+ wtcon_save = readl(wdt_base + S3C2410_WTCON);
+ wtdat_save = readl(wdt_base + S3C2410_WTDAT);
- /* Note that WTCNT doesn't need to be saved. */
- s3c2410wdt_stop();
- }
+ /* Note that WTCNT doesn't need to be saved. */
+ s3c2410wdt_stop();
return 0;
}
-static int s3c2410wdt_resume(struct device *dev, u32 level)
+static int s3c2410wdt_resume(struct device *dev)
{
- if (level == RESUME_POWER_ON) {
- /* Restore watchdog state. */
+ /* Restore watchdog state. */
- writel(wtdat_save, wdt_base + S3C2410_WTDAT);
- writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */
- writel(wtcon_save, wdt_base + S3C2410_WTCON);
+ writel(wtdat_save, wdt_base + S3C2410_WTDAT);
+ writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */
+ writel(wtcon_save, wdt_base + S3C2410_WTCON);
- printk(KERN_INFO PFX "watchdog %sabled\n",
- (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis");
- }
+ printk(KERN_INFO PFX "watchdog %sabled\n",
+ (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis");
return 0;
}
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index e1df376e709ea0..2ed5c4363b5362 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -315,9 +315,9 @@ static void dbs_check_cpu(int cpu)
policy = this_dbs_info->cur_policy;
if ( init_flag == 0 ) {
- for ( /* NULL */; init_flag < NR_CPUS; init_flag++ ) {
- dbs_info = &per_cpu(cpu_dbs_info, init_flag);
- requested_freq[cpu] = dbs_info->cur_policy->cur;
+ for_each_online_cpu(j) {
+ dbs_info = &per_cpu(cpu_dbs_info, j);
+ requested_freq[j] = dbs_info->cur_policy->cur;
}
init_flag = 1;
}
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index e928cdb041cba2..8102876c7c3f2c 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -121,7 +121,7 @@ static int adm1021_write_value(struct i2c_client *client, u8 reg,
static struct adm1021_data *adm1021_update_device(struct device *dev);
/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
-static int read_only = 0;
+static int read_only;
/* This is the driver that will be inserted */
@@ -204,11 +204,10 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
client structure, even though we cannot fill it completely yet.
But it allows us to access adm1021_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct adm1021_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct adm1021_data), GFP_KERNEL))) {
err = -ENOMEM;
goto error0;
}
- memset(data, 0, sizeof(struct adm1021_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c
index 526b7ff179ebb8..3ec12421694f59 100644
--- a/drivers/hwmon/adm1025.c
+++ b/drivers/hwmon/adm1025.c
@@ -331,11 +331,10 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct adm1025_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct adm1025_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct adm1025_data));
/* The common I2C client data is placed right before the
ADM1025-specific data. */
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index 625158110fd4ff..e0f56549d1d803 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -315,7 +315,7 @@ static struct i2c_driver adm1026_driver = {
.detach_client = adm1026_detach_client,
};
-int adm1026_attach_adapter(struct i2c_adapter *adapter)
+static int adm1026_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON)) {
return 0;
@@ -323,7 +323,7 @@ int adm1026_attach_adapter(struct i2c_adapter *adapter)
return i2c_probe(adapter, &addr_data, adm1026_detect);
}
-int adm1026_detach_client(struct i2c_client *client)
+static int adm1026_detach_client(struct i2c_client *client)
{
struct adm1026_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->class_dev);
@@ -332,7 +332,7 @@ int adm1026_detach_client(struct i2c_client *client)
return 0;
}
-int adm1026_read_value(struct i2c_client *client, u8 reg)
+static int adm1026_read_value(struct i2c_client *client, u8 reg)
{
int res;
@@ -346,7 +346,7 @@ int adm1026_read_value(struct i2c_client *client, u8 reg)
return res;
}
-int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
+static int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
{
int res;
@@ -360,7 +360,7 @@ int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
return res;
}
-void adm1026_init_client(struct i2c_client *client)
+static void adm1026_init_client(struct i2c_client *client)
{
int value, i;
struct adm1026_data *data = i2c_get_clientdata(client);
@@ -460,7 +460,7 @@ void adm1026_init_client(struct i2c_client *client)
}
}
-void adm1026_print_gpio(struct i2c_client *client)
+static void adm1026_print_gpio(struct i2c_client *client)
{
struct adm1026_data *data = i2c_get_clientdata(client);
int i;
@@ -492,7 +492,7 @@ void adm1026_print_gpio(struct i2c_client *client)
}
}
-void adm1026_fixup_gpio(struct i2c_client *client)
+static void adm1026_fixup_gpio(struct i2c_client *client)
{
struct adm1026_data *data = i2c_get_clientdata(client);
int i;
@@ -1452,8 +1452,8 @@ static DEVICE_ATTR(temp1_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
static DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
static DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
-int adm1026_detect(struct i2c_adapter *adapter, int address,
- int kind)
+static int adm1026_detect(struct i2c_adapter *adapter, int address,
+ int kind)
{
int company, verstep;
struct i2c_client *new_client;
@@ -1470,13 +1470,11 @@ int adm1026_detect(struct i2c_adapter *adapter, int address,
client structure, even though we cannot fill it completely yet.
But it allows us to access adm1026_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct adm1026_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct adm1026_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct adm1026_data));
-
new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
index 58338ed7c8a1c6..7c545d5eee4570 100644
--- a/drivers/hwmon/adm1031.c
+++ b/drivers/hwmon/adm1031.c
@@ -740,11 +740,10 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct adm1031_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct adm1031_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct adm1031_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c
index bc7faef162f7b5..11dc95f8a17ea5 100644
--- a/drivers/hwmon/adm9240.c
+++ b/drivers/hwmon/adm9240.c
@@ -45,6 +45,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
+#include <linux/hwmon-sysfs.h>
#include <linux/hwmon.h>
#include <linux/hwmon-vid.h>
#include <linux/err.h>
@@ -69,8 +70,7 @@ I2C_CLIENT_INSMOD_3(adm9240, ds1780, lm81);
#define ADM9240_REG_INT(nr) (0x41 + (nr))
#define ADM9240_REG_INT_MASK(nr) (0x43 + (nr))
#define ADM9240_REG_TEMP 0x27
-#define ADM9240_REG_TEMP_HIGH 0x39
-#define ADM9240_REG_TEMP_HYST 0x3a
+#define ADM9240_REG_TEMP_MAX(nr) (0x39 + (nr)) /* 0, 1 = high, hyst */
#define ADM9240_REG_ANALOG_OUT 0x19
#define ADM9240_REG_CHASSIS_CLEAR 0x46
#define ADM9240_REG_VID_FAN_DIV 0x47
@@ -162,177 +162,155 @@ struct adm9240_data {
u8 fan_min[2]; /* rw fan1_min */
u8 fan_div[2]; /* rw fan1_div, read-only accessor */
s16 temp; /* ro temp1_input, 9-bit sign-extended */
- s8 temp_high; /* rw temp1_max */
- s8 temp_hyst; /* rw temp1_max_hyst */
+ s8 temp_max[2]; /* rw 0 -> temp_max, 1 -> temp_max_hyst */
u16 alarms; /* ro alarms */
u8 aout; /* rw aout_output */
u8 vid; /* ro vid */
u8 vrm; /* -- vrm set on startup, no accessor */
};
-/* i2c byte read/write interface */
-static int adm9240_read_value(struct i2c_client *client, u8 reg)
+/*** sysfs accessors ***/
+
+/* temperature */
+static ssize_t show_temp(struct device *dev, struct device_attribute *dummy,
+ char *buf)
{
- return i2c_smbus_read_byte_data(client, reg);
+ struct adm9240_data *data = adm9240_update_device(dev);
+ return sprintf(buf, "%d\n", data->temp * 500); /* 9-bit value */
}
-static int adm9240_write_value(struct i2c_client *client, u8 reg, u8 value)
+static ssize_t show_max(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
- return i2c_smbus_write_byte_data(client, reg, value);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adm9240_data *data = adm9240_update_device(dev);
+ return sprintf(buf, "%d\n", data->temp_max[attr->index] * 1000);
}
-/*** sysfs accessors ***/
+static ssize_t set_max(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adm9240_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_max[attr->index] = TEMP_TO_REG(val);
+ i2c_smbus_write_byte_data(client, ADM9240_REG_TEMP_MAX(attr->index),
+ data->temp_max[attr->index]);
+ up(&data->update_lock);
+ return count;
+}
-/* temperature */
-#define show_temp(value, scale) \
-static ssize_t show_##value(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- struct adm9240_data *data = adm9240_update_device(dev); \
- return sprintf(buf, "%d\n", data->value * scale); \
-}
-show_temp(temp_high, 1000);
-show_temp(temp_hyst, 1000);
-show_temp(temp, 500); /* 0.5'C per bit */
-
-#define set_temp(value, reg) \
-static ssize_t set_##value(struct device *dev, \
- struct device_attribute *attr, \
- const char *buf, size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct adm9240_data *data = adm9240_update_device(dev); \
- long temp = simple_strtoul(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->value = TEMP_TO_REG(temp); \
- adm9240_write_value(client, reg, data->value); \
- up(&data->update_lock); \
- return count; \
-}
-
-set_temp(temp_high, ADM9240_REG_TEMP_HIGH);
-set_temp(temp_hyst, ADM9240_REG_TEMP_HYST);
-
-static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
- show_temp_high, set_temp_high);
-static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
- show_temp_hyst, set_temp_hyst);
static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
+ show_max, set_max, 0);
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
+ show_max, set_max, 1);
/* voltage */
-static ssize_t show_in(struct device *dev, char *buf, int nr)
+static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct adm9240_data *data = adm9240_update_device(dev);
- return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr));
+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in[attr->index],
+ attr->index));
}
-static ssize_t show_in_min(struct device *dev, char *buf, int nr)
+static ssize_t show_in_min(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct adm9240_data *data = adm9240_update_device(dev);
- return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr));
+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[attr->index],
+ attr->index));
}
-static ssize_t show_in_max(struct device *dev, char *buf, int nr)
+static ssize_t show_in_max(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct adm9240_data *data = adm9240_update_device(dev);
- return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr));
+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[attr->index],
+ attr->index));
}
-static ssize_t set_in_min(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_in_min(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adm9240_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock);
- data->in_min[nr] = IN_TO_REG(val, nr);
- adm9240_write_value(client, ADM9240_REG_IN_MIN(nr), data->in_min[nr]);
+ data->in_min[attr->index] = IN_TO_REG(val, attr->index);
+ i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MIN(attr->index),
+ data->in_min[attr->index]);
up(&data->update_lock);
return count;
}
-static ssize_t set_in_max(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_in_max(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adm9240_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock);
- data->in_max[nr] = IN_TO_REG(val, nr);
- adm9240_write_value(client, ADM9240_REG_IN_MAX(nr), data->in_max[nr]);
+ data->in_max[attr->index] = IN_TO_REG(val, attr->index);
+ i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MAX(attr->index),
+ data->in_max[attr->index]);
up(&data->update_lock);
return count;
}
-#define show_in_offset(offset) \
-static ssize_t show_in##offset(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- return show_in(dev, buf, offset); \
-} \
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL); \
-static ssize_t show_in##offset##_min(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- return show_in_min(dev, buf, offset); \
-} \
-static ssize_t show_in##offset##_max(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- return show_in_max(dev, buf, offset); \
-} \
-static ssize_t \
-set_in##offset##_min(struct device *dev, \
- struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- return set_in_min(dev, buf, count, offset); \
-} \
-static ssize_t \
-set_in##offset##_max(struct device *dev, \
- struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- return set_in_max(dev, buf, count, offset); \
-} \
-static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
- show_in##offset##_min, set_in##offset##_min); \
-static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
- show_in##offset##_max, set_in##offset##_max);
-
-show_in_offset(0);
-show_in_offset(1);
-show_in_offset(2);
-show_in_offset(3);
-show_in_offset(4);
-show_in_offset(5);
+#define vin(nr) \
+static SENSOR_DEVICE_ATTR(in##nr##_input, S_IRUGO, \
+ show_in, NULL, nr); \
+static SENSOR_DEVICE_ATTR(in##nr##_min, S_IRUGO | S_IWUSR, \
+ show_in_min, set_in_min, nr); \
+static SENSOR_DEVICE_ATTR(in##nr##_max, S_IRUGO | S_IWUSR, \
+ show_in_max, set_in_max, nr);
+
+vin(0);
+vin(1);
+vin(2);
+vin(3);
+vin(4);
+vin(5);
/* fans */
-static ssize_t show_fan(struct device *dev, char *buf, int nr)
+static ssize_t show_fan(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct adm9240_data *data = adm9240_update_device(dev);
- return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
- 1 << data->fan_div[nr]));
+ return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index],
+ 1 << data->fan_div[attr->index]));
}
-static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_min(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct adm9240_data *data = adm9240_update_device(dev);
- return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
- 1 << data->fan_div[nr]));
+ return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[attr->index],
+ 1 << data->fan_div[attr->index]));
}
-static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_div(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct adm9240_data *data = adm9240_update_device(dev);
- return sprintf(buf, "%d\n", 1 << data->fan_div[nr]);
+ return sprintf(buf, "%d\n", 1 << data->fan_div[attr->index]);
}
/* write new fan div, callers must hold data->update_lock */
@@ -341,16 +319,16 @@ static void adm9240_write_fan_div(struct i2c_client *client, int nr,
{
u8 reg, old, shift = (nr + 2) * 2;
- reg = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV);
+ reg = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV);
old = (reg >> shift) & 3;
reg &= ~(3 << shift);
reg |= (fan_div << shift);
- adm9240_write_value(client, ADM9240_REG_VID_FAN_DIV, reg);
+ i2c_smbus_write_byte_data(client, ADM9240_REG_VID_FAN_DIV, reg);
dev_dbg(&client->dev, "fan%d clock divider changed from %u "
"to %u\n", nr + 1, 1 << old, 1 << fan_div);
}
-/*
+/*
* set fan speed low limit:
*
* - value is zero: disable fan speed low limit alarm
@@ -361,12 +339,15 @@ static void adm9240_write_fan_div(struct i2c_client *client, int nr,
* - otherwise: select fan clock divider to suit fan speed low limit,
* measurement code may adjust registers to ensure fan speed reading
*/
-static ssize_t set_fan_min(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_fan_min(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adm9240_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10);
+ int nr = attr->index;
u8 new_div;
down(&data->update_lock);
@@ -406,50 +387,27 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
data->fan_div[nr] = new_div;
adm9240_write_fan_div(client, nr, new_div);
}
- adm9240_write_value(client, ADM9240_REG_FAN_MIN(nr),
+ i2c_smbus_write_byte_data(client, ADM9240_REG_FAN_MIN(nr),
data->fan_min[nr]);
up(&data->update_lock);
return count;
}
-#define show_fan_offset(offset) \
-static ssize_t show_fan_##offset (struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
-return show_fan(dev, buf, offset - 1); \
-} \
-static ssize_t show_fan_##offset##_div (struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
-return show_fan_div(dev, buf, offset - 1); \
-} \
-static ssize_t show_fan_##offset##_min (struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
-return show_fan_min(dev, buf, offset - 1); \
-} \
-static ssize_t set_fan_##offset##_min (struct device *dev, \
- struct device_attribute *attr, \
- const char *buf, size_t count) \
-{ \
-return set_fan_min(dev, buf, count, offset - 1); \
-} \
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
- show_fan_##offset, NULL); \
-static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
- show_fan_##offset##_div, NULL); \
-static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
- show_fan_##offset##_min, set_fan_##offset##_min);
-
-show_fan_offset(1);
-show_fan_offset(2);
+#define fan(nr) \
+static SENSOR_DEVICE_ATTR(fan##nr##_input, S_IRUGO, \
+ show_fan, NULL, nr - 1); \
+static SENSOR_DEVICE_ATTR(fan##nr##_div, S_IRUGO, \
+ show_fan_div, NULL, nr - 1); \
+static SENSOR_DEVICE_ATTR(fan##nr##_min, S_IRUGO | S_IWUSR, \
+ show_fan_min, set_fan_min, nr - 1);
+
+fan(1);
+fan(2);
/* alarms */
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct adm9240_data *data = adm9240_update_device(dev);
return sprintf(buf, "%u\n", data->alarms);
@@ -457,7 +415,8 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
/* vid */
-static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_vid(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct adm9240_data *data = adm9240_update_device(dev);
return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
@@ -465,13 +424,16 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
/* analog output */
-static ssize_t show_aout(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_aout(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct adm9240_data *data = adm9240_update_device(dev);
return sprintf(buf, "%d\n", AOUT_FROM_REG(data->aout));
}
-static ssize_t set_aout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_aout(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct adm9240_data *data = i2c_get_clientdata(client);
@@ -479,20 +441,23 @@ static ssize_t set_aout(struct device *dev, struct device_attribute *attr, const
down(&data->update_lock);
data->aout = AOUT_TO_REG(val);
- adm9240_write_value(client, ADM9240_REG_ANALOG_OUT, data->aout);
+ i2c_smbus_write_byte_data(client, ADM9240_REG_ANALOG_OUT, data->aout);
up(&data->update_lock);
return count;
}
static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout);
/* chassis_clear */
-static ssize_t chassis_clear(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t chassis_clear(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
unsigned long val = simple_strtol(buf, NULL, 10);
if (val == 1) {
- adm9240_write_value(client, ADM9240_REG_CHASSIS_CLEAR, 0x80);
+ i2c_smbus_write_byte_data(client,
+ ADM9240_REG_CHASSIS_CLEAR, 0x80);
dev_dbg(&client->dev, "chassis intrusion latch cleared\n");
}
return count;
@@ -513,11 +478,10 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct adm9240_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(*data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct adm9240_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -533,7 +497,7 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
if (kind < 0) {
/* verify chip: reg address should match i2c address */
- if (adm9240_read_value(new_client, ADM9240_REG_I2C_ADDR)
+ if (i2c_smbus_read_byte_data(new_client, ADM9240_REG_I2C_ADDR)
!= address) {
dev_err(&adapter->dev, "detect fail: address match, "
"0x%02x\n", address);
@@ -541,8 +505,8 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* check known chip manufacturer */
- man_id = adm9240_read_value(new_client, ADM9240_REG_MAN_ID);
-
+ man_id = i2c_smbus_read_byte_data(new_client,
+ ADM9240_REG_MAN_ID);
if (man_id == 0x23) {
kind = adm9240;
} else if (man_id == 0xda) {
@@ -556,7 +520,8 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* successful detect, print chip info */
- die_rev = adm9240_read_value(new_client, ADM9240_REG_DIE_REV);
+ die_rev = i2c_smbus_read_byte_data(new_client,
+ ADM9240_REG_DIE_REV);
dev_info(&adapter->dev, "found %s revision %u\n",
man_id == 0x23 ? "ADM9240" :
man_id == 0xda ? "DS1780" : "LM81", die_rev);
@@ -588,33 +553,59 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
goto exit_detach;
}
- device_create_file(&new_client->dev, &dev_attr_in0_input);
- device_create_file(&new_client->dev, &dev_attr_in0_min);
- device_create_file(&new_client->dev, &dev_attr_in0_max);
- device_create_file(&new_client->dev, &dev_attr_in1_input);
- device_create_file(&new_client->dev, &dev_attr_in1_min);
- device_create_file(&new_client->dev, &dev_attr_in1_max);
- device_create_file(&new_client->dev, &dev_attr_in2_input);
- device_create_file(&new_client->dev, &dev_attr_in2_min);
- device_create_file(&new_client->dev, &dev_attr_in2_max);
- device_create_file(&new_client->dev, &dev_attr_in3_input);
- device_create_file(&new_client->dev, &dev_attr_in3_min);
- device_create_file(&new_client->dev, &dev_attr_in3_max);
- device_create_file(&new_client->dev, &dev_attr_in4_input);
- device_create_file(&new_client->dev, &dev_attr_in4_min);
- device_create_file(&new_client->dev, &dev_attr_in4_max);
- device_create_file(&new_client->dev, &dev_attr_in5_input);
- device_create_file(&new_client->dev, &dev_attr_in5_min);
- device_create_file(&new_client->dev, &dev_attr_in5_max);
- device_create_file(&new_client->dev, &dev_attr_temp1_max);
- device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in0_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in0_min.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in0_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in1_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in1_min.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in1_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in2_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in2_min.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in2_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in3_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in3_min.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in3_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in4_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in4_min.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in4_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in5_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in5_min.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in5_max.dev_attr);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
- device_create_file(&new_client->dev, &dev_attr_fan1_input);
- device_create_file(&new_client->dev, &dev_attr_fan1_div);
- device_create_file(&new_client->dev, &dev_attr_fan1_min);
- device_create_file(&new_client->dev, &dev_attr_fan2_input);
- device_create_file(&new_client->dev, &dev_attr_fan2_div);
- device_create_file(&new_client->dev, &dev_attr_fan2_min);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp1_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp1_max_hyst.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_fan1_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_fan1_div.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_fan1_min.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_fan2_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_fan2_div.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_fan2_min.dev_attr);
device_create_file(&new_client->dev, &dev_attr_alarms);
device_create_file(&new_client->dev, &dev_attr_aout_output);
device_create_file(&new_client->dev, &dev_attr_chassis_clear);
@@ -654,8 +645,8 @@ static int adm9240_detach_client(struct i2c_client *client)
static void adm9240_init_client(struct i2c_client *client)
{
struct adm9240_data *data = i2c_get_clientdata(client);
- u8 conf = adm9240_read_value(client, ADM9240_REG_CONFIG);
- u8 mode = adm9240_read_value(client, ADM9240_REG_TEMP_CONF) & 3;
+ u8 conf = i2c_smbus_read_byte_data(client, ADM9240_REG_CONFIG);
+ u8 mode = i2c_smbus_read_byte_data(client, ADM9240_REG_TEMP_CONF) & 3;
data->vrm = vid_which_vrm(); /* need this to report vid as mV */
@@ -672,18 +663,22 @@ static void adm9240_init_client(struct i2c_client *client)
for (i = 0; i < 6; i++)
{
- adm9240_write_value(client,
+ i2c_smbus_write_byte_data(client,
ADM9240_REG_IN_MIN(i), 0);
- adm9240_write_value(client,
+ i2c_smbus_write_byte_data(client,
ADM9240_REG_IN_MAX(i), 255);
}
- adm9240_write_value(client, ADM9240_REG_FAN_MIN(0), 255);
- adm9240_write_value(client, ADM9240_REG_FAN_MIN(1), 255);
- adm9240_write_value(client, ADM9240_REG_TEMP_HIGH, 127);
- adm9240_write_value(client, ADM9240_REG_TEMP_HYST, 127);
+ i2c_smbus_write_byte_data(client,
+ ADM9240_REG_FAN_MIN(0), 255);
+ i2c_smbus_write_byte_data(client,
+ ADM9240_REG_FAN_MIN(1), 255);
+ i2c_smbus_write_byte_data(client,
+ ADM9240_REG_TEMP_MAX(0), 127);
+ i2c_smbus_write_byte_data(client,
+ ADM9240_REG_TEMP_MAX(1), 127);
/* start measurement cycle */
- adm9240_write_value(client, ADM9240_REG_CONFIG, 1);
+ i2c_smbus_write_byte_data(client, ADM9240_REG_CONFIG, 1);
dev_info(&client->dev, "cold start: config was 0x%02x "
"mode %u\n", conf, mode);
@@ -704,25 +699,25 @@ static struct adm9240_data *adm9240_update_device(struct device *dev)
for (i = 0; i < 6; i++) /* read voltages */
{
- data->in[i] = adm9240_read_value(client,
+ data->in[i] = i2c_smbus_read_byte_data(client,
ADM9240_REG_IN(i));
}
- data->alarms = adm9240_read_value(client,
+ data->alarms = i2c_smbus_read_byte_data(client,
ADM9240_REG_INT(0)) |
- adm9240_read_value(client,
+ i2c_smbus_read_byte_data(client,
ADM9240_REG_INT(1)) << 8;
/* read temperature: assume temperature changes less than
* 0.5'C per two measurement cycles thus ignore possible
* but unlikely aliasing error on lsb reading. --Grant */
- data->temp = ((adm9240_read_value(client,
+ data->temp = ((i2c_smbus_read_byte_data(client,
ADM9240_REG_TEMP) << 8) |
- adm9240_read_value(client,
+ i2c_smbus_read_byte_data(client,
ADM9240_REG_TEMP_CONF)) / 128;
for (i = 0; i < 2; i++) /* read fans */
{
- data->fan[i] = adm9240_read_value(client,
+ data->fan[i] = i2c_smbus_read_byte_data(client,
ADM9240_REG_FAN(i));
/* adjust fan clock divider on overflow */
@@ -747,30 +742,30 @@ static struct adm9240_data *adm9240_update_device(struct device *dev)
for (i = 0; i < 6; i++)
{
- data->in_min[i] = adm9240_read_value(client,
+ data->in_min[i] = i2c_smbus_read_byte_data(client,
ADM9240_REG_IN_MIN(i));
- data->in_max[i] = adm9240_read_value(client,
+ data->in_max[i] = i2c_smbus_read_byte_data(client,
ADM9240_REG_IN_MAX(i));
}
for (i = 0; i < 2; i++)
{
- data->fan_min[i] = adm9240_read_value(client,
+ data->fan_min[i] = i2c_smbus_read_byte_data(client,
ADM9240_REG_FAN_MIN(i));
}
- data->temp_high = adm9240_read_value(client,
- ADM9240_REG_TEMP_HIGH);
- data->temp_hyst = adm9240_read_value(client,
- ADM9240_REG_TEMP_HYST);
+ data->temp_max[0] = i2c_smbus_read_byte_data(client,
+ ADM9240_REG_TEMP_MAX(0));
+ data->temp_max[1] = i2c_smbus_read_byte_data(client,
+ ADM9240_REG_TEMP_MAX(1));
/* read fan divs and 5-bit VID */
- i = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV);
+ i = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV);
data->fan_div[0] = (i >> 4) & 3;
data->fan_div[1] = (i >> 6) & 3;
data->vid = i & 0x0f;
- data->vid |= (adm9240_read_value(client,
+ data->vid |= (i2c_smbus_read_byte_data(client,
ADM9240_REG_VID4) & 1) << 4;
/* read analog out */
- data->aout = adm9240_read_value(client,
+ data->aout = i2c_smbus_read_byte_data(client,
ADM9240_REG_ANALOG_OUT);
data->last_updated_config = jiffies;
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index 8e34855a627406..52c469722a6584 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -629,19 +629,17 @@ static int asb100_detect_subclients(struct i2c_adapter *adapter, int address,
int i, id, err;
struct asb100_data *data = i2c_get_clientdata(new_client);
- data->lm75[0] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!(data->lm75[0])) {
err = -ENOMEM;
goto ERROR_SC_0;
}
- memset(data->lm75[0], 0x00, sizeof(struct i2c_client));
- data->lm75[1] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ data->lm75[1] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!(data->lm75[1])) {
err = -ENOMEM;
goto ERROR_SC_1;
}
- memset(data->lm75[1], 0x00, sizeof(struct i2c_client));
id = i2c_adapter_id(adapter);
@@ -724,12 +722,11 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
client structure, even though we cannot fill it completely yet.
But it allows us to access asb100_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct asb100_data), GFP_KERNEL))) {
- pr_debug("asb100.o: detect failed, kmalloc failed!\n");
+ if (!(data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL))) {
+ pr_debug("asb100.o: detect failed, kzalloc failed!\n");
err = -ENOMEM;
goto ERROR0;
}
- memset(data, 0, sizeof(struct asb100_data));
new_client = &data->client;
init_MUTEX(&data->lock);
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index deb4d34c9539ba..53324f56404e2c 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -253,6 +253,8 @@ static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2);
static int atxp1_attach_adapter(struct i2c_adapter *adapter)
{
+ if (!(adapter->class & I2C_CLASS_HWMON))
+ return 0;
return i2c_probe(adapter, &addr_data, &atxp1_detect);
};
@@ -266,12 +268,11 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct atxp1_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct atxp1_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct atxp1_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index b0199e063d0ebf..34f71b7c7f3786 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -180,12 +180,14 @@ static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
static int ds1621_attach_adapter(struct i2c_adapter *adapter)
{
+ if (!(adapter->class & I2C_CLASS_HWMON))
+ return 0;
return i2c_probe(adapter, &addr_data, ds1621_detect);
}
/* This function is called by i2c_probe */
-int ds1621_detect(struct i2c_adapter *adapter, int address,
- int kind)
+static int ds1621_detect(struct i2c_adapter *adapter, int address,
+ int kind)
{
int conf, temp;
struct i2c_client *new_client;
@@ -200,11 +202,10 @@ int ds1621_detect(struct i2c_adapter *adapter, int address,
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet.
But it allows us to access ds1621_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct ds1621_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct ds1621_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct ds1621_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c
index eef6061d786b4e..a02e1c34c757db 100644
--- a/drivers/hwmon/fscher.c
+++ b/drivers/hwmon/fscher.c
@@ -303,11 +303,10 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
/* OK. For now, we presume we have a valid client. We now create the
* client structure, even though we cannot fill it completely yet.
* But it allows us to access i2c_smbus_read_byte_data. */
- if (!(data = kmalloc(sizeof(struct fscher_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct fscher_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct fscher_data));
/* The common I2C client data is placed right before the
* Hermes-specific data. */
diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c
index 5fc77a5fed07b4..64e4edc64f8d40 100644
--- a/drivers/hwmon/fscpos.c
+++ b/drivers/hwmon/fscpos.c
@@ -438,7 +438,7 @@ static int fscpos_attach_adapter(struct i2c_adapter *adapter)
return i2c_probe(adapter, &addr_data, fscpos_detect);
}
-int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
+static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
struct fscpos_data *data;
@@ -453,11 +453,10 @@ int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
* But it allows us to access fscpos_{read,write}_value.
*/
- if (!(data = kmalloc(sizeof(struct fscpos_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct fscpos_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct fscpos_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c
index 256b9323c84b1e..2f178dbe3d87f5 100644
--- a/drivers/hwmon/gl518sm.c
+++ b/drivers/hwmon/gl518sm.c
@@ -365,11 +365,10 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
client structure, even though we cannot fill it completely yet.
But it allows us to access gl518_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct gl518_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct gl518_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct gl518_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c
index 12fd757066fc9c..c39ba12394260f 100644
--- a/drivers/hwmon/gl520sm.c
+++ b/drivers/hwmon/gl520sm.c
@@ -536,11 +536,10 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
client structure, even though we cannot fill it completely yet.
But it allows us to access gl520_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct gl520_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct gl520_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct gl520_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index 7f0107613827bc..0015da5668a181 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -296,11 +296,9 @@ static int hdaps_probe(struct device *dev)
return 0;
}
-static int hdaps_resume(struct device *dev, u32 level)
+static int hdaps_resume(struct device *dev)
{
- if (level == RESUME_ENABLE)
- return hdaps_device_init();
- return 0;
+ return hdaps_device_init();
}
static struct device_driver hdaps_driver = {
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 9b41c9bd805f56..6f48579799b588 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -45,7 +45,7 @@ struct class_device *hwmon_device_register(struct device *dev)
return ERR_PTR(-ENOMEM);
id = id & MAX_ID_MASK;
- cdev = class_device_create(hwmon_class, MKDEV(0,0), dev,
+ cdev = class_device_create(hwmon_class, NULL, MKDEV(0,0), dev,
HWMON_ID_FORMAT, id);
if (IS_ERR(cdev))
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 53cc2b6d63854a..6c41e25e670be0 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -2,7 +2,7 @@
it87.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring.
- Supports: IT8705F Super I/O chip w/LPC interface & SMBus
+ Supports: IT8705F Super I/O chip w/LPC interface
IT8712F Super I/O chip w/LPC interface & SMBus
Sis950 A clone of the IT8705F
@@ -47,7 +47,7 @@
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
0x2e, 0x2f, I2C_CLIENT_END };
-static unsigned short isa_address = 0x290;
+static unsigned short isa_address;
/* Insmod parameters */
I2C_CLIENT_INSMOD_2(it87, it8712);
@@ -706,7 +706,7 @@ static int it87_isa_attach_adapter(struct i2c_adapter *adapter)
}
/* SuperIO detection - will change isa_address if a chip is found */
-static int __init it87_find(int *address)
+static int __init it87_find(unsigned short *address)
{
int err = -ENODEV;
@@ -738,7 +738,7 @@ exit:
}
/* This function is called by i2c_probe */
-int it87_detect(struct i2c_adapter *adapter, int address, int kind)
+static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
{
int i;
struct i2c_client *new_client;
@@ -757,42 +757,14 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
if (!request_region(address, IT87_EXTENT, it87_isa_driver.name))
goto ERROR0;
- /* Probe whether there is anything available on this address. Already
- done for SMBus and Super-I/O clients */
- if (kind < 0) {
- if (is_isa && !chip_type) {
-#define REALLY_SLOW_IO
- /* We need the timeouts for at least some IT87-like chips. But only
- if we read 'undefined' registers. */
- i = inb_p(address + 1);
- if (inb_p(address + 2) != i
- || inb_p(address + 3) != i
- || inb_p(address + 7) != i) {
- err = -ENODEV;
- goto ERROR1;
- }
-#undef REALLY_SLOW_IO
-
- /* Let's just hope nothing breaks here */
- i = inb_p(address + 5) & 0x7f;
- outb_p(~i & 0x7f, address + 5);
- if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
- outb_p(i, address + 5);
- err = -ENODEV;
- goto ERROR1;
- }
- }
- }
-
- /* OK. For now, we presume we have a valid client. We now create the
+ /* For now, we presume we have a valid client. We create the
client structure, even though we cannot fill it completely yet.
But it allows us to access it87_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct it87_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct it87_data), GFP_KERNEL))) {
err = -ENOMEM;
goto ERROR1;
}
- memset(data, 0, sizeof(struct it87_data));
new_client = &data->client;
if (is_isa)
@@ -1182,20 +1154,18 @@ static struct it87_data *it87_update_device(struct device *dev)
static int __init sm_it87_init(void)
{
- int addr, res;
-
- if (!it87_find(&addr)) {
- isa_address = addr;
- }
+ int res;
res = i2c_add_driver(&it87_driver);
if (res)
return res;
- res = i2c_isa_add_driver(&it87_isa_driver);
- if (res) {
- i2c_del_driver(&it87_driver);
- return res;
+ if (!it87_find(&isa_address)) {
+ res = i2c_isa_add_driver(&it87_isa_driver);
+ if (res) {
+ i2c_del_driver(&it87_driver);
+ return res;
+ }
}
return 0;
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index be5c7095ecbb26..954ec249724974 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -375,11 +375,10 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct lm63_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct lm63_data));
/* The common I2C client data is placed right before the
LM63-specific data. */
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index 9a3ebdf583f403..d70f4c8fc1e683 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -127,11 +127,10 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet.
But it allows us to access lm75_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct lm75_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm75_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct lm75_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index 866eab96a6f6f6..9380fda7dcd129 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -226,11 +226,10 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet.
But it allows us to access lm77_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct lm77_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm77_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct lm77_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index f6730dc3573b68..bde0cda9477e1a 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -480,7 +480,7 @@ static int lm78_isa_attach_adapter(struct i2c_adapter *adapter)
}
/* This function is called by i2c_probe */
-int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
+static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
{
int i, err;
struct i2c_client *new_client;
@@ -540,11 +540,10 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
client structure, even though we cannot fill it completely yet.
But it allows us to access lm78_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct lm78_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm78_data), GFP_KERNEL))) {
err = -ENOMEM;
goto ERROR1;
}
- memset(data, 0, sizeof(struct lm78_data));
new_client = &data->client;
if (is_isa)
@@ -726,7 +725,6 @@ static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value)
return i2c_smbus_write_byte_data(client, reg, value);
}
-/* Called when we have found a new LM78. It should set limits, etc. */
static void lm78_init_client(struct i2c_client *client)
{
u8 config = lm78_read_value(client, LM78_REG_CONFIG);
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index 83af8b3a0cac02..c359fdea211edd 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -393,7 +393,7 @@ static int lm80_attach_adapter(struct i2c_adapter *adapter)
return i2c_probe(adapter, &addr_data, lm80_detect);
}
-int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
+static int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
{
int i, cur;
struct i2c_client *new_client;
@@ -407,11 +407,10 @@ int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet.
But it allows us to access lm80_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct lm80_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm80_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct lm80_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index d74b2c20c71937..9a70611a9f69ed 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -230,11 +230,10 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct lm83_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm83_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct lm83_data));
/* The common I2C client data is placed right after the
* LM83-specific data. */
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index ab214df9624bc4..d1070ed2bee617 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -1007,14 +1007,14 @@ temp_auto(1);
temp_auto(2);
temp_auto(3);
-int lm85_attach_adapter(struct i2c_adapter *adapter)
+static int lm85_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, lm85_detect);
}
-int lm85_detect(struct i2c_adapter *adapter, int address,
+static int lm85_detect(struct i2c_adapter *adapter, int address,
int kind)
{
int company, verstep ;
@@ -1033,11 +1033,10 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
client structure, even though we cannot fill it completely yet.
But it allows us to access lm85_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct lm85_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm85_data), GFP_KERNEL))) {
err = -ENOMEM;
goto ERROR0;
}
- memset(data, 0, sizeof(struct lm85_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -1236,7 +1235,7 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
return err;
}
-int lm85_detach_client(struct i2c_client *client)
+static int lm85_detach_client(struct i2c_client *client)
{
struct lm85_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->class_dev);
@@ -1246,7 +1245,7 @@ int lm85_detach_client(struct i2c_client *client)
}
-int lm85_read_value(struct i2c_client *client, u8 reg)
+static int lm85_read_value(struct i2c_client *client, u8 reg)
{
int res;
@@ -1276,7 +1275,7 @@ int lm85_read_value(struct i2c_client *client, u8 reg)
return res ;
}
-int lm85_write_value(struct i2c_client *client, u8 reg, int value)
+static int lm85_write_value(struct i2c_client *client, u8 reg, int value)
{
int res ;
@@ -1305,7 +1304,7 @@ int lm85_write_value(struct i2c_client *client, u8 reg, int value)
return res ;
}
-void lm85_init_client(struct i2c_client *client)
+static void lm85_init_client(struct i2c_client *client)
{
int value;
struct lm85_data *data = i2c_get_clientdata(client);
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index dca996de4c331e..eeec18177861ca 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -554,11 +554,10 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct lm87_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm87_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct lm87_data));
/* The common I2C client data is placed right before the
LM87-specific data. */
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index 14de05fcd431e7..83cf2e1b09f547 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -31,7 +31,7 @@
* Devices. That chip is similar to the LM90, with a few differences
* that are not handled by this driver. Complete datasheet can be
* obtained from Analog's website at:
- * http://products.analog.com/products/info.asp?product=ADM1032
+ * http://www.analog.com/en/prod/0,2877,ADM1032,00.html
* Among others, it has a higher accuracy than the LM90, much like the
* LM86 does.
*
@@ -49,7 +49,7 @@
* register values are decoded differently) it is ignored by this
* driver. Complete datasheet can be obtained from Analog's website
* at:
- * http://products.analog.com/products/info.asp?product=ADT7461
+ * http://www.analog.com/en/prod/0,2877,ADT7461,00.html
*
* Since the LM90 was the first chipset supported by this driver, most
* comments will refer to this chipset, but are actually general and
@@ -83,10 +83,10 @@
* Addresses to scan
* Address is fully defined internally and cannot be changed except for
* MAX6659.
- * LM86, LM89, LM90, LM99, ADM1032, MAX6657 and MAX6658 have address 0x4c.
- * LM89-1, and LM99-1 have address 0x4d.
+ * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, MAX6657 and MAX6658
+ * have address 0x4c.
+ * ADM1032-2, ADT7461-2, LM89-1, and LM99-1 have address 0x4d.
* MAX6659 can have address 0x4c, 0x4d or 0x4e (unsupported).
- * ADT7461 always has address 0x4c.
*/
static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END };
@@ -345,10 +345,74 @@ static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst,
static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4);
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+/* pec used for ADM1032 only */
+static ssize_t show_pec(struct device *dev, struct device_attribute *dummy,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ return sprintf(buf, "%d\n", !!(client->flags & I2C_CLIENT_PEC));
+}
+
+static ssize_t set_pec(struct device *dev, struct device_attribute *dummy,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ long val = simple_strtol(buf, NULL, 10);
+
+ switch (val) {
+ case 0:
+ client->flags &= ~I2C_CLIENT_PEC;
+ break;
+ case 1:
+ client->flags |= I2C_CLIENT_PEC;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(pec, S_IWUSR | S_IRUGO, show_pec, set_pec);
+
/*
* Real code
*/
+/* The ADM1032 supports PEC but not on write byte transactions, so we need
+ to explicitely ask for a transaction without PEC. */
+static inline s32 adm1032_write_byte(struct i2c_client *client, u8 value)
+{
+ return i2c_smbus_xfer(client->adapter, client->addr,
+ client->flags & ~I2C_CLIENT_PEC,
+ I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
+}
+
+/* It is assumed that client->update_lock is held (unless we are in
+ detection or initialization steps). This matters when PEC is enabled,
+ because we don't want the address pointer to change between the write
+ byte and the read byte transactions. */
+static int lm90_read_reg(struct i2c_client* client, u8 reg, u8 *value)
+{
+ int err;
+
+ if (client->flags & I2C_CLIENT_PEC) {
+ err = adm1032_write_byte(client, reg);
+ if (err >= 0)
+ err = i2c_smbus_read_byte(client);
+ } else
+ err = i2c_smbus_read_byte_data(client, reg);
+
+ if (err < 0) {
+ dev_warn(&client->dev, "Register %#02x read failed (%d)\n",
+ reg, err);
+ return err;
+ }
+ *value = err;
+
+ return 0;
+}
+
static int lm90_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
@@ -370,11 +434,10 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct lm90_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm90_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct lm90_data));
/* The common I2C client data is placed right before the
LM90-specific data. */
@@ -403,20 +466,22 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
if (kind < 0) { /* detection and identification */
u8 man_id, chip_id, reg_config1, reg_convrate;
- man_id = i2c_smbus_read_byte_data(new_client,
- LM90_REG_R_MAN_ID);
- chip_id = i2c_smbus_read_byte_data(new_client,
- LM90_REG_R_CHIP_ID);
- reg_config1 = i2c_smbus_read_byte_data(new_client,
- LM90_REG_R_CONFIG1);
- reg_convrate = i2c_smbus_read_byte_data(new_client,
- LM90_REG_R_CONVRATE);
+ if (lm90_read_reg(new_client, LM90_REG_R_MAN_ID,
+ &man_id) < 0
+ || lm90_read_reg(new_client, LM90_REG_R_CHIP_ID,
+ &chip_id) < 0
+ || lm90_read_reg(new_client, LM90_REG_R_CONFIG1,
+ &reg_config1) < 0
+ || lm90_read_reg(new_client, LM90_REG_R_CONVRATE,
+ &reg_convrate) < 0)
+ goto exit_free;
if (man_id == 0x01) { /* National Semiconductor */
u8 reg_config2;
- reg_config2 = i2c_smbus_read_byte_data(new_client,
- LM90_REG_R_CONFIG2);
+ if (lm90_read_reg(new_client, LM90_REG_R_CONFIG2,
+ &reg_config2) < 0)
+ goto exit_free;
if ((reg_config1 & 0x2A) == 0x00
&& (reg_config2 & 0xF8) == 0x00
@@ -435,14 +500,12 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
}
} else
if (man_id == 0x41) { /* Analog Devices */
- if (address == 0x4C
- && (chip_id & 0xF0) == 0x40 /* ADM1032 */
+ if ((chip_id & 0xF0) == 0x40 /* ADM1032 */
&& (reg_config1 & 0x3F) == 0x00
&& reg_convrate <= 0x0A) {
kind = adm1032;
} else
- if (address == 0x4c
- && chip_id == 0x51 /* ADT7461 */
+ if (chip_id == 0x51 /* ADT7461 */
&& (reg_config1 & 0x1F) == 0x00 /* check compat mode */
&& reg_convrate <= 0x0A) {
kind = adt7461;
@@ -477,6 +540,10 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
name = "lm90";
} else if (kind == adm1032) {
name = "adm1032";
+ /* The ADM1032 supports PEC, but only if combined
+ transactions are not used. */
+ if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
+ new_client->flags |= I2C_CLIENT_PEC;
} else if (kind == lm99) {
name = "lm99";
} else if (kind == lm86) {
@@ -529,6 +596,9 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
&sensor_dev_attr_temp2_crit_hyst.dev_attr);
device_create_file(&new_client->dev, &dev_attr_alarms);
+ if (new_client->flags & I2C_CLIENT_PEC)
+ device_create_file(&new_client->dev, &dev_attr_pec);
+
return 0;
exit_detach:
@@ -548,7 +618,10 @@ static void lm90_init_client(struct i2c_client *client)
*/
i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE,
5); /* 2 Hz */
- config = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG1);
+ if (lm90_read_reg(client, LM90_REG_R_CONFIG1, &config) < 0) {
+ dev_warn(&client->dev, "Initialization failed!\n");
+ return;
+ }
if (config & 0x40)
i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
config & 0xBF); /* run */
@@ -576,21 +649,15 @@ static struct lm90_data *lm90_update_device(struct device *dev)
down(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
- u8 oldh, newh;
+ u8 oldh, newh, l;
dev_dbg(&client->dev, "Updating lm90 data.\n");
- data->temp8[0] = i2c_smbus_read_byte_data(client,
- LM90_REG_R_LOCAL_TEMP);
- data->temp8[1] = i2c_smbus_read_byte_data(client,
- LM90_REG_R_LOCAL_LOW);
- data->temp8[2] = i2c_smbus_read_byte_data(client,
- LM90_REG_R_LOCAL_HIGH);
- data->temp8[3] = i2c_smbus_read_byte_data(client,
- LM90_REG_R_LOCAL_CRIT);
- data->temp8[4] = i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_CRIT);
- data->temp_hyst = i2c_smbus_read_byte_data(client,
- LM90_REG_R_TCRIT_HYST);
+ lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP, &data->temp8[0]);
+ lm90_read_reg(client, LM90_REG_R_LOCAL_LOW, &data->temp8[1]);
+ lm90_read_reg(client, LM90_REG_R_LOCAL_HIGH, &data->temp8[2]);
+ lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT, &data->temp8[3]);
+ lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[4]);
+ lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst);
/*
* There is a trick here. We have to read two registers to
@@ -606,36 +673,20 @@ static struct lm90_data *lm90_update_device(struct device *dev)
* then we have a valid reading. Else we have to read the low
* byte again, and now we believe we have a correct reading.
*/
- oldh = i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_TEMPH);
- data->temp11[0] = i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_TEMPL);
- newh = i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_TEMPH);
- if (newh != oldh) {
- data->temp11[0] = i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_TEMPL);
-#ifdef DEBUG
- oldh = i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_TEMPH);
- /* oldh is actually newer */
- if (newh != oldh)
- dev_warn(&client->dev, "Remote temperature may be "
- "wrong.\n");
-#endif
- }
- data->temp11[0] |= (newh << 8);
-
- data->temp11[1] = (i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_LOWH) << 8) +
- i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_LOWL);
- data->temp11[2] = (i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_HIGHH) << 8) +
- i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_HIGHL);
- data->alarms = i2c_smbus_read_byte_data(client,
- LM90_REG_R_STATUS);
+ if (lm90_read_reg(client, LM90_REG_R_REMOTE_TEMPH, &oldh) == 0
+ && lm90_read_reg(client, LM90_REG_R_REMOTE_TEMPL, &l) == 0
+ && lm90_read_reg(client, LM90_REG_R_REMOTE_TEMPH, &newh) == 0
+ && (newh == oldh
+ || lm90_read_reg(client, LM90_REG_R_REMOTE_TEMPL, &l) == 0))
+ data->temp11[0] = (newh << 8) | l;
+
+ if (lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &newh) == 0
+ && lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL, &l) == 0)
+ data->temp11[1] = (newh << 8) | l;
+ if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &newh) == 0
+ && lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL, &l) == 0)
+ data->temp11[2] = (newh << 8) | l;
+ lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms);
data->last_updated = jiffies;
data->valid = 1;
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c
index 647b7c7cd575df..7a4b3701ed1a5c 100644
--- a/drivers/hwmon/lm92.c
+++ b/drivers/hwmon/lm92.c
@@ -300,11 +300,10 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
| I2C_FUNC_SMBUS_WORD_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct lm92_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm92_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct lm92_data));
/* Fill in enough client fields so that we can read from the chip,
which is required for identication */
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c
index 16bf71f3a04d94..6a82ffae1bfd6a 100644
--- a/drivers/hwmon/max1619.c
+++ b/drivers/hwmon/max1619.c
@@ -197,11 +197,10 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct max1619_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct max1619_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct max1619_data));
/* The common I2C client data is placed right before the
MAX1619-specific data. */
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index cf2a35799c7ce5..17f745a23d0498 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -754,9 +754,8 @@ static int pc87360_detect(struct i2c_adapter *adapter)
const char *name = "pc87360";
int use_thermistors = 0;
- if (!(data = kmalloc(sizeof(struct pc87360_data), GFP_KERNEL)))
+ if (!(data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL)))
return -ENOMEM;
- memset(data, 0x00, sizeof(struct pc87360_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 21aa9a41f62cbc..9c6cadec108713 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -518,11 +518,10 @@ static int sis5595_detect(struct i2c_adapter *adapter)
goto exit_release;
}
- if (!(data = kmalloc(sizeof(struct sis5595_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct sis5595_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit_release;
}
- memset(data, 0, sizeof(struct sis5595_data));
new_client = &data->client;
new_client->addr = address;
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index 7fe71576dea4b7..2a3e21b5b6b444 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -244,11 +244,10 @@ static int smsc47b397_detect(struct i2c_adapter *adapter)
return -EBUSY;
}
- if (!(data = kmalloc(sizeof(struct smsc47b397_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct smsc47b397_data), GFP_KERNEL))) {
err = -ENOMEM;
goto error_release;
}
- memset(data, 0x00, sizeof(struct smsc47b397_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -299,7 +298,7 @@ static int __init smsc47b397_find(unsigned short *addr)
superio_enter();
id = superio_inb(SUPERIO_REG_DEVID);
- if (id != 0x6f) {
+ if ((id != 0x6f) && (id != 0x81)) {
superio_exit();
return -ENODEV;
}
@@ -310,8 +309,9 @@ static int __init smsc47b397_find(unsigned short *addr)
*addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
| superio_inb(SUPERIO_REG_BASE_LSB);
- printk(KERN_INFO "smsc47b397: found SMSC LPC47B397-NC "
- "(base address 0x%04x, revision %u)\n", *addr, rev);
+ printk(KERN_INFO "smsc47b397: found SMSC %s "
+ "(base address 0x%04x, revision %u)\n",
+ id == 0x81 ? "SCH5307-NS" : "LPC47B397-NC", *addr, rev);
superio_exit();
return 0;
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index c9cc683eba4a9f..5905c1af88f21a 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -3,7 +3,7 @@
for hardware monitoring
Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x, LPC47M14x,
- LPC47M15x and LPC47M192 Super-I/O chips.
+ LPC47M15x, LPC47M192 and LPC47M997 Super-I/O chips.
Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
@@ -356,6 +356,8 @@ static int __init smsc47m1_find(unsigned short *addr)
* 0x5F) and LPC47B27x (device id 0x51) have fan control.
* The LPC47M15x and LPC47M192 chips "with hardware monitoring block"
* can do much more besides (device id 0x60).
+ * The LPC47M997 is undocumented, but seems to be compatible with
+ * the LPC47M192, and has the same device id.
*/
if (val == 0x51)
printk(KERN_INFO "smsc47m1: Found SMSC LPC47B27x\n");
@@ -364,7 +366,8 @@ static int __init smsc47m1_find(unsigned short *addr)
else if (val == 0x5F)
printk(KERN_INFO "smsc47m1: Found SMSC LPC47M14x\n");
else if (val == 0x60)
- printk(KERN_INFO "smsc47m1: Found SMSC LPC47M15x/LPC47M192\n");
+ printk(KERN_INFO "smsc47m1: Found SMSC "
+ "LPC47M15x/LPC47M192/LPC47M997\n");
else {
superio_exit();
return -ENODEV;
@@ -396,11 +399,10 @@ static int smsc47m1_detect(struct i2c_adapter *adapter)
return -EBUSY;
}
- if (!(data = kmalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
err = -ENOMEM;
goto error_release;
}
- memset(data, 0x00, sizeof(struct smsc47m1_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index 05ddc88e7dd2e4..6f696f897176b6 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -44,7 +44,7 @@
/* If force_addr is set to anything different from 0, we forcibly enable
the device at the given address. */
-static unsigned short force_addr = 0;
+static unsigned short force_addr;
module_param(force_addr, ushort, 0);
MODULE_PARM_DESC(force_addr,
"Initialize the base address of the sensors");
@@ -198,7 +198,7 @@ static inline u8 FAN_TO_REG(long rpm, int div)
but the function is very linear in the useful range (0-80 deg C), so
we'll just use linear interpolation for 10-bit readings.) So, tempLUT
is the temp at via register values 0-255: */
-static const long tempLUT[] =
+static const s16 tempLUT[] =
{ -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
-503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
-362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
@@ -270,7 +270,7 @@ static inline u8 TEMP_TO_REG(long val)
}
/* for 8-bit temperature hyst and over registers */
-#define TEMP_FROM_REG(val) (tempLUT[(val)] * 100)
+#define TEMP_FROM_REG(val) ((long)tempLUT[val] * 100)
/* for 10-bit temperature readings */
static inline long TEMP_FROM_REG10(u16 val)
@@ -589,10 +589,8 @@ static int via686a_detect(struct i2c_adapter *adapter)
u16 val;
/* 8231 requires multiple of 256, we enforce that on 686 as well */
- if (force_addr)
- address = force_addr & 0xFF00;
-
if (force_addr) {
+ address = force_addr & 0xFF00;
dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n",
address);
if (PCIBIOS_SUCCESSFUL !=
@@ -603,11 +601,17 @@ static int via686a_detect(struct i2c_adapter *adapter)
pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))
return -ENODEV;
if (!(val & 0x0001)) {
- dev_warn(&adapter->dev, "enabling sensors\n");
- if (PCIBIOS_SUCCESSFUL !=
- pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
- val | 0x0001))
+ if (force_addr) {
+ dev_info(&adapter->dev, "enabling sensors\n");
+ if (PCIBIOS_SUCCESSFUL !=
+ pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
+ val | 0x0001))
+ return -ENODEV;
+ } else {
+ dev_warn(&adapter->dev, "sensors disabled - enable "
+ "with force_addr=0x%x\n", address);
return -ENODEV;
+ }
}
/* Reserve the ISA region */
@@ -617,11 +621,10 @@ static int via686a_detect(struct i2c_adapter *adapter)
return -ENODEV;
}
- if (!(data = kmalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit_release;
}
- memset(data, 0, sizeof(struct via686a_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -708,7 +711,6 @@ static int via686a_detach_client(struct i2c_client *client)
return 0;
}
-/* Called when we have found a new VIA686A. Set limits, etc. */
static void via686a_init_client(struct i2c_client *client)
{
u8 reg;
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index b60efe8f8b2669..eee22a57e929db 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -105,7 +105,9 @@ superio_exit(void)
* ISA constants
*/
-#define REGION_LENGTH 8
+#define REGION_ALIGNMENT ~7
+#define REGION_OFFSET 5
+#define REGION_LENGTH 2
#define ADDR_REG_OFFSET 5
#define DATA_REG_OFFSET 6
@@ -673,16 +675,16 @@ static int w83627ehf_detect(struct i2c_adapter *adapter)
struct w83627ehf_data *data;
int i, err = 0;
- if (!request_region(address, REGION_LENGTH, w83627ehf_driver.name)) {
+ if (!request_region(address + REGION_OFFSET, REGION_LENGTH,
+ w83627ehf_driver.name)) {
err = -EBUSY;
goto exit;
}
- if (!(data = kmalloc(sizeof(struct w83627ehf_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct w83627ehf_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit_release;
}
- memset(data, 0, sizeof(struct w83627ehf_data));
client = &data->client;
i2c_set_clientdata(client, data);
@@ -762,7 +764,7 @@ exit_detach:
exit_free:
kfree(data);
exit_release:
- release_region(address, REGION_LENGTH);
+ release_region(address + REGION_OFFSET, REGION_LENGTH);
exit:
return err;
}
@@ -776,7 +778,7 @@ static int w83627ehf_detach_client(struct i2c_client *client)
if ((err = i2c_detach_client(client)))
return err;
- release_region(client->addr, REGION_LENGTH);
+ release_region(client->addr + REGION_OFFSET, REGION_LENGTH);
kfree(data);
return 0;
@@ -807,7 +809,7 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr)
superio_select(W83627EHF_LD_HWM);
val = (superio_inb(SIO_REG_ADDR) << 8)
| superio_inb(SIO_REG_ADDR + 1);
- *addr = val & ~(REGION_LENGTH - 1);
+ *addr = val & REGION_ALIGNMENT;
if (*addr == 0) {
superio_exit();
return -ENODEV;
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 3479dc5208e2d3..70ef926c3bd834 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -142,10 +142,14 @@ superio_exit(void)
#define WINB_BASE_REG 0x60
/* Constants specified below */
-/* Length of ISA address segment */
-#define WINB_EXTENT 8
+/* Alignment of the base address */
+#define WINB_ALIGNMENT ~7
-/* Where are the ISA address/data registers relative to the base address */
+/* Offset & size of I/O region we are interested in */
+#define WINB_REGION_OFFSET 5
+#define WINB_REGION_SIZE 2
+
+/* Where are the sensors address/data registers relative to the base address */
#define W83781D_ADDR_REG_OFFSET 5
#define W83781D_DATA_REG_OFFSET 6
@@ -197,7 +201,6 @@ superio_exit(void)
#define W83627HF_REG_PWM1 0x5A
#define W83627HF_REG_PWM2 0x5B
-#define W83627HF_REG_PWMCLK12 0x5C
#define W83627THF_REG_PWM1 0x01 /* 697HF and 637HF too */
#define W83627THF_REG_PWM2 0x03 /* 697HF and 637HF too */
@@ -981,7 +984,7 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr)
superio_select(W83627HF_LD_HWM);
val = (superio_inb(WINB_BASE_REG) << 8) |
superio_inb(WINB_BASE_REG + 1);
- *addr = val & ~(WINB_EXTENT - 1);
+ *addr = val & WINB_ALIGNMENT;
if (*addr == 0 && force_addr == 0) {
superio_exit();
return -ENODEV;
@@ -1000,9 +1003,10 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
const char *client_name = "";
if(force_addr)
- address = force_addr & ~(WINB_EXTENT - 1);
+ address = force_addr & WINB_ALIGNMENT;
- if (!request_region(address, WINB_EXTENT, w83627hf_driver.name)) {
+ if (!request_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE,
+ w83627hf_driver.name)) {
err = -EBUSY;
goto ERROR0;
}
@@ -1041,11 +1045,10 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
client structure, even though we cannot fill it completely yet.
But it allows us to access w83627hf_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
err = -ENOMEM;
goto ERROR1;
}
- memset(data, 0, sizeof(struct w83627hf_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -1148,7 +1151,7 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
ERROR2:
kfree(data);
ERROR1:
- release_region(address, WINB_EXTENT);
+ release_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE);
ERROR0:
return err;
}
@@ -1163,7 +1166,7 @@ static int w83627hf_detach_client(struct i2c_client *client)
if ((err = i2c_detach_client(client)))
return err;
- release_region(client->addr, WINB_EXTENT);
+ release_region(client->addr + WINB_REGION_OFFSET, WINB_REGION_SIZE);
kfree(data);
return 0;
@@ -1275,7 +1278,6 @@ static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value)
return 0;
}
-/* Called when we have found a new W83781D. It should set limits, etc. */
static void w83627hf_init_client(struct i2c_client *client)
{
struct w83627hf_data *data = i2c_get_clientdata(client);
@@ -1369,12 +1371,6 @@ static void w83627hf_init_client(struct i2c_client *client)
}
}
- if (type == w83627hf) {
- /* enable PWM2 control (can't hurt since PWM reg
- should have been reset to 0xff) */
- w83627hf_write_value(client, W83627HF_REG_PWMCLK12,
- 0x19);
- }
/* enable comparator mode for temp2 and temp3 so
alarm indication will work correctly */
i = w83627hf_read_value(client, W83781D_REG_IRQ);
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 4c43337ca780ab..9265f32122fa4b 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -889,12 +889,11 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
const char *client_name = "";
struct w83781d_data *data = i2c_get_clientdata(new_client);
- data->lm75[0] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!(data->lm75[0])) {
err = -ENOMEM;
goto ERROR_SC_0;
}
- memset(data->lm75[0], 0x00, sizeof (struct i2c_client));
id = i2c_adapter_id(adapter);
@@ -919,13 +918,11 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
}
if (kind != w83783s) {
-
- data->lm75[1] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ data->lm75[1] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!(data->lm75[1])) {
err = -ENOMEM;
goto ERROR_SC_1;
}
- memset(data->lm75[1], 0x0, sizeof(struct i2c_client));
if (force_subclients[0] == id &&
force_subclients[1] == address) {
@@ -1064,11 +1061,10 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
client structure, even though we cannot fill it completely yet.
But it allows us to access w83781d_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
err = -ENOMEM;
goto ERROR1;
}
- memset(data, 0, sizeof(struct w83781d_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -1451,7 +1447,6 @@ w83781d_write_value(struct i2c_client *client, u16 reg, u16 value)
return 0;
}
-/* Called when we have found a new W83781D. It should set limits, etc. */
static void
w83781d_init_client(struct i2c_client *client)
{
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index ba0c28015f6af5..4be59dbb78c472 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -1086,11 +1086,10 @@ w83792d_create_subclient(struct i2c_adapter *adapter,
int err;
struct i2c_client *sub_client;
- (*sub_cli) = sub_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ (*sub_cli) = sub_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!(sub_client)) {
return -ENOMEM;
}
- memset(sub_client, 0x00, sizeof(struct i2c_client));
sub_client->addr = 0x48 + addr;
i2c_set_clientdata(sub_client, NULL);
sub_client->adapter = adapter;
@@ -1184,11 +1183,10 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
client structure, even though we cannot fill it completely yet.
But it allows us to access w83792d_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct w83792d_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct w83792d_data), GFP_KERNEL))) {
err = -ENOMEM;
goto ERROR0;
}
- memset(data, 0, sizeof(struct w83792d_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -1429,7 +1427,6 @@ w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
return 0;
}
-/* Called when we have found a new W83792D. It should set limits, etc. */
static void
w83792d_init_client(struct i2c_client *client)
{
diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c
index 133e34ab1d0af1..f495b63786685b 100644
--- a/drivers/hwmon/w83l785ts.c
+++ b/drivers/hwmon/w83l785ts.c
@@ -37,6 +37,7 @@
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
/* How many retries on register read error */
@@ -73,7 +74,7 @@ I2C_CLIENT_INSMOD_1(w83l785ts);
* The W83L785TS-S uses signed 8-bit values.
*/
-#define TEMP_FROM_REG(val) ((val & 0x80 ? val-0x100 : val) * 1000)
+#define TEMP_FROM_REG(val) ((val) * 1000)
/*
* Functions declaration
@@ -111,27 +112,24 @@ struct w83l785ts_data {
unsigned long last_updated; /* in jiffies */
/* registers values */
- u8 temp, temp_over;
+ s8 temp[2]; /* 0: input
+ 1: critical limit */
};
/*
* Sysfs stuff
*/
-static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct w83l785ts_data *data = w83l785ts_update_device(dev);
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
}
-static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct w83l785ts_data *data = w83l785ts_update_device(dev);
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
-}
-
-static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
-static DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_over, NULL);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 1);
/*
* Real code
@@ -158,12 +156,10 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct w83l785ts_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct w83l785ts_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct w83l785ts_data));
-
/* The common I2C client data is placed right before the
* W83L785TS-specific data. */
@@ -228,7 +224,7 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
init_MUTEX(&data->update_lock);
/* Default values in case the first read fails (unlikely). */
- data->temp_over = data->temp = 0;
+ data->temp[1] = data->temp[0] = 0;
/* Tell the I2C layer a new client has arrived. */
if ((err = i2c_attach_client(new_client)))
@@ -246,8 +242,10 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
goto exit_detach;
}
- device_create_file(&new_client->dev, &dev_attr_temp1_input);
- device_create_file(&new_client->dev, &dev_attr_temp1_max);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp1_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp1_max.dev_attr);
return 0;
@@ -305,10 +303,10 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev)
if (!data->valid || time_after(jiffies, data->last_updated + HZ * 2)) {
dev_dbg(&client->dev, "Updating w83l785ts data.\n");
- data->temp = w83l785ts_read_value(client,
- W83L785TS_REG_TEMP, data->temp);
- data->temp_over = w83l785ts_read_value(client,
- W83L785TS_REG_TEMP_OVER, data->temp_over);
+ data->temp[0] = w83l785ts_read_value(client,
+ W83L785TS_REG_TEMP, data->temp[0]);
+ data->temp[1] = w83l785ts_read_value(client,
+ W83L785TS_REG_TEMP_OVER, data->temp[1]);
data->last_updated = jiffies;
data->valid = 1;
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index beb10edfe9c177..82946acab4c759 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -34,7 +34,7 @@
#define DEB2(fmt, args...) do { if (i2c_debug>=2) printk(fmt, ## args); } while(0)
#define DEB3(fmt, args...) do { if (i2c_debug>=3) printk(fmt, ## args); } while(0)
-static int i2c_debug=0;
+static int i2c_debug;
#define pca_outw(adap, reg, val) adap->write_byte(adap, reg, val)
#define pca_inw(adap, reg) adap->read_byte(adap, reg)
diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c
index 8ed5ad12552fed..938848ae162d44 100644
--- a/drivers/i2c/algos/i2c-algo-sibyte.c
+++ b/drivers/i2c/algos/i2c-algo-sibyte.c
@@ -42,7 +42,7 @@
/* module parameters:
*/
-static int bit_scan=0; /* have a look at what's hanging 'round */
+static int bit_scan; /* have a look at what's hanging 'round */
static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 3badfec75b1c8b..4010fe92e72b63 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -135,11 +135,12 @@ config I2C_I810
help
If you say yes to this option, support will be included for the Intel
810/815 family of mainboard I2C interfaces. Specifically, the
- following versions of the chipset is supported:
+ following versions of the chipset are supported:
i810AA
i810AB
i810E
i815
+ i845G
This driver can also be built as a module. If so, the module
will be called i2c-i810.
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index f021acd2674e9c..ba90f5140af672 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -134,7 +134,7 @@
/* -> Read = 1 */
#define ALI1535_SMBIO_EN 0x04 /* SMB I/O Space enable */
-
+static struct pci_driver ali1535_driver;
static unsigned short ali1535_smba;
static DECLARE_MUTEX(i2c_ali1535_sem);
@@ -162,7 +162,8 @@ static int ali1535_setup(struct pci_dev *dev)
goto exit;
}
- if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE, "ali1535-smb")) {
+ if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE,
+ ali1535_driver.name)) {
dev_err(&dev->dev, "ALI1535_smb region 0x%x already in use!\n",
ali1535_smba);
goto exit;
@@ -480,7 +481,6 @@ static struct i2c_adapter ali1535_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
static struct pci_device_id ali1535_ids[] = {
@@ -513,6 +513,7 @@ static void __devexit ali1535_remove(struct pci_dev *dev)
}
static struct pci_driver ali1535_driver = {
+ .owner = THIS_MODULE,
.name = "ali1535_smbus",
.id_table = ali1535_ids,
.probe = ali1535_probe,
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
index 86947504aea1e0..f1a62d8924255c 100644
--- a/drivers/i2c/busses/i2c-ali1563.c
+++ b/drivers/i2c/busses/i2c-ali1563.c
@@ -60,6 +60,7 @@
#define HST_CNTL2_SIZEMASK 0x38
+static struct pci_driver ali1563_pci_driver;
static unsigned short ali1563_smba;
static int ali1563_transaction(struct i2c_adapter * a, int size)
@@ -350,7 +351,8 @@ static int __devinit ali1563_setup(struct pci_dev * dev)
dev_warn(&dev->dev,"ali1563_smba Uninitialized\n");
goto Err;
}
- if (!request_region(ali1563_smba,ALI1563_SMB_IOSIZE,"i2c-ali1563")) {
+ if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE,
+ ali1563_pci_driver.name)) {
dev_warn(&dev->dev,"Could not allocate I/O space");
goto Err;
}
@@ -406,7 +408,8 @@ static struct pci_device_id __devinitdata ali1563_id_table[] = {
MODULE_DEVICE_TABLE (pci, ali1563_id_table);
static struct pci_driver ali1563_pci_driver = {
- .name = "ali1563_i2c",
+ .owner = THIS_MODULE,
+ .name = "ali1563_smbus",
.id_table = ali1563_id_table,
.probe = ali1563_probe,
.remove = __devexit_p(ali1563_remove),
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index b3f50bff39a06c..400b08ed429934 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -125,12 +125,13 @@
/* If force_addr is set to anything different from 0, we forcibly enable
the device at the given address. */
-static u16 force_addr = 0;
+static u16 force_addr;
module_param(force_addr, ushort, 0);
MODULE_PARM_DESC(force_addr,
"Initialize the base address of the i2c controller");
-static unsigned short ali15x3_smba = 0;
+static struct pci_driver ali15x3_driver;
+static unsigned short ali15x3_smba;
static int ali15x3_setup(struct pci_dev *ALI15X3_dev)
{
@@ -166,7 +167,8 @@ static int ali15x3_setup(struct pci_dev *ALI15X3_dev)
if(force_addr)
ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1);
- if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb")) {
+ if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE,
+ ali15x3_driver.name)) {
dev_err(&ALI15X3_dev->dev,
"ALI15X3_smb region 0x%x already in use!\n",
ali15x3_smba);
@@ -470,7 +472,6 @@ static struct i2c_adapter ali15x3_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
static struct pci_device_id ali15x3_ids[] = {
@@ -503,6 +504,7 @@ static void __devexit ali15x3_remove(struct pci_dev *dev)
}
static struct pci_driver ali15x3_driver = {
+ .owner = THIS_MODULE,
.name = "ali15x3_smbus",
.id_table = ali15x3_ids,
.probe = ali15x3_probe,
diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c
index 4e553e8c5cbada..f51ab652300a66 100644
--- a/drivers/i2c/busses/i2c-amd756-s4882.c
+++ b/drivers/i2c/busses/i2c-amd756-s4882.c
@@ -169,12 +169,12 @@ static int __init amd756_s4882_init(void)
init_MUTEX(&amd756_lock);
/* Define the 5 virtual adapters and algorithms structures */
- if (!(s4882_adapter = kmalloc(5 * sizeof(struct i2c_adapter),
+ if (!(s4882_adapter = kzalloc(5 * sizeof(struct i2c_adapter),
GFP_KERNEL))) {
error = -ENOMEM;
goto ERROR1;
}
- if (!(s4882_algo = kmalloc(5 * sizeof(struct i2c_algorithm),
+ if (!(s4882_algo = kzalloc(5 * sizeof(struct i2c_algorithm),
GFP_KERNEL))) {
error = -ENOMEM;
goto ERROR2;
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index 6ad0603384b8a3..de035d137c3f30 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -85,8 +85,8 @@
#define AMD756_PROCESS_CALL 0x04
#define AMD756_BLOCK_DATA 0x05
-
-static unsigned short amd756_ioport = 0;
+static struct pci_driver amd756_driver;
+static unsigned short amd756_ioport;
/*
SMBUS event = I/O 28-29 bit 11
@@ -303,7 +303,6 @@ struct i2c_adapter amd756_smbus = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
enum chiptype { AMD756, AMD766, AMD768, NFORCE, AMD8111 };
@@ -365,7 +364,7 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
amd756_ioport += SMB_ADDR_OFFSET;
}
- if (!request_region(amd756_ioport, SMB_IOSIZE, "amd756-smbus")) {
+ if (!request_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name)) {
dev_err(&pdev->dev, "SMB region 0x%x already in use!\n",
amd756_ioport);
return -ENODEV;
@@ -402,6 +401,7 @@ static void __devexit amd756_remove(struct pci_dev *dev)
}
static struct pci_driver amd756_driver = {
+ .owner = THIS_MODULE,
.name = "amd756_smbus",
.id_table = amd756_ids,
.probe = amd756_probe,
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index 45ea24ba14d5b2..f3b79a68dbec5a 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -30,6 +30,8 @@ struct amd_smbus {
int size;
};
+static struct pci_driver amd8111_driver;
+
/*
* AMD PCI control registers definitions.
*/
@@ -242,7 +244,6 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short fl
break;
case I2C_SMBUS_BLOCK_PROC_CALL:
- protocol |= pec;
len = min_t(u8, data->block[0], 31);
amd_ec_write(smbus, AMD_SMB_CMD, command);
amd_ec_write(smbus, AMD_SMB_BCNT, len);
@@ -252,13 +253,6 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short fl
read_write = I2C_SMBUS_READ;
break;
- case I2C_SMBUS_WORD_DATA_PEC:
- case I2C_SMBUS_BLOCK_DATA_PEC:
- case I2C_SMBUS_PROC_CALL_PEC:
- case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
- dev_warn(&adap->dev, "Unexpected software PEC transaction %d\n.", size);
- return -1;
-
default:
dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
return -1;
@@ -343,16 +337,15 @@ static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_
if (~pci_resource_flags(dev, 0) & IORESOURCE_IO)
return -ENODEV;
- smbus = kmalloc(sizeof(struct amd_smbus), GFP_KERNEL);
+ smbus = kzalloc(sizeof(struct amd_smbus), GFP_KERNEL);
if (!smbus)
return -ENOMEM;
- memset(smbus, 0, sizeof(struct amd_smbus));
smbus->dev = dev;
smbus->base = pci_resource_start(dev, 0);
smbus->size = pci_resource_len(dev, 0);
- if (!request_region(smbus->base, smbus->size, "amd8111 SMBus 2.0"))
+ if (!request_region(smbus->base, smbus->size, amd8111_driver.name))
goto out_kfree;
smbus->adapter.owner = THIS_MODULE;
@@ -391,6 +384,7 @@ static void __devexit amd8111_remove(struct pci_dev *dev)
}
static struct pci_driver amd8111_driver = {
+ .owner = THIS_MODULE,
.name = "amd8111_smbus2",
.id_table = amd8111_ids,
.probe = amd8111_probe,
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index 6930b660e508d8..59f8308c2356cc 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -22,7 +22,7 @@
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl> */
-/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of
+/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of
for Alpha Processor Inc. UP-2000(+) boards */
#include <linux/kernel.h>
@@ -46,12 +46,14 @@
#define DEFAULT_BASE 0x330
static int base;
+static u8 __iomem *base_iomem;
+
static int irq;
static int clock = 0x1c;
static int own = 0x55;
static int mmapped;
-/* vdovikin: removed static struct i2c_pcf_isa gpi; code -
+/* vdovikin: removed static struct i2c_pcf_isa gpi; code -
this module in real supports only one device, due to missing arguments
in some functions, called from the algo-pcf module. Sometimes it's
need to be rewriten - but for now just remove this for simpler reading */
@@ -60,40 +62,33 @@ static wait_queue_head_t pcf_wait;
static int pcf_pending;
static spinlock_t lock;
+static struct i2c_adapter pcf_isa_ops;
+
/* ----- local functions ---------------------------------------------- */
static void pcf_isa_setbyte(void *data, int ctl, int val)
{
- int address = ctl ? (base + 1) : base;
+ u8 __iomem *address = ctl ? (base_iomem + 1) : base_iomem;
/* enable irq if any specified for serial operation */
if (ctl && irq && (val & I2C_PCF_ESO)) {
val |= I2C_PCF_ENI;
}
- pr_debug("i2c-elektor: Write 0x%X 0x%02X\n", address, val & 255);
-
- switch (mmapped) {
- case 0: /* regular I/O */
- outb(val, address);
- break;
- case 2: /* double mapped I/O needed for UP2000 board,
- I don't know why this... */
- writeb(val, (void *)address);
- /* fall */
- case 1: /* memory mapped I/O */
- writeb(val, (void *)address);
- break;
- }
+ pr_debug("%s: Write %p 0x%02X\n", pcf_isa_ops.name, address, val);
+ iowrite8(val, address);
+#ifdef __alpha__
+ /* API UP2000 needs some hardware fudging to make the write stick */
+ iowrite8(val, address);
+#endif
}
static int pcf_isa_getbyte(void *data, int ctl)
{
- int address = ctl ? (base + 1) : base;
- int val = mmapped ? readb((void *)address) : inb(address);
-
- pr_debug("i2c-elektor: Read 0x%X 0x%02X\n", address, val);
+ u8 __iomem *address = ctl ? (base_iomem + 1) : base_iomem;
+ int val = ioread8(address);
+ pr_debug("%s: Read %p 0x%02X\n", pcf_isa_ops.name, address, val);
return (val);
}
@@ -149,16 +144,40 @@ static int pcf_isa_init(void)
{
spin_lock_init(&lock);
if (!mmapped) {
- if (!request_region(base, 2, "i2c (isa bus adapter)")) {
- printk(KERN_ERR
- "i2c-elektor: requested I/O region (0x%X:2) "
- "is in use.\n", base);
+ if (!request_region(base, 2, pcf_isa_ops.name)) {
+ printk(KERN_ERR "%s: requested I/O region (%#x:2) is "
+ "in use\n", pcf_isa_ops.name, base);
+ return -ENODEV;
+ }
+ base_iomem = ioport_map(base, 2);
+ if (!base_iomem) {
+ printk(KERN_ERR "%s: remap of I/O region %#x failed\n",
+ pcf_isa_ops.name, base);
+ release_region(base, 2);
+ return -ENODEV;
+ }
+ } else {
+ if (!request_mem_region(base, 2, pcf_isa_ops.name)) {
+ printk(KERN_ERR "%s: requested memory region (%#x:2) "
+ "is in use\n", pcf_isa_ops.name, base);
+ return -ENODEV;
+ }
+ base_iomem = ioremap(base, 2);
+ if (base_iomem == NULL) {
+ printk(KERN_ERR "%s: remap of memory region %#x "
+ "failed\n", pcf_isa_ops.name, base);
+ release_mem_region(base, 2);
return -ENODEV;
}
}
+ pr_debug("%s: registers %#x remapped to %p\n", pcf_isa_ops.name, base,
+ base_iomem);
+
if (irq > 0) {
- if (request_irq(irq, pcf_isa_handler, 0, "PCF8584", NULL) < 0) {
- printk(KERN_ERR "i2c-elektor: Request irq%d failed\n", irq);
+ if (request_irq(irq, pcf_isa_handler, 0, pcf_isa_ops.name,
+ NULL) < 0) {
+ printk(KERN_ERR "%s: Request irq%d failed\n",
+ pcf_isa_ops.name, irq);
irq = 0;
} else
enable_irq(irq);
@@ -186,47 +205,49 @@ static struct i2c_adapter pcf_isa_ops = {
.class = I2C_CLASS_HWMON,
.id = I2C_HW_P_ELEK,
.algo_data = &pcf_isa_data,
- .name = "PCF8584 ISA adapter",
+ .name = "i2c-elektor",
};
-static int __init i2c_pcfisa_init(void)
+static int __init i2c_pcfisa_init(void)
{
#ifdef __alpha__
- /* check to see we have memory mapped PCF8584 connected to the
+ /* check to see we have memory mapped PCF8584 connected to the
Cypress cy82c693 PCI-ISA bridge as on UP2000 board */
if (base == 0) {
struct pci_dev *cy693_dev;
-
- cy693_dev = pci_get_device(PCI_VENDOR_ID_CONTAQ,
+
+ cy693_dev = pci_get_device(PCI_VENDOR_ID_CONTAQ,
PCI_DEVICE_ID_CONTAQ_82C693, NULL);
if (cy693_dev) {
- char config;
+ unsigned char config;
/* yeap, we've found cypress, let's check config */
if (!pci_read_config_byte(cy693_dev, 0x47, &config)) {
-
- pr_debug("i2c-elektor: found cy82c693, config register 0x47 = 0x%02x.\n", config);
+
+ pr_debug("%s: found cy82c693, config "
+ "register 0x47 = 0x%02x\n",
+ pcf_isa_ops.name, config);
/* UP2000 board has this register set to 0xe1,
- but the most significant bit as seems can be
+ but the most significant bit as seems can be
reset during the proper initialisation
- sequence if guys from API decides to do that
- (so, we can even enable Tsunami Pchip
- window for the upper 1 Gb) */
+ sequence if guys from API decides to do that
+ (so, we can even enable Tsunami Pchip
+ window for the upper 1 Gb) */
/* so just check for ROMCS at 0xe0000,
- ROMCS enabled for writes
+ ROMCS enabled for writes
and external XD Bus buffer in use. */
if ((config & 0x7f) == 0x61) {
/* seems to be UP2000 like board */
base = 0xe0000;
- /* I don't know why we need to
- write twice */
- mmapped = 2;
- /* UP2000 drives ISA with
+ mmapped = 1;
+ /* UP2000 drives ISA with
8.25 MHz (PCI/4) clock
(this can be read from cypress) */
clock = I2C_PCF_CLK | I2C_PCF_TRNS90;
- printk(KERN_INFO "i2c-elektor: found API UP2000 like board, will probe PCF8584 later.\n");
+ pr_info("%s: found API UP2000 like "
+ "board, will probe PCF8584 "
+ "later\n", pcf_isa_ops.name);
}
}
pci_dev_put(cy693_dev);
@@ -236,12 +257,11 @@ static int __init i2c_pcfisa_init(void)
/* sanity checks for mmapped I/O */
if (mmapped && base < 0xc8000) {
- printk(KERN_ERR "i2c-elektor: incorrect base address (0x%0X) specified for mmapped I/O.\n", base);
+ printk(KERN_ERR "%s: incorrect base address (%#x) specified "
+ "for mmapped I/O\n", pcf_isa_ops.name, base);
return -ENODEV;
}
- printk(KERN_INFO "i2c-elektor: i2c pcf8584-isa adapter driver\n");
-
if (base == 0) {
base = DEFAULT_BASE;
}
@@ -251,8 +271,8 @@ static int __init i2c_pcfisa_init(void)
return -ENODEV;
if (i2c_pcf_add_bus(&pcf_isa_ops) < 0)
goto fail;
-
- printk(KERN_ERR "i2c-elektor: found device at %#x.\n", base);
+
+ dev_info(&pcf_isa_ops.dev, "found device at %#x\n", base);
return 0;
@@ -262,8 +282,13 @@ static int __init i2c_pcfisa_init(void)
free_irq(irq, NULL);
}
- if (!mmapped)
- release_region(base , 2);
+ if (!mmapped) {
+ ioport_unmap(base_iomem);
+ release_region(base, 2);
+ } else {
+ iounmap(base_iomem);
+ release_mem_region(base, 2);
+ }
return -ENODEV;
}
@@ -276,8 +301,13 @@ static void i2c_pcfisa_exit(void)
free_irq(irq, NULL);
}
- if (!mmapped)
- release_region(base , 2);
+ if (!mmapped) {
+ ioport_unmap(base_iomem);
+ release_region(base, 2);
+ } else {
+ iounmap(base_iomem);
+ release_mem_region(base, 2);
+ }
}
MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
index e0cb3b0f92faba..1b5354e24bf56c 100644
--- a/drivers/i2c/busses/i2c-hydra.c
+++ b/drivers/i2c/busses/i2c-hydra.c
@@ -155,6 +155,7 @@ static void __devexit hydra_remove(struct pci_dev *dev)
static struct pci_driver hydra_driver = {
+ .owner = THIS_MODULE,
.name = "hydra_smbus",
.id_table = hydra_ids,
.probe = hydra_probe,
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 709beab76609eb..4f63195069dafa 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -52,10 +52,6 @@
#include <linux/i2c.h>
#include <asm/io.h>
-#ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC
-#define HAVE_PEC
-#endif
-
/* I801 SMBus address offsets */
#define SMBHSTSTS (0 + i801_smba)
#define SMBHSTCNT (2 + i801_smba)
@@ -106,10 +102,11 @@ MODULE_PARM_DESC(force_addr,
"EXTREMELY DANGEROUS!");
static int i801_transaction(void);
-static int i801_block_transaction(union i2c_smbus_data *data,
- char read_write, int command);
+static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
+ int command, int hwpec);
static unsigned short i801_smba;
+static struct pci_driver i801_driver;
static struct pci_dev *I801_dev;
static int isich4;
@@ -143,7 +140,7 @@ static int i801_setup(struct pci_dev *dev)
}
}
- if (!request_region(i801_smba, (isich4 ? 16 : 8), "i801-smbus")) {
+ if (!request_region(i801_smba, (isich4 ? 16 : 8), i801_driver.name)) {
dev_err(&dev->dev, "I801_smb region 0x%x already in use!\n",
i801_smba);
error_return = -EBUSY;
@@ -252,7 +249,7 @@ static int i801_transaction(void)
/* All-inclusive block transaction function */
static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
- int command)
+ int command, int hwpec)
{
int i, len;
int smbcmd;
@@ -391,8 +388,7 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
goto END;
}
-#ifdef HAVE_PEC
- if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) {
+ if (hwpec) {
/* wait for INTR bit as advised by Intel */
timeout = 0;
do {
@@ -406,7 +402,6 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
}
outb_p(temp, SMBHSTSTS);
}
-#endif
result = 0;
END:
if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
@@ -421,14 +416,13 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write, u8 command,
int size, union i2c_smbus_data * data)
{
- int hwpec = 0;
+ int hwpec;
int block = 0;
int ret, xact = 0;
-#ifdef HAVE_PEC
- if(isich4)
- hwpec = (flags & I2C_CLIENT_PEC) != 0;
-#endif
+ hwpec = isich4 && (flags & I2C_CLIENT_PEC)
+ && size != I2C_SMBUS_QUICK
+ && size != I2C_SMBUS_I2C_BLOCK_DATA;
switch (size) {
case I2C_SMBUS_QUICK:
@@ -463,11 +457,6 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
break;
case I2C_SMBUS_BLOCK_DATA:
case I2C_SMBUS_I2C_BLOCK_DATA:
-#ifdef HAVE_PEC
- case I2C_SMBUS_BLOCK_DATA_PEC:
- if(hwpec && size == I2C_SMBUS_BLOCK_DATA)
- size = I2C_SMBUS_BLOCK_DATA_PEC;
-#endif
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
SMBHSTADD);
outb_p(command, SMBHSTCMD);
@@ -479,27 +468,18 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
return -1;
}
-#ifdef HAVE_PEC
- if(isich4 && hwpec) {
- if(size != I2C_SMBUS_QUICK &&
- size != I2C_SMBUS_I2C_BLOCK_DATA)
- outb_p(1, SMBAUXCTL); /* enable HW PEC */
- }
-#endif
+ if (hwpec)
+ outb_p(1, SMBAUXCTL); /* enable hardware PEC */
+
if(block)
- ret = i801_block_transaction(data, read_write, size);
+ ret = i801_block_transaction(data, read_write, size, hwpec);
else {
outb_p(xact | ENABLE_INT9, SMBHSTCNT);
ret = i801_transaction();
}
-#ifdef HAVE_PEC
- if(isich4 && hwpec) {
- if(size != I2C_SMBUS_QUICK &&
- size != I2C_SMBUS_I2C_BLOCK_DATA)
- outb_p(0, SMBAUXCTL);
- }
-#endif
+ if (hwpec)
+ outb_p(0, SMBAUXCTL); /* disable hardware PEC */
if(block)
return ret;
@@ -526,12 +506,7 @@ static u32 i801_func(struct i2c_adapter *adapter)
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
-#ifdef HAVE_PEC
- | (isich4 ? I2C_FUNC_SMBUS_BLOCK_DATA_PEC |
- I2C_FUNC_SMBUS_HWPEC_CALC
- : 0)
-#endif
- ;
+ | (isich4 ? I2C_FUNC_SMBUS_HWPEC_CALC : 0);
}
static struct i2c_algorithm smbus_algorithm = {
@@ -543,7 +518,6 @@ static struct i2c_adapter i801_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
static struct pci_device_id i801_ids[] = {
@@ -586,6 +560,7 @@ static void __devexit i801_remove(struct pci_dev *dev)
}
static struct pci_driver i801_driver = {
+ .owner = THIS_MODULE,
.name = "i801_smbus",
.id_table = i801_ids,
.probe = i801_probe,
diff --git a/drivers/i2c/busses/i2c-i810.c b/drivers/i2c/busses/i2c-i810.c
index 0ff7016e0629b6..52bc30593bd7e9 100644
--- a/drivers/i2c/busses/i2c-i810.c
+++ b/drivers/i2c/busses/i2c-i810.c
@@ -32,6 +32,7 @@
i810AB 7123
i810E 7125
i815 1132
+ i845G 2562
*/
#include <linux/kernel.h>
@@ -232,6 +233,7 @@ static void __devexit i810_remove(struct pci_dev *dev)
}
static struct pci_driver i810_driver = {
+ .owner = THIS_MODULE,
.name = "i810_smbus",
.id_table = i810_ids,
.probe = i810_probe,
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index a3ed9590f028b1..1a587253d716cd 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -672,13 +672,12 @@ static int __devinit iic_probe(struct ocp_device *ocp){
printk(KERN_WARNING"ibm-iic%d: missing additional data!\n",
ocp->def->index);
- if (!(dev = kmalloc(sizeof(*dev), GFP_KERNEL))){
+ if (!(dev = kzalloc(sizeof(*dev), GFP_KERNEL))) {
printk(KERN_CRIT "ibm-iic%d: failed to allocate device data\n",
ocp->def->index);
return -ENOMEM;
}
- memset(dev, 0, sizeof(*dev));
dev->idx = ocp->def->index;
ocp_set_drvdata(ocp, dev);
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 7bd9102db701cd..9888fae1f37a8f 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -43,7 +43,7 @@
#include "i2c-iop3xx.h"
/* global unit counter */
-static int i2c_id = 0;
+static int i2c_id;
static inline unsigned char
iic_cook_addr(struct i2c_msg *msg)
@@ -440,19 +440,17 @@ iop3xx_i2c_probe(struct device *dev)
struct i2c_adapter *new_adapter;
struct i2c_algo_iop3xx_data *adapter_data;
- new_adapter = kmalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+ new_adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
if (!new_adapter) {
ret = -ENOMEM;
goto out;
}
- memset((void*)new_adapter, 0, sizeof(*new_adapter));
- adapter_data = kmalloc(sizeof(struct i2c_algo_iop3xx_data), GFP_KERNEL);
+ adapter_data = kzalloc(sizeof(struct i2c_algo_iop3xx_data), GFP_KERNEL);
if (!adapter_data) {
ret = -ENOMEM;
goto free_adapter;
}
- memset((void*)adapter_data, 0, sizeof(*adapter_data));
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@@ -525,6 +523,7 @@ out:
static struct device_driver iop3xx_i2c_driver = {
+ .owner = THIS_MODULE,
.name = "IOP3xx-I2C",
.bus = &platform_bus_type,
.probe = iop3xx_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
index bdc6806dafaece..4fdc0241160920 100644
--- a/drivers/i2c/busses/i2c-isa.c
+++ b/drivers/i2c/busses/i2c-isa.c
@@ -92,6 +92,7 @@ int i2c_isa_add_driver(struct i2c_driver *driver)
/* Add the driver to the list of i2c drivers in the driver core */
driver->driver.name = driver->name;
+ driver->driver.owner = driver->owner;
driver->driver.bus = &i2c_bus_type;
driver->driver.probe = i2c_isa_device_probe;
driver->driver.remove = i2c_isa_device_remove;
diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
index 1956af382cd896..42016ee6ef1339 100644
--- a/drivers/i2c/busses/i2c-ixp2000.c
+++ b/drivers/i2c/busses/i2c-ixp2000.c
@@ -36,6 +36,8 @@
#include <asm/hardware.h> /* Pick up IXP2000-specific bits */
#include <asm/arch/gpio.h>
+static struct device_driver ixp2000_i2c_driver;
+
static inline int ixp2000_scl_pin(void *data)
{
return ((struct ixp2000_i2c_pins*)data)->scl_pin;
@@ -104,11 +106,10 @@ static int ixp2000_i2c_probe(struct device *dev)
struct platform_device *plat_dev = to_platform_device(dev);
struct ixp2000_i2c_pins *gpio = plat_dev->dev.platform_data;
struct ixp2000_i2c_data *drv_data =
- kmalloc(sizeof(struct ixp2000_i2c_data), GFP_KERNEL);
+ kzalloc(sizeof(struct ixp2000_i2c_data), GFP_KERNEL);
if (!drv_data)
return -ENOMEM;
- memzero(drv_data, sizeof(*drv_data));
drv_data->gpio_pins = gpio;
drv_data->algo_data.data = gpio;
@@ -121,6 +122,8 @@ static int ixp2000_i2c_probe(struct device *dev)
drv_data->algo_data.timeout = 100;
drv_data->adapter.id = I2C_HW_B_IXP2000,
+ strlcpy(drv_data->adapter.name, ixp2000_i2c_driver.name,
+ I2C_NAME_SIZE);
drv_data->adapter.algo_data = &drv_data->algo_data,
drv_data->adapter.dev.parent = &plat_dev->dev;
@@ -142,6 +145,7 @@ static int ixp2000_i2c_probe(struct device *dev)
}
static struct device_driver ixp2000_i2c_driver = {
+ .owner = THIS_MODULE,
.name = "IXP2000-I2C",
.bus = &platform_bus_type,
.probe = ixp2000_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c
index f6f5ca31fdba09..69303ab65e0488 100644
--- a/drivers/i2c/busses/i2c-ixp4xx.c
+++ b/drivers/i2c/busses/i2c-ixp4xx.c
@@ -35,6 +35,8 @@
#include <asm/hardware.h> /* Pick up IXP4xx-specific bits */
+static struct device_driver ixp4xx_i2c_driver;
+
static inline int ixp4xx_scl_pin(void *data)
{
return ((struct ixp4xx_i2c_pins*)data)->scl_pin;
@@ -105,12 +107,11 @@ static int ixp4xx_i2c_probe(struct device *dev)
struct platform_device *plat_dev = to_platform_device(dev);
struct ixp4xx_i2c_pins *gpio = plat_dev->dev.platform_data;
struct ixp4xx_i2c_data *drv_data =
- kmalloc(sizeof(struct ixp4xx_i2c_data), GFP_KERNEL);
+ kzalloc(sizeof(struct ixp4xx_i2c_data), GFP_KERNEL);
if(!drv_data)
return -ENOMEM;
- memzero(drv_data, sizeof(struct ixp4xx_i2c_data));
drv_data->gpio_pins = gpio;
/*
@@ -129,6 +130,8 @@ static int ixp4xx_i2c_probe(struct device *dev)
drv_data->algo_data.timeout = 100;
drv_data->adapter.id = I2C_HW_B_IXP4XX;
+ strlcpy(drv_data->adapter.name, ixp4xx_i2c_driver.name,
+ I2C_NAME_SIZE);
drv_data->adapter.algo_data = &drv_data->algo_data;
drv_data->adapter.dev.parent = &plat_dev->dev;
@@ -151,6 +154,7 @@ static int ixp4xx_i2c_probe(struct device *dev)
}
static struct device_driver ixp4xx_i2c_driver = {
+ .owner = THIS_MODULE,
.name = "IXP4XX-I2C",
.bus = &platform_bus_type,
.probe = ixp4xx_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
index eff5896ce86557..d61f748278fc47 100644
--- a/drivers/i2c/busses/i2c-keywest.c
+++ b/drivers/i2c/busses/i2c-keywest.c
@@ -535,13 +535,12 @@ create_iface(struct device_node *np, struct device *dev)
tsize = sizeof(struct keywest_iface) +
(sizeof(struct keywest_chan) + 4) * nchan;
- iface = (struct keywest_iface *) kmalloc(tsize, GFP_KERNEL);
+ iface = kzalloc(tsize, GFP_KERNEL);
if (iface == NULL) {
printk(KERN_ERR "i2c-keywest: can't allocate inteface !\n");
pmac_low_i2c_unlock(np);
return -ENOMEM;
}
- memset(iface, 0, tsize);
spin_lock_init(&iface->lock);
init_completion(&iface->complete);
iface->node = of_node_get(np);
@@ -716,6 +715,7 @@ static struct of_device_id i2c_keywest_match[] =
static struct macio_driver i2c_keywest_macio_driver =
{
+ .owner = THIS_MODULE,
.name = "i2c-keywest",
.match_table = i2c_keywest_match,
.probe = create_iface_macio,
@@ -724,6 +724,7 @@ static struct macio_driver i2c_keywest_macio_driver =
static struct of_platform_driver i2c_keywest_of_platform_driver =
{
+ .owner = THIS_MODULE,
.name = "i2c-keywest",
.match_table = i2c_keywest_match,
.probe = create_iface_of_platform,
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index f065583ddcf104..8491633005b87f 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -296,10 +296,9 @@ static int fsl_i2c_probe(struct device *device)
pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
- if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) {
+ if (!(i2c = kzalloc(sizeof(*i2c), GFP_KERNEL))) {
return -ENOMEM;
}
- memset(i2c, 0, sizeof(*i2c));
i2c->irq = platform_get_irq(pdev, 0);
i2c->flags = pdata->device_flags;
@@ -361,6 +360,7 @@ static int fsl_i2c_remove(struct device *device)
/* Structure for a device driver */
static struct device_driver fsl_i2c_driver = {
+ .owner = THIS_MODULE,
.name = "fsl-i2c",
.bus = &platform_bus_type,
.probe = fsl_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 99abca45fece4d..d0d2a6f1386e03 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -500,13 +500,10 @@ mv64xxx_i2c_probe(struct device *dev)
if ((pd->id != 0) || !pdata)
return -ENODEV;
- drv_data = kmalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL);
-
+ drv_data = kzalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL);
if (!drv_data)
return -ENOMEM;
- memset(drv_data, 0, sizeof(struct mv64xxx_i2c_data));
-
if (mv64xxx_i2c_map_regs(pd, drv_data)) {
rc = -ENODEV;
goto exit_kfree;
@@ -570,6 +567,7 @@ mv64xxx_i2c_remove(struct device *dev)
}
static struct device_driver mv64xxx_i2c_driver = {
+ .owner = THIS_MODULE,
.name = MV64XXX_I2C_CTLR_NAME,
.bus = &platform_bus_type,
.probe = mv64xxx_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index fe9c0f42a2b773..fd26036e68a3ee 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -97,6 +97,7 @@ struct nforce2_smbus {
#define NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA 0x4a
#define NVIDIA_SMB_PRTCL_PEC 0x80
+static struct pci_driver nforce2_driver;
static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
@@ -113,7 +114,6 @@ static struct i2c_adapter nforce2_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
/* Return -1 on error. See smbus.h for more information */
@@ -188,13 +188,6 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
dev_err(&adap->dev, "I2C_SMBUS_BLOCK_PROC_CALL not supported!\n");
return -1;
- case I2C_SMBUS_WORD_DATA_PEC:
- case I2C_SMBUS_BLOCK_DATA_PEC:
- case I2C_SMBUS_PROC_CALL_PEC:
- case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
- dev_err(&adap->dev, "Unexpected software PEC transaction %d\n.", size);
- return -1;
-
default:
dev_err(&adap->dev, "Unsupported transaction %d\n", size);
return -1;
@@ -285,7 +278,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int reg,
smbus->base = iobase & 0xfffc;
smbus->size = 8;
- if (!request_region(smbus->base, smbus->size, "nForce2 SMBus")) {
+ if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) {
dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n",
smbus->base, smbus->base+smbus->size-1, name);
return -1;
@@ -313,10 +306,8 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_
int res1, res2;
/* we support 2 SMBus adapters */
- if (!(smbuses = (void *)kmalloc(2*sizeof(struct nforce2_smbus),
- GFP_KERNEL)))
+ if (!(smbuses = kzalloc(2*sizeof(struct nforce2_smbus), GFP_KERNEL)))
return -ENOMEM;
- memset (smbuses, 0, 2*sizeof(struct nforce2_smbus));
pci_set_drvdata(dev, smbuses);
/* SMBus adapter 1 */
@@ -356,6 +347,7 @@ static void __devexit nforce2_remove(struct pci_dev *dev)
}
static struct pci_driver nforce2_driver = {
+ .owner = THIS_MODULE,
.name = "nForce2_smbus",
.id_table = nforce2_ids,
.probe = nforce2_probe,
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 71a2502fe0690e..2854d858fc9b11 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -155,12 +155,11 @@ static void i2c_parport_attach (struct parport *port)
{
struct i2c_par *adapter;
- adapter = kmalloc(sizeof(struct i2c_par), GFP_KERNEL);
+ adapter = kzalloc(sizeof(struct i2c_par), GFP_KERNEL);
if (adapter == NULL) {
- printk(KERN_ERR "i2c-parport: Failed to kmalloc\n");
+ printk(KERN_ERR "i2c-parport: Failed to kzalloc\n");
return;
}
- memset(adapter, 0x00, sizeof(struct i2c_par));
pr_debug("i2c-parport: attaching to %s\n", port->name);
adapter->pdev = parport_register_device(port, "i2c-parport",
@@ -232,7 +231,7 @@ static void i2c_parport_detach (struct parport *port)
}
}
-static struct parport_driver i2c_driver = {
+static struct parport_driver i2c_parport_driver = {
.name = "i2c-parport",
.attach = i2c_parport_attach,
.detach = i2c_parport_detach,
@@ -250,12 +249,12 @@ static int __init i2c_parport_init(void)
type = 0;
}
- return parport_register_driver(&i2c_driver);
+ return parport_register_driver(&i2c_parport_driver);
}
static void __exit i2c_parport_exit(void)
{
- parport_unregister_driver(&i2c_driver);
+ parport_unregister_driver(&i2c_parport_driver);
}
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 6d48a4da7bed97..7d63eec423fef2 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -90,13 +90,13 @@ struct sd {
/* If force is set to anything different from 0, we forcibly enable the
PIIX4. DANGEROUS! */
-static int force = 0;
+static int force;
module_param (force, int, 0);
MODULE_PARM_DESC(force, "Forcibly enable the PIIX4. DANGEROUS!");
/* If force_addr is set to anything different from 0, we forcibly enable
the PIIX4 at the given address. VERY DANGEROUS! */
-static int force_addr = 0;
+static int force_addr;
module_param (force_addr, int, 0);
MODULE_PARM_DESC(force_addr,
"Forcibly enable the PIIX4 at the given address. "
@@ -104,14 +104,15 @@ MODULE_PARM_DESC(force_addr,
/* If fix_hstcfg is set to anything different from 0, we reset one of the
registers to be a valid value. */
-static int fix_hstcfg = 0;
+static int fix_hstcfg;
module_param (fix_hstcfg, int, 0);
MODULE_PARM_DESC(fix_hstcfg,
"Fix config register. Needed on some boards (Force CPCI735).");
static int piix4_transaction(void);
-static unsigned short piix4_smba = 0;
+static unsigned short piix4_smba;
+static struct pci_driver piix4_driver;
static struct i2c_adapter piix4_adapter;
static struct dmi_system_id __devinitdata piix4_dmi_table[] = {
@@ -157,7 +158,7 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
}
}
- if (!request_region(piix4_smba, SMBIOSIZE, "piix4-smbus")) {
+ if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) {
dev_err(&PIIX4_dev->dev, "SMB region 0x%x already in use!\n",
piix4_smba);
return -ENODEV;
@@ -407,7 +408,6 @@ static struct i2c_adapter piix4_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
static struct pci_device_id piix4_ids[] = {
@@ -462,6 +462,7 @@ static void __devexit piix4_remove(struct pci_dev *dev)
}
static struct pci_driver piix4_driver = {
+ .owner = THIS_MODULE,
.name = "piix4_smbus",
.id_table = piix4_ids,
.probe = piix4_probe,
diff --git a/drivers/i2c/busses/i2c-pmac-smu.c b/drivers/i2c/busses/i2c-pmac-smu.c
index 8a9f5648a23dde..bfefe7f7a53d1f 100644
--- a/drivers/i2c/busses/i2c-pmac-smu.c
+++ b/drivers/i2c/busses/i2c-pmac-smu.c
@@ -211,12 +211,11 @@ static int create_iface(struct device_node *np, struct device *dev)
}
busid = *reg;
- iface = kmalloc(sizeof(struct smu_iface), GFP_KERNEL);
+ iface = kzalloc(sizeof(struct smu_iface), GFP_KERNEL);
if (iface == NULL) {
printk(KERN_ERR "i2c-pmac-smu: can't allocate inteface !\n");
return -ENOMEM;
}
- memset(iface, 0, sizeof(struct smu_iface));
init_completion(&iface->complete);
iface->busid = busid;
diff --git a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c
index 83fd16d61ce547..42cb1d8ca6596b 100644
--- a/drivers/i2c/busses/i2c-prosavage.c
+++ b/drivers/i2c/busses/i2c-prosavage.c
@@ -83,11 +83,6 @@ struct s_i2c_chip {
/*
* i2c configuration
*/
-#ifndef I2C_HW_B_S3VIA
-#define I2C_HW_B_S3VIA 0x18 /* S3VIA ProSavage adapter */
-#endif
-
-/* delays */
#define CYCLE_DELAY 10
#define TIMEOUT (HZ / 2)
@@ -241,14 +236,12 @@ static int __devinit prosavage_probe(struct pci_dev *dev, const struct pci_devic
struct s_i2c_chip *chip;
struct s_i2c_bus *bus;
- pci_set_drvdata(dev, kmalloc(sizeof(struct s_i2c_chip), GFP_KERNEL));
+ pci_set_drvdata(dev, kzalloc(sizeof(struct s_i2c_chip), GFP_KERNEL));
chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
if (chip == NULL) {
return -ENOMEM;
}
- memset(chip, 0, sizeof(struct s_i2c_chip));
-
base = dev->resource[0].start & PCI_BASE_ADDRESS_MEM_MASK;
len = dev->resource[0].end - base + 1;
chip->mmio = ioremap_nocache(base, len);
@@ -308,6 +301,7 @@ static struct pci_device_id prosavage_pci_tbl[] = {
MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl);
static struct pci_driver prosavage_driver = {
+ .owner = THIS_MODULE,
.name = "prosavage_smbus",
.id_table = prosavage_pci_tbl,
.probe = prosavage_probe,
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 73a092fb0e7e95..6ced28e90070a9 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -879,14 +879,12 @@ static int s3c24xx_i2c_remove(struct device *dev)
}
#ifdef CONFIG_PM
-static int s3c24xx_i2c_resume(struct device *dev, u32 level)
+static int s3c24xx_i2c_resume(struct device *dev)
{
struct s3c24xx_i2c *i2c = dev_get_drvdata(dev);
-
- if (i2c != NULL && level == RESUME_ENABLE) {
- dev_dbg(dev, "resume: level %d\n", level);
+
+ if (i2c != NULL)
s3c24xx_i2c_init(i2c);
- }
return 0;
}
@@ -898,6 +896,7 @@ static int s3c24xx_i2c_resume(struct device *dev, u32 level)
/* device driver for platform bus bits */
static struct device_driver s3c2410_i2c_driver = {
+ .owner = THIS_MODULE,
.name = "s3c2410-i2c",
.bus = &platform_bus_type,
.probe = s3c24xx_i2c_probe,
@@ -906,6 +905,7 @@ static struct device_driver s3c2410_i2c_driver = {
};
static struct device_driver s3c2440_i2c_driver = {
+ .owner = THIS_MODULE,
.name = "s3c2440-i2c",
.bus = &platform_bus_type,
.probe = s3c24xx_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c
index 0c8518298e4da3..aebe87ba403331 100644
--- a/drivers/i2c/busses/i2c-savage4.c
+++ b/drivers/i2c/busses/i2c-savage4.c
@@ -179,6 +179,7 @@ static void __devexit savage4_remove(struct pci_dev *dev)
}
static struct pci_driver savage4_driver = {
+ .owner = THIS_MODULE,
.name = "savage4_smbus",
.id_table = savage4_ids,
.probe = savage4_probe,
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index 080318d6f54b31..3ad27c3ba15b70 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -123,11 +123,12 @@ static int blacklist[] = {
/* If force_addr is set to anything different from 0, we forcibly enable
the device at the given address. */
-static u16 force_addr = 0;
+static u16 force_addr;
module_param(force_addr, ushort, 0);
MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller");
-static unsigned short sis5595_base = 0;
+static struct pci_driver sis5595_driver;
+static unsigned short sis5595_base;
static u8 sis5595_read(u8 reg)
{
@@ -172,7 +173,8 @@ static int sis5595_setup(struct pci_dev *SIS5595_dev)
/* NB: We grab just the two SMBus registers here, but this may still
* interfere with ACPI :-( */
- if (!request_region(sis5595_base + SMB_INDEX, 2, "sis5595-smbus")) {
+ if (!request_region(sis5595_base + SMB_INDEX, 2,
+ sis5595_driver.name)) {
dev_err(&SIS5595_dev->dev, "SMBus registers 0x%04x-0x%04x already in use!\n",
sis5595_base + SMB_INDEX, sis5595_base + SMB_INDEX + 1);
return -ENODEV;
@@ -364,7 +366,6 @@ static struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter sis5595_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
- .name = "unset",
.algo = &smbus_algorithm,
};
@@ -397,6 +398,7 @@ static void __devexit sis5595_remove(struct pci_dev *dev)
}
static struct pci_driver sis5595_driver = {
+ .owner = THIS_MODULE,
.name = "sis5595_smbus",
.id_table = sis5595_ids,
.probe = sis5595_probe,
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
index 86f0f448fa0b91..7f49e5fd3ff050 100644
--- a/drivers/i2c/busses/i2c-sis630.c
+++ b/drivers/i2c/busses/i2c-sis630.c
@@ -92,6 +92,8 @@
#define SIS630_PCALL 0x04
#define SIS630_BLOCK_DATA 0x05
+static struct pci_driver sis630_driver;
+
/* insmod parameters */
static int high_clock;
static int force;
@@ -101,7 +103,7 @@ module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!");
/* acpi base address */
-static unsigned short acpi_base = 0;
+static unsigned short acpi_base;
/* supported chips */
static int supported[] = {
@@ -432,7 +434,8 @@ static int sis630_setup(struct pci_dev *sis630_dev)
dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base);
/* Everything is happy, let's grab the memory and set things up. */
- if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION, "sis630-smbus")) {
+ if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
+ sis630_driver.name)) {
dev_err(&sis630_dev->dev, "SMBus registers 0x%04x-0x%04x already "
"in use!\n", acpi_base + SMB_STS, acpi_base + SMB_SAA);
goto exit;
@@ -455,7 +458,6 @@ static struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter sis630_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
- .name = "unset",
.algo = &smbus_algorithm,
};
@@ -494,6 +496,7 @@ static void __devexit sis630_remove(struct pci_dev *dev)
static struct pci_driver sis630_driver = {
+ .owner = THIS_MODULE,
.name = "sis630_smbus",
.id_table = sis630_ids,
.probe = sis630_probe,
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index ead2ff3cf60e70..6a134c09132404 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -82,8 +82,9 @@
#define SIS96x_PROC_CALL 0x04
#define SIS96x_BLOCK_DATA 0x05
+static struct pci_driver sis96x_driver;
static struct i2c_adapter sis96x_adapter;
-static u16 sis96x_smbus_base = 0;
+static u16 sis96x_smbus_base;
static inline u8 sis96x_read(u8 reg)
{
@@ -257,7 +258,6 @@ static struct i2c_adapter sis96x_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
static struct pci_device_id sis96x_ids[] = {
@@ -294,7 +294,8 @@ static int __devinit sis96x_probe(struct pci_dev *dev,
sis96x_smbus_base);
/* Everything is happy, let's grab the memory and set things up. */
- if (!request_region(sis96x_smbus_base, SMB_IOSIZE, "sis96x-smbus")) {
+ if (!request_region(sis96x_smbus_base, SMB_IOSIZE,
+ sis96x_driver.name)) {
dev_err(&dev->dev, "SMBus registers 0x%04x-0x%04x "
"already in use!\n", sis96x_smbus_base,
sis96x_smbus_base + SMB_IOSIZE - 1);
@@ -328,6 +329,7 @@ static void __devexit sis96x_remove(struct pci_dev *dev)
}
static struct pci_driver sis96x_driver = {
+ .owner = THIS_MODULE,
.name = "sis96x_smbus",
.id_table = sis96x_ids,
.probe = sis96x_probe,
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
index 040b8abeabba8b..544a38e6439461 100644
--- a/drivers/i2c/busses/i2c-via.c
+++ b/drivers/i2c/busses/i2c-via.c
@@ -43,9 +43,9 @@
/* io-region reservation */
#define IOSPACE 0x06
-#define IOTEXT "via-i2c"
-static u16 pm_io_base = 0;
+static struct pci_driver vt586b_driver;
+static u16 pm_io_base;
/*
It does not appear from the datasheet that the GPIO pins are
@@ -130,7 +130,7 @@ static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_i
pci_read_config_word(dev, base, &pm_io_base);
pm_io_base &= (0xff << 8);
- if (!request_region(I2C_DIR, IOSPACE, IOTEXT)) {
+ if (!request_region(I2C_DIR, IOSPACE, vt586b_driver.name)) {
dev_err(&dev->dev, "IO 0x%x-0x%x already in use\n", I2C_DIR, I2C_DIR + IOSPACE);
return -ENODEV;
}
@@ -159,6 +159,7 @@ static void __devexit vt586b_remove(struct pci_dev *dev)
static struct pci_driver vt586b_driver = {
+ .owner = THIS_MODULE,
.name = "vt586b_smbus",
.id_table = vt586b_ids,
.probe = vt586b_probe,
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 99d209e0485adb..c9366b504833ac 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -1,9 +1,10 @@
/*
i2c-viapro.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
- Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
+ Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>,
Mark D. Studebaker <mdsxyz123@yahoo.com>
+ Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
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
@@ -21,15 +22,19 @@
*/
/*
- Supports Via devices:
- 82C596A/B (0x3050)
- 82C596B (0x3051)
- 82C686A/B
- 8231
- 8233
- 8233A (0x3147 and 0x3177)
- 8235
- 8237
+ Supports the following VIA south bridges:
+
+ Chip name PCI ID REV I2C block
+ VT82C596A 0x3050 no
+ VT82C596B 0x3051 no
+ VT82C686A 0x3057 0x30 no
+ VT82C686B 0x3057 0x40 yes
+ VT8231 0x8235 no?
+ VT8233 0x3074 yes
+ VT8233A 0x3147 yes?
+ VT8235 0x3177 yes
+ VT8237R 0x3227 yes
+
Note: we assume there can only be one device, with one SMBus interface.
*/
@@ -38,7 +43,6 @@
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/stddef.h>
-#include <linux/sched.h>
#include <linux/ioport.h>
#include <linux/i2c.h>
#include <linux/init.h>
@@ -46,48 +50,37 @@
static struct pci_dev *vt596_pdev;
-#define SMBBA1 0x90
-#define SMBBA2 0x80
-#define SMBBA3 0xD0
+#define SMBBA1 0x90
+#define SMBBA2 0x80
+#define SMBBA3 0xD0
/* SMBus address offsets */
static unsigned short vt596_smba;
#define SMBHSTSTS (vt596_smba + 0)
-#define SMBHSLVSTS (vt596_smba + 1)
#define SMBHSTCNT (vt596_smba + 2)
#define SMBHSTCMD (vt596_smba + 3)
#define SMBHSTADD (vt596_smba + 4)
#define SMBHSTDAT0 (vt596_smba + 5)
#define SMBHSTDAT1 (vt596_smba + 6)
#define SMBBLKDAT (vt596_smba + 7)
-#define SMBSLVCNT (vt596_smba + 8)
-#define SMBSHDWCMD (vt596_smba + 9)
-#define SMBSLVEVT (vt596_smba + 0xA)
-#define SMBSLVDAT (vt596_smba + 0xC)
/* PCI Address Constants */
/* SMBus data in configuration space can be found in two places,
- We try to select the better one*/
-
-static unsigned short smb_cf_hstcfg = 0xD2;
+ We try to select the better one */
-#define SMBHSTCFG (smb_cf_hstcfg)
-#define SMBSLVC (smb_cf_hstcfg + 1)
-#define SMBSHDW1 (smb_cf_hstcfg + 2)
-#define SMBSHDW2 (smb_cf_hstcfg + 3)
-#define SMBREV (smb_cf_hstcfg + 4)
+static unsigned short SMBHSTCFG = 0xD2;
/* Other settings */
#define MAX_TIMEOUT 500
-#define ENABLE_INT9 0
/* VT82C596 constants */
-#define VT596_QUICK 0x00
-#define VT596_BYTE 0x04
-#define VT596_BYTE_DATA 0x08
-#define VT596_WORD_DATA 0x0C
-#define VT596_BLOCK_DATA 0x14
+#define VT596_QUICK 0x00
+#define VT596_BYTE 0x04
+#define VT596_BYTE_DATA 0x08
+#define VT596_WORD_DATA 0x0C
+#define VT596_BLOCK_DATA 0x14
+#define VT596_I2C_BLOCK_DATA 0x34
/* If force is set to anything different from 0, we forcibly enable the
@@ -105,40 +98,65 @@ MODULE_PARM_DESC(force_addr,
"EXTREMELY DANGEROUS!");
+static struct pci_driver vt596_driver;
static struct i2c_adapter vt596_adapter;
-/* Another internally used function */
-static int vt596_transaction(void)
+#define FEATURE_I2CBLOCK (1<<0)
+static unsigned int vt596_features;
+
+#ifdef DEBUG
+static void vt596_dump_regs(const char *msg, u8 size)
+{
+ dev_dbg(&vt596_adapter.dev, "%s: STS=%02x CNT=%02x CMD=%02x ADD=%02x "
+ "DAT=%02x,%02x\n", msg, inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
+ inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+ inb_p(SMBHSTDAT1));
+
+ if (size == VT596_BLOCK_DATA
+ || size == VT596_I2C_BLOCK_DATA) {
+ int i;
+
+ dev_dbg(&vt596_adapter.dev, "BLK=");
+ for (i = 0; i < I2C_SMBUS_BLOCK_MAX / 2; i++)
+ printk("%02x,", inb_p(SMBBLKDAT));
+ printk("\n");
+ dev_dbg(&vt596_adapter.dev, " ");
+ for (; i < I2C_SMBUS_BLOCK_MAX - 1; i++)
+ printk("%02x,", inb_p(SMBBLKDAT));
+ printk("%02x\n", inb_p(SMBBLKDAT));
+ }
+}
+#else
+static inline void vt596_dump_regs(const char *msg, u8 size) { }
+#endif
+
+/* Return -1 on error, 0 on success */
+static int vt596_transaction(u8 size)
{
int temp;
int result = 0;
int timeout = 0;
- dev_dbg(&vt596_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
- "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
- inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
- inb_p(SMBHSTDAT1));
+ vt596_dump_regs("Transaction (pre)", size);
/* Make sure the SMBus host is ready to start transmitting */
if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). "
- "Resetting...\n", temp);
-
+ "Resetting... ", temp);
+
outb_p(temp, SMBHSTSTS);
if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
- dev_dbg(&vt596_adapter.dev, "Failed! (0x%02x)\n", temp);
-
+ printk("Failed! (0x%02x)\n", temp);
return -1;
} else {
- dev_dbg(&vt596_adapter.dev, "Successfull!\n");
+ printk("Successful!\n");
}
}
- /* start the transaction by setting bit 6 */
- outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
+ /* Start the transaction by setting bit 6 */
+ outb_p(0x40 | (size & 0x3C), SMBHSTCNT);
- /* We will always wait for a fraction of a second!
- I don't know if VIA needs this, Intel did */
+ /* We will always wait for a fraction of a second */
do {
msleep(1);
temp = inb_p(SMBHSTSTS);
@@ -147,77 +165,61 @@ static int vt596_transaction(void)
/* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) {
result = -1;
- dev_dbg(&vt596_adapter.dev, "SMBus Timeout!\n");
+ dev_err(&vt596_adapter.dev, "SMBus timeout!\n");
}
if (temp & 0x10) {
result = -1;
- dev_dbg(&vt596_adapter.dev, "Error: Failed bus transaction\n");
+ dev_err(&vt596_adapter.dev, "Transaction failed (0x%02x)\n",
+ inb_p(SMBHSTCNT) & 0x3C);
}
if (temp & 0x08) {
result = -1;
- dev_info(&vt596_adapter.dev, "Bus collision! SMBus may be "
- "locked until next hard\nreset. (sorry!)\n");
- /* Clock stops and slave is stuck in mid-transmission */
+ dev_err(&vt596_adapter.dev, "SMBus collision!\n");
}
if (temp & 0x04) {
result = -1;
- dev_dbg(&vt596_adapter.dev, "Error: no response!\n");
+ /* Quick commands are used to probe for chips, so
+ errors are expected, and we don't want to frighten the
+ user. */
+ if ((inb_p(SMBHSTCNT) & 0x3C) != VT596_QUICK)
+ dev_err(&vt596_adapter.dev, "Transaction error!\n");
}
- if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
+ /* Resetting status register */
+ if (temp & 0x1F)
outb_p(temp, SMBHSTSTS);
- if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
- dev_warn(&vt596_adapter.dev, "Failed reset at end "
- "of transaction (%02x)\n", temp);
- }
- }
- dev_dbg(&vt596_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, "
- "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
- inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
- inb_p(SMBHSTDAT1));
-
+ vt596_dump_regs("Transaction (post)", size);
+
return result;
}
-/* Return -1 on error. */
+/* Return -1 on error, 0 on success */
static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
- unsigned short flags, char read_write, u8 command,
- int size, union i2c_smbus_data *data)
+ unsigned short flags, char read_write, u8 command,
+ int size, union i2c_smbus_data *data)
{
- int i, len;
+ int i;
switch (size) {
- case I2C_SMBUS_PROC_CALL:
- dev_info(&vt596_adapter.dev,
- "I2C_SMBUS_PROC_CALL not supported!\n");
- return -1;
case I2C_SMBUS_QUICK:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
- SMBHSTADD);
size = VT596_QUICK;
break;
case I2C_SMBUS_BYTE:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
- SMBHSTADD);
if (read_write == I2C_SMBUS_WRITE)
outb_p(command, SMBHSTCMD);
size = VT596_BYTE;
break;
case I2C_SMBUS_BYTE_DATA:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
- SMBHSTADD);
outb_p(command, SMBHSTCMD);
if (read_write == I2C_SMBUS_WRITE)
outb_p(data->byte, SMBHSTDAT0);
size = VT596_BYTE_DATA;
break;
case I2C_SMBUS_WORD_DATA:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
- SMBHSTADD);
outb_p(command, SMBHSTCMD);
if (read_write == I2C_SMBUS_WRITE) {
outb_p(data->word & 0xff, SMBHSTDAT0);
@@ -225,28 +227,33 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
}
size = VT596_WORD_DATA;
break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ if (!(vt596_features & FEATURE_I2CBLOCK))
+ goto exit_unsupported;
+ if (read_write == I2C_SMBUS_READ)
+ outb_p(I2C_SMBUS_BLOCK_MAX, SMBHSTDAT0);
+ /* Fall through */
case I2C_SMBUS_BLOCK_DATA:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
- SMBHSTADD);
outb_p(command, SMBHSTCMD);
if (read_write == I2C_SMBUS_WRITE) {
- len = data->block[0];
- if (len < 0)
- len = 0;
+ u8 len = data->block[0];
if (len > I2C_SMBUS_BLOCK_MAX)
len = I2C_SMBUS_BLOCK_MAX;
outb_p(len, SMBHSTDAT0);
- i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
+ inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
for (i = 1; i <= len; i++)
outb_p(data->block[i], SMBBLKDAT);
}
- size = VT596_BLOCK_DATA;
+ size = (size == I2C_SMBUS_I2C_BLOCK_DATA) ?
+ VT596_I2C_BLOCK_DATA : VT596_BLOCK_DATA;
break;
+ default:
+ goto exit_unsupported;
}
- outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
+ outb_p(((addr & 0x7f) << 1) | read_write, SMBHSTADD);
- if (vt596_transaction()) /* Error in transaction */
+ if (vt596_transaction(size)) /* Error in transaction */
return -1;
if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
@@ -254,35 +261,39 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
switch (size) {
case VT596_BYTE:
- /* Where is the result put? I assume here it is in
- * SMBHSTDAT0 but it might just as well be in the
- * SMBHSTCMD. No clue in the docs
- */
- data->byte = inb_p(SMBHSTDAT0);
- break;
case VT596_BYTE_DATA:
data->byte = inb_p(SMBHSTDAT0);
break;
case VT596_WORD_DATA:
data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
break;
+ case VT596_I2C_BLOCK_DATA:
case VT596_BLOCK_DATA:
data->block[0] = inb_p(SMBHSTDAT0);
if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
data->block[0] = I2C_SMBUS_BLOCK_MAX;
- i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
+ inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
for (i = 1; i <= data->block[0]; i++)
data->block[i] = inb_p(SMBBLKDAT);
break;
}
return 0;
+
+exit_unsupported:
+ dev_warn(&vt596_adapter.dev, "Unsupported command invoked! (0x%02x)\n",
+ size);
+ return -1;
}
static u32 vt596_func(struct i2c_adapter *adapter)
{
- return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+ u32 func = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_BLOCK_DATA;
+
+ if (vt596_features & FEATURE_I2CBLOCK)
+ func |= I2C_FUNC_SMBUS_I2C_BLOCK;
+ return func;
}
static struct i2c_algorithm smbus_algorithm = {
@@ -294,7 +305,6 @@ static struct i2c_adapter vt596_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
static int __devinit vt596_probe(struct pci_dev *pdev,
@@ -302,7 +312,7 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
{
unsigned char temp;
int error = -ENODEV;
-
+
/* Determine the address of the SMBus areas */
if (force_addr) {
vt596_smba = force_addr & 0xfff0;
@@ -311,12 +321,12 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
}
if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) ||
- !(vt596_smba & 0x1)) {
+ !(vt596_smba & 0x0001)) {
/* try 2nd address and config reg. for 596 */
if (id->device == PCI_DEVICE_ID_VIA_82C596_3 &&
!pci_read_config_word(pdev, SMBBA2, &vt596_smba) &&
- (vt596_smba & 0x1)) {
- smb_cf_hstcfg = 0x84;
+ (vt596_smba & 0x0001)) {
+ SMBHSTCFG = 0x84;
} else {
/* no matches at all */
dev_err(&pdev->dev, "Cannot configure "
@@ -333,10 +343,10 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
return -ENODEV;
}
- found:
- if (!request_region(vt596_smba, 8, "viapro-smbus")) {
+found:
+ if (!request_region(vt596_smba, 8, vt596_driver.name)) {
dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n",
- vt596_smba);
+ vt596_smba);
return -ENODEV;
}
@@ -348,16 +358,16 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
pci_write_config_word(pdev, id->driver_data, vt596_smba);
pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
dev_warn(&pdev->dev, "WARNING: SMBus interface set to new "
- "address 0x%04x!\n", vt596_smba);
- } else if ((temp & 1) == 0) {
+ "address 0x%04x!\n", vt596_smba);
+ } else if (!(temp & 0x01)) {
if (force) {
- /* NOTE: This assumes I/O space and other allocations
- * WERE done by the Bios! Don't complain if your
- * hardware does weird things after enabling this.
- * :') Check for Bios updates before resorting to
+ /* NOTE: This assumes I/O space and other allocations
+ * WERE done by the Bios! Don't complain if your
+ * hardware does weird things after enabling this.
+ * :') Check for Bios updates before resorting to
* this.
*/
- pci_write_config_byte(pdev, SMBHSTCFG, temp | 1);
+ pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
dev_info(&pdev->dev, "Enabling SMBus device\n");
} else {
dev_err(&pdev->dev, "SMBUS: Error: Host SMBus "
@@ -367,22 +377,28 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
}
}
- if ((temp & 0x0E) == 8)
- dev_dbg(&pdev->dev, "using Interrupt 9 for SMBus.\n");
- else if ((temp & 0x0E) == 0)
- dev_dbg(&pdev->dev, "using Interrupt SMI# for SMBus.\n");
- else
- dev_dbg(&pdev->dev, "Illegal Interrupt configuration "
- "(or code out of date)!\n");
-
- pci_read_config_byte(pdev, SMBREV, &temp);
- dev_dbg(&pdev->dev, "SMBREV = 0x%X\n", temp);
dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba);
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_VIA_8237:
+ case PCI_DEVICE_ID_VIA_8235:
+ case PCI_DEVICE_ID_VIA_8233A:
+ case PCI_DEVICE_ID_VIA_8233_0:
+ vt596_features |= FEATURE_I2CBLOCK;
+ break;
+ case PCI_DEVICE_ID_VIA_82C686_4:
+ /* The VT82C686B (rev 0x40) does support I2C block
+ transactions, but the VT82C686A (rev 0x30) doesn't */
+ if (!pci_read_config_byte(pdev, PCI_REVISION_ID, &temp)
+ && temp >= 0x40)
+ vt596_features |= FEATURE_I2CBLOCK;
+ break;
+ }
+
vt596_adapter.dev.parent = &pdev->dev;
snprintf(vt596_adapter.name, I2C_NAME_SIZE,
- "SMBus Via Pro adapter at %04x", vt596_smba);
-
+ "SMBus Via Pro adapter at %04x", vt596_smba);
+
vt596_pdev = pci_dev_get(pdev);
if (i2c_add_adapter(&vt596_adapter)) {
pci_dev_put(vt596_pdev);
@@ -395,7 +411,7 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
*/
return -ENODEV;
- release_region:
+release_region:
release_region(vt596_smba, 8);
return error;
}
@@ -420,9 +436,10 @@ static struct pci_device_id vt596_ids[] = {
{ 0, }
};
-MODULE_DEVICE_TABLE (pci, vt596_ids);
+MODULE_DEVICE_TABLE(pci, vt596_ids);
static struct pci_driver vt596_driver = {
+ .owner = THIS_MODULE,
.name = "vt596_smbus",
.id_table = vt596_ids,
.probe = vt596_probe,
diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c
index b675773b0cc1d1..650c3ebde84c0a 100644
--- a/drivers/i2c/busses/i2c-voodoo3.c
+++ b/drivers/i2c/busses/i2c-voodoo3.c
@@ -225,6 +225,7 @@ static void __devexit voodoo3_remove(struct pci_dev *dev)
}
static struct pci_driver voodoo3_driver = {
+ .owner = THIS_MODULE,
.name = "voodoo3_smbus",
.id_table = voodoo3_ids,
.probe = voodoo3_probe,
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index a1d580e0536125..d3478e08452202 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -442,14 +442,13 @@ static int __init scx200_acb_create(int base, int index)
int rc = 0;
char description[64];
- iface = kmalloc(sizeof(*iface), GFP_KERNEL);
+ iface = kzalloc(sizeof(*iface), GFP_KERNEL);
if (!iface) {
printk(KERN_ERR NAME ": can't allocate memory\n");
rc = -ENOMEM;
goto errout;
}
- memset(iface, 0, sizeof(*iface));
adapter = &iface->adapter;
i2c_set_adapdata(adapter, iface);
snprintf(adapter->name, I2C_NAME_SIZE, "SCx200 ACB%d", index);
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 6bd44a44cd28be..f9fae28f5612d8 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -126,4 +126,13 @@ config SENSORS_MAX6875
This driver can also be built as a module. If so, the module
will be called max6875.
+config RTC_X1205_I2C
+ tristate "Xicor X1205 RTC chip"
+ depends on I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for the Xicor X1205 RTC chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called x1205.
+
endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index a876dd42b86060..46178b57b1f1e1 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
obj-$(CONFIG_TPS65010) += tps65010.o
+obj-$(CONFIG_RTC_X1205_I2C) += x1205.o
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c
index 9d3175c0339568..01b0370074101a 100644
--- a/drivers/i2c/chips/ds1337.c
+++ b/drivers/i2c/chips/ds1337.c
@@ -243,11 +243,10 @@ static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind)
I2C_FUNC_I2C))
goto exit;
- if (!(data = kmalloc(sizeof(struct ds1337_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct ds1337_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct ds1337_data));
INIT_LIST_HEAD(&data->list);
/* The common I2C client data is placed right before the
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
index 0936327a946db0..da488b735abf62 100644
--- a/drivers/i2c/chips/ds1374.c
+++ b/drivers/i2c/chips/ds1374.c
@@ -167,7 +167,8 @@ static void ds1374_set_tlet(ulong arg)
static ulong new_time;
-DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet, (ulong) & new_time);
+static DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet,
+ (ulong) & new_time);
int ds1374_set_rtc_time(ulong nowtime)
{
@@ -193,13 +194,11 @@ static int ds1374_probe(struct i2c_adapter *adap, int addr, int kind)
struct i2c_client *client;
int rc;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!client)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
strncpy(client->name, DS1374_DRV_NAME, I2C_NAME_SIZE);
- client->flags = I2C_DF_NOTIFY;
client->addr = addr;
client->adapter = adap;
client->driver = &ds1374_driver;
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index d58403a479086d..4baf573fa04f37 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -88,8 +88,8 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice)
dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
- for (i = slice << 5; i < (slice + 1) << 5; i += I2C_SMBUS_I2C_BLOCK_MAX)
- if (i2c_smbus_read_i2c_block_data(client, i, data->data + i) != I2C_SMBUS_I2C_BLOCK_MAX)
+ for (i = slice << 5; i < (slice + 1) << 5; i += I2C_SMBUS_BLOCK_MAX)
+ if (i2c_smbus_read_i2c_block_data(client, i, data->data + i) != I2C_SMBUS_BLOCK_MAX)
goto exit;
} else {
if (i2c_smbus_write_byte(client, slice << 5)) {
@@ -155,7 +155,7 @@ static int eeprom_attach_adapter(struct i2c_adapter *adapter)
}
/* This function is called by i2c_probe */
-int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
+static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
struct eeprom_data *data;
@@ -171,11 +171,10 @@ int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
| I2C_FUNC_SMBUS_BYTE))
goto exit;
- if (!(data = kmalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct eeprom_data));
new_client = &data->client;
memset(data->data, 0xff, EEPROM_SIZE);
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
index 8ee56d4b389104..eaa4742e04fa66 100644
--- a/drivers/i2c/chips/isp1301_omap.c
+++ b/drivers/i2c/chips/isp1301_omap.c
@@ -888,6 +888,7 @@ static int otg_remove(struct device *dev)
}
struct device_driver omap_otg_driver = {
+ .owner = THIS_MODULE,
.name = "omap_otg",
.bus = &platform_bus_type,
.probe = otg_probe,
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index 3f14528a52a924..3df309ae44a6e9 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -174,13 +174,11 @@ m41t00_probe(struct i2c_adapter *adap, int addr, int kind)
struct i2c_client *client;
int rc;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!client)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
strncpy(client->name, M41T00_DRV_NAME, I2C_NAME_SIZE);
- client->flags = I2C_DF_NOTIFY;
client->addr = addr;
client->adapter = adap;
client->driver = &m41t00_driver;
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c
index 9e1aeb69abf9fa..b376a006883cdc 100644
--- a/drivers/i2c/chips/max6875.c
+++ b/drivers/i2c/chips/max6875.c
@@ -179,16 +179,14 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
if (address & 1)
return 0;
- if (!(data = kmalloc(sizeof(struct max6875_data), GFP_KERNEL)))
+ if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL)))
return -ENOMEM;
- memset(data, 0, sizeof(struct max6875_data));
/* A fake client is created on the odd address */
- if (!(fake_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
+ if (!(fake_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
err = -ENOMEM;
goto exit_kfree1;
}
- memset(fake_client, 0, sizeof(struct i2c_client));
/* Init real i2c_client */
real_client = &data->client;
diff --git a/drivers/i2c/chips/pca9539.c b/drivers/i2c/chips/pca9539.c
index 225577fdda4d58..59a93034622977 100644
--- a/drivers/i2c/chips/pca9539.c
+++ b/drivers/i2c/chips/pca9539.c
@@ -122,11 +122,10 @@ static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet. */
- if (!(data = kmalloc(sizeof(struct pca9539_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct pca9539_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct pca9539_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
index 6525743ff9fd76..c323c2de236c87 100644
--- a/drivers/i2c/chips/pcf8574.c
+++ b/drivers/i2c/chips/pcf8574.c
@@ -115,7 +115,7 @@ static int pcf8574_attach_adapter(struct i2c_adapter *adapter)
}
/* This function is called by i2c_probe */
-int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
+static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
struct pcf8574_data *data;
@@ -127,11 +127,10 @@ int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet. */
- if (!(data = kmalloc(sizeof(struct pcf8574_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct pcf8574_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct pcf8574_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
index 80f1df9a4500f7..ce420a67560bf2 100644
--- a/drivers/i2c/chips/pcf8591.c
+++ b/drivers/i2c/chips/pcf8591.c
@@ -166,7 +166,7 @@ static int pcf8591_attach_adapter(struct i2c_adapter *adapter)
}
/* This function is called by i2c_probe */
-int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
+static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
struct pcf8591_data *data;
@@ -178,11 +178,10 @@ int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet. */
- if (!(data = kmalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct pcf8591_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
index 0b5385c892b1ae..916cdc1af23c01 100644
--- a/drivers/i2c/chips/rtc8564.c
+++ b/drivers/i2c/chips/rtc8564.c
@@ -148,17 +148,16 @@ static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind)
{addr, I2C_M_RD, 2, data}
};
- d = kmalloc(sizeof(struct rtc8564_data), GFP_KERNEL);
+ d = kzalloc(sizeof(struct rtc8564_data), GFP_KERNEL);
if (!d) {
ret = -ENOMEM;
goto done;
}
- memset(d, 0, sizeof(struct rtc8564_data));
new_client = &d->client;
strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE);
i2c_set_clientdata(new_client, d);
- new_client->flags = I2C_CLIENT_ALLOW_USE | I2C_DF_NOTIFY;
+ new_client->flags = I2C_CLIENT_ALLOW_USE;
new_client->addr = addr;
new_client->adapter = adap;
new_client->driver = &rtc8564_driver;
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
index 280e9638c0f8af..280dd7a45db65b 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/i2c/chips/tps65010.c
@@ -500,11 +500,10 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
return 0;
}
- tps = kmalloc(sizeof *tps, GFP_KERNEL);
+ tps = kzalloc(sizeof *tps, GFP_KERNEL);
if (!tps)
return 0;
- memset(tps, 0, sizeof *tps);
init_MUTEX(&tps->lock);
INIT_WORK(&tps->work, tps65010_work, tps);
tps->irq = -1;
diff --git a/drivers/i2c/chips/x1205.c b/drivers/i2c/chips/x1205.c
new file mode 100644
index 00000000000000..7da366cdc18c54
--- /dev/null
+++ b/drivers/i2c/chips/x1205.c
@@ -0,0 +1,698 @@
+/*
+ * x1205.c - An i2c driver for the Xicor X1205 RTC
+ * Copyright 2004 Karen Spearel
+ * Copyright 2005 Alessandro Zummo
+ *
+ * please send all reports to:
+ * kas11 at tampabay dot rr dot com
+ * a dot zummo at towertech dot it
+ *
+ * based on the other drivers in this same directory.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/string.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+#include <linux/list.h>
+
+#include <linux/x1205.h>
+
+#define DRV_VERSION "0.9.9"
+
+/* Addresses to scan: none. This chip is located at
+ * 0x6f and uses a two bytes register addressing.
+ * Two bytes need to be written to read a single register,
+ * while most other chips just require one and take the second
+ * one as the data to be written. To prevent corrupting
+ * unknown chips, the user must explicitely set the probe parameter.
+ */
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD;
+I2C_CLIENT_MODULE_PARM(hctosys,
+ "Set the system time from the hardware clock upon initialization");
+
+/* offsets into CCR area */
+
+#define CCR_SEC 0
+#define CCR_MIN 1
+#define CCR_HOUR 2
+#define CCR_MDAY 3
+#define CCR_MONTH 4
+#define CCR_YEAR 5
+#define CCR_WDAY 6
+#define CCR_Y2K 7
+
+#define X1205_REG_SR 0x3F /* status register */
+#define X1205_REG_Y2K 0x37
+#define X1205_REG_DW 0x36
+#define X1205_REG_YR 0x35
+#define X1205_REG_MO 0x34
+#define X1205_REG_DT 0x33
+#define X1205_REG_HR 0x32
+#define X1205_REG_MN 0x31
+#define X1205_REG_SC 0x30
+#define X1205_REG_DTR 0x13
+#define X1205_REG_ATR 0x12
+#define X1205_REG_INT 0x11
+#define X1205_REG_0 0x10
+#define X1205_REG_Y2K1 0x0F
+#define X1205_REG_DWA1 0x0E
+#define X1205_REG_YRA1 0x0D
+#define X1205_REG_MOA1 0x0C
+#define X1205_REG_DTA1 0x0B
+#define X1205_REG_HRA1 0x0A
+#define X1205_REG_MNA1 0x09
+#define X1205_REG_SCA1 0x08
+#define X1205_REG_Y2K0 0x07
+#define X1205_REG_DWA0 0x06
+#define X1205_REG_YRA0 0x05
+#define X1205_REG_MOA0 0x04
+#define X1205_REG_DTA0 0x03
+#define X1205_REG_HRA0 0x02
+#define X1205_REG_MNA0 0x01
+#define X1205_REG_SCA0 0x00
+
+#define X1205_CCR_BASE 0x30 /* Base address of CCR */
+#define X1205_ALM0_BASE 0x00 /* Base address of ALARM0 */
+
+#define X1205_SR_RTCF 0x01 /* Clock failure */
+#define X1205_SR_WEL 0x02 /* Write Enable Latch */
+#define X1205_SR_RWEL 0x04 /* Register Write Enable */
+
+#define X1205_DTR_DTR0 0x01
+#define X1205_DTR_DTR1 0x02
+#define X1205_DTR_DTR2 0x04
+
+#define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */
+
+/* Prototypes */
+static int x1205_attach(struct i2c_adapter *adapter);
+static int x1205_detach(struct i2c_client *client);
+static int x1205_probe(struct i2c_adapter *adapter, int address, int kind);
+static int x1205_command(struct i2c_client *client, unsigned int cmd,
+ void *arg);
+
+static struct i2c_driver x1205_driver = {
+ .owner = THIS_MODULE,
+ .name = "x1205",
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = &x1205_attach,
+ .detach_client = &x1205_detach,
+};
+
+struct x1205_data {
+ struct i2c_client client;
+ struct list_head list;
+ unsigned int epoch;
+};
+
+static const unsigned char days_in_mo[] =
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+static LIST_HEAD(x1205_clients);
+
+/* Workaround until the I2C subsytem will allow to send
+ * commands to a specific client. This function will send the command
+ * to the first client.
+ */
+int x1205_do_command(unsigned int cmd, void *arg)
+{
+ struct list_head *walk;
+ struct list_head *tmp;
+ struct x1205_data *data;
+
+ list_for_each_safe(walk, tmp, &x1205_clients) {
+ data = list_entry(walk, struct x1205_data, list);
+ return x1205_command(&data->client, cmd, arg);
+ }
+
+ return -ENODEV;
+}
+
+#define is_leap(year) \
+ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
+
+/* make sure the rtc_time values are in bounds */
+static int x1205_validate_tm(struct rtc_time *tm)
+{
+ int year = tm->tm_year + 1900;
+
+ if ((tm->tm_year < 70) || (tm->tm_year > 255))
+ return -EINVAL;
+
+ if ((tm->tm_mon > 11) || (tm->tm_mday == 0))
+ return -EINVAL;
+
+ if (tm->tm_mday > days_in_mo[tm->tm_mon]
+ + ((tm->tm_mon == 1) && is_leap(year)))
+ return -EINVAL;
+
+ if ((tm->tm_hour >= 24) || (tm->tm_min >= 60) || (tm->tm_sec >= 60))
+ return -EINVAL;
+
+ return 0;
+}
+
+/*
+ * In the routines that deal directly with the x1205 hardware, we use
+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch
+ * Epoch is initialized as 2000. Time is set to UTC.
+ */
+static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
+ u8 reg_base)
+{
+ unsigned char dt_addr[2] = { 0, reg_base };
+ static unsigned char sr_addr[2] = { 0, X1205_REG_SR };
+
+ unsigned char buf[8], sr;
+
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 2, sr_addr }, /* setup read ptr */
+ { client->addr, I2C_M_RD, 1, &sr }, /* read status */
+ { client->addr, 0, 2, dt_addr }, /* setup read ptr */
+ { client->addr, I2C_M_RD, 8, buf }, /* read date */
+ };
+
+ struct x1205_data *data = i2c_get_clientdata(client);
+
+ /* read status register */
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ /* check for battery failure */
+ if (sr & X1205_SR_RTCF) {
+ dev_warn(&client->dev,
+ "Clock had a power failure, you must set the date.\n");
+ return -EINVAL;
+ }
+
+ /* read date registers */
+ if ((i2c_transfer(client->adapter, &msgs[2], 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ dev_dbg(&client->dev,
+ "%s: raw read data - sec=%02x, min=%02x, hr=%02x, "
+ "mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n",
+ __FUNCTION__,
+ buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5], buf[6], buf[7]);
+
+ tm->tm_sec = BCD2BIN(buf[CCR_SEC]);
+ tm->tm_min = BCD2BIN(buf[CCR_MIN]);
+ tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
+ tm->tm_mday = BCD2BIN(buf[CCR_MDAY]);
+ tm->tm_mon = BCD2BIN(buf[CCR_MONTH]);
+ data->epoch = BCD2BIN(buf[CCR_Y2K]) * 100;
+ tm->tm_year = BCD2BIN(buf[CCR_YEAR]) + data->epoch - 1900;
+ tm->tm_wday = buf[CCR_WDAY];
+
+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ return 0;
+}
+
+static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
+ int datetoo, u8 reg_base)
+{
+ int i, err, xfer;
+
+ unsigned char buf[8];
+
+ static const unsigned char wel[3] = { 0, X1205_REG_SR,
+ X1205_SR_WEL };
+
+ static const unsigned char rwel[3] = { 0, X1205_REG_SR,
+ X1205_SR_WEL | X1205_SR_RWEL };
+
+ static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 };
+
+ struct x1205_data *data = i2c_get_clientdata(client);
+
+ /* check if all values in the tm struct are correct */
+ if ((err = x1205_validate_tm(tm)) < 0)
+ return err;
+
+ dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ buf[CCR_SEC] = BIN2BCD(tm->tm_sec);
+ buf[CCR_MIN] = BIN2BCD(tm->tm_min);
+
+ /* set hour and 24hr bit */
+ buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL;
+
+ /* should we also set the date? */
+ if (datetoo) {
+ buf[CCR_MDAY] = BIN2BCD(tm->tm_mday);
+
+ /* month, 0 - 11 */
+ buf[CCR_MONTH] = BIN2BCD(tm->tm_mon);
+
+ /* year, since 1900 */
+ buf[CCR_YEAR] = BIN2BCD(tm->tm_year + 1900 - data->epoch);
+ buf[CCR_WDAY] = tm->tm_wday & 0x07;
+ buf[CCR_Y2K] = BIN2BCD(data->epoch / 100);
+ }
+
+ /* this sequence is required to unlock the chip */
+ xfer = i2c_master_send(client, wel, 3);
+ if (xfer != 3) {
+ dev_err(&client->dev, "%s: wel - %d\n", __FUNCTION__, xfer);
+ return -EIO;
+ }
+
+ xfer = i2c_master_send(client, rwel, 3);
+ if (xfer != 3) {
+ dev_err(&client->dev, "%s: rwel - %d\n", __FUNCTION__, xfer);
+ return -EIO;
+ }
+
+ /* write register's data */
+ for (i = 0; i < (datetoo ? 8 : 3); i++) {
+ unsigned char rdata[3] = { 0, reg_base + i, buf[i] };
+
+ xfer = i2c_master_send(client, rdata, 3);
+ if (xfer != 3) {
+ dev_err(&client->dev,
+ "%s: xfer=%d addr=%02x, data=%02x\n",
+ __FUNCTION__,
+ xfer, rdata[1], rdata[2]);
+ return -EIO;
+ }
+ };
+
+ /* disable further writes */
+ xfer = i2c_master_send(client, diswe, 3);
+ if (xfer != 3) {
+ dev_err(&client->dev, "%s: diswe - %d\n", __FUNCTION__, xfer);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int x1205_get_dtrim(struct i2c_client *client, int *trim)
+{
+ unsigned char dtr;
+ static unsigned char dtr_addr[2] = { 0, X1205_REG_DTR };
+
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 2, dtr_addr }, /* setup read ptr */
+ { client->addr, I2C_M_RD, 1, &dtr }, /* read dtr */
+ };
+
+ /* read dtr register */
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ dev_dbg(&client->dev, "%s: raw dtr=%x\n", __FUNCTION__, dtr);
+
+ *trim = 0;
+
+ if (dtr & X1205_DTR_DTR0)
+ *trim += 20;
+
+ if (dtr & X1205_DTR_DTR1)
+ *trim += 10;
+
+ if (dtr & X1205_DTR_DTR2)
+ *trim = -*trim;
+
+ return 0;
+}
+
+static int x1205_get_atrim(struct i2c_client *client, int *trim)
+{
+ s8 atr;
+ static unsigned char atr_addr[2] = { 0, X1205_REG_ATR };
+
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 2, atr_addr }, /* setup read ptr */
+ { client->addr, I2C_M_RD, 1, &atr }, /* read atr */
+ };
+
+ /* read atr register */
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ dev_dbg(&client->dev, "%s: raw atr=%x\n", __FUNCTION__, atr);
+
+ /* atr is a two's complement value on 6 bits,
+ * perform sign extension. The formula is
+ * Catr = (atr * 0.25pF) + 11.00pF.
+ */
+ if (atr & 0x20)
+ atr |= 0xC0;
+
+ dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __FUNCTION__, atr, atr);
+
+ *trim = (atr * 250) + 11000;
+
+ dev_dbg(&client->dev, "%s: real=%d\n", __FUNCTION__, *trim);
+
+ return 0;
+}
+
+static int x1205_hctosys(struct i2c_client *client)
+{
+ int err;
+
+ struct rtc_time tm;
+ struct timespec tv;
+
+ err = x1205_command(client, X1205_CMD_GETDATETIME, &tm);
+
+ if (err) {
+ dev_err(&client->dev,
+ "Unable to set the system clock\n");
+ return err;
+ }
+
+ /* IMPORTANT: the RTC only stores whole seconds. It is arbitrary
+ * whether it stores the most close value or the value with partial
+ * seconds truncated. However, it is important that we use it to store
+ * the truncated value. This is because otherwise it is necessary,
+ * in an rtc sync function, to read both xtime.tv_sec and
+ * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read
+ * of >32bits is not possible. So storing the most close value would
+ * slow down the sync API. So here we have the truncated value and
+ * the best guess is to add 0.5s.
+ */
+
+ tv.tv_nsec = NSEC_PER_SEC >> 1;
+
+ /* WARNING: this is not the C library 'mktime' call, it is a built in
+ * inline function from include/linux/time.h. It expects (requires)
+ * the month to be in the range 1-12
+ */
+
+ tv.tv_sec = mktime(tm.tm_year + 1900, tm.tm_mon + 1,
+ tm.tm_mday, tm.tm_hour,
+ tm.tm_min, tm.tm_sec);
+
+ do_settimeofday(&tv);
+
+ dev_info(&client->dev,
+ "setting the system clock to %d-%d-%d %d:%d:%d\n",
+ tm.tm_year + 1900, tm.tm_mon + 1,
+ tm.tm_mday, tm.tm_hour, tm.tm_min,
+ tm.tm_sec);
+
+ return 0;
+}
+
+struct x1205_limit
+{
+ unsigned char reg;
+ unsigned char mask;
+ unsigned char min;
+ unsigned char max;
+};
+
+static int x1205_validate_client(struct i2c_client *client)
+{
+ int i, xfer;
+
+ /* Probe array. We will read the register at the specified
+ * address and check if the given bits are zero.
+ */
+ static const unsigned char probe_zero_pattern[] = {
+ /* register, mask */
+ X1205_REG_SR, 0x18,
+ X1205_REG_DTR, 0xF8,
+ X1205_REG_ATR, 0xC0,
+ X1205_REG_INT, 0x18,
+ X1205_REG_0, 0xFF,
+ };
+
+ static const struct x1205_limit probe_limits_pattern[] = {
+ /* register, mask, min, max */
+ { X1205_REG_Y2K, 0xFF, 19, 20 },
+ { X1205_REG_DW, 0xFF, 0, 6 },
+ { X1205_REG_YR, 0xFF, 0, 99 },
+ { X1205_REG_MO, 0xFF, 0, 12 },
+ { X1205_REG_DT, 0xFF, 0, 31 },
+ { X1205_REG_HR, 0x7F, 0, 23 },
+ { X1205_REG_MN, 0xFF, 0, 59 },
+ { X1205_REG_SC, 0xFF, 0, 59 },
+ { X1205_REG_Y2K1, 0xFF, 19, 20 },
+ { X1205_REG_Y2K0, 0xFF, 19, 20 },
+ };
+
+ /* check that registers have bits a 0 where expected */
+ for (i = 0; i < ARRAY_SIZE(probe_zero_pattern); i += 2) {
+ unsigned char buf;
+
+ unsigned char addr[2] = { 0, probe_zero_pattern[i] };
+
+ struct i2c_msg msgs[2] = {
+ { client->addr, 0, 2, addr },
+ { client->addr, I2C_M_RD, 1, &buf },
+ };
+
+ xfer = i2c_transfer(client->adapter, msgs, 2);
+ if (xfer != 2) {
+ dev_err(&client->adapter->dev,
+ "%s: could not read register %x\n",
+ __FUNCTION__, addr[1]);
+
+ return -EIO;
+ }
+
+ if ((buf & probe_zero_pattern[i+1]) != 0) {
+ dev_err(&client->adapter->dev,
+ "%s: register=%02x, zero pattern=%d, value=%x\n",
+ __FUNCTION__, addr[1], i, buf);
+
+ return -ENODEV;
+ }
+ }
+
+ /* check limits (only registers with bcd values) */
+ for (i = 0; i < ARRAY_SIZE(probe_limits_pattern); i++) {
+ unsigned char reg, value;
+
+ unsigned char addr[2] = { 0, probe_limits_pattern[i].reg };
+
+ struct i2c_msg msgs[2] = {
+ { client->addr, 0, 2, addr },
+ { client->addr, I2C_M_RD, 1, &reg },
+ };
+
+ xfer = i2c_transfer(client->adapter, msgs, 2);
+
+ if (xfer != 2) {
+ dev_err(&client->adapter->dev,
+ "%s: could not read register %x\n",
+ __FUNCTION__, addr[1]);
+
+ return -EIO;
+ }
+
+ value = BCD2BIN(reg & probe_limits_pattern[i].mask);
+
+ if (value > probe_limits_pattern[i].max ||
+ value < probe_limits_pattern[i].min) {
+ dev_dbg(&client->adapter->dev,
+ "%s: register=%x, lim pattern=%d, value=%d\n",
+ __FUNCTION__, addr[1], i, value);
+
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+static int x1205_attach(struct i2c_adapter *adapter)
+{
+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+
+ return i2c_probe(adapter, &addr_data, x1205_probe);
+}
+
+int x1205_direct_attach(int adapter_id,
+ struct i2c_client_address_data *address_data)
+{
+ int err;
+ struct i2c_adapter *adapter = i2c_get_adapter(adapter_id);
+
+ if (adapter) {
+ err = i2c_probe(adapter,
+ address_data, x1205_probe);
+
+ i2c_put_adapter(adapter);
+
+ return err;
+ }
+
+ return -ENODEV;
+}
+
+static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *client;
+ struct x1205_data *data;
+
+ int err = 0;
+
+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+ err = -ENODEV;
+ goto exit;
+ }
+
+ if (!(data = kzalloc(sizeof(struct x1205_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ /* Initialize our structures */
+ data->epoch = 2000;
+
+ client = &data->client;
+ client->addr = address;
+ client->driver = &x1205_driver;
+ client->adapter = adapter;
+
+ strlcpy(client->name, "x1205", I2C_NAME_SIZE);
+
+ i2c_set_clientdata(client, data);
+
+ /* Verify the chip is really an X1205 */
+ if (kind < 0) {
+ if (x1205_validate_client(client) < 0) {
+ err = -ENODEV;
+ goto exit_kfree;
+ }
+ }
+
+ /* Inform the i2c layer */
+ if ((err = i2c_attach_client(client)))
+ goto exit_kfree;
+
+ list_add(&data->list, &x1205_clients);
+
+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+
+ /* If requested, set the system time */
+ if (hctosys)
+ x1205_hctosys(client);
+
+ return 0;
+
+exit_kfree:
+ kfree(data);
+
+exit:
+ return err;
+}
+
+static int x1205_detach(struct i2c_client *client)
+{
+ int err;
+ struct x1205_data *data = i2c_get_clientdata(client);
+
+ dev_dbg(&client->dev, "%s\n", __FUNCTION__);
+
+ if ((err = i2c_detach_client(client)))
+ return err;
+
+ list_del(&data->list);
+
+ kfree(data);
+
+ return 0;
+}
+
+static int x1205_command(struct i2c_client *client, unsigned int cmd,
+ void *param)
+{
+ if (param == NULL)
+ return -EINVAL;
+
+ if (!capable(CAP_SYS_TIME))
+ return -EACCES;
+
+ dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
+
+ switch (cmd) {
+ case X1205_CMD_GETDATETIME:
+ return x1205_get_datetime(client, param, X1205_CCR_BASE);
+
+ case X1205_CMD_SETTIME:
+ return x1205_set_datetime(client, param, 0,
+ X1205_CCR_BASE);
+
+ case X1205_CMD_SETDATETIME:
+ return x1205_set_datetime(client, param, 1,
+ X1205_CCR_BASE);
+
+ case X1205_CMD_GETALARM:
+ return x1205_get_datetime(client, param, X1205_ALM0_BASE);
+
+ case X1205_CMD_SETALARM:
+ return x1205_set_datetime(client, param, 1,
+ X1205_ALM0_BASE);
+
+ case X1205_CMD_GETDTRIM:
+ return x1205_get_dtrim(client, param);
+
+ case X1205_CMD_GETATRIM:
+ return x1205_get_atrim(client, param);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int __init x1205_init(void)
+{
+ return i2c_add_driver(&x1205_driver);
+}
+
+static void __exit x1205_exit(void)
+{
+ i2c_del_driver(&x1205_driver);
+}
+
+MODULE_AUTHOR(
+ "Karen Spearel <kas11@tampabay.rr.com>, "
+ "Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("Xicor X1205 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+EXPORT_SYMBOL_GPL(x1205_do_command);
+EXPORT_SYMBOL_GPL(x1205_direct_attach);
+
+module_init(x1205_init);
+module_exit(x1205_exit);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index dda472e5e8be3b..02e335a04f095a 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -19,7 +19,8 @@
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>.
All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl>
- SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> */
+ SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and
+ Jean Delvare <khali@linux-fr.org> */
#include <linux/module.h>
#include <linux/kernel.h>
@@ -48,7 +49,7 @@ static int i2c_bus_suspend(struct device * dev, pm_message_t state)
int rc = 0;
if (dev->driver && dev->driver->suspend)
- rc = dev->driver->suspend(dev,state,0);
+ rc = dev->driver->suspend(dev, state);
return rc;
}
@@ -57,7 +58,7 @@ static int i2c_bus_resume(struct device * dev)
int rc = 0;
if (dev->driver && dev->driver->resume)
- rc = dev->driver->resume(dev,0);
+ rc = dev->driver->resume(dev);
return rc;
}
@@ -85,6 +86,7 @@ void i2c_adapter_dev_release(struct device *dev)
}
struct device_driver i2c_adapter_driver = {
+ .owner = THIS_MODULE,
.name = "i2c_adapter",
.bus = &i2c_bus_type,
.probe = i2c_device_probe,
@@ -98,6 +100,7 @@ static void i2c_adapter_class_dev_release(struct class_device *dev)
}
struct class i2c_adapter_class = {
+ .owner = THIS_MODULE,
.name = "i2c-adapter",
.release = &i2c_adapter_class_dev_release,
};
@@ -291,6 +294,7 @@ int i2c_add_driver(struct i2c_driver *driver)
down(&core_lists);
/* add the driver to the list of i2c drivers in the driver core */
+ driver->driver.owner = driver->owner;
driver->driver.name = driver->name;
driver->driver.bus = &i2c_bus_type;
driver->driver.probe = i2c_device_probe;
@@ -706,10 +710,6 @@ int i2c_probe(struct i2c_adapter *adapter,
int i, err;
int adap_id = i2c_adapter_id(adapter);
- /* Forget it if we can't probe using SMBUS_QUICK */
- if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_QUICK))
- return -1;
-
/* Force entries are done first, and are not affected by ignore
entries */
if (address_data->forces) {
@@ -736,6 +736,17 @@ int i2c_probe(struct i2c_adapter *adapter,
}
}
+ /* Stop here if we can't use SMBUS_QUICK */
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) {
+ if (address_data->probe[0] == I2C_CLIENT_END
+ && address_data->normal_i2c[0] == I2C_CLIENT_END)
+ return 0;
+
+ dev_warn(&adapter->dev, "SMBus Quick command not supported, "
+ "can't probe for chips\n");
+ return -1;
+ }
+
/* Probe entries are done second, and are not affected by ignore
entries either */
for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2) {
@@ -820,101 +831,44 @@ crc8(u16 data)
return (u8)(data >> 8);
}
-/* CRC over count bytes in the first array plus the bytes in the rest
- array if it is non-null. rest[0] is the (length of rest) - 1
- and is included. */
-static u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest)
+/* Incremental CRC8 over count bytes in the array pointed to by p */
+static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count)
{
int i;
for(i = 0; i < count; i++)
- crc = crc8((crc ^ first[i]) << 8);
- if(rest != NULL)
- for(i = 0; i <= rest[0]; i++)
- crc = crc8((crc ^ rest[i]) << 8);
+ crc = crc8((crc ^ p[i]) << 8);
return crc;
}
-static u8 i2c_smbus_pec(int count, u8 *first, u8 *rest)
+/* Assume a 7-bit address, which is reasonable for SMBus */
+static u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg)
{
- return i2c_smbus_partial_pec(0, count, first, rest);
+ /* The address will be sent first */
+ u8 addr = (msg->addr << 1) | !!(msg->flags & I2C_M_RD);
+ pec = i2c_smbus_pec(pec, &addr, 1);
+
+ /* The data buffer follows */
+ return i2c_smbus_pec(pec, msg->buf, msg->len);
}
-/* Returns new "size" (transaction type)
- Note that we convert byte to byte_data and byte_data to word_data
- rather than invent new xxx_PEC transactions. */
-static int i2c_smbus_add_pec(u16 addr, u8 command, int size,
- union i2c_smbus_data *data)
+/* Used for write only transactions */
+static inline void i2c_smbus_add_pec(struct i2c_msg *msg)
{
- u8 buf[3];
-
- buf[0] = addr << 1;
- buf[1] = command;
- switch(size) {
- case I2C_SMBUS_BYTE:
- data->byte = i2c_smbus_pec(2, buf, NULL);
- size = I2C_SMBUS_BYTE_DATA;
- break;
- case I2C_SMBUS_BYTE_DATA:
- buf[2] = data->byte;
- data->word = buf[2] ||
- (i2c_smbus_pec(3, buf, NULL) << 8);
- size = I2C_SMBUS_WORD_DATA;
- break;
- case I2C_SMBUS_WORD_DATA:
- /* unsupported */
- break;
- case I2C_SMBUS_BLOCK_DATA:
- data->block[data->block[0] + 1] =
- i2c_smbus_pec(2, buf, data->block);
- size = I2C_SMBUS_BLOCK_DATA_PEC;
- break;
- }
- return size;
+ msg->buf[msg->len] = i2c_smbus_msg_pec(0, msg);
+ msg->len++;
}
-static int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial,
- union i2c_smbus_data *data)
+/* Return <0 on CRC error
+ If there was a write before this read (most cases) we need to take the
+ partial CRC from the write part into account.
+ Note that this function does modify the message (we need to decrease the
+ message length to hide the CRC byte from the caller). */
+static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg)
{
- u8 buf[3], rpec, cpec;
+ u8 rpec = msg->buf[--msg->len];
+ cpec = i2c_smbus_msg_pec(cpec, msg);
- buf[1] = command;
- switch(size) {
- case I2C_SMBUS_BYTE_DATA:
- buf[0] = (addr << 1) | 1;
- cpec = i2c_smbus_pec(2, buf, NULL);
- rpec = data->byte;
- break;
- case I2C_SMBUS_WORD_DATA:
- buf[0] = (addr << 1) | 1;
- buf[2] = data->word & 0xff;
- cpec = i2c_smbus_pec(3, buf, NULL);
- rpec = data->word >> 8;
- break;
- case I2C_SMBUS_WORD_DATA_PEC:
- /* unsupported */
- cpec = rpec = 0;
- break;
- case I2C_SMBUS_PROC_CALL_PEC:
- /* unsupported */
- cpec = rpec = 0;
- break;
- case I2C_SMBUS_BLOCK_DATA_PEC:
- buf[0] = (addr << 1);
- buf[2] = (addr << 1) | 1;
- cpec = i2c_smbus_pec(3, buf, data->block);
- rpec = data->block[data->block[0] + 1];
- break;
- case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
- buf[0] = (addr << 1) | 1;
- rpec = i2c_smbus_partial_pec(partial, 1,
- buf, data->block);
- cpec = data->block[data->block[0] + 1];
- break;
- default:
- cpec = rpec = 0;
- break;
- }
if (rpec != cpec) {
pr_debug("i2c-core: Bad PEC 0x%02x vs. 0x%02x\n",
rpec, cpec);
@@ -941,9 +895,8 @@ s32 i2c_smbus_read_byte(struct i2c_client *client)
s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
{
- union i2c_smbus_data data; /* only for PEC */
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,&data);
+ I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
}
s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
@@ -1026,13 +979,14 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
need to use only one message; when reading, we need two. We initialize
most things with sane defaults, to keep the code below somewhat
simpler. */
- unsigned char msgbuf0[34];
- unsigned char msgbuf1[34];
+ unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3];
+ unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];
int num = read_write == I2C_SMBUS_READ?2:1;
struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
{ addr, flags | I2C_M_RD, 0, msgbuf1 }
};
int i;
+ u8 partial_pec = 0;
msgbuf0[0] = command;
switch(size) {
@@ -1075,7 +1029,6 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
msgbuf0[2] = (data->word >> 8) & 0xff;
break;
case I2C_SMBUS_BLOCK_DATA:
- case I2C_SMBUS_BLOCK_DATA_PEC:
if (read_write == I2C_SMBUS_READ) {
dev_err(&adapter->dev, "Block read not supported "
"under I2C emulation!\n");
@@ -1088,23 +1041,20 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
data->block[0]);
return -1;
}
- if(size == I2C_SMBUS_BLOCK_DATA_PEC)
- (msg[0].len)++;
- for (i = 1; i <= msg[0].len; i++)
+ for (i = 1; i < msg[0].len; i++)
msgbuf0[i] = data->block[i-1];
}
break;
case I2C_SMBUS_BLOCK_PROC_CALL:
- case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
dev_dbg(&adapter->dev, "Block process call not supported "
"under I2C emulation!\n");
return -1;
case I2C_SMBUS_I2C_BLOCK_DATA:
if (read_write == I2C_SMBUS_READ) {
- msg[1].len = I2C_SMBUS_I2C_BLOCK_MAX;
+ msg[1].len = I2C_SMBUS_BLOCK_MAX;
} else {
msg[0].len = data->block[0] + 1;
- if (msg[0].len > I2C_SMBUS_I2C_BLOCK_MAX + 1) {
+ if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) {
dev_err(&adapter->dev, "i2c_smbus_xfer_emulated called with "
"invalid block write size (%d)\n",
data->block[0]);
@@ -1120,9 +1070,30 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
return -1;
}
+ i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK
+ && size != I2C_SMBUS_I2C_BLOCK_DATA);
+ if (i) {
+ /* Compute PEC if first message is a write */
+ if (!(msg[0].flags & I2C_M_RD)) {
+ if (num == 1) /* Write only */
+ i2c_smbus_add_pec(&msg[0]);
+ else /* Write followed by read */
+ partial_pec = i2c_smbus_msg_pec(0, &msg[0]);
+ }
+ /* Ask for PEC if last message is a read */
+ if (msg[num-1].flags & I2C_M_RD)
+ msg[num-1].len++;
+ }
+
if (i2c_transfer(adapter, msg, num) < 0)
return -1;
+ /* Check PEC if last message is a read */
+ if (i && (msg[num-1].flags & I2C_M_RD)) {
+ if (i2c_smbus_check_pec(partial_pec, &msg[num-1]) < 0)
+ return -1;
+ }
+
if (read_write == I2C_SMBUS_READ)
switch(size) {
case I2C_SMBUS_BYTE:
@@ -1137,8 +1108,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
/* fixed at 32 for now */
- data->block[0] = I2C_SMBUS_I2C_BLOCK_MAX;
- for (i = 0; i < I2C_SMBUS_I2C_BLOCK_MAX; i++)
+ data->block[0] = I2C_SMBUS_BLOCK_MAX;
+ for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
data->block[i+1] = msgbuf1[i];
break;
}
@@ -1151,28 +1122,8 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
union i2c_smbus_data * data)
{
s32 res;
- int swpec = 0;
- u8 partial = 0;
flags &= I2C_M_TEN | I2C_CLIENT_PEC;
- if((flags & I2C_CLIENT_PEC) &&
- !(i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HWPEC_CALC))) {
- swpec = 1;
- if(read_write == I2C_SMBUS_READ &&
- size == I2C_SMBUS_BLOCK_DATA)
- size = I2C_SMBUS_BLOCK_DATA_PEC;
- else if(size == I2C_SMBUS_PROC_CALL)
- size = I2C_SMBUS_PROC_CALL_PEC;
- else if(size == I2C_SMBUS_BLOCK_PROC_CALL) {
- i2c_smbus_add_pec(addr, command,
- I2C_SMBUS_BLOCK_DATA, data);
- partial = data->block[data->block[0] + 1];
- size = I2C_SMBUS_BLOCK_PROC_CALL_PEC;
- } else if(read_write == I2C_SMBUS_WRITE &&
- size != I2C_SMBUS_QUICK &&
- size != I2C_SMBUS_I2C_BLOCK_DATA)
- size = i2c_smbus_add_pec(addr, command, size, data);
- }
if (adapter->algo->smbus_xfer) {
down(&adapter->bus_lock);
@@ -1183,13 +1134,6 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
command,size,data);
- if(res >= 0 && swpec &&
- size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA &&
- (read_write == I2C_SMBUS_READ || size == I2C_SMBUS_PROC_CALL_PEC ||
- size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)) {
- if(i2c_smbus_check_pec(addr, command, size, partial, data))
- return -1;
- }
return res;
}
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index aa7a4fadef64d6..ea14c8f1c82baa 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -26,15 +26,11 @@
/* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */
-/* The devfs code is contributed by Philipp Matthias Hahn
- <pmhahn@titan.lahn.de> */
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
-#include <linux/devfs_fs_kernel.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
@@ -80,10 +76,9 @@ static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap)
{
struct i2c_dev *i2c_dev;
- i2c_dev = kmalloc(sizeof(*i2c_dev), GFP_KERNEL);
+ i2c_dev = kzalloc(sizeof(*i2c_dev), GFP_KERNEL);
if (!i2c_dev)
return ERR_PTR(-ENOMEM);
- memset(i2c_dev, 0x00, sizeof(*i2c_dev));
spin_lock(&i2c_dev_array_lock);
if (i2c_dev_array[adap->nr]) {
@@ -177,8 +172,8 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
int i,datasize,res;
unsigned long funcs;
- dev_dbg(&client->adapter->dev, "i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n",
- iminor(inode),cmd, arg);
+ dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n",
+ cmd, arg);
switch ( cmd ) {
case I2C_SLAVE:
@@ -432,8 +427,6 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
if (IS_ERR(i2c_dev))
return PTR_ERR(i2c_dev);
- devfs_mk_cdev(MKDEV(I2C_MAJOR, i2c_dev->minor),
- S_IFCHR|S_IRUSR|S_IWUSR, "i2c/%d", i2c_dev->minor);
pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
adap->name, i2c_dev->minor);
@@ -466,7 +459,6 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
return -ENODEV;
init_completion(&i2c_dev->released);
- devfs_remove("i2c/%d", i2c_dev->minor);
return_i2c_dev(i2c_dev);
class_device_unregister(&i2c_dev->class_dev);
wait_for_completion(&i2c_dev->released);
@@ -522,8 +514,6 @@ static int __init i2c_dev_init(void)
if (res)
goto out_unreg_class;
- devfs_mk_dir("i2c");
-
return 0;
out_unreg_class:
@@ -539,7 +529,6 @@ static void __exit i2c_dev_exit(void)
{
i2c_del_driver(&i2cdev_driver);
class_unregister(&i2c_dev_class);
- devfs_remove("i2c");
unregister_chrdev(I2C_MAJOR,"i2c");
}
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index ee38e6b143a4c2..47f2b832555fd2 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -1013,6 +1013,8 @@ typedef struct ide_tape_obj {
static DECLARE_MUTEX(idetape_ref_sem);
+static struct class *idetape_sysfs_class;
+
#define to_ide_tape(obj) container_of(obj, struct ide_tape_obj, kref)
#define ide_tape_g(disk) \
@@ -4704,6 +4706,10 @@ static void ide_tape_release(struct kref *kref)
drive->dsc_overlap = 0;
drive->driver_data = NULL;
+ class_device_destroy(idetape_sysfs_class,
+ MKDEV(IDETAPE_MAJOR, tape->minor));
+ class_device_destroy(idetape_sysfs_class,
+ MKDEV(IDETAPE_MAJOR, tape->minor + 128));
devfs_remove("%s/mt", drive->devfs_name);
devfs_remove("%s/mtn", drive->devfs_name);
devfs_unregister_tape(g->number);
@@ -4878,6 +4884,11 @@ static int ide_tape_probe(struct device *dev)
idetape_setup(drive, tape, minor);
+ class_device_create(idetape_sysfs_class, NULL,
+ MKDEV(IDETAPE_MAJOR, minor), dev, "%s", tape->name);
+ class_device_create(idetape_sysfs_class, NULL,
+ MKDEV(IDETAPE_MAJOR, minor + 128), dev, "n%s", tape->name);
+
devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor),
S_IFCHR | S_IRUGO | S_IWUGO,
"%s/mt", drive->devfs_name);
@@ -4903,6 +4914,7 @@ MODULE_LICENSE("GPL");
static void __exit idetape_exit (void)
{
driver_unregister(&idetape_driver.gen_driver);
+ class_destroy(idetape_sysfs_class);
unregister_chrdev(IDETAPE_MAJOR, "ht");
}
@@ -4911,11 +4923,33 @@ static void __exit idetape_exit (void)
*/
static int idetape_init (void)
{
+ int error = 1;
+ idetape_sysfs_class = class_create(THIS_MODULE, "ide_tape");
+ if (IS_ERR(idetape_sysfs_class)) {
+ idetape_sysfs_class = NULL;
+ printk(KERN_ERR "Unable to create sysfs class for ide tapes\n");
+ error = -EBUSY;
+ goto out;
+ }
+
if (register_chrdev(IDETAPE_MAJOR, "ht", &idetape_fops)) {
printk(KERN_ERR "ide-tape: Failed to register character device interface\n");
- return -EBUSY;
+ error = -EBUSY;
+ goto out_free_class;
}
- return driver_register(&idetape_driver.gen_driver);
+
+ error = driver_register(&idetape_driver.gen_driver);
+ if (error)
+ goto out_free_driver;
+
+ return 0;
+
+out_free_driver:
+ driver_unregister(&idetape_driver.gen_driver);
+out_free_class:
+ class_destroy(idetape_sysfs_class);
+out:
+ return error;
}
module_init(idetape_init);
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index e34730c7a8748a..cbbbe14b88495f 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2361,7 +2361,7 @@ static void dv1394_add_host (struct hpsb_host *host)
ohci = (struct ti_ohci *)host->hostdata;
- class_device_create(hpsb_protocol_class, MKDEV(
+ class_device_create(hpsb_protocol_class, NULL, MKDEV(
IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
NULL, "dv1394-%d", id);
devfs_mk_dir("ieee1394/dv/host%d", id);
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index 4802bbbb6dc981..c9e92d85c8931e 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -1630,7 +1630,7 @@ static void ether1394_complete_cb(void *__ptask)
/* Transmit a packet (called by kernel) */
static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
{
- int kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+ gfp_t kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
struct eth1394hdr *eth;
struct eth1394_priv *priv = netdev_priv(dev);
int proto;
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 347ece6b583c19..7fff5a1d2ea4c7 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -1292,7 +1292,7 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
if (ud->device.driver &&
(!ud->device.driver->suspend ||
- ud->device.driver->suspend(&ud->device, PMSG_SUSPEND, 0)))
+ ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))
device_release_driver(&ud->device);
}
up_write(&ne->device.bus->subsys.rwsem);
@@ -1315,7 +1315,7 @@ static void nodemgr_resume_ne(struct node_entry *ne)
continue;
if (ud->device.driver && ud->device.driver->resume)
- ud->device.driver->resume(&ud->device, 0);
+ ud->device.driver->resume(&ud->device);
}
up_read(&ne->device.bus->subsys.rwsem);
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 0470f77a9cd172..24411e666b2145 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -2912,7 +2912,7 @@ static int __init init_raw1394(void)
hpsb_register_highlevel(&raw1394_highlevel);
- if (IS_ERR(class_device_create(hpsb_protocol_class, MKDEV(
+ if (IS_ERR(class_device_create(hpsb_protocol_class, NULL, MKDEV(
IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
NULL, RAW1394_DEVICE_NAME))) {
ret = -EFAULT;
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 11be9c9c82a874..23911da5015493 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -1370,7 +1370,7 @@ static void video1394_add_host (struct hpsb_host *host)
hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
- class_device_create(hpsb_protocol_class, MKDEV(
+ class_device_create(hpsb_protocol_class, NULL, MKDEV(
IEEE1394_MAJOR, minor),
NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 9220473dbfbdde..49f211d55df7f8 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -525,7 +525,7 @@ void mthca_cmd_use_polling(struct mthca_dev *dev)
}
struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev,
- unsigned int gfp_mask)
+ gfp_t gfp_mask)
{
struct mthca_mailbox *mailbox;
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h
index 65f976a13e0206..18175bec84c276 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.h
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.h
@@ -248,7 +248,7 @@ void mthca_cmd_event(struct mthca_dev *dev, u16 token,
u8 status, u64 out_param);
struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev,
- unsigned int gfp_mask);
+ gfp_t gfp_mask);
void mthca_free_mailbox(struct mthca_dev *dev, struct mthca_mailbox *mailbox);
int mthca_SYS_EN(struct mthca_dev *dev, u8 *status);
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index d63b1a14710060..d72fe95cba0885 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -82,7 +82,7 @@ void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm)
}
struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
- unsigned int gfp_mask)
+ gfp_t gfp_mask)
{
struct mthca_icm *icm;
struct mthca_icm_chunk *chunk = NULL;
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.h b/drivers/infiniband/hw/mthca/mthca_memfree.h
index 29c01a4b26568a..4fdca26eea8596 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.h
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.h
@@ -77,7 +77,7 @@ struct mthca_icm_iter {
struct mthca_dev;
struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
- unsigned int gfp_mask);
+ gfp_t gfp_mask);
void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm);
struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 3738d173f9a65a..a4696cd0978ca6 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -20,7 +20,6 @@
#include <linux/major.h>
#include <linux/smp_lock.h>
#include <linux/device.h>
-#include <linux/devfs_fs_kernel.h>
#include <linux/compat.h>
struct evdev {
@@ -662,6 +661,7 @@ static struct file_operations evdev_fops = {
static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
{
struct evdev *evdev;
+ struct class_device *cdev;
int minor;
for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++);
@@ -687,11 +687,13 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct
evdev_table[minor] = evdev;
- devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
- S_IFCHR|S_IRUGO|S_IWUSR, "input/event%d", minor);
- class_device_create(input_class,
+ cdev = class_device_create(&input_class, &dev->cdev,
MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
- dev->dev, "event%d", minor);
+ dev->cdev.dev, evdev->name);
+
+ /* temporary symlink to keep userspace happy */
+ sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
+ evdev->name);
return &evdev->handle;
}
@@ -701,9 +703,9 @@ static void evdev_disconnect(struct input_handle *handle)
struct evdev *evdev = handle->private;
struct evdev_list *list;
- class_device_destroy(input_class,
+ sysfs_remove_link(&input_class.subsys.kset.kobj, evdev->name);
+ class_device_destroy(&input_class,
MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
- devfs_remove("input/event%d", evdev->minor);
evdev->exist = 0;
if (evdev->open) {
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 14ae5583e198fa..3b1685ff9d10b3 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -22,12 +22,12 @@
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/device.h>
-#include <linux/devfs_fs_kernel.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("Input core");
MODULE_LICENSE("GPL");
+EXPORT_SYMBOL(input_allocate_device);
EXPORT_SYMBOL(input_register_device);
EXPORT_SYMBOL(input_unregister_device);
EXPORT_SYMBOL(input_register_handler);
@@ -39,7 +39,7 @@ EXPORT_SYMBOL(input_close_device);
EXPORT_SYMBOL(input_accept_process);
EXPORT_SYMBOL(input_flush_device);
EXPORT_SYMBOL(input_event);
-EXPORT_SYMBOL(input_class);
+EXPORT_SYMBOL_GPL(input_class);
#define INPUT_DEVICES 256
@@ -316,124 +316,21 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st
return NULL;
}
-
-/*
- * Input hotplugging interface - loading event handlers based on
- * device bitfields.
- */
-
-#ifdef CONFIG_HOTPLUG
-
-/*
- * Input hotplugging invokes what /proc/sys/kernel/hotplug says
- * (normally /sbin/hotplug) when input devices get added or removed.
- *
- * This invokes a user mode policy agent, typically helping to load driver
- * or other modules, configure the device, and more. Drivers can provide
- * a MODULE_DEVICE_TABLE to help with module loading subtasks.
- *
- */
-
-#define SPRINTF_BIT_A(bit, name, max) \
- do { \
- envp[i++] = scratch; \
- scratch += sprintf(scratch, name); \
- for (j = NBITS(max) - 1; j >= 0; j--) \
- if (dev->bit[j]) break; \
- for (; j >= 0; j--) \
- scratch += sprintf(scratch, "%lx ", dev->bit[j]); \
- scratch++; \
- } while (0)
-
-#define SPRINTF_BIT_A2(bit, name, max, ev) \
- do { \
- if (test_bit(ev, dev->evbit)) \
- SPRINTF_BIT_A(bit, name, max); \
- } while (0)
-
-static void input_call_hotplug(char *verb, struct input_dev *dev)
+static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, int max)
{
- char *argv[3], **envp, *buf, *scratch;
- int i = 0, j, value;
-
- if (!hotplug_path[0]) {
- printk(KERN_ERR "input.c: calling hotplug without a hotplug agent defined\n");
- return;
- }
- if (in_interrupt()) {
- printk(KERN_ERR "input.c: calling hotplug from interrupt\n");
- return;
- }
- if (!current->fs->root) {
- printk(KERN_WARNING "input.c: calling hotplug without valid filesystem\n");
- return;
- }
- if (!(envp = (char **) kmalloc(20 * sizeof(char *), GFP_KERNEL))) {
- printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
- return;
- }
- if (!(buf = kmalloc(1024, GFP_KERNEL))) {
- kfree (envp);
- printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
- return;
- }
-
- argv[0] = hotplug_path;
- argv[1] = "input";
- argv[2] = NULL;
-
- envp[i++] = "HOME=/";
- envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-
- scratch = buf;
-
- envp[i++] = scratch;
- scratch += sprintf(scratch, "ACTION=%s", verb) + 1;
-
- envp[i++] = scratch;
- scratch += sprintf(scratch, "PRODUCT=%x/%x/%x/%x",
- dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version) + 1;
-
- if (dev->name) {
- envp[i++] = scratch;
- scratch += sprintf(scratch, "NAME=%s", dev->name) + 1;
- }
-
- if (dev->phys) {
- envp[i++] = scratch;
- scratch += sprintf(scratch, "PHYS=%s", dev->phys) + 1;
- }
-
- SPRINTF_BIT_A(evbit, "EV=", EV_MAX);
- SPRINTF_BIT_A2(keybit, "KEY=", KEY_MAX, EV_KEY);
- SPRINTF_BIT_A2(relbit, "REL=", REL_MAX, EV_REL);
- SPRINTF_BIT_A2(absbit, "ABS=", ABS_MAX, EV_ABS);
- SPRINTF_BIT_A2(mscbit, "MSC=", MSC_MAX, EV_MSC);
- SPRINTF_BIT_A2(ledbit, "LED=", LED_MAX, EV_LED);
- SPRINTF_BIT_A2(sndbit, "SND=", SND_MAX, EV_SND);
- SPRINTF_BIT_A2(ffbit, "FF=", FF_MAX, EV_FF);
- SPRINTF_BIT_A2(swbit, "SW=", SW_MAX, EV_SW);
-
- envp[i++] = NULL;
-
-#ifdef INPUT_DEBUG
- printk(KERN_DEBUG "input.c: calling %s %s [%s %s %s %s %s]\n",
- argv[0], argv[1], envp[0], envp[1], envp[2], envp[3], envp[4]);
-#endif
-
- value = call_usermodehelper(argv [0], argv, envp, 0);
+ int i;
+ int len = 0;
- kfree(buf);
- kfree(envp);
+ for (i = NBITS(max) - 1; i > 0; i--)
+ if (bitmap[i])
+ break;
-#ifdef INPUT_DEBUG
- if (value != 0)
- printk(KERN_DEBUG "input.c: hotplug returned %d\n", value);
-#endif
+ for (; i >= 0; i--)
+ len += snprintf(buf + len, max(buf_size - len, 0),
+ "%lx%s", bitmap[i], i > 0 ? " " : "");
+ return len;
}
-#endif
-
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *proc_bus_input_dir;
@@ -455,37 +352,39 @@ static unsigned int input_devices_poll(struct file *file, poll_table *wait)
return 0;
}
-#define SPRINTF_BIT_B(bit, name, max) \
- do { \
- len += sprintf(buf + len, "B: %s", name); \
- for (i = NBITS(max) - 1; i >= 0; i--) \
- if (dev->bit[i]) break; \
- for (; i >= 0; i--) \
- len += sprintf(buf + len, "%lx ", dev->bit[i]); \
- len += sprintf(buf + len, "\n"); \
+#define SPRINTF_BIT(ev, bm) \
+ do { \
+ len += sprintf(buf + len, "B: %s=", #ev); \
+ len += input_print_bitmap(buf + len, INT_MAX, \
+ dev->bm##bit, ev##_MAX); \
+ len += sprintf(buf + len, "\n"); \
} while (0)
-#define SPRINTF_BIT_B2(bit, name, max, ev) \
- do { \
- if (test_bit(ev, dev->evbit)) \
- SPRINTF_BIT_B(bit, name, max); \
+#define TEST_AND_SPRINTF_BIT(ev, bm) \
+ do { \
+ if (test_bit(EV_##ev, dev->evbit)) \
+ SPRINTF_BIT(ev, bm); \
} while (0)
static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
{
struct input_dev *dev;
struct input_handle *handle;
+ const char *path;
off_t at = 0;
- int i, len, cnt = 0;
+ int len, cnt = 0;
list_for_each_entry(dev, &input_dev_list, node) {
+ path = dev->dynalloc ? kobject_get_path(&dev->cdev.kobj, GFP_KERNEL) : NULL;
+
len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version);
len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : "");
+ len += sprintf(buf + len, "S: Sysfs=%s\n", path ? path : "");
len += sprintf(buf + len, "H: Handlers=");
list_for_each_entry(handle, &dev->h_list, d_node)
@@ -493,15 +392,15 @@ static int input_devices_read(char *buf, char **start, off_t pos, int count, int
len += sprintf(buf + len, "\n");
- SPRINTF_BIT_B(evbit, "EV=", EV_MAX);
- SPRINTF_BIT_B2(keybit, "KEY=", KEY_MAX, EV_KEY);
- SPRINTF_BIT_B2(relbit, "REL=", REL_MAX, EV_REL);
- SPRINTF_BIT_B2(absbit, "ABS=", ABS_MAX, EV_ABS);
- SPRINTF_BIT_B2(mscbit, "MSC=", MSC_MAX, EV_MSC);
- SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED);
- SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND);
- SPRINTF_BIT_B2(ffbit, "FF=", FF_MAX, EV_FF);
- SPRINTF_BIT_B2(swbit, "SW=", SW_MAX, EV_SW);
+ SPRINTF_BIT(EV, ev);
+ TEST_AND_SPRINTF_BIT(KEY, key);
+ TEST_AND_SPRINTF_BIT(REL, rel);
+ TEST_AND_SPRINTF_BIT(ABS, abs);
+ TEST_AND_SPRINTF_BIT(MSC, msc);
+ TEST_AND_SPRINTF_BIT(LED, led);
+ TEST_AND_SPRINTF_BIT(SND, snd);
+ TEST_AND_SPRINTF_BIT(FF, ff);
+ TEST_AND_SPRINTF_BIT(SW, sw);
len += sprintf(buf + len, "\n");
@@ -516,6 +415,8 @@ static int input_devices_read(char *buf, char **start, off_t pos, int count, int
if (cnt >= count)
break;
}
+
+ kfree(path);
}
if (&dev->node == &input_dev_list)
@@ -606,6 +507,240 @@ static inline int input_proc_init(void) { return 0; }
static inline void input_proc_exit(void) { }
#endif
+#define INPUT_DEV_STRING_ATTR_SHOW(name) \
+static ssize_t input_dev_show_##name(struct class_device *dev, char *buf) \
+{ \
+ struct input_dev *input_dev = to_input_dev(dev); \
+ int retval; \
+ \
+ retval = down_interruptible(&input_dev->sem); \
+ if (retval) \
+ return retval; \
+ \
+ retval = sprintf(buf, "%s\n", input_dev->name ? input_dev->name : ""); \
+ \
+ up(&input_dev->sem); \
+ \
+ return retval; \
+} \
+static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL);
+
+INPUT_DEV_STRING_ATTR_SHOW(name);
+INPUT_DEV_STRING_ATTR_SHOW(phys);
+INPUT_DEV_STRING_ATTR_SHOW(uniq);
+
+static struct attribute *input_dev_attrs[] = {
+ &class_device_attr_name.attr,
+ &class_device_attr_phys.attr,
+ &class_device_attr_uniq.attr,
+ NULL
+};
+
+static struct attribute_group input_dev_group = {
+ .attrs = input_dev_attrs,
+};
+
+#define INPUT_DEV_ID_ATTR(name) \
+static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf) \
+{ \
+ struct input_dev *input_dev = to_input_dev(dev); \
+ return sprintf(buf, "%04x\n", input_dev->id.name); \
+} \
+static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL);
+
+INPUT_DEV_ID_ATTR(bustype);
+INPUT_DEV_ID_ATTR(vendor);
+INPUT_DEV_ID_ATTR(product);
+INPUT_DEV_ID_ATTR(version);
+
+static struct attribute *input_dev_id_attrs[] = {
+ &class_device_attr_bustype.attr,
+ &class_device_attr_vendor.attr,
+ &class_device_attr_product.attr,
+ &class_device_attr_version.attr,
+ NULL
+};
+
+static struct attribute_group input_dev_id_attr_group = {
+ .name = "id",
+ .attrs = input_dev_id_attrs,
+};
+
+#define INPUT_DEV_CAP_ATTR(ev, bm) \
+static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf) \
+{ \
+ struct input_dev *input_dev = to_input_dev(dev); \
+ return input_print_bitmap(buf, PAGE_SIZE, input_dev->bm##bit, ev##_MAX);\
+} \
+static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL);
+
+INPUT_DEV_CAP_ATTR(EV, ev);
+INPUT_DEV_CAP_ATTR(KEY, key);
+INPUT_DEV_CAP_ATTR(REL, rel);
+INPUT_DEV_CAP_ATTR(ABS, abs);
+INPUT_DEV_CAP_ATTR(MSC, msc);
+INPUT_DEV_CAP_ATTR(LED, led);
+INPUT_DEV_CAP_ATTR(SND, snd);
+INPUT_DEV_CAP_ATTR(FF, ff);
+INPUT_DEV_CAP_ATTR(SW, sw);
+
+static struct attribute *input_dev_caps_attrs[] = {
+ &class_device_attr_ev.attr,
+ &class_device_attr_key.attr,
+ &class_device_attr_rel.attr,
+ &class_device_attr_abs.attr,
+ &class_device_attr_msc.attr,
+ &class_device_attr_led.attr,
+ &class_device_attr_snd.attr,
+ &class_device_attr_ff.attr,
+ &class_device_attr_sw.attr,
+ NULL
+};
+
+static struct attribute_group input_dev_caps_attr_group = {
+ .name = "capabilities",
+ .attrs = input_dev_caps_attrs,
+};
+
+static void input_dev_release(struct class_device *class_dev)
+{
+ struct input_dev *dev = to_input_dev(class_dev);
+
+ kfree(dev);
+ module_put(THIS_MODULE);
+}
+
+/*
+ * Input hotplugging interface - loading event handlers based on
+ * device bitfields.
+ */
+static int input_add_hotplug_bm_var(char **envp, int num_envp, int *cur_index,
+ char *buffer, int buffer_size, int *cur_len,
+ const char *name, unsigned long *bitmap, int max)
+{
+ if (*cur_index >= num_envp - 1)
+ return -ENOMEM;
+
+ envp[*cur_index] = buffer + *cur_len;
+
+ *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name);
+ if (*cur_len > buffer_size)
+ return -ENOMEM;
+
+ *cur_len += input_print_bitmap(buffer + *cur_len,
+ max(buffer_size - *cur_len, 0),
+ bitmap, max) + 1;
+ if (*cur_len > buffer_size)
+ return -ENOMEM;
+
+ (*cur_index)++;
+ return 0;
+}
+
+#define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \
+ do { \
+ int err = add_hotplug_env_var(envp, num_envp, &i, \
+ buffer, buffer_size, &len, \
+ fmt, val); \
+ if (err) \
+ return err; \
+ } while (0)
+
+#define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \
+ do { \
+ int err = input_add_hotplug_bm_var(envp, num_envp, &i, \
+ buffer, buffer_size, &len, \
+ name, bm, max); \
+ if (err) \
+ return err; \
+ } while (0)
+
+static int input_dev_hotplug(struct class_device *cdev, char **envp,
+ int num_envp, char *buffer, int buffer_size)
+{
+ struct input_dev *dev = to_input_dev(cdev);
+ int i = 0;
+ int len = 0;
+
+ INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x",
+ dev->id.bustype, dev->id.vendor,
+ dev->id.product, dev->id.version);
+ if (dev->name)
+ INPUT_ADD_HOTPLUG_VAR("NAME=\"%s\"", dev->name);
+ if (dev->phys)
+ INPUT_ADD_HOTPLUG_VAR("PHYS=\"%s\"", dev->phys);
+ if (dev->phys)
+ INPUT_ADD_HOTPLUG_VAR("UNIQ=\"%s\"", dev->uniq);
+
+ INPUT_ADD_HOTPLUG_BM_VAR("EV=", dev->evbit, EV_MAX);
+ if (test_bit(EV_KEY, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("KEY=", dev->keybit, KEY_MAX);
+ if (test_bit(EV_REL, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("REL=", dev->relbit, REL_MAX);
+ if (test_bit(EV_ABS, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("ABS=", dev->absbit, ABS_MAX);
+ if (test_bit(EV_MSC, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("MSC=", dev->mscbit, MSC_MAX);
+ if (test_bit(EV_LED, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("LED=", dev->ledbit, LED_MAX);
+ if (test_bit(EV_SND, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("SND=", dev->sndbit, SND_MAX);
+ if (test_bit(EV_FF, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("FF=", dev->ffbit, FF_MAX);
+ if (test_bit(EV_SW, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX);
+
+ envp[i] = NULL;
+
+ return 0;
+}
+
+struct class input_class = {
+ .name = "input",
+ .release = input_dev_release,
+ .hotplug = input_dev_hotplug,
+};
+
+struct input_dev *input_allocate_device(void)
+{
+ struct input_dev *dev;
+
+ dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
+ if (dev) {
+ dev->dynalloc = 1;
+ dev->cdev.class = &input_class;
+ class_device_initialize(&dev->cdev);
+ INIT_LIST_HEAD(&dev->h_list);
+ INIT_LIST_HEAD(&dev->node);
+ }
+
+ return dev;
+}
+
+static void input_register_classdevice(struct input_dev *dev)
+{
+ static atomic_t input_no = ATOMIC_INIT(0);
+ const char *path;
+
+ __module_get(THIS_MODULE);
+
+ dev->dev = dev->cdev.dev;
+
+ snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
+ "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
+
+ path = kobject_get_path(&dev->cdev.class->subsys.kset.kobj, GFP_KERNEL);
+ printk(KERN_INFO "input: %s/%s as %s\n",
+ dev->name ? dev->name : "Unspecified device",
+ path ? path : "", dev->cdev.class_id);
+ kfree(path);
+
+ class_device_add(&dev->cdev);
+ sysfs_create_group(&dev->cdev.kobj, &input_dev_group);
+ sysfs_create_group(&dev->cdev.kobj, &input_dev_id_attr_group);
+ sysfs_create_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
+}
+
void input_register_device(struct input_dev *dev)
{
struct input_handle *handle;
@@ -632,15 +767,15 @@ void input_register_device(struct input_dev *dev)
INIT_LIST_HEAD(&dev->h_list);
list_add_tail(&dev->node, &input_dev_list);
+ if (dev->dynalloc)
+ input_register_classdevice(dev);
+
list_for_each_entry(handler, &input_handler_list, node)
if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
if ((id = input_match_device(handler->id_table, dev)))
if ((handle = handler->connect(handler, dev, id)))
input_link_handle(handle);
-#ifdef CONFIG_HOTPLUG
- input_call_hotplug("add", dev);
-#endif
input_wakeup_procfs_readers();
}
@@ -660,12 +795,14 @@ void input_unregister_device(struct input_dev *dev)
handle->handler->disconnect(handle);
}
-#ifdef CONFIG_HOTPLUG
- input_call_hotplug("remove", dev);
-#endif
-
list_del_init(&dev->node);
+ if (dev->dynalloc) {
+ sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
+ sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
+ class_device_unregister(&dev->cdev);
+ }
+
input_wakeup_procfs_readers();
}
@@ -748,16 +885,14 @@ static struct file_operations input_fops = {
.open = input_open_file,
};
-struct class *input_class;
-
static int __init input_init(void)
{
int err;
- input_class = class_create(THIS_MODULE, "input");
- if (IS_ERR(input_class)) {
- printk(KERN_ERR "input: unable to register input class\n");
- return PTR_ERR(input_class);
+ err = class_register(&input_class);
+ if (err) {
+ printk(KERN_ERR "input: unable to register input_dev class\n");
+ return err;
}
err = input_proc_init();
@@ -770,24 +905,18 @@ static int __init input_init(void)
goto fail2;
}
- err = devfs_mk_dir("input");
- if (err)
- goto fail3;
-
return 0;
- fail3: unregister_chrdev(INPUT_MAJOR, "input");
fail2: input_proc_exit();
- fail1: class_destroy(input_class);
+ fail1: class_unregister(&input_class);
return err;
}
static void __exit input_exit(void)
{
input_proc_exit();
- devfs_remove("input");
unregister_chrdev(INPUT_MAJOR, "input");
- class_destroy(input_class);
+ class_unregister(&input_class);
}
subsys_initcall(input_init);
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index e0938d1d3ad791..20e2972b9204f2 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -26,7 +26,6 @@
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/device.h>
-#include <linux/devfs_fs_kernel.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Joystick device interfaces");
@@ -449,6 +448,7 @@ static struct file_operations joydev_fops = {
static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
{
struct joydev *joydev;
+ struct class_device *cdev;
int i, j, t, minor;
for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
@@ -514,11 +514,13 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
joydev_table[minor] = joydev;
- devfs_mk_cdev(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
- S_IFCHR|S_IRUGO|S_IWUSR, "input/js%d", minor);
- class_device_create(input_class,
+ cdev = class_device_create(&input_class, &dev->cdev,
MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
- dev->dev, "js%d", minor);
+ dev->cdev.dev, joydev->name);
+
+ /* temporary symlink to keep userspace happy */
+ sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
+ joydev->name);
return &joydev->handle;
}
@@ -528,8 +530,8 @@ static void joydev_disconnect(struct input_handle *handle)
struct joydev *joydev = handle->private;
struct joydev_list *list;
- class_device_destroy(input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
- devfs_remove("input/js%d", joydev->minor);
+ sysfs_remove_link(&input_class.subsys.kset.kobj, joydev->name);
+ class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
joydev->exist = 0;
if (joydev->open) {
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
index cf35ae638a0d2c..9d95459f4bcbf4 100644
--- a/drivers/input/joystick/adi.c
+++ b/drivers/input/joystick/adi.c
@@ -54,7 +54,7 @@ MODULE_LICENSE("GPL");
#define ADI_MIN_LENGTH 8
#define ADI_MIN_LEN_LENGTH 10
#define ADI_MIN_ID_LENGTH 66
-#define ADI_MAX_NAME_LENGTH 48
+#define ADI_MAX_NAME_LENGTH 64
#define ADI_MAX_CNAME_LENGTH 16
#define ADI_MAX_PHYS_LENGTH 64
@@ -106,7 +106,7 @@ static struct {
*/
struct adi {
- struct input_dev dev;
+ struct input_dev *dev;
int length;
int ret;
int idx;
@@ -215,7 +215,7 @@ static inline int adi_get_bits(struct adi *adi, int count)
static int adi_decode(struct adi *adi)
{
- struct input_dev *dev = &adi->dev;
+ struct input_dev *dev = adi->dev;
char *abs = adi->abs;
short *key = adi->key;
int i, t;
@@ -318,7 +318,8 @@ static void adi_init_digital(struct gameport *gameport)
for (i = 0; seq[i]; i++) {
gameport_trigger(gameport);
- if (seq[i] > 0) msleep(seq[i]);
+ if (seq[i] > 0)
+ msleep(seq[i]);
if (seq[i] < 0) {
mdelay(-seq[i]);
udelay(-seq[i]*14); /* It looks like mdelay() is off by approx 1.4% */
@@ -397,42 +398,46 @@ static void adi_id_decode(struct adi *adi, struct adi_port *port)
}
}
-static void adi_init_input(struct adi *adi, struct adi_port *port, int half)
+static int adi_init_input(struct adi *adi, struct adi_port *port, int half)
{
- int i, t;
+ struct input_dev *input_dev;
char buf[ADI_MAX_NAME_LENGTH];
+ int i, t;
- if (!adi->length) return;
-
- init_input_dev(&adi->dev);
+ adi->dev = input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
t = adi->id < ADI_ID_MAX ? adi->id : ADI_ID_MAX;
snprintf(buf, ADI_MAX_PHYS_LENGTH, adi_names[t], adi->id);
- snprintf(adi->name, ADI_MAX_NAME_LENGTH, "Logitech %s", buf);
+ snprintf(adi->name, ADI_MAX_NAME_LENGTH, "Logitech %s [%s]", buf, adi->cname);
snprintf(adi->phys, ADI_MAX_PHYS_LENGTH, "%s/input%d", port->gameport->phys, half);
adi->abs = adi_abs[t];
adi->key = adi_key[t];
- adi->dev.open = adi_open;
- adi->dev.close = adi_close;
+ input_dev->name = adi->name;
+ input_dev->phys = adi->phys;
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_LOGITECH;
+ input_dev->id.product = adi->id;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &port->gameport->dev;
+ input_dev->private = port;
- adi->dev.name = adi->name;
- adi->dev.phys = adi->phys;
- adi->dev.id.bustype = BUS_GAMEPORT;
- adi->dev.id.vendor = GAMEPORT_ID_VENDOR_LOGITECH;
- adi->dev.id.product = adi->id;
- adi->dev.id.version = 0x0100;
+ input_dev->open = adi_open;
+ input_dev->close = adi_close;
- adi->dev.private = port;
- adi->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++)
- set_bit(adi->abs[i], adi->dev.absbit);
+ set_bit(adi->abs[i], input_dev->absbit);
for (i = 0; i < adi->buttons; i++)
- set_bit(adi->key[i], adi->dev.keybit);
+ set_bit(adi->key[i], input_dev->keybit);
+
+ return 0;
}
static void adi_init_center(struct adi *adi)
@@ -445,17 +450,17 @@ static void adi_init_center(struct adi *adi)
for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) {
t = adi->abs[i];
- x = adi->dev.abs[t];
+ x = adi->dev->abs[t];
if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE)
x = i < adi->axes10 ? 512 : 128;
if (i < adi->axes10)
- input_set_abs_params(&adi->dev, t, 64, x * 2 - 64, 2, 16);
+ input_set_abs_params(adi->dev, t, 64, x * 2 - 64, 2, 16);
else if (i < adi->axes10 + adi->axes8)
- input_set_abs_params(&adi->dev, t, 48, x * 2 - 48, 1, 16);
+ input_set_abs_params(adi->dev, t, 48, x * 2 - 48, 1, 16);
else
- input_set_abs_params(&adi->dev, t, -1, 1, 0, 0);
+ input_set_abs_params(adi->dev, t, -1, 1, 0, 0);
}
}
@@ -469,7 +474,8 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
int i;
int err;
- if (!(port = kzalloc(sizeof(struct adi_port), GFP_KERNEL)))
+ port = kzalloc(sizeof(struct adi_port), GFP_KERNEL);
+ if (!port)
return -ENOMEM;
port->gameport = gameport;
@@ -477,10 +483,8 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
gameport_set_drvdata(gameport, port);
err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
- if (err) {
- kfree(port);
- return err;
- }
+ if (err)
+ goto fail1;
adi_init_digital(gameport);
adi_read_packet(port);
@@ -490,13 +494,18 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
for (i = 0; i < 2; i++) {
adi_id_decode(port->adi + i, port);
- adi_init_input(port->adi + i, port, i);
+
+ if (!port->adi[i].length)
+ continue;
+
+ err = adi_init_input(port->adi + i, port, i);
+ if (err)
+ goto fail2;
}
if (!port->adi[0].length && !port->adi[1].length) {
- gameport_close(gameport);
- kfree(port);
- return -ENODEV;
+ err = -ENODEV;
+ goto fail2;
}
gameport_set_poll_handler(gameport, adi_poll);
@@ -511,12 +520,18 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
for (i = 0; i < 2; i++)
if (port->adi[i].length > 0) {
adi_init_center(port->adi + i);
- input_register_device(&port->adi[i].dev);
- printk(KERN_INFO "input: %s [%s] on %s\n",
- port->adi[i].name, port->adi[i].cname, gameport->phys);
+ input_register_device(port->adi[i].dev);
}
return 0;
+
+ fail2: for (i = 0; i < 2; i++)
+ if (port->adi[i].dev)
+ input_free_device(port->adi[i].dev);
+ gameport_close(gameport);
+ fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(port);
+ return err;
}
static void adi_disconnect(struct gameport *gameport)
@@ -526,7 +541,7 @@ static void adi_disconnect(struct gameport *gameport)
for (i = 0; i < 2; i++)
if (port->adi[i].length > 0)
- input_unregister_device(&port->adi[i].dev);
+ input_unregister_device(port->adi[i].dev);
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
kfree(port);
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
index e996183c5b065a..8558a99f6635a6 100644
--- a/drivers/input/joystick/amijoy.c
+++ b/drivers/input/joystick/amijoy.c
@@ -53,11 +53,9 @@ __obsolete_setup("amijoy=");
static int amijoy_used;
static DECLARE_MUTEX(amijoy_sem);
-static struct input_dev amijoy_dev[2];
+static struct input_dev *amijoy_dev[2];
static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" };
-static char *amijoy_name = "Amiga joystick";
-
static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp)
{
int i, data = 0, button = 0;
@@ -70,15 +68,15 @@ static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp)
case 1: data = ~custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break;
}
- input_regs(amijoy_dev + i, fp);
+ input_regs(amijoy_dev[i], fp);
- input_report_key(amijoy_dev + i, BTN_TRIGGER, button);
+ input_report_key(amijoy_dev[i], BTN_TRIGGER, button);
- input_report_abs(amijoy_dev + i, ABS_X, ((data >> 1) & 1) - ((data >> 9) & 1));
+ input_report_abs(amijoy_dev[i], ABS_X, ((data >> 1) & 1) - ((data >> 9) & 1));
data = ~(data ^ (data << 1));
- input_report_abs(amijoy_dev + i, ABS_Y, ((data >> 1) & 1) - ((data >> 9) & 1));
+ input_report_abs(amijoy_dev[i], ABS_Y, ((data >> 1) & 1) - ((data >> 9) & 1));
- input_sync(amijoy_dev + i);
+ input_sync(amijoy_dev[i]);
}
return IRQ_HANDLED;
}
@@ -114,39 +112,52 @@ static void amijoy_close(struct input_dev *dev)
static int __init amijoy_init(void)
{
int i, j;
+ int err;
- for (i = 0; i < 2; i++)
- if (amijoy[i]) {
- if (!request_mem_region(CUSTOM_PHYSADDR+10+i*2, 2,
- "amijoy [Denise]")) {
- if (i == 1 && amijoy[0]) {
- input_unregister_device(amijoy_dev);
- release_mem_region(CUSTOM_PHYSADDR+10, 2);
- }
- return -EBUSY;
- }
+ for (i = 0; i < 2; i++) {
+ if (!amijoy[i])
+ continue;
- amijoy_dev[i].open = amijoy_open;
- amijoy_dev[i].close = amijoy_close;
- amijoy_dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- amijoy_dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
- amijoy_dev[i].keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- for (j = 0; j < 2; j++) {
- amijoy_dev[i].absmin[ABS_X + j] = -1;
- amijoy_dev[i].absmax[ABS_X + j] = 1;
- }
+ amijoy_dev[i] = input_allocate_device();
+ if (!amijoy_dev[i]) {
+ err = -ENOMEM;
+ goto fail;
+ }
- amijoy_dev[i].name = amijoy_name;
- amijoy_dev[i].phys = amijoy_phys[i];
- amijoy_dev[i].id.bustype = BUS_AMIGA;
- amijoy_dev[i].id.vendor = 0x0001;
- amijoy_dev[i].id.product = 0x0003;
- amijoy_dev[i].id.version = 0x0100;
+ if (!request_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2, "amijoy [Denise]")) {
+ input_free_device(amijoy_dev[i]);
+ err = -EBUSY;
+ goto fail;
+ }
- input_register_device(amijoy_dev + i);
- printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i);
+ amijoy_dev[i]->name = "Amiga joystick";
+ amijoy_dev[i]->phys = amijoy_phys[i];
+ amijoy_dev[i]->id.bustype = BUS_AMIGA;
+ amijoy_dev[i]->id.vendor = 0x0001;
+ amijoy_dev[i]->id.product = 0x0003;
+ amijoy_dev[i]->id.version = 0x0100;
+
+ amijoy_dev[i]->open = amijoy_open;
+ amijoy_dev[i]->close = amijoy_close;
+
+ amijoy_dev[i]->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ amijoy_dev[i]->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+ amijoy_dev[i]->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ for (j = 0; j < 2; j++) {
+ amijoy_dev[i]->absmin[ABS_X + j] = -1;
+ amijoy_dev[i]->absmax[ABS_X + j] = 1;
}
+
+ input_register_device(amijoy_dev[i]);
+ }
return 0;
+
+ fail: while (--i >= 0)
+ if (amijoy[i]) {
+ input_unregister_device(amijoy_dev[i]);
+ release_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2);
+ }
+ return err;
}
static void __exit amijoy_exit(void)
@@ -155,8 +166,8 @@ static void __exit amijoy_exit(void)
for (i = 0; i < 2; i++)
if (amijoy[i]) {
- input_unregister_device(amijoy_dev + i);
- release_mem_region(CUSTOM_PHYSADDR+10+i*2, 2);
+ input_unregister_device(amijoy_dev[i]);
+ release_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2);
}
}
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index 64b1313a3c66d0..c75ac6eb1ffbcd 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -111,7 +111,7 @@ static short analog_joy_btn[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN
static unsigned char analog_chf[] = { 0xf, 0x0, 0x1, 0x9, 0x2, 0x4, 0xc, 0x8, 0x3, 0x5, 0xb, 0x7, 0xd, 0xe, 0xa, 0x6 };
struct analog {
- struct input_dev dev;
+ struct input_dev *dev;
int mask;
short *buttons;
char name[ANALOG_MAX_NAME_LENGTH];
@@ -182,7 +182,7 @@ static unsigned long analog_faketime = 0;
static void analog_decode(struct analog *analog, int *axes, int *initial, int buttons)
{
- struct input_dev *dev = &analog->dev;
+ struct input_dev *dev = analog->dev;
int i, j;
if (analog->mask & ANALOG_HAT_FCS)
@@ -428,27 +428,30 @@ static void analog_name(struct analog *analog)
* analog_init_device()
*/
-static void analog_init_device(struct analog_port *port, struct analog *analog, int index)
+static int analog_init_device(struct analog_port *port, struct analog *analog, int index)
{
+ struct input_dev *input_dev;
int i, j, t, v, w, x, y, z;
analog_name(analog);
sprintf(analog->phys, "%s/input%d", port->gameport->phys, index);
analog->buttons = (analog->mask & ANALOG_GAMEPAD) ? analog_pad_btn : analog_joy_btn;
- init_input_dev(&analog->dev);
+ analog->dev = input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
- analog->dev.name = analog->name;
- analog->dev.phys = analog->phys;
- analog->dev.id.bustype = BUS_GAMEPORT;
- analog->dev.id.vendor = GAMEPORT_ID_VENDOR_ANALOG;
- analog->dev.id.product = analog->mask >> 4;
- analog->dev.id.version = 0x0100;
+ input_dev->name = analog->name;
+ input_dev->phys = analog->phys;
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_ANALOG;
+ input_dev->id.product = analog->mask >> 4;
+ input_dev->id.version = 0x0100;
- analog->dev.open = analog_open;
- analog->dev.close = analog_close;
- analog->dev.private = port;
- analog->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->open = analog_open;
+ input_dev->close = analog_close;
+ input_dev->private = port;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = j = 0; i < 4; i++)
if (analog->mask & (1 << i)) {
@@ -461,8 +464,6 @@ static void analog_init_device(struct analog_port *port, struct analog *analog,
v = (x >> 3);
w = (x >> 3);
- set_bit(t, analog->dev.absbit);
-
if ((i == 2 || i == 3) && (j == 2 || j == 3) && (z > (y >> 3)))
x = y;
@@ -472,11 +473,7 @@ static void analog_init_device(struct analog_port *port, struct analog *analog,
w = (x >> 4);
}
- analog->dev.absmax[t] = (x << 1) - v;
- analog->dev.absmin[t] = v;
- analog->dev.absfuzz[t] = port->fuzz;
- analog->dev.absflat[t] = w;
-
+ input_set_abs_params(input_dev, t, v, (x << 1) - v, port->fuzz, w);
j++;
}
@@ -484,41 +481,30 @@ static void analog_init_device(struct analog_port *port, struct analog *analog,
if (analog->mask & analog_exts[i])
for (x = 0; x < 2; x++) {
t = analog_hats[j++];
- set_bit(t, analog->dev.absbit);
- analog->dev.absmax[t] = 1;
- analog->dev.absmin[t] = -1;
+ input_set_abs_params(input_dev, t, -1, 1, 0, 0);
}
for (i = j = 0; i < 4; i++)
if (analog->mask & (0x10 << i))
- set_bit(analog->buttons[j++], analog->dev.keybit);
+ set_bit(analog->buttons[j++], input_dev->keybit);
if (analog->mask & ANALOG_BTNS_CHF)
for (i = 0; i < 2; i++)
- set_bit(analog->buttons[j++], analog->dev.keybit);
+ set_bit(analog->buttons[j++], input_dev->keybit);
if (analog->mask & ANALOG_HBTN_CHF)
for (i = 0; i < 4; i++)
- set_bit(analog->buttons[j++], analog->dev.keybit);
+ set_bit(analog->buttons[j++], input_dev->keybit);
for (i = 0; i < 4; i++)
if (analog->mask & (ANALOG_BTN_TL << i))
- set_bit(analog_pads[i], analog->dev.keybit);
+ set_bit(analog_pads[i], input_dev->keybit);
analog_decode(analog, port->axes, port->initial, port->buttons);
- input_register_device(&analog->dev);
+ input_register_device(analog->dev);
- printk(KERN_INFO "input: %s at %s", analog->name, port->gameport->phys);
-
- if (port->cooked)
- printk(" [ADC port]\n");
- else
- printk(" [%s timer, %d %sHz clock, %d ns res]\n", TIME_NAME,
- port->speed > 10000 ? (port->speed + 800) / 1000 : port->speed,
- port->speed > 10000 ? "M" : "k",
- port->speed > 10000 ? (port->loop * 1000) / (port->speed / 1000)
- : (port->loop * 1000000) / port->speed);
+ return 0;
}
/*
@@ -659,37 +645,41 @@ static int analog_connect(struct gameport *gameport, struct gameport_driver *drv
return - ENOMEM;
err = analog_init_port(gameport, drv, port);
- if (err) {
- kfree(port);
- return err;
- }
+ if (err)
+ goto fail1;
err = analog_init_masks(port);
- if (err) {
- gameport_close(gameport);
- gameport_set_drvdata(gameport, NULL);
- kfree(port);
- return err;
- }
+ if (err)
+ goto fail2;
gameport_set_poll_handler(gameport, analog_poll);
gameport_set_poll_interval(gameport, 10);
for (i = 0; i < 2; i++)
- if (port->analog[i].mask)
- analog_init_device(port, port->analog + i, i);
+ if (port->analog[i].mask) {
+ err = analog_init_device(port, port->analog + i, i);
+ if (err)
+ goto fail3;
+ }
return 0;
+
+ fail3: while (--i >= 0)
+ input_unregister_device(port->analog[i].dev);
+ fail2: gameport_close(gameport);
+ fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(port);
+ return err;
}
static void analog_disconnect(struct gameport *gameport)
{
- int i;
struct analog_port *port = gameport_get_drvdata(gameport);
+ int i;
for (i = 0; i < 2; i++)
if (port->analog[i].mask)
- input_unregister_device(&port->analog[i].dev);
+ input_unregister_device(port->analog[i].dev);
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
printk(KERN_INFO "analog.c: %d out of %d reads (%d%%) on %s failed\n",
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
index 0b2e9fa2657969..9a3dfc724a41ae 100644
--- a/drivers/input/joystick/cobra.c
+++ b/drivers/input/joystick/cobra.c
@@ -44,13 +44,11 @@ MODULE_LICENSE("GPL");
#define COBRA_MAX_STROBE 45 /* 45 us max wait for first strobe */
#define COBRA_LENGTH 36
-static char* cobra_name = "Creative Labs Blaster GamePad Cobra";
-
static int cobra_btn[] = { BTN_START, BTN_SELECT, BTN_TL, BTN_TR, BTN_X, BTN_Y, BTN_Z, BTN_A, BTN_B, BTN_C, BTN_TL2, BTN_TR2, 0 };
struct cobra {
struct gameport *gameport;
- struct input_dev dev[2];
+ struct input_dev *dev[2];
int reads;
int bads;
unsigned char exists;
@@ -128,7 +126,7 @@ static void cobra_poll(struct gameport *gameport)
for (i = 0; i < 2; i++)
if (cobra->exists & r & (1 << i)) {
- dev = cobra->dev + i;
+ dev = cobra->dev[i];
input_report_abs(dev, ABS_X, ((data[i] >> 4) & 1) - ((data[i] >> 3) & 1));
input_report_abs(dev, ABS_Y, ((data[i] >> 2) & 1) - ((data[i] >> 1) & 1));
@@ -159,11 +157,13 @@ static void cobra_close(struct input_dev *dev)
static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct cobra *cobra;
+ struct input_dev *input_dev;
unsigned int data[2];
int i, j;
int err;
- if (!(cobra = kzalloc(sizeof(struct cobra), GFP_KERNEL)))
+ cobra = kzalloc(sizeof(struct cobra), GFP_KERNEL);
+ if (!cobra)
return -ENOMEM;
cobra->gameport = gameport;
@@ -191,38 +191,46 @@ static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
gameport_set_poll_handler(gameport, cobra_poll);
gameport_set_poll_interval(gameport, 20);
- for (i = 0; i < 2; i++)
- if ((cobra->exists >> i) & 1) {
-
- sprintf(cobra->phys[i], "%s/input%d", gameport->phys, i);
+ for (i = 0; i < 2; i++) {
+ if (~(cobra->exists >> i) & 1)
+ continue;
- cobra->dev[i].private = cobra;
- cobra->dev[i].open = cobra_open;
- cobra->dev[i].close = cobra_close;
+ cobra->dev[i] = input_dev = input_allocate_device();
+ if (!input_dev) {
+ err = -ENOMEM;
+ goto fail3;
+ }
- cobra->dev[i].name = cobra_name;
- cobra->dev[i].phys = cobra->phys[i];
- cobra->dev[i].id.bustype = BUS_GAMEPORT;
- cobra->dev[i].id.vendor = GAMEPORT_ID_VENDOR_CREATIVE;
- cobra->dev[i].id.product = 0x0008;
- cobra->dev[i].id.version = 0x0100;
+ sprintf(cobra->phys[i], "%s/input%d", gameport->phys, i);
- cobra->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->name = "Creative Labs Blaster GamePad Cobra";
+ input_dev->phys = cobra->phys[i];
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_CREATIVE;
+ input_dev->id.product = 0x0008;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &gameport->dev;
+ input_dev->private = cobra;
- input_set_abs_params(&cobra->dev[i], ABS_X, -1, 1, 0, 0);
- input_set_abs_params(&cobra->dev[i], ABS_Y, -1, 1, 0, 0);
+ input_dev->open = cobra_open;
+ input_dev->close = cobra_close;
- for (j = 0; cobra_btn[j]; j++)
- set_bit(cobra_btn[j], cobra->dev[i].keybit);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_set_abs_params(input_dev, ABS_X, -1, 1, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, -1, 1, 0, 0);
+ for (j = 0; cobra_btn[j]; j++)
+ set_bit(cobra_btn[j], input_dev->keybit);
- input_register_device(&cobra->dev[i]);
- printk(KERN_INFO "input: %s on %s\n", cobra_name, gameport->phys);
- }
+ input_register_device(cobra->dev[i]);
+ }
return 0;
-fail2: gameport_close(gameport);
-fail1: gameport_set_drvdata(gameport, NULL);
+ fail3: for (i = 0; i < 2; i++)
+ if (cobra->dev[i])
+ input_unregister_device(cobra->dev[i]);
+ fail2: gameport_close(gameport);
+ fail1: gameport_set_drvdata(gameport, NULL);
kfree(cobra);
return err;
}
@@ -234,7 +242,7 @@ static void cobra_disconnect(struct gameport *gameport)
for (i = 0; i < 2; i++)
if ((cobra->exists >> i) & 1)
- input_unregister_device(cobra->dev + i);
+ input_unregister_device(cobra->dev[i]);
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
kfree(cobra);
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index 2a3e4bb2da507e..499344c72756dc 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -43,25 +43,28 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver");
MODULE_LICENSE("GPL");
-static int db9[] __initdata = { -1, 0 };
-static int db9_nargs __initdata = 0;
-module_param_array_named(dev, db9, int, &db9_nargs, 0);
-MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)");
+struct db9_config {
+ int args[2];
+ int nargs;
+};
-static int db9_2[] __initdata = { -1, 0 };
-static int db9_nargs_2 __initdata = 0;
-module_param_array_named(dev2, db9_2, int, &db9_nargs_2, 0);
-MODULE_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)");
+#define DB9_MAX_PORTS 3
+static struct db9_config db9[DB9_MAX_PORTS] __initdata;
-static int db9_3[] __initdata = { -1, 0 };
-static int db9_nargs_3 __initdata = 0;
-module_param_array_named(dev3, db9_3, int, &db9_nargs_3, 0);
+module_param_array_named(dev, db9[0].args, int, &db9[0].nargs, 0);
+MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)");
+module_param_array_named(dev2, db9[1].args, int, &db9[0].nargs, 0);
+MODULE_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)");
+module_param_array_named(dev3, db9[2].args, int, &db9[2].nargs, 0);
MODULE_PARM_DESC(dev3, "Describes third attached device (<parport#>,<type>)");
__obsolete_setup("db9=");
__obsolete_setup("db9_2=");
__obsolete_setup("db9_3=");
+#define DB9_ARG_PARPORT 0
+#define DB9_ARG_MODE 1
+
#define DB9_MULTI_STICK 0x01
#define DB9_MULTI2_STICK 0x02
#define DB9_GENESIS_PAD 0x03
@@ -87,40 +90,53 @@ __obsolete_setup("db9_3=");
#define DB9_NORMAL 0x0a
#define DB9_NOSELECT 0x08
-#define DB9_MAX_DEVICES 2
-
#define DB9_GENESIS6_DELAY 14
#define DB9_REFRESH_TIME HZ/100
+#define DB9_MAX_DEVICES 2
+
+struct db9_mode_data {
+ const char *name;
+ const short *buttons;
+ int n_buttons;
+ int n_pads;
+ int n_axis;
+ int bidirectional;
+ int reverse;
+};
+
struct db9 {
- struct input_dev dev[DB9_MAX_DEVICES];
+ struct input_dev *dev[DB9_MAX_DEVICES];
struct timer_list timer;
struct pardevice *pd;
int mode;
int used;
struct semaphore sem;
- char phys[2][32];
+ char phys[DB9_MAX_DEVICES][32];
};
static struct db9 *db9_base[3];
-static short db9_multi_btn[] = { BTN_TRIGGER, BTN_THUMB };
-static short db9_genesis_btn[] = { BTN_START, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_MODE };
-static short db9_cd32_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START };
-
-static char db9_buttons[DB9_MAX_PAD] = { 0, 1, 2, 4, 0, 6, 8, 9, 1, 1, 7, 9, 9 };
-static short *db9_btn[DB9_MAX_PAD] = { NULL, db9_multi_btn, db9_multi_btn, db9_genesis_btn, NULL, db9_genesis_btn,
- db9_genesis_btn, db9_cd32_btn, db9_multi_btn, db9_multi_btn, db9_cd32_btn,
- db9_cd32_btn, db9_cd32_btn };
-static char *db9_name[DB9_MAX_PAD] = { NULL, "Multisystem joystick", "Multisystem joystick (2 fire)", "Genesis pad",
- NULL, "Genesis 5 pad", "Genesis 6 pad", "Saturn pad", "Multisystem (0.8.0.2) joystick",
- "Multisystem (0.8.0.2-dual) joystick", "Amiga CD-32 pad", "Saturn dpp", "Saturn dpp dual" };
-
-static const int db9_max_pads[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 6, 1, 2, 1, 6, 12 };
-static const int db9_num_axis[DB9_MAX_PAD] = { 0, 2, 2, 2, 0, 2, 2, 7, 2, 2, 2 ,7, 7 };
+static const short db9_multi_btn[] = { BTN_TRIGGER, BTN_THUMB };
+static const short db9_genesis_btn[] = { BTN_START, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_MODE };
+static const short db9_cd32_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START };
static const short db9_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_RZ, ABS_Z, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y };
-static const int db9_bidirectional[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0 };
-static const int db9_reverse[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0 };
+
+static const struct db9_mode_data db9_modes[] = {
+ { NULL, NULL, 0, 0, 0, 0, 0 },
+ { "Multisystem joystick", db9_multi_btn, 1, 1, 2, 1, 1 },
+ { "Multisystem joystick (2 fire)", db9_multi_btn, 2, 1, 2, 1, 1 },
+ { "Genesis pad", db9_genesis_btn, 4, 1, 2, 1, 1 },
+ { NULL, NULL, 0, 0, 0, 0, 0 },
+ { "Genesis 5 pad", db9_genesis_btn, 6, 1, 2, 1, 1 },
+ { "Genesis 6 pad", db9_genesis_btn, 8, 1, 2, 1, 1 },
+ { "Saturn pad", db9_cd32_btn, 9, 6, 7, 0, 1 },
+ { "Multisystem (0.8.0.2) joystick", db9_multi_btn, 1, 1, 2, 1, 1 },
+ { "Multisystem (0.8.0.2-dual) joystick", db9_multi_btn, 1, 2, 2, 1, 1 },
+ { "Amiga CD-32 pad", db9_cd32_btn, 7, 1, 2, 1, 1 },
+ { "Saturn dpp", db9_cd32_btn, 9, 6, 7, 0, 0 },
+ { "Saturn dpp dual", db9_cd32_btn, 9, 12, 7, 0, 0 },
+};
/*
* Saturn controllers
@@ -342,7 +358,7 @@ static int db9_saturn(int mode, struct parport *port, struct input_dev *dev)
default:
return -1;
}
- max_pads = min(db9_max_pads[mode], DB9_MAX_DEVICES);
+ max_pads = min(db9_modes[mode].n_pads, DB9_MAX_DEVICES);
for (tmp = 0, i = 0; i < n; i++) {
id = db9_saturn_read_packet(port, data, type + i, 1);
tmp = db9_saturn_report(id, data, dev, tmp, max_pads);
@@ -354,17 +370,18 @@ static void db9_timer(unsigned long private)
{
struct db9 *db9 = (void *) private;
struct parport *port = db9->pd->port;
- struct input_dev *dev = db9->dev;
+ struct input_dev *dev = db9->dev[0];
+ struct input_dev *dev2 = db9->dev[1];
int data, i;
- switch(db9->mode) {
+ switch (db9->mode) {
case DB9_MULTI_0802_2:
data = parport_read_data(port) >> 3;
- input_report_abs(dev + 1, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
- input_report_abs(dev + 1, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
- input_report_key(dev + 1, BTN_TRIGGER, ~data & DB9_FIRE1);
+ input_report_abs(dev2, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+ input_report_abs(dev2, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
+ input_report_key(dev2, BTN_TRIGGER, ~data & DB9_FIRE1);
case DB9_MULTI_0802:
@@ -405,7 +422,7 @@ static void db9_timer(unsigned long private)
input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
parport_write_control(port, DB9_NORMAL);
- data=parport_read_data(port);
+ data = parport_read_data(port);
input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
@@ -414,7 +431,7 @@ static void db9_timer(unsigned long private)
case DB9_GENESIS5_PAD:
parport_write_control(port, DB9_NOSELECT);
- data=parport_read_data(port);
+ data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
@@ -422,7 +439,7 @@ static void db9_timer(unsigned long private)
input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
parport_write_control(port, DB9_NORMAL);
- data=parport_read_data(port);
+ data = parport_read_data(port);
input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
input_report_key(dev, BTN_X, ~data & DB9_FIRE2);
@@ -434,7 +451,7 @@ static void db9_timer(unsigned long private)
parport_write_control(port, DB9_NOSELECT); /* 1 */
udelay(DB9_GENESIS6_DELAY);
- data=parport_read_data(port);
+ data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
@@ -443,7 +460,7 @@ static void db9_timer(unsigned long private)
parport_write_control(port, DB9_NORMAL);
udelay(DB9_GENESIS6_DELAY);
- data=parport_read_data(port);
+ data = parport_read_data(port);
input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
@@ -477,7 +494,7 @@ static void db9_timer(unsigned long private)
case DB9_CD32_PAD:
- data=parport_read_data(port);
+ data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
@@ -489,7 +506,7 @@ static void db9_timer(unsigned long private)
parport_write_control(port, 0x02);
parport_write_control(port, 0x0a);
input_report_key(dev, db9_cd32_btn[i], ~data & DB9_FIRE2);
- }
+ }
parport_write_control(port, 0x00);
break;
@@ -513,7 +530,7 @@ static int db9_open(struct input_dev *dev)
if (!db9->used++) {
parport_claim(db9->pd);
parport_write_data(port, 0xff);
- if (db9_reverse[db9->mode]) {
+ if (db9_modes[db9->mode].reverse) {
parport_data_reverse(port);
parport_write_control(port, DB9_NORMAL);
}
@@ -539,117 +556,160 @@ static void db9_close(struct input_dev *dev)
up(&db9->sem);
}
-static struct db9 __init *db9_probe(int *config, int nargs)
+static struct db9 __init *db9_probe(int parport, int mode)
{
struct db9 *db9;
+ const struct db9_mode_data *db9_mode;
struct parport *pp;
+ struct pardevice *pd;
+ struct input_dev *input_dev;
int i, j;
+ int err;
- if (config[0] < 0)
- return NULL;
-
- if (nargs < 2) {
- printk(KERN_ERR "db9.c: Device type must be specified.\n");
- return NULL;
+ if (mode < 1 || mode >= DB9_MAX_PAD || !db9_modes[mode].n_buttons) {
+ printk(KERN_ERR "db9.c: Bad device type %d\n", mode);
+ err = -EINVAL;
+ goto err_out;
}
- if (config[1] < 1 || config[1] >= DB9_MAX_PAD || !db9_buttons[config[1]]) {
- printk(KERN_ERR "db9.c: bad config\n");
- return NULL;
- }
+ db9_mode = &db9_modes[mode];
- pp = parport_find_number(config[0]);
+ pp = parport_find_number(parport);
if (!pp) {
printk(KERN_ERR "db9.c: no such parport\n");
- return NULL;
+ err = -ENODEV;
+ goto err_out;
}
- if (db9_bidirectional[config[1]]) {
- if (!(pp->modes & PARPORT_MODE_TRISTATE)) {
- printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
- parport_put_port(pp);
- return NULL;
- }
+ if (db9_mode[mode].bidirectional && !(pp->modes & PARPORT_MODE_TRISTATE)) {
+ printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
+ err = -EINVAL;
+ goto err_put_pp;
+ }
+
+ pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+ if (!pd) {
+ printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n");
+ err = -EBUSY;
+ goto err_put_pp;
}
- if (!(db9 = kzalloc(sizeof(struct db9), GFP_KERNEL))) {
- parport_put_port(pp);
- return NULL;
+ db9 = kzalloc(sizeof(struct db9), GFP_KERNEL);
+ if (!db9) {
+ printk(KERN_ERR "db9.c: Not enough memory\n");
+ err = -ENOMEM;
+ goto err_unreg_pardev;
}
init_MUTEX(&db9->sem);
- db9->mode = config[1];
+ db9->pd = pd;
+ db9->mode = mode;
init_timer(&db9->timer);
db9->timer.data = (long) db9;
db9->timer.function = db9_timer;
- db9->pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
- parport_put_port(pp);
-
- if (!db9->pd) {
- printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n");
- kfree(db9);
- return NULL;
- }
+ for (i = 0; i < (min(db9_mode->n_pads, DB9_MAX_DEVICES)); i++) {
- for (i = 0; i < (min(db9_max_pads[db9->mode], DB9_MAX_DEVICES)); i++) {
+ db9->dev[i] = input_dev = input_allocate_device();
+ if (!input_dev) {
+ printk(KERN_ERR "db9.c: Not enough memory for input device\n");
+ err = -ENOMEM;
+ goto err_free_devs;
+ }
sprintf(db9->phys[i], "%s/input%d", db9->pd->port->name, i);
- db9->dev[i].private = db9;
- db9->dev[i].open = db9_open;
- db9->dev[i].close = db9_close;
-
- db9->dev[i].name = db9_name[db9->mode];
- db9->dev[i].phys = db9->phys[i];
- db9->dev[i].id.bustype = BUS_PARPORT;
- db9->dev[i].id.vendor = 0x0002;
- db9->dev[i].id.product = config[1];
- db9->dev[i].id.version = 0x0100;
-
- db9->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- for (j = 0; j < db9_buttons[db9->mode]; j++)
- set_bit(db9_btn[db9->mode][j], db9->dev[i].keybit);
- for (j = 0; j < db9_num_axis[db9->mode]; j++) {
- set_bit(db9_abs[j], db9->dev[i].absbit);
- if (j < 2) {
- db9->dev[i].absmin[db9_abs[j]] = -1;
- db9->dev[i].absmax[db9_abs[j]] = 1;
- } else {
- db9->dev[i].absmin[db9_abs[j]] = 1;
- db9->dev[i].absmax[db9_abs[j]] = 255;
- db9->dev[i].absflat[db9_abs[j]] = 0;
- }
+ input_dev->name = db9_mode->name;
+ input_dev->phys = db9->phys[i];
+ input_dev->id.bustype = BUS_PARPORT;
+ input_dev->id.vendor = 0x0002;
+ input_dev->id.product = mode;
+ input_dev->id.version = 0x0100;
+ input_dev->private = db9;
+
+ input_dev->open = db9_open;
+ input_dev->close = db9_close;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ for (j = 0; j < db9_mode->n_buttons; j++)
+ set_bit(db9_mode->buttons[j], input_dev->keybit);
+ for (j = 0; j < db9_mode->n_axis; j++) {
+ if (j < 2)
+ input_set_abs_params(input_dev, db9_abs[j], -1, 1, 0, 0);
+ else
+ input_set_abs_params(input_dev, db9_abs[j], 1, 255, 0, 0);
}
- input_register_device(db9->dev + i);
- printk(KERN_INFO "input: %s on %s\n", db9->dev[i].name, db9->pd->port->name);
+
+ input_register_device(input_dev);
}
+ parport_put_port(pp);
return db9;
+
+ err_free_devs:
+ while (--i >= 0)
+ input_unregister_device(db9->dev[i]);
+ kfree(db9);
+ err_unreg_pardev:
+ parport_unregister_device(pd);
+ err_put_pp:
+ parport_put_port(pp);
+ err_out:
+ return ERR_PTR(err);
+}
+
+static void __exit db9_remove(struct db9 *db9)
+{
+ int i;
+
+ for (i = 0; i < min(db9_modes[db9->mode].n_pads, DB9_MAX_DEVICES); i++)
+ input_unregister_device(db9->dev[i]);
+ parport_unregister_device(db9->pd);
+ kfree(db9);
}
static int __init db9_init(void)
{
- db9_base[0] = db9_probe(db9, db9_nargs);
- db9_base[1] = db9_probe(db9_2, db9_nargs_2);
- db9_base[2] = db9_probe(db9_3, db9_nargs_3);
+ int i;
+ int have_dev = 0;
+ int err = 0;
+
+ for (i = 0; i < DB9_MAX_PORTS; i++) {
+ if (db9[i].nargs == 0 || db9[i].args[DB9_ARG_PARPORT] < 0)
+ continue;
+
+ if (db9[i].nargs < 2) {
+ printk(KERN_ERR "db9.c: Device type must be specified.\n");
+ err = -EINVAL;
+ break;
+ }
+
+ db9_base[i] = db9_probe(db9[i].args[DB9_ARG_PARPORT],
+ db9[i].args[DB9_ARG_MODE]);
+ if (IS_ERR(db9_base[i])) {
+ err = PTR_ERR(db9_base[i]);
+ break;
+ }
+
+ have_dev = 1;
+ }
- if (db9_base[0] || db9_base[1] || db9_base[2])
- return 0;
+ if (err) {
+ while (--i >= 0)
+ db9_remove(db9_base[i]);
+ return err;
+ }
- return -ENODEV;
+ return have_dev ? 0 : -ENODEV;
}
static void __exit db9_exit(void)
{
- int i, j;
+ int i;
- for (i = 0; i < 3; i++)
- if (db9_base[i]) {
- for (j = 0; j < min(db9_max_pads[db9_base[i]->mode], DB9_MAX_DEVICES); j++)
- input_unregister_device(db9_base[i]->dev + j);
- parport_unregister_device(db9_base[i]->pd);
- }
+ for (i = 0; i < DB9_MAX_PORTS; i++)
+ if (db9_base[i])
+ db9_remove(db9_base[i]);
}
module_init(db9_init);
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index 5427bf9fc86232..7df2d82f2c83b2 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -41,20 +41,22 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver");
MODULE_LICENSE("GPL");
-static int gc[] __initdata = { -1, 0, 0, 0, 0, 0 };
-static int gc_nargs __initdata = 0;
-module_param_array_named(map, gc, int, &gc_nargs, 0);
-MODULE_PARM_DESC(map, "Describers first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
+#define GC_MAX_PORTS 3
+#define GC_MAX_DEVICES 5
-static int gc_2[] __initdata = { -1, 0, 0, 0, 0, 0 };
-static int gc_nargs_2 __initdata = 0;
-module_param_array_named(map2, gc_2, int, &gc_nargs_2, 0);
-MODULE_PARM_DESC(map2, "Describers second set of devices");
+struct gc_config {
+ int args[GC_MAX_DEVICES + 1];
+ int nargs;
+};
+
+static struct gc_config gc[GC_MAX_PORTS] __initdata;
-static int gc_3[] __initdata = { -1, 0, 0, 0, 0, 0 };
-static int gc_nargs_3 __initdata = 0;
-module_param_array_named(map3, gc_3, int, &gc_nargs_3, 0);
-MODULE_PARM_DESC(map3, "Describers third set of devices");
+module_param_array_named(map, gc[0].args, int, &gc[0].nargs, 0);
+MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
+module_param_array_named(map2, gc[1].args, int, &gc[1].nargs, 0);
+MODULE_PARM_DESC(map2, "Describes second set of devices");
+module_param_array_named(map3, gc[2].args, int, &gc[2].nargs, 0);
+MODULE_PARM_DESC(map3, "Describes third set of devices");
__obsolete_setup("gc=");
__obsolete_setup("gc_2=");
@@ -77,12 +79,12 @@ __obsolete_setup("gc_3=");
struct gc {
struct pardevice *pd;
- struct input_dev dev[5];
+ struct input_dev *dev[GC_MAX_DEVICES];
struct timer_list timer;
unsigned char pads[GC_MAX + 1];
int used;
struct semaphore sem;
- char phys[5][32];
+ char phys[GC_MAX_DEVICES][32];
};
static struct gc *gc_base[3];
@@ -330,7 +332,6 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES
static void gc_timer(unsigned long private)
{
struct gc *gc = (void *) private;
- struct input_dev *dev = gc->dev;
unsigned char data[GC_MAX_LENGTH];
unsigned char data_psx[5][GC_PSX_BYTES];
int i, j, s;
@@ -357,16 +358,16 @@ static void gc_timer(unsigned long private)
if (data[31 - j] & s) axes[1] |= 1 << j;
}
- input_report_abs(dev + i, ABS_X, axes[0]);
- input_report_abs(dev + i, ABS_Y, -axes[1]);
+ input_report_abs(gc->dev[i], ABS_X, axes[0]);
+ input_report_abs(gc->dev[i], ABS_Y, -axes[1]);
- input_report_abs(dev + i, ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
- input_report_abs(dev + i, ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
+ input_report_abs(gc->dev[i], ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
+ input_report_abs(gc->dev[i], ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
for (j = 0; j < 10; j++)
- input_report_key(dev + i, gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
+ input_report_key(gc->dev[i], gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
- input_sync(dev + i);
+ input_sync(gc->dev[i]);
}
}
}
@@ -384,19 +385,19 @@ static void gc_timer(unsigned long private)
s = gc_status_bit[i];
if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) {
- input_report_abs(dev + i, ABS_X, !(s & data[6]) - !(s & data[7]));
- input_report_abs(dev + i, ABS_Y, !(s & data[4]) - !(s & data[5]));
+ input_report_abs(gc->dev[i], ABS_X, !(s & data[6]) - !(s & data[7]));
+ input_report_abs(gc->dev[i], ABS_Y, !(s & data[4]) - !(s & data[5]));
}
if (s & gc->pads[GC_NES])
for (j = 0; j < 4; j++)
- input_report_key(dev + i, gc_snes_btn[j], s & data[gc_nes_bytes[j]]);
+ input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_nes_bytes[j]]);
if (s & gc->pads[GC_SNES])
for (j = 0; j < 8; j++)
- input_report_key(dev + i, gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
+ input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
- input_sync(dev + i);
+ input_sync(gc->dev[i]);
}
}
@@ -413,15 +414,15 @@ static void gc_timer(unsigned long private)
s = gc_status_bit[i];
if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) {
- input_report_abs(dev + i, ABS_X, !(s & data[2]) - !(s & data[3]));
- input_report_abs(dev + i, ABS_Y, !(s & data[0]) - !(s & data[1]));
- input_report_key(dev + i, BTN_TRIGGER, s & data[4]);
+ input_report_abs(gc->dev[i], ABS_X, !(s & data[2]) - !(s & data[3]));
+ input_report_abs(gc->dev[i], ABS_Y, !(s & data[0]) - !(s & data[1]));
+ input_report_key(gc->dev[i], BTN_TRIGGER, s & data[4]);
}
if (s & gc->pads[GC_MULTI2])
- input_report_key(dev + i, BTN_THUMB, s & data[5]);
+ input_report_key(gc->dev[i], BTN_THUMB, s & data[5]);
- input_sync(dev + i);
+ input_sync(gc->dev[i]);
}
}
@@ -438,44 +439,44 @@ static void gc_timer(unsigned long private)
case GC_PSX_RUMBLE:
- input_report_key(dev + i, BTN_THUMBL, ~data_psx[i][0] & 0x04);
- input_report_key(dev + i, BTN_THUMBR, ~data_psx[i][0] & 0x02);
+ input_report_key(gc->dev[i], BTN_THUMBL, ~data_psx[i][0] & 0x04);
+ input_report_key(gc->dev[i], BTN_THUMBR, ~data_psx[i][0] & 0x02);
case GC_PSX_NEGCON:
case GC_PSX_ANALOG:
- if(gc->pads[GC_DDR] & gc_status_bit[i]) {
+ if (gc->pads[GC_DDR] & gc_status_bit[i]) {
for(j = 0; j < 4; j++)
- input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
+ input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
} else {
for (j = 0; j < 4; j++)
- input_report_abs(dev + i, gc_psx_abs[j+2], data_psx[i][j + 2]);
+ input_report_abs(gc->dev[i], gc_psx_abs[j+2], data_psx[i][j + 2]);
- input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
- input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
+ input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
+ input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
}
for (j = 0; j < 8; j++)
- input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
+ input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
- input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08);
- input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
+ input_report_key(gc->dev[i], BTN_START, ~data_psx[i][0] & 0x08);
+ input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01);
- input_sync(dev + i);
+ input_sync(gc->dev[i]);
break;
case GC_PSX_NORMAL:
- if(gc->pads[GC_DDR] & gc_status_bit[i]) {
+ if (gc->pads[GC_DDR] & gc_status_bit[i]) {
for(j = 0; j < 4; j++)
- input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
+ input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
} else {
- input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
- input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
+ input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
+ input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
/* for some reason if the extra axes are left unset they drift */
/* for (j = 0; j < 4; j++)
- input_report_abs(dev + i, gc_psx_abs[j+2], 128);
+ input_report_abs(gc->dev[i], gc_psx_abs[j+2], 128);
* This needs to be debugged properly,
* maybe fuzz processing needs to be done in input_sync()
* --vojtech
@@ -483,12 +484,12 @@ static void gc_timer(unsigned long private)
}
for (j = 0; j < 8; j++)
- input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
+ input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
- input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08);
- input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
+ input_report_key(gc->dev[i], BTN_START, ~data_psx[i][0] & 0x08);
+ input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01);
- input_sync(dev + i);
+ input_sync(gc->dev[i]);
break;
@@ -533,177 +534,212 @@ static void gc_close(struct input_dev *dev)
up(&gc->sem);
}
-static struct gc __init *gc_probe(int *config, int nargs)
+static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
{
- struct gc *gc;
- struct parport *pp;
- int i, j;
+ struct input_dev *input_dev;
+ int i;
- if (config[0] < 0)
- return NULL;
+ if (!pad_type)
+ return 0;
- if (nargs < 2) {
- printk(KERN_ERR "gamecon.c: at least one device must be specified\n");
- return NULL;
+ if (pad_type < 1 || pad_type > GC_MAX) {
+ printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", pad_type);
+ return -EINVAL;
}
- pp = parport_find_number(config[0]);
-
- if (!pp) {
- printk(KERN_ERR "gamecon.c: no such parport\n");
- return NULL;
+ gc->dev[idx] = input_dev = input_allocate_device();
+ if (!input_dev) {
+ printk(KERN_ERR "gamecon.c: Not enough memory for input device\n");
+ return -ENOMEM;
}
- if (!(gc = kzalloc(sizeof(struct gc), GFP_KERNEL))) {
- parport_put_port(pp);
- return NULL;
+ input_dev->name = gc_names[pad_type];
+ input_dev->phys = gc->phys[idx];
+ input_dev->id.bustype = BUS_PARPORT;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = pad_type;
+ input_dev->id.version = 0x0100;
+ input_dev->private = gc;
+
+ input_dev->open = gc_open;
+ input_dev->close = gc_close;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+ for (i = 0; i < 2; i++)
+ input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0);
+
+ gc->pads[0] |= gc_status_bit[idx];
+ gc->pads[pad_type] |= gc_status_bit[idx];
+
+ switch (pad_type) {
+
+ case GC_N64:
+ for (i = 0; i < 10; i++)
+ set_bit(gc_n64_btn[i], input_dev->keybit);
+
+ for (i = 0; i < 2; i++) {
+ input_set_abs_params(input_dev, ABS_X + i, -127, 126, 0, 2);
+ input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0);
+ }
+
+ break;
+
+ case GC_SNES:
+ for (i = 4; i < 8; i++)
+ set_bit(gc_snes_btn[i], input_dev->keybit);
+ case GC_NES:
+ for (i = 0; i < 4; i++)
+ set_bit(gc_snes_btn[i], input_dev->keybit);
+ break;
+
+ case GC_MULTI2:
+ set_bit(BTN_THUMB, input_dev->keybit);
+ case GC_MULTI:
+ set_bit(BTN_TRIGGER, input_dev->keybit);
+ break;
+
+ case GC_PSX:
+ for (i = 0; i < 6; i++)
+ input_set_abs_params(input_dev, gc_psx_abs[i], 4, 252, 0, 2);
+ for (i = 0; i < 12; i++)
+ set_bit(gc_psx_btn[i], input_dev->keybit);
+
+ break;
+
+ case GC_DDR:
+ for (i = 0; i < 4; i++)
+ set_bit(gc_psx_ddr_btn[i], input_dev->keybit);
+ for (i = 0; i < 12; i++)
+ set_bit(gc_psx_btn[i], input_dev->keybit);
+
+ break;
}
- init_MUTEX(&gc->sem);
+ return 0;
+}
- gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
+{
+ struct gc *gc;
+ struct parport *pp;
+ struct pardevice *pd;
+ int i;
+ int err;
- parport_put_port(pp);
+ pp = parport_find_number(parport);
+ if (!pp) {
+ printk(KERN_ERR "gamecon.c: no such parport\n");
+ err = -EINVAL;
+ goto err_out;
+ }
- if (!gc->pd) {
+ pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+ if (!pd) {
printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n");
- kfree(gc);
- return NULL;
+ err = -EBUSY;
+ goto err_put_pp;
}
- parport_claim(gc->pd);
+ gc = kzalloc(sizeof(struct gc), GFP_KERNEL);
+ if (!gc) {
+ printk(KERN_ERR "gamecon.c: Not enough memory\n");
+ err = -ENOMEM;
+ goto err_unreg_pardev;
+ }
+ init_MUTEX(&gc->sem);
+ gc->pd = pd;
init_timer(&gc->timer);
gc->timer.data = (long) gc;
gc->timer.function = gc_timer;
- for (i = 0; i < nargs - 1; i++) {
-
- if (!config[i + 1])
+ for (i = 0; i < n_pads; i++) {
+ if (!pads[i])
continue;
- if (config[i + 1] < 1 || config[i + 1] > GC_MAX) {
- printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", config[i + 1]);
- continue;
- }
-
- gc->dev[i].private = gc;
- gc->dev[i].open = gc_open;
- gc->dev[i].close = gc_close;
+ sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i);
+ err = gc_setup_pad(gc, i, pads[i]);
+ if (err)
+ goto err_free_devs;
- gc->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_register_device(gc->dev[i]);
+ }
- for (j = 0; j < 2; j++) {
- set_bit(ABS_X + j, gc->dev[i].absbit);
- gc->dev[i].absmin[ABS_X + j] = -1;
- gc->dev[i].absmax[ABS_X + j] = 1;
- }
+ if (!gc->pads[0]) {
+ printk(KERN_ERR "gamecon.c: No valid devices specified\n");
+ err = -EINVAL;
+ goto err_free_gc;
+ }
- gc->pads[0] |= gc_status_bit[i];
- gc->pads[config[i + 1]] |= gc_status_bit[i];
+ parport_put_port(pp);
+ return gc;
- switch(config[i + 1]) {
+ err_free_devs:
+ while (--i >= 0)
+ input_unregister_device(gc->dev[i]);
+ err_free_gc:
+ kfree(gc);
+ err_unreg_pardev:
+ parport_unregister_device(pd);
+ err_put_pp:
+ parport_put_port(pp);
+ err_out:
+ return ERR_PTR(err);
+}
- case GC_N64:
- for (j = 0; j < 10; j++)
- set_bit(gc_n64_btn[j], gc->dev[i].keybit);
-
- for (j = 0; j < 2; j++) {
- set_bit(ABS_X + j, gc->dev[i].absbit);
- gc->dev[i].absmin[ABS_X + j] = -127;
- gc->dev[i].absmax[ABS_X + j] = 126;
- gc->dev[i].absflat[ABS_X + j] = 2;
- set_bit(ABS_HAT0X + j, gc->dev[i].absbit);
- gc->dev[i].absmin[ABS_HAT0X + j] = -1;
- gc->dev[i].absmax[ABS_HAT0X + j] = 1;
- }
+static void __exit gc_remove(struct gc *gc)
+{
+ int i;
- break;
+ for (i = 0; i < GC_MAX_DEVICES; i++)
+ if (gc->dev[i])
+ input_unregister_device(gc->dev[i]);
+ parport_unregister_device(gc->pd);
+ kfree(gc);
+}
- case GC_SNES:
- for (j = 4; j < 8; j++)
- set_bit(gc_snes_btn[j], gc->dev[i].keybit);
- case GC_NES:
- for (j = 0; j < 4; j++)
- set_bit(gc_snes_btn[j], gc->dev[i].keybit);
- break;
-
- case GC_MULTI2:
- set_bit(BTN_THUMB, gc->dev[i].keybit);
- case GC_MULTI:
- set_bit(BTN_TRIGGER, gc->dev[i].keybit);
- break;
-
- case GC_PSX:
- case GC_DDR:
- if(config[i + 1] == GC_DDR) {
- for (j = 0; j < 4; j++)
- set_bit(gc_psx_ddr_btn[j], gc->dev[i].keybit);
- } else {
- for (j = 0; j < 6; j++) {
- set_bit(gc_psx_abs[j], gc->dev[i].absbit);
- gc->dev[i].absmin[gc_psx_abs[j]] = 4;
- gc->dev[i].absmax[gc_psx_abs[j]] = 252;
- gc->dev[i].absflat[gc_psx_abs[j]] = 2;
- }
- }
+static int __init gc_init(void)
+{
+ int i;
+ int have_dev = 0;
+ int err = 0;
- for (j = 0; j < 12; j++)
- set_bit(gc_psx_btn[j], gc->dev[i].keybit);
+ for (i = 0; i < GC_MAX_PORTS; i++) {
+ if (gc[i].nargs == 0 || gc[i].args[0] < 0)
+ continue;
- break;
+ if (gc[i].nargs < 2) {
+ printk(KERN_ERR "gamecon.c: at least one device must be specified\n");
+ err = -EINVAL;
+ break;
}
- sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i);
+ gc_base[i] = gc_probe(gc[i].args[0], gc[i].args + 1, gc[i].nargs - 1);
+ if (IS_ERR(gc_base[i])) {
+ err = PTR_ERR(gc_base[i]);
+ break;
+ }
- gc->dev[i].name = gc_names[config[i + 1]];
- gc->dev[i].phys = gc->phys[i];
- gc->dev[i].id.bustype = BUS_PARPORT;
- gc->dev[i].id.vendor = 0x0001;
- gc->dev[i].id.product = config[i + 1];
- gc->dev[i].id.version = 0x0100;
+ have_dev = 1;
}
- parport_release(gc->pd);
-
- if (!gc->pads[0]) {
- parport_unregister_device(gc->pd);
- kfree(gc);
- return NULL;
+ if (err) {
+ while (--i >= 0)
+ gc_remove(gc_base[i]);
+ return err;
}
- for (i = 0; i < 5; i++)
- if (gc->pads[0] & gc_status_bit[i]) {
- input_register_device(gc->dev + i);
- printk(KERN_INFO "input: %s on %s\n", gc->dev[i].name, gc->pd->port->name);
- }
-
- return gc;
-}
-
-static int __init gc_init(void)
-{
- gc_base[0] = gc_probe(gc, gc_nargs);
- gc_base[1] = gc_probe(gc_2, gc_nargs_2);
- gc_base[2] = gc_probe(gc_3, gc_nargs_3);
-
- if (gc_base[0] || gc_base[1] || gc_base[2])
- return 0;
-
- return -ENODEV;
+ return have_dev ? 0 : -ENODEV;
}
static void __exit gc_exit(void)
{
- int i, j;
-
- for (i = 0; i < 3; i++)
- if (gc_base[i]) {
- for (j = 0; j < 5; j++)
- if (gc_base[i]->pads[0] & gc_status_bit[j])
- input_unregister_device(gc_base[i]->dev + j);
- parport_unregister_device(gc_base[i]->pd);
- }
+ int i;
+
+ for (i = 0; i < GC_MAX_PORTS; i++)
+ if (gc_base[i])
+ gc_remove(gc_base[i]);
}
module_init(gc_init);
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
index 8e4f92b115e6aa..e151f8c5bcb9fa 100644
--- a/drivers/input/joystick/gf2k.c
+++ b/drivers/input/joystick/gf2k.c
@@ -81,7 +81,7 @@ static short gf2k_seq_digital[] = { 590, 320, 860, 0 };
struct gf2k {
struct gameport *gameport;
- struct input_dev dev;
+ struct input_dev *dev;
int reads;
int bads;
unsigned char id;
@@ -175,7 +175,7 @@ static int gf2k_get_bits(unsigned char *buf, int pos, int num, int shift)
static void gf2k_read(struct gf2k *gf2k, unsigned char *data)
{
- struct input_dev *dev = &gf2k->dev;
+ struct input_dev *dev = gf2k->dev;
int i, t;
for (i = 0; i < 4 && i < gf2k_axes[gf2k->id]; i++)
@@ -239,13 +239,19 @@ static void gf2k_close(struct input_dev *dev)
static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct gf2k *gf2k;
+ struct input_dev *input_dev;
unsigned char data[GF2K_LENGTH];
int i, err;
- if (!(gf2k = kzalloc(sizeof(struct gf2k), GFP_KERNEL)))
- return -ENOMEM;
+ gf2k = kzalloc(sizeof(struct gf2k), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!gf2k || !input_dev) {
+ err = -ENOMEM;
+ goto fail1;
+ }
gf2k->gameport = gameport;
+ gf2k->dev = input_dev;
gameport_set_drvdata(gameport, gf2k);
@@ -295,53 +301,52 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
gf2k->length = gf2k_lens[gf2k->id];
- init_input_dev(&gf2k->dev);
-
- gf2k->dev.private = gf2k;
- gf2k->dev.open = gf2k_open;
- gf2k->dev.close = gf2k_close;
- gf2k->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->name = gf2k_names[gf2k->id];
+ input_dev->phys = gf2k->phys;
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_GENIUS;
+ input_dev->id.product = gf2k->id;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &gameport->dev;
+ input_dev->private = gf2k;
- gf2k->dev.name = gf2k_names[gf2k->id];
- gf2k->dev.phys = gf2k->phys;
- gf2k->dev.id.bustype = BUS_GAMEPORT;
- gf2k->dev.id.vendor = GAMEPORT_ID_VENDOR_GENIUS;
- gf2k->dev.id.product = gf2k->id;
- gf2k->dev.id.version = 0x0100;
+ input_dev->open = gf2k_open;
+ input_dev->close = gf2k_close;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; i < gf2k_axes[gf2k->id]; i++)
- set_bit(gf2k_abs[i], gf2k->dev.absbit);
+ set_bit(gf2k_abs[i], input_dev->absbit);
for (i = 0; i < gf2k_hats[gf2k->id]; i++) {
- set_bit(ABS_HAT0X + i, gf2k->dev.absbit);
- gf2k->dev.absmin[ABS_HAT0X + i] = -1;
- gf2k->dev.absmax[ABS_HAT0X + i] = 1;
+ set_bit(ABS_HAT0X + i, input_dev->absbit);
+ input_dev->absmin[ABS_HAT0X + i] = -1;
+ input_dev->absmax[ABS_HAT0X + i] = 1;
}
for (i = 0; i < gf2k_joys[gf2k->id]; i++)
- set_bit(gf2k_btn_joy[i], gf2k->dev.keybit);
+ set_bit(gf2k_btn_joy[i], input_dev->keybit);
for (i = 0; i < gf2k_pads[gf2k->id]; i++)
- set_bit(gf2k_btn_pad[i], gf2k->dev.keybit);
+ set_bit(gf2k_btn_pad[i], input_dev->keybit);
gf2k_read_packet(gameport, gf2k->length, data);
gf2k_read(gf2k, data);
for (i = 0; i < gf2k_axes[gf2k->id]; i++) {
- gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 :
- gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32;
- gf2k->dev.absmin[gf2k_abs[i]] = 32;
- gf2k->dev.absfuzz[gf2k_abs[i]] = 8;
- gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0;
+ input_dev->absmax[gf2k_abs[i]] = (i < 2) ? input_dev->abs[gf2k_abs[i]] * 2 - 32 :
+ input_dev->abs[gf2k_abs[0]] + input_dev->abs[gf2k_abs[1]] - 32;
+ input_dev->absmin[gf2k_abs[i]] = 32;
+ input_dev->absfuzz[gf2k_abs[i]] = 8;
+ input_dev->absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0;
}
- input_register_device(&gf2k->dev);
- printk(KERN_INFO "input: %s on %s\n", gf2k_names[gf2k->id], gameport->phys);
+ input_register_device(gf2k->dev);
return 0;
-fail2: gameport_close(gameport);
-fail1: gameport_set_drvdata(gameport, NULL);
+ fail2: gameport_close(gameport);
+ fail1: gameport_set_drvdata(gameport, NULL);
+ input_free_device(input_dev);
kfree(gf2k);
return err;
}
@@ -350,7 +355,7 @@ static void gf2k_disconnect(struct gameport *gameport)
{
struct gf2k *gf2k = gameport_get_drvdata(gameport);
- input_unregister_device(&gf2k->dev);
+ input_unregister_device(gf2k->dev);
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
kfree(gf2k);
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
index 9d3f910dd568b4..e206bb56e53ce3 100644
--- a/drivers/input/joystick/grip.c
+++ b/drivers/input/joystick/grip.c
@@ -55,7 +55,7 @@ MODULE_LICENSE("GPL");
struct grip {
struct gameport *gameport;
- struct input_dev dev[2];
+ struct input_dev *dev[2];
unsigned char mode[2];
int reads;
int bads;
@@ -190,7 +190,7 @@ static void grip_poll(struct gameport *gameport)
for (i = 0; i < 2; i++) {
- dev = grip->dev + i;
+ dev = grip->dev[i];
grip->reads++;
switch (grip->mode[i]) {
@@ -297,6 +297,7 @@ static void grip_close(struct input_dev *dev)
static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct grip *grip;
+ struct input_dev *input_dev;
unsigned int data[GRIP_LENGTH_XT];
int i, j, t;
int err;
@@ -339,48 +340,56 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
gameport_set_poll_handler(gameport, grip_poll);
gameport_set_poll_interval(gameport, 20);
- for (i = 0; i < 2; i++)
- if (grip->mode[i]) {
+ for (i = 0; i < 2; i++) {
+ if (!grip->mode[i])
+ continue;
- sprintf(grip->phys[i], "%s/input%d", gameport->phys, i);
+ grip->dev[i] = input_dev = input_allocate_device();
+ if (!input_dev) {
+ err = -ENOMEM;
+ goto fail3;
+ }
- grip->dev[i].private = grip;
+ sprintf(grip->phys[i], "%s/input%d", gameport->phys, i);
- grip->dev[i].open = grip_open;
- grip->dev[i].close = grip_close;
+ input_dev->name = grip_name[grip->mode[i]];
+ input_dev->phys = grip->phys[i];
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
+ input_dev->id.product = grip->mode[i];
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &gameport->dev;
+ input_dev->private = grip;
- grip->dev[i].name = grip_name[grip->mode[i]];
- grip->dev[i].phys = grip->phys[i];
- grip->dev[i].id.bustype = BUS_GAMEPORT;
- grip->dev[i].id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
- grip->dev[i].id.product = grip->mode[i];
- grip->dev[i].id.version = 0x0100;
+ input_dev->open = grip_open;
+ input_dev->close = grip_close;
- grip->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {
+ for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {
- if (j < grip_cen[grip->mode[i]])
- input_set_abs_params(&grip->dev[i], t, 14, 52, 1, 2);
- else if (j < grip_anx[grip->mode[i]])
- input_set_abs_params(&grip->dev[i], t, 3, 57, 1, 0);
- else
- input_set_abs_params(&grip->dev[i], t, -1, 1, 0, 0);
- }
+ if (j < grip_cen[grip->mode[i]])
+ input_set_abs_params(input_dev, t, 14, 52, 1, 2);
+ else if (j < grip_anx[grip->mode[i]])
+ input_set_abs_params(input_dev, t, 3, 57, 1, 0);
+ else
+ input_set_abs_params(input_dev, t, -1, 1, 0, 0);
+ }
- for (j = 0; (t = grip_btn[grip->mode[i]][j]) >= 0; j++)
- if (t > 0)
- set_bit(t, grip->dev[i].keybit);
+ for (j = 0; (t = grip_btn[grip->mode[i]][j]) >= 0; j++)
+ if (t > 0)
+ set_bit(t, input_dev->keybit);
- printk(KERN_INFO "input: %s on %s\n",
- grip_name[grip->mode[i]], gameport->phys);
- input_register_device(grip->dev + i);
- }
+ input_register_device(grip->dev[i]);
+ }
return 0;
-fail2: gameport_close(gameport);
-fail1: gameport_set_drvdata(gameport, NULL);
+ fail3: for (i = 0; i < 2; i++)
+ if (grip->dev[i])
+ input_unregister_device(grip->dev[i]);
+ fail2: gameport_close(gameport);
+ fail1: gameport_set_drvdata(gameport, NULL);
kfree(grip);
return err;
}
@@ -391,8 +400,8 @@ static void grip_disconnect(struct gameport *gameport)
int i;
for (i = 0; i < 2; i++)
- if (grip->mode[i])
- input_unregister_device(grip->dev + i);
+ if (grip->dev[i])
+ input_unregister_device(grip->dev[i]);
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
kfree(grip);
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index da17eee6f5741f..a0ba93ccac7255 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -32,23 +32,37 @@ MODULE_LICENSE("GPL");
#define dbg(format, arg...) do {} while (0)
#endif
+#define GRIP_MAX_PORTS 4
/*
* Grip multiport state
*/
+struct grip_port {
+ struct input_dev *dev;
+ int mode;
+ int registered;
+
+ /* individual gamepad states */
+ int buttons;
+ int xaxes;
+ int yaxes;
+ int dirty; /* has the state been updated? */
+};
+
struct grip_mp {
struct gameport *gameport;
- struct input_dev dev[4];
- int mode[4];
- int registered[4];
+ struct grip_port *port[GRIP_MAX_PORTS];
+// struct input_dev *dev[4];
+// int mode[4];
+// int registered[4];
int reads;
int bads;
/* individual gamepad states */
- int buttons[4];
- int xaxes[4];
- int yaxes[4];
- int dirty[4]; /* has the state been updated? */
+// int buttons[4];
+// int xaxes[4];
+// int yaxes[4];
+// int dirty[4]; /* has the state been updated? */
};
/*
@@ -85,16 +99,16 @@ struct grip_mp {
#define GRIP_MODE_GP 2
#define GRIP_MODE_C64 3
-static int grip_btn_gp[] = { BTN_TR, BTN_TL, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, -1 };
-static int grip_btn_c64[] = { BTN_JOYSTICK, -1 };
+static const int grip_btn_gp[] = { BTN_TR, BTN_TL, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, -1 };
+static const int grip_btn_c64[] = { BTN_JOYSTICK, -1 };
-static int grip_abs_gp[] = { ABS_X, ABS_Y, -1 };
-static int grip_abs_c64[] = { ABS_X, ABS_Y, -1 };
+static const int grip_abs_gp[] = { ABS_X, ABS_Y, -1 };
+static const int grip_abs_c64[] = { ABS_X, ABS_Y, -1 };
-static int *grip_abs[] = { NULL, NULL, grip_abs_gp, grip_abs_c64 };
-static int *grip_btn[] = { NULL, NULL, grip_btn_gp, grip_btn_c64 };
+static const int *grip_abs[] = { NULL, NULL, grip_abs_gp, grip_abs_c64 };
+static const int *grip_btn[] = { NULL, NULL, grip_btn_gp, grip_btn_c64 };
-static char *grip_name[] = { NULL, NULL, "Gravis Grip Pad", "Commodore 64 Joystick" };
+static const char *grip_name[] = { NULL, NULL, "Gravis Grip Pad", "Commodore 64 Joystick" };
static const int init_seq[] = {
1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1,
@@ -104,9 +118,9 @@ static const int init_seq[] = {
/* Maps multiport directional values to X,Y axis values (each axis encoded in 3 bits) */
-static int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5 };
+static const int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5 };
-static void register_slot(int i, struct grip_mp *grip);
+static int register_slot(int i, struct grip_mp *grip);
/*
* Returns whether an odd or even number of bits are on in pkt.
@@ -353,9 +367,10 @@ static int dig_mode_start(struct gameport *gameport, u32 *packet)
static int get_and_decode_packet(struct grip_mp *grip, int flags)
{
+ struct grip_port *port;
u32 packet;
int joytype = 0;
- int slot = 0;
+ int slot;
/* Get a packet and check for validity */
@@ -377,6 +392,8 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags)
if ((slot < 0) || (slot > 3))
return flags;
+ port = grip->port[slot];
+
/*
* Handle "reset" packets, which occur at startup, and when gamepads
* are removed or plugged in. May contain configuration of a new gamepad.
@@ -385,14 +402,14 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags)
joytype = (packet >> 16) & 0x1f;
if (!joytype) {
- if (grip->registered[slot]) {
+ if (port->registered) {
printk(KERN_INFO "grip_mp: removing %s, slot %d\n",
- grip_name[grip->mode[slot]], slot);
- input_unregister_device(grip->dev + slot);
- grip->registered[slot] = 0;
+ grip_name[port->mode], slot);
+ input_unregister_device(port->dev);
+ port->registered = 0;
}
dbg("Reset: grip multiport slot %d\n", slot);
- grip->mode[slot] = GRIP_MODE_RESET;
+ port->mode = GRIP_MODE_RESET;
flags |= IO_SLOT_CHANGE;
return flags;
}
@@ -402,17 +419,17 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags)
if (joytype == 0x1f) {
int dir = (packet >> 8) & 0xf; /* eight way directional value */
- grip->buttons[slot] = (~packet) & 0xff;
- grip->yaxes[slot] = ((axis_map[dir] >> 2) & 3) - 1;
- grip->xaxes[slot] = (axis_map[dir] & 3) - 1;
- grip->dirty[slot] = 1;
+ port->buttons = (~packet) & 0xff;
+ port->yaxes = ((axis_map[dir] >> 2) & 3) - 1;
+ port->xaxes = (axis_map[dir] & 3) - 1;
+ port->dirty = 1;
- if (grip->mode[slot] == GRIP_MODE_RESET)
+ if (port->mode == GRIP_MODE_RESET)
flags |= IO_SLOT_CHANGE;
- grip->mode[slot] = GRIP_MODE_GP;
+ port->mode = GRIP_MODE_GP;
- if (!grip->registered[slot]) {
+ if (!port->registered) {
dbg("New Grip pad in multiport slot %d.\n", slot);
register_slot(slot, grip);
}
@@ -445,9 +462,9 @@ static int slots_valid(struct grip_mp *grip)
return 0;
for (slot = 0; slot < 4; slot++) {
- if (grip->mode[slot] == GRIP_MODE_RESET)
+ if (grip->port[slot]->mode == GRIP_MODE_RESET)
invalid = 1;
- if (grip->mode[slot] != GRIP_MODE_NONE)
+ if (grip->port[slot]->mode != GRIP_MODE_NONE)
active = 1;
}
@@ -484,7 +501,7 @@ static int multiport_init(struct grip_mp *grip)
/* Get packets, store multiport state, and check state's validity */
for (tries = 0; tries < 4096; tries++) {
- if ( slots_valid(grip) ) {
+ if (slots_valid(grip)) {
initialized = 1;
break;
}
@@ -499,24 +516,24 @@ static int multiport_init(struct grip_mp *grip)
static void report_slot(struct grip_mp *grip, int slot)
{
- struct input_dev *dev = &(grip->dev[slot]);
- int i, buttons = grip->buttons[slot];
+ struct grip_port *port = grip->port[slot];
+ int i;
/* Store button states with linux input driver */
for (i = 0; i < 8; i++)
- input_report_key(dev, grip_btn_gp[i], (buttons >> i) & 1);
+ input_report_key(port->dev, grip_btn_gp[i], (port->buttons >> i) & 1);
/* Store axis states with linux driver */
- input_report_abs(dev, ABS_X, grip->xaxes[slot]);
- input_report_abs(dev, ABS_Y, grip->yaxes[slot]);
+ input_report_abs(port->dev, ABS_X, port->xaxes);
+ input_report_abs(port->dev, ABS_Y, port->yaxes);
/* Tell the receiver of the events to process them */
- input_sync(dev);
+ input_sync(port->dev);
- grip->dirty[slot] = 0;
+ port->dirty = 0;
}
/*
@@ -540,7 +557,7 @@ static void grip_poll(struct gameport *gameport)
}
for (i = 0; i < 4; i++)
- if (grip->dirty[i])
+ if (grip->port[i]->dirty)
report_slot(grip, i);
}
@@ -571,35 +588,43 @@ static void grip_close(struct input_dev *dev)
* Tell the linux input layer about a newly plugged-in gamepad.
*/
-static void register_slot(int slot, struct grip_mp *grip)
+static int register_slot(int slot, struct grip_mp *grip)
{
+ struct grip_port *port = grip->port[slot];
+ struct input_dev *input_dev;
int j, t;
- grip->dev[slot].private = grip;
- grip->dev[slot].open = grip_open;
- grip->dev[slot].close = grip_close;
- grip->dev[slot].name = grip_name[grip->mode[slot]];
- grip->dev[slot].id.bustype = BUS_GAMEPORT;
- grip->dev[slot].id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
- grip->dev[slot].id.product = 0x0100 + grip->mode[slot];
- grip->dev[slot].id.version = 0x0100;
- grip->dev[slot].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ port->dev = input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
+
+ input_dev->name = grip_name[port->mode];
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
+ input_dev->id.product = 0x0100 + port->mode;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &grip->gameport->dev;
+ input_dev->private = grip;
+
+ input_dev->open = grip_open;
+ input_dev->close = grip_close;
- for (j = 0; (t = grip_abs[grip->mode[slot]][j]) >= 0; j++)
- input_set_abs_params(&grip->dev[slot], t, -1, 1, 0, 0);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- for (j = 0; (t = grip_btn[grip->mode[slot]][j]) >= 0; j++)
+ for (j = 0; (t = grip_abs[port->mode][j]) >= 0; j++)
+ input_set_abs_params(input_dev, t, -1, 1, 0, 0);
+
+ for (j = 0; (t = grip_btn[port->mode][j]) >= 0; j++)
if (t > 0)
- set_bit(t, grip->dev[slot].keybit);
+ set_bit(t, input_dev->keybit);
- input_register_device(grip->dev + slot);
- grip->registered[slot] = 1;
+ input_register_device(port->dev);
+ port->registered = 1;
- if (grip->dirty[slot]) /* report initial state, if any */
+ if (port->dirty) /* report initial state, if any */
report_slot(grip, slot);
- printk(KERN_INFO "grip_mp: added %s, slot %d\n",
- grip_name[grip->mode[slot]], slot);
+ return 0;
}
static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
@@ -626,7 +651,7 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
goto fail2;
}
- if (!grip->mode[0] && !grip->mode[1] && !grip->mode[2] && !grip->mode[3]) {
+ if (!grip->port[0]->mode && !grip->port[1]->mode && !grip->port[2]->mode && !grip->port[3]->mode) {
/* nothing plugged in */
err = -ENODEV;
goto fail2;
@@ -646,8 +671,8 @@ static void grip_disconnect(struct gameport *gameport)
int i;
for (i = 0; i < 4; i++)
- if (grip->registered[i])
- input_unregister_device(grip->dev + i);
+ if (grip->port[i]->registered)
+ input_unregister_device(grip->port[i]->dev);
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
kfree(grip);
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
index 6a70ec429f063e..c528473c09d894 100644
--- a/drivers/input/joystick/guillemot.c
+++ b/drivers/input/joystick/guillemot.c
@@ -67,7 +67,7 @@ struct guillemot_type {
struct guillemot {
struct gameport *gameport;
- struct input_dev dev;
+ struct input_dev *dev;
int bads;
int reads;
struct guillemot_type *type;
@@ -123,7 +123,7 @@ static int guillemot_read_packet(struct gameport *gameport, u8 *data)
static void guillemot_poll(struct gameport *gameport)
{
struct guillemot *guillemot = gameport_get_drvdata(gameport);
- struct input_dev *dev = &guillemot->dev;
+ struct input_dev *dev = guillemot->dev;
u8 data[GUILLEMOT_MAX_LENGTH];
int i;
@@ -179,14 +179,20 @@ static void guillemot_close(struct input_dev *dev)
static int guillemot_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct guillemot *guillemot;
+ struct input_dev *input_dev;
u8 data[GUILLEMOT_MAX_LENGTH];
int i, t;
int err;
- if (!(guillemot = kzalloc(sizeof(struct guillemot), GFP_KERNEL)))
- return -ENOMEM;
+ guillemot = kzalloc(sizeof(struct guillemot), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!guillemot || !input_dev) {
+ err = -ENOMEM;
+ goto fail1;
+ }
guillemot->gameport = gameport;
+ guillemot->dev = input_dev;
gameport_set_drvdata(gameport, guillemot);
@@ -216,41 +222,40 @@ static int guillemot_connect(struct gameport *gameport, struct gameport_driver *
gameport_set_poll_interval(gameport, 20);
sprintf(guillemot->phys, "%s/input0", gameport->phys);
-
guillemot->type = guillemot_type + i;
- guillemot->dev.private = guillemot;
- guillemot->dev.open = guillemot_open;
- guillemot->dev.close = guillemot_close;
+ input_dev->name = guillemot_type[i].name;
+ input_dev->phys = guillemot->phys;
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_GUILLEMOT;
+ input_dev->id.product = guillemot_type[i].id;
+ input_dev->id.version = (int)data[14] << 8 | data[15];
+ input_dev->cdev.dev = &gameport->dev;
+ input_dev->private = guillemot;
- guillemot->dev.name = guillemot_type[i].name;
- guillemot->dev.phys = guillemot->phys;
- guillemot->dev.id.bustype = BUS_GAMEPORT;
- guillemot->dev.id.vendor = GAMEPORT_ID_VENDOR_GUILLEMOT;
- guillemot->dev.id.product = guillemot_type[i].id;
- guillemot->dev.id.version = (int)data[14] << 8 | data[15];
+ input_dev->open = guillemot_open;
+ input_dev->close = guillemot_close;
- guillemot->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; (t = guillemot->type->abs[i]) >= 0; i++)
- input_set_abs_params(&guillemot->dev, t, 0, 255, 0, 0);
+ input_set_abs_params(input_dev, t, 0, 255, 0, 0);
if (guillemot->type->hat) {
- input_set_abs_params(&guillemot->dev, ABS_HAT0X, -1, 1, 0, 0);
- input_set_abs_params(&guillemot->dev, ABS_HAT0Y, -1, 1, 0, 0);
+ input_set_abs_params(input_dev, ABS_HAT0X, -1, 1, 0, 0);
+ input_set_abs_params(input_dev, ABS_HAT0Y, -1, 1, 0, 0);
}
for (i = 0; (t = guillemot->type->btn[i]) >= 0; i++)
- set_bit(t, guillemot->dev.keybit);
+ set_bit(t, input_dev->keybit);
- input_register_device(&guillemot->dev);
- printk(KERN_INFO "input: %s ver %d.%02d on %s\n",
- guillemot->type->name, data[14], data[15], gameport->phys);
+ input_register_device(guillemot->dev);
return 0;
fail2: gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL);
+ input_free_device(input_dev);
kfree(guillemot);
return err;
}
@@ -260,7 +265,7 @@ static void guillemot_disconnect(struct gameport *gameport)
struct guillemot *guillemot = gameport_get_drvdata(gameport);
printk(KERN_INFO "guillemot.c: Failed %d reads out of %d on %s\n", guillemot->reads, guillemot->bads, guillemot->phys);
- input_unregister_device(&guillemot->dev);
+ input_unregister_device(guillemot->dev);
gameport_close(gameport);
kfree(guillemot);
}
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index e31b7b93fde200..64b9c31c47fc6a 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -144,7 +144,7 @@ static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect)
int is_update;
/* Check this effect type is supported by this device */
- if (!test_bit(effect->type, iforce->dev.ffbit))
+ if (!test_bit(effect->type, iforce->dev->ffbit))
return -EINVAL;
/*
@@ -152,30 +152,31 @@ static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect)
*/
if (effect->id == -1) {
- for (id=0; id < FF_EFFECTS_MAX; ++id)
- if (!test_and_set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags)) break;
+ for (id = 0; id < FF_EFFECTS_MAX; ++id)
+ if (!test_and_set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags))
+ break;
- if ( id == FF_EFFECTS_MAX || id >= iforce->dev.ff_effects_max)
+ if (id == FF_EFFECTS_MAX || id >= iforce->dev->ff_effects_max)
return -ENOMEM;
effect->id = id;
iforce->core_effects[id].owner = current->pid;
- iforce->core_effects[id].flags[0] = (1<<FF_CORE_IS_USED); /* Only IS_USED bit must be set */
+ iforce->core_effects[id].flags[0] = (1 << FF_CORE_IS_USED); /* Only IS_USED bit must be set */
is_update = FALSE;
}
else {
/* We want to update an effect */
- if (!CHECK_OWNERSHIP(effect->id, iforce)) return -EACCES;
+ if (!CHECK_OWNERSHIP(effect->id, iforce))
+ return -EACCES;
/* Parameter type cannot be updated */
if (effect->type != iforce->core_effects[effect->id].effect.type)
return -EINVAL;
/* Check the effect is not already being updated */
- if (test_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags)) {
+ if (test_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags))
return -EAGAIN;
- }
is_update = TRUE;
}
@@ -339,15 +340,19 @@ void iforce_delete_device(struct iforce *iforce)
int iforce_init_device(struct iforce *iforce)
{
+ struct input_dev *input_dev;
unsigned char c[] = "CEOV";
int i;
+ input_dev = input_allocate_device();
+ if (input_dev)
+ return -ENOMEM;
+
init_waitqueue_head(&iforce->wait);
spin_lock_init(&iforce->xmit_lock);
init_MUTEX(&iforce->mem_mutex);
iforce->xmit.buf = iforce->xmit_data;
-
- iforce->dev.ff_effects_max = 10;
+ iforce->dev = input_dev;
/*
* Input device fields.
@@ -356,26 +361,27 @@ int iforce_init_device(struct iforce *iforce)
switch (iforce->bus) {
#ifdef CONFIG_JOYSTICK_IFORCE_USB
case IFORCE_USB:
- iforce->dev.id.bustype = BUS_USB;
- iforce->dev.dev = &iforce->usbdev->dev;
+ input_dev->id.bustype = BUS_USB;
+ input_dev->cdev.dev = &iforce->usbdev->dev;
break;
#endif
#ifdef CONFIG_JOYSTICK_IFORCE_232
case IFORCE_232:
- iforce->dev.id.bustype = BUS_RS232;
- iforce->dev.dev = &iforce->serio->dev;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->cdev.dev = &iforce->serio->dev;
break;
#endif
}
- iforce->dev.private = iforce;
- iforce->dev.name = "Unknown I-Force device";
- iforce->dev.open = iforce_open;
- iforce->dev.close = iforce_release;
- iforce->dev.flush = iforce_flush;
- iforce->dev.event = iforce_input_event;
- iforce->dev.upload_effect = iforce_upload_effect;
- iforce->dev.erase_effect = iforce_erase_effect;
+ input_dev->private = iforce;
+ input_dev->name = "Unknown I-Force device";
+ input_dev->open = iforce_open;
+ input_dev->close = iforce_release;
+ input_dev->flush = iforce_flush;
+ input_dev->event = iforce_input_event;
+ input_dev->upload_effect = iforce_upload_effect;
+ input_dev->erase_effect = iforce_erase_effect;
+ input_dev->ff_effects_max = 10;
/*
* On-device memory allocation.
@@ -399,7 +405,8 @@ int iforce_init_device(struct iforce *iforce)
if (i == 20) { /* 5 seconds */
printk(KERN_ERR "iforce-main.c: Timeout waiting for response from device.\n");
- return -1;
+ input_free_device(input_dev);
+ return -ENODEV;
}
/*
@@ -407,12 +414,12 @@ int iforce_init_device(struct iforce *iforce)
*/
if (!iforce_get_id_packet(iforce, "M"))
- iforce->dev.id.vendor = (iforce->edata[2] << 8) | iforce->edata[1];
+ input_dev->id.vendor = (iforce->edata[2] << 8) | iforce->edata[1];
else
printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet M\n");
if (!iforce_get_id_packet(iforce, "P"))
- iforce->dev.id.product = (iforce->edata[2] << 8) | iforce->edata[1];
+ input_dev->id.product = (iforce->edata[2] << 8) | iforce->edata[1];
else
printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet P\n");
@@ -422,15 +429,15 @@ int iforce_init_device(struct iforce *iforce)
printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet B\n");
if (!iforce_get_id_packet(iforce, "N"))
- iforce->dev.ff_effects_max = iforce->edata[1];
+ iforce->dev->ff_effects_max = iforce->edata[1];
else
printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet N\n");
/* Check if the device can store more effects than the driver can really handle */
- if (iforce->dev.ff_effects_max > FF_EFFECTS_MAX) {
+ if (iforce->dev->ff_effects_max > FF_EFFECTS_MAX) {
printk(KERN_WARNING "input??: Device can handle %d effects, but N_EFFECTS_MAX is set to %d in iforce.h\n",
- iforce->dev.ff_effects_max, FF_EFFECTS_MAX);
- iforce->dev.ff_effects_max = FF_EFFECTS_MAX;
+ iforce->dev->ff_effects_max, FF_EFFECTS_MAX);
+ iforce->dev->ff_effects_max = FF_EFFECTS_MAX;
}
/*
@@ -453,29 +460,28 @@ int iforce_init_device(struct iforce *iforce)
*/
for (i = 0; iforce_device[i].idvendor; i++)
- if (iforce_device[i].idvendor == iforce->dev.id.vendor &&
- iforce_device[i].idproduct == iforce->dev.id.product)
+ if (iforce_device[i].idvendor == input_dev->id.vendor &&
+ iforce_device[i].idproduct == input_dev->id.product)
break;
iforce->type = iforce_device + i;
- iforce->dev.name = iforce->type->name;
+ input_dev->name = iforce->type->name;
/*
* Set input device bitfields and ranges.
*/
- iforce->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF) | BIT(EV_FF_STATUS);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF) | BIT(EV_FF_STATUS);
for (i = 0; iforce->type->btn[i] >= 0; i++) {
signed short t = iforce->type->btn[i];
- set_bit(t, iforce->dev.keybit);
+ set_bit(t, input_dev->keybit);
}
- set_bit(BTN_DEAD, iforce->dev.keybit);
+ set_bit(BTN_DEAD, input_dev->keybit);
for (i = 0; iforce->type->abs[i] >= 0; i++) {
signed short t = iforce->type->abs[i];
- set_bit(t, iforce->dev.absbit);
switch (t) {
@@ -483,52 +489,42 @@ int iforce_init_device(struct iforce *iforce)
case ABS_Y:
case ABS_WHEEL:
- iforce->dev.absmax[t] = 1920;
- iforce->dev.absmin[t] = -1920;
- iforce->dev.absflat[t] = 128;
- iforce->dev.absfuzz[t] = 16;
-
- set_bit(t, iforce->dev.ffbit);
+ input_set_abs_params(input_dev, t, -1920, 1920, 16, 128);
+ set_bit(t, input_dev->ffbit);
break;
case ABS_THROTTLE:
case ABS_GAS:
case ABS_BRAKE:
- iforce->dev.absmax[t] = 255;
- iforce->dev.absmin[t] = 0;
+ input_set_abs_params(input_dev, t, 0, 255, 0, 0);
break;
case ABS_RUDDER:
- iforce->dev.absmax[t] = 127;
- iforce->dev.absmin[t] = -128;
+ input_set_abs_params(input_dev, t, -128, 127, 0, 0);
break;
case ABS_HAT0X:
case ABS_HAT0Y:
case ABS_HAT1X:
case ABS_HAT1Y:
- iforce->dev.absmax[t] = 1;
- iforce->dev.absmin[t] = -1;
+
+ input_set_abs_params(input_dev, t, -1, 1, 0, 0);
break;
}
}
for (i = 0; iforce->type->ff[i] >= 0; i++)
- set_bit(iforce->type->ff[i], iforce->dev.ffbit);
+ set_bit(iforce->type->ff[i], input_dev->ffbit);
/*
* Register input device.
*/
- input_register_device(&iforce->dev);
-
- printk(KERN_DEBUG "iforce->dev.open = %p\n", iforce->dev.open);
+ input_register_device(iforce->dev);
- printk(KERN_INFO "input: %s [%d effects, %ld bytes memory]\n",
- iforce->dev.name, iforce->dev.ff_effects_max,
- iforce->device_memory.end);
+ printk(KERN_DEBUG "iforce->dev->open = %p\n", iforce->dev->open);
return 0;
}
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index e5a31e55d3e247..4a2629243e1964 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -139,7 +139,8 @@ printk(KERN_DEBUG "iforce-packets.c: control_playback %d %d\n", id, value);
static int mark_core_as_ready(struct iforce *iforce, unsigned short addr)
{
int i;
- for (i=0; i<iforce->dev.ff_effects_max; ++i) {
+
+ for (i = 0; i < iforce->dev->ff_effects_max; ++i) {
if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) &&
(iforce->core_effects[i].mod1_chunk.start == addr ||
iforce->core_effects[i].mod2_chunk.start == addr)) {
@@ -153,7 +154,7 @@ static int mark_core_as_ready(struct iforce *iforce, unsigned short addr)
void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data, struct pt_regs *regs)
{
- struct input_dev *dev = &iforce->dev;
+ struct input_dev *dev = iforce->dev;
int i;
static int being_used = 0;
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
index 11f51905cba78c..64a78c5154847b 100644
--- a/drivers/input/joystick/iforce/iforce-serio.c
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -131,11 +131,10 @@ static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
struct iforce *iforce;
int err;
- if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL)))
+ iforce = kzalloc(sizeof(struct iforce), GFP_KERNEL);
+ if (!iforce)
return -ENOMEM;
- memset(iforce, 0, sizeof(struct iforce));
-
iforce->bus = IFORCE_232;
iforce->serio = serio;
@@ -148,7 +147,8 @@ static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
return err;
}
- if (iforce_init_device(iforce)) {
+ err = iforce_init_device(iforce);
+ if (err) {
serio_close(serio);
serio_set_drvdata(serio, NULL);
kfree(iforce);
@@ -162,7 +162,7 @@ static void iforce_serio_disconnect(struct serio *serio)
{
struct iforce *iforce = serio_get_drvdata(serio);
- input_unregister_device(&iforce->dev);
+ input_unregister_device(iforce->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
kfree(iforce);
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 58600f91eff521..64b4a308098521 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -135,28 +135,24 @@ static int iforce_usb_probe(struct usb_interface *intf,
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *epirq, *epout;
struct iforce *iforce;
+ int err = -ENOMEM;
interface = intf->cur_altsetting;
epirq = &interface->endpoint[0].desc;
epout = &interface->endpoint[1].desc;
- if (!(iforce = kmalloc(sizeof(struct iforce) + 32, GFP_KERNEL)))
+ if (!(iforce = kzalloc(sizeof(struct iforce) + 32, GFP_KERNEL)))
goto fail;
- memset(iforce, 0, sizeof(struct iforce));
-
- if (!(iforce->irq = usb_alloc_urb(0, GFP_KERNEL))) {
+ if (!(iforce->irq = usb_alloc_urb(0, GFP_KERNEL)))
goto fail;
- }
- if (!(iforce->out = usb_alloc_urb(0, GFP_KERNEL))) {
+ if (!(iforce->out = usb_alloc_urb(0, GFP_KERNEL)))
goto fail;
- }
- if (!(iforce->ctrl = usb_alloc_urb(0, GFP_KERNEL))) {
+ if (!(iforce->ctrl = usb_alloc_urb(0, GFP_KERNEL)))
goto fail;
- }
iforce->bus = IFORCE_USB;
iforce->usbdev = dev;
@@ -174,7 +170,9 @@ static int iforce_usb_probe(struct usb_interface *intf,
usb_fill_control_urb(iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0),
(void*) &iforce->cr, iforce->edata, 16, iforce_usb_ctrl, iforce);
- if (iforce_init_device(iforce)) goto fail;
+ err = iforce_init_device(iforce);
+ if (err)
+ goto fail;
usb_set_intfdata(intf, iforce);
return 0;
@@ -187,7 +185,7 @@ fail:
kfree(iforce);
}
- return -ENODEV;
+ return err;
}
/* Called by iforce_delete() */
@@ -211,7 +209,7 @@ static void iforce_usb_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (iforce) {
iforce->usbdev = NULL;
- input_unregister_device(&iforce->dev);
+ input_unregister_device(iforce->dev);
if (!open) {
iforce_delete_device(iforce);
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h
index bce247bc300b02..146f406b8f8a4d 100644
--- a/drivers/input/joystick/iforce/iforce.h
+++ b/drivers/input/joystick/iforce/iforce.h
@@ -117,7 +117,7 @@ struct iforce_device {
};
struct iforce {
- struct input_dev dev; /* Input device interface */
+ struct input_dev *dev; /* Input device interface */
struct iforce_device *type;
int bus;
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
index d7b3472bd68661..8511ee7bb2637b 100644
--- a/drivers/input/joystick/interact.c
+++ b/drivers/input/joystick/interact.c
@@ -54,7 +54,7 @@ MODULE_LICENSE("GPL");
struct interact {
struct gameport *gameport;
- struct input_dev dev;
+ struct input_dev *dev;
int bads;
int reads;
unsigned char type;
@@ -130,7 +130,7 @@ static int interact_read_packet(struct gameport *gameport, int length, u32 *data
static void interact_poll(struct gameport *gameport)
{
struct interact *interact = gameport_get_drvdata(gameport);
- struct input_dev *dev = &interact->dev;
+ struct input_dev *dev = interact->dev;
u32 data[3];
int i;
@@ -208,14 +208,20 @@ static void interact_close(struct input_dev *dev)
static int interact_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct interact *interact;
+ struct input_dev *input_dev;
__u32 data[3];
int i, t;
int err;
- if (!(interact = kzalloc(sizeof(struct interact), GFP_KERNEL)))
- return -ENOMEM;
+ interact = kzalloc(sizeof(struct interact), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!interact || !input_dev) {
+ err = -ENOMEM;
+ goto fail1;
+ }
interact->gameport = gameport;
+ interact->dev = input_dev;
gameport_set_drvdata(gameport, interact);
@@ -249,41 +255,40 @@ static int interact_connect(struct gameport *gameport, struct gameport_driver *d
interact->type = i;
interact->length = interact_type[i].length;
- interact->dev.private = interact;
- interact->dev.open = interact_open;
- interact->dev.close = interact_close;
+ input_dev->name = interact_type[i].name;
+ input_dev->phys = interact->phys;
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_INTERACT;
+ input_dev->id.product = interact_type[i].id;
+ input_dev->id.version = 0x0100;
+ input_dev->private = interact;
- interact->dev.name = interact_type[i].name;
- interact->dev.phys = interact->phys;
- interact->dev.id.bustype = BUS_GAMEPORT;
- interact->dev.id.vendor = GAMEPORT_ID_VENDOR_INTERACT;
- interact->dev.id.product = interact_type[i].id;
- interact->dev.id.version = 0x0100;
+ input_dev->open = interact_open;
+ input_dev->close = interact_close;
- interact->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; (t = interact_type[interact->type].abs[i]) >= 0; i++) {
- set_bit(t, interact->dev.absbit);
+ set_bit(t, input_dev->absbit);
if (i < interact_type[interact->type].b8) {
- interact->dev.absmin[t] = 0;
- interact->dev.absmax[t] = 255;
+ input_dev->absmin[t] = 0;
+ input_dev->absmax[t] = 255;
} else {
- interact->dev.absmin[t] = -1;
- interact->dev.absmax[t] = 1;
+ input_dev->absmin[t] = -1;
+ input_dev->absmax[t] = 1;
}
}
for (i = 0; (t = interact_type[interact->type].btn[i]) >= 0; i++)
- set_bit(t, interact->dev.keybit);
+ set_bit(t, input_dev->keybit);
- input_register_device(&interact->dev);
- printk(KERN_INFO "input: %s on %s\n",
- interact_type[interact->type].name, gameport->phys);
+ input_register_device(interact->dev);
return 0;
fail2: gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL);
+ input_free_device(input_dev);
kfree(interact);
return err;
}
@@ -292,7 +297,7 @@ static void interact_disconnect(struct gameport *gameport)
{
struct interact *interact = gameport_get_drvdata(gameport);
- input_unregister_device(&interact->dev);
+ input_unregister_device(interact->dev);
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
kfree(interact);
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
index 1ba50362724226..ca3cc2319d6ae3 100644
--- a/drivers/input/joystick/magellan.c
+++ b/drivers/input/joystick/magellan.c
@@ -49,14 +49,13 @@ MODULE_LICENSE("GPL");
static int magellan_buttons[] = { BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 };
static int magellan_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
-static char *magellan_name = "LogiCad3D Magellan / SpaceMouse";
/*
* Per-Magellan data.
*/
struct magellan {
- struct input_dev dev;
+ struct input_dev *dev;
int idx;
unsigned char data[MAGELLAN_MAX_LENGTH];
char phys[32];
@@ -85,7 +84,7 @@ static int magellan_crunch_nibbles(unsigned char *data, int count)
static void magellan_process_packet(struct magellan* magellan, struct pt_regs *regs)
{
- struct input_dev *dev = &magellan->dev;
+ struct input_dev *dev = magellan->dev;
unsigned char *data = magellan->data;
int i, t;
@@ -138,9 +137,9 @@ static void magellan_disconnect(struct serio *serio)
{
struct magellan* magellan = serio_get_drvdata(serio);
- input_unregister_device(&magellan->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(magellan->dev);
kfree(magellan);
}
@@ -153,52 +152,48 @@ static void magellan_disconnect(struct serio *serio)
static int magellan_connect(struct serio *serio, struct serio_driver *drv)
{
struct magellan *magellan;
- int i, t;
- int err;
-
- if (!(magellan = kmalloc(sizeof(struct magellan), GFP_KERNEL)))
- return -ENOMEM;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
+ int i;
- memset(magellan, 0, sizeof(struct magellan));
+ magellan = kzalloc(sizeof(struct magellan), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!magellan || !input_dev)
+ goto fail;
- magellan->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ magellan->dev = input_dev;
+ sprintf(magellan->phys, "%s/input0", serio->phys);
- for (i = 0; i < 9; i++)
- set_bit(magellan_buttons[i], magellan->dev.keybit);
+ input_dev->name = "LogiCad3D Magellan / SpaceMouse";
+ input_dev->phys = magellan->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_MAGELLAN;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = magellan;
- for (i = 0; i < 6; i++) {
- t = magellan_axes[i];
- set_bit(t, magellan->dev.absbit);
- magellan->dev.absmin[t] = -360;
- magellan->dev.absmax[t] = 360;
- }
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- sprintf(magellan->phys, "%s/input0", serio->phys);
+ for (i = 0; i < 9; i++)
+ set_bit(magellan_buttons[i], input_dev->keybit);
- init_input_dev(&magellan->dev);
- magellan->dev.private = magellan;
- magellan->dev.name = magellan_name;
- magellan->dev.phys = magellan->phys;
- magellan->dev.id.bustype = BUS_RS232;
- magellan->dev.id.vendor = SERIO_MAGELLAN;
- magellan->dev.id.product = 0x0001;
- magellan->dev.id.version = 0x0100;
- magellan->dev.dev = &serio->dev;
+ for (i = 0; i < 6; i++)
+ input_set_abs_params(input_dev, magellan_axes[i], -360, 360, 0, 0);
serio_set_drvdata(serio, magellan);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(magellan);
- return err;
- }
-
- input_register_device(&magellan->dev);
-
- printk(KERN_INFO "input: %s on %s\n", magellan_name, serio->phys);
+ if (err)
+ goto fail;
+ input_register_device(magellan->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(magellan);
+ return err;
}
/*
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
index 9e0353721a35d8..eaaad45cc7501d 100644
--- a/drivers/input/joystick/sidewinder.c
+++ b/drivers/input/joystick/sidewinder.c
@@ -113,7 +113,7 @@ static struct {
struct sw {
struct gameport *gameport;
- struct input_dev dev[4];
+ struct input_dev *dev[4];
char name[64];
char phys[4][32];
int length;
@@ -301,7 +301,7 @@ static int sw_check(__u64 t)
static int sw_parse(unsigned char *buf, struct sw *sw)
{
int hat, i, j;
- struct input_dev *dev = sw->dev;
+ struct input_dev *dev;
switch (sw->type) {
@@ -310,6 +310,8 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
if (sw_check(GB(0,64)) || (hat = (GB(6,1) << 3) | GB(60,3)) > 8)
return -1;
+ dev = sw->dev[0];
+
input_report_abs(dev, ABS_X, (GB( 3,3) << 7) | GB(16,7));
input_report_abs(dev, ABS_Y, (GB( 0,3) << 7) | GB(24,7));
input_report_abs(dev, ABS_RZ, (GB(35,2) << 7) | GB(40,7));
@@ -335,13 +337,13 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
if (sw_parity(GB(i*15,15)))
return -1;
- input_report_abs(dev + i, ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
- input_report_abs(dev + i, ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
+ input_report_abs(sw->dev[i], ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
+ input_report_abs(sw->dev[i], ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
for (j = 0; j < 10; j++)
- input_report_key(dev + i, sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1));
+ input_report_key(sw->dev[i], sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1));
- input_sync(dev + i);
+ input_sync(sw->dev[i]);
}
return 0;
@@ -352,6 +354,7 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8)
return -1;
+ dev = sw->dev[0];
input_report_abs(dev, ABS_X, GB( 9,10));
input_report_abs(dev, ABS_Y, GB(19,10));
input_report_abs(dev, ABS_RZ, GB(36, 6));
@@ -372,6 +375,7 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8)
return -1;
+ dev = sw->dev[0];
input_report_abs(dev, ABS_X, GB( 0,10));
input_report_abs(dev, ABS_Y, GB(16,10));
input_report_abs(dev, ABS_THROTTLE, GB(32, 6));
@@ -396,6 +400,7 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
if (!sw_parity(GB(0,33)))
return -1;
+ dev = sw->dev[0];
input_report_abs(dev, ABS_RX, GB( 0,10));
input_report_abs(dev, ABS_RUDDER, GB(10, 6));
input_report_abs(dev, ABS_THROTTLE, GB(16, 6));
@@ -581,6 +586,7 @@ static int sw_guess_mode(unsigned char *buf, int len)
static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct sw *sw;
+ struct input_dev *input_dev;
int i, j, k, l;
int err;
unsigned char *buf = NULL; /* [SW_LENGTH] */
@@ -729,42 +735,50 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
sprintf(sw->name, "Microsoft SideWinder %s", sw_name[sw->type]);
sprintf(sw->phys[i], "%s/input%d", gameport->phys, i);
- sw->dev[i].private = sw;
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ err = -ENOMEM;
+ goto fail3;
+ }
- sw->dev[i].open = sw_open;
- sw->dev[i].close = sw_close;
+ input_dev->name = sw->name;
+ input_dev->phys = sw->phys[i];
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_MICROSOFT;
+ input_dev->id.product = sw->type;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &gameport->dev;
+ input_dev->private = sw;
- sw->dev[i].name = sw->name;
- sw->dev[i].phys = sw->phys[i];
- sw->dev[i].id.bustype = BUS_GAMEPORT;
- sw->dev[i].id.vendor = GAMEPORT_ID_VENDOR_MICROSOFT;
- sw->dev[i].id.product = sw->type;
- sw->dev[i].id.version = 0x0100;
+ input_dev->open = sw_open;
+ input_dev->close = sw_close;
- sw->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (j = 0; (bits = sw_bit[sw->type][j]); j++) {
code = sw_abs[sw->type][j];
- set_bit(code, sw->dev[i].absbit);
- sw->dev[i].absmax[code] = (1 << bits) - 1;
- sw->dev[i].absmin[code] = (bits == 1) ? -1 : 0;
- sw->dev[i].absfuzz[code] = ((bits >> 1) >= 2) ? (1 << ((bits >> 1) - 2)) : 0;
+ set_bit(code, input_dev->absbit);
+ input_dev->absmax[code] = (1 << bits) - 1;
+ input_dev->absmin[code] = (bits == 1) ? -1 : 0;
+ input_dev->absfuzz[code] = ((bits >> 1) >= 2) ? (1 << ((bits >> 1) - 2)) : 0;
if (code != ABS_THROTTLE)
- sw->dev[i].absflat[code] = (bits >= 5) ? (1 << (bits - 5)) : 0;
+ input_dev->absflat[code] = (bits >= 5) ? (1 << (bits - 5)) : 0;
}
for (j = 0; (code = sw_btn[sw->type][j]); j++)
- set_bit(code, sw->dev[i].keybit);
+ set_bit(code, input_dev->keybit);
+
+ dbg("%s%s [%d-bit id %d data %d]\n", sw->name, comment, m, l, k);
- input_register_device(sw->dev + i);
- printk(KERN_INFO "input: %s%s on %s [%d-bit id %d data %d]\n",
- sw->name, comment, gameport->phys, m, l, k);
+ input_register_device(sw->dev[i]);
}
return 0;
-fail2: gameport_close(gameport);
-fail1: gameport_set_drvdata(gameport, NULL);
+ fail3: while (--i >= 0)
+ input_unregister_device(sw->dev[i]);
+ fail2: gameport_close(gameport);
+ fail1: gameport_set_drvdata(gameport, NULL);
kfree(sw);
kfree(buf);
kfree(idbuf);
@@ -777,7 +791,7 @@ static void sw_disconnect(struct gameport *gameport)
int i;
for (i = 0; i < sw->number; i++)
- input_unregister_device(sw->dev + i);
+ input_unregister_device(sw->dev[i]);
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
kfree(sw);
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index a436f22208562c..d6f8db8ec3fd34 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -70,8 +70,7 @@ static char *spaceball_names[] = {
*/
struct spaceball {
- struct input_dev dev;
- struct serio *serio;
+ struct input_dev *dev;
int idx;
int escape;
unsigned char data[SPACEBALL_MAX_LENGTH];
@@ -85,7 +84,7 @@ struct spaceball {
static void spaceball_process_packet(struct spaceball* spaceball, struct pt_regs *regs)
{
- struct input_dev *dev = &spaceball->dev;
+ struct input_dev *dev = spaceball->dev;
unsigned char *data = spaceball->data;
int i;
@@ -193,9 +192,9 @@ static void spaceball_disconnect(struct serio *serio)
{
struct spaceball* spaceball = serio_get_drvdata(serio);
- input_unregister_device(&spaceball->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(spaceball->dev);
kfree(spaceball);
}
@@ -208,69 +207,62 @@ static void spaceball_disconnect(struct serio *serio)
static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
{
struct spaceball *spaceball;
- int i, t, id;
- int err;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
+ int i, id;
if ((id = serio->id.id) > SPACEBALL_MAX_ID)
return -ENODEV;
- if (!(spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL)))
- return - ENOMEM;
+ spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!spaceball || !input_dev)
+ goto fail;
- memset(spaceball, 0, sizeof(struct spaceball));
+ spaceball->dev = input_dev;
+ sprintf(spaceball->phys, "%s/input0", serio->phys);
+
+ input_dev->name = spaceball_names[id];
+ input_dev->phys = spaceball->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_SPACEBALL;
+ input_dev->id.product = id;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = spaceball;
- spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
switch (id) {
case SPACEBALL_4000FLX:
case SPACEBALL_4000FLX_L:
- spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_9);
- spaceball->dev.keybit[LONG(BTN_A)] |= BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_MODE);
+ input_dev->keybit[LONG(BTN_0)] |= BIT(BTN_9);
+ input_dev->keybit[LONG(BTN_A)] |= BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_MODE);
default:
- spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4)
+ input_dev->keybit[LONG(BTN_0)] |= BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4)
| BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7) | BIT(BTN_8);
case SPACEBALL_3003C:
- spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_1) | BIT(BTN_8);
+ input_dev->keybit[LONG(BTN_0)] |= BIT(BTN_1) | BIT(BTN_8);
}
- for (i = 0; i < 6; i++) {
- t = spaceball_axes[i];
- set_bit(t, spaceball->dev.absbit);
- spaceball->dev.absmin[t] = i < 3 ? -8000 : -1600;
- spaceball->dev.absmax[t] = i < 3 ? 8000 : 1600;
- spaceball->dev.absflat[t] = i < 3 ? 40 : 8;
- spaceball->dev.absfuzz[t] = i < 3 ? 8 : 2;
+ for (i = 0; i < 3; i++) {
+ input_set_abs_params(input_dev, ABS_X + i, -8000, 8000, 8, 40);
+ input_set_abs_params(input_dev, ABS_RX + i, -1600, 1600, 2, 8);
}
- spaceball->serio = serio;
- spaceball->dev.private = spaceball;
-
- sprintf(spaceball->phys, "%s/input0", serio->phys);
-
- init_input_dev(&spaceball->dev);
- spaceball->dev.name = spaceball_names[id];
- spaceball->dev.phys = spaceball->phys;
- spaceball->dev.id.bustype = BUS_RS232;
- spaceball->dev.id.vendor = SERIO_SPACEBALL;
- spaceball->dev.id.product = id;
- spaceball->dev.id.version = 0x0100;
- spaceball->dev.dev = &serio->dev;
-
serio_set_drvdata(serio, spaceball);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(spaceball);
- return err;
- }
-
- input_register_device(&spaceball->dev);
-
- printk(KERN_INFO "input: %s on serio%s\n",
- spaceball_names[id], serio->phys);
+ if (err)
+ goto fail;
+ input_register_device(spaceball->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(spaceball);
+ return err;
}
/*
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
index 01fd2e4791aeb2..7c123a01c58e52 100644
--- a/drivers/input/joystick/spaceorb.c
+++ b/drivers/input/joystick/spaceorb.c
@@ -52,15 +52,13 @@ MODULE_LICENSE("GPL");
static int spaceorb_buttons[] = { BTN_TL, BTN_TR, BTN_Y, BTN_X, BTN_B, BTN_A };
static int spaceorb_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
-static char *spaceorb_name = "SpaceTec SpaceOrb 360 / Avenger";
/*
* Per-Orb data.
*/
struct spaceorb {
- struct input_dev dev;
- struct serio *serio;
+ struct input_dev *dev;
int idx;
unsigned char data[SPACEORB_MAX_LENGTH];
char phys[32];
@@ -78,7 +76,7 @@ static unsigned char *spaceorb_errors[] = { "EEPROM storing 0 failed", "Receive
static void spaceorb_process_packet(struct spaceorb *spaceorb, struct pt_regs *regs)
{
- struct input_dev *dev = &spaceorb->dev;
+ struct input_dev *dev = spaceorb->dev;
unsigned char *data = spaceorb->data;
unsigned char c = 0;
int axes[6];
@@ -95,8 +93,8 @@ static void spaceorb_process_packet(struct spaceorb *spaceorb, struct pt_regs *r
case 'R': /* Reset packet */
spaceorb->data[spaceorb->idx - 1] = 0;
for (i = 1; i < spaceorb->idx && spaceorb->data[i] == ' '; i++);
- printk(KERN_INFO "input: %s [%s] on %s\n",
- spaceorb_name, spaceorb->data + i, spaceorb->serio->phys);
+ printk(KERN_INFO "input: %s [%s] is %s\n",
+ dev->name, spaceorb->data + i, spaceorb->phys);
break;
case 'D': /* Ball + button data */
@@ -123,7 +121,7 @@ static void spaceorb_process_packet(struct spaceorb *spaceorb, struct pt_regs *r
case 'E': /* Error packet */
if (spaceorb->idx != 4) return;
- printk(KERN_ERR "joy-spaceorb: Device error. [ ");
+ printk(KERN_ERR "spaceorb: Device error. [ ");
for (i = 0; i < 7; i++) if (data[1] & (1 << i)) printk("%s ", spaceorb_errors[i]);
printk("]\n");
break;
@@ -154,9 +152,9 @@ static void spaceorb_disconnect(struct serio *serio)
{
struct spaceorb* spaceorb = serio_get_drvdata(serio);
- input_unregister_device(&spaceorb->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(spaceorb->dev);
kfree(spaceorb);
}
@@ -169,52 +167,48 @@ static void spaceorb_disconnect(struct serio *serio)
static int spaceorb_connect(struct serio *serio, struct serio_driver *drv)
{
struct spaceorb *spaceorb;
- int i, t;
- int err;
-
- if (!(spaceorb = kmalloc(sizeof(struct spaceorb), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(spaceorb, 0, sizeof(struct spaceorb));
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
+ int i;
- spaceorb->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ spaceorb = kzalloc(sizeof(struct spaceorb), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!spaceorb || !input_dev)
+ goto fail;
- for (i = 0; i < 6; i++)
- set_bit(spaceorb_buttons[i], spaceorb->dev.keybit);
+ spaceorb->dev = input_dev;
+ sprintf(spaceorb->phys, "%s/input0", serio->phys);
- for (i = 0; i < 6; i++) {
- t = spaceorb_axes[i];
- set_bit(t, spaceorb->dev.absbit);
- spaceorb->dev.absmin[t] = -508;
- spaceorb->dev.absmax[t] = 508;
- }
+ input_dev->name = "SpaceTec SpaceOrb 360 / Avenger";
+ input_dev->phys = spaceorb->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_SPACEORB;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = spaceorb;
- spaceorb->serio = serio;
- spaceorb->dev.private = spaceorb;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- sprintf(spaceorb->phys, "%s/input0", serio->phys);
+ for (i = 0; i < 6; i++)
+ set_bit(spaceorb_buttons[i], input_dev->keybit);
- init_input_dev(&spaceorb->dev);
- spaceorb->dev.name = spaceorb_name;
- spaceorb->dev.phys = spaceorb->phys;
- spaceorb->dev.id.bustype = BUS_RS232;
- spaceorb->dev.id.vendor = SERIO_SPACEORB;
- spaceorb->dev.id.product = 0x0001;
- spaceorb->dev.id.version = 0x0100;
- spaceorb->dev.dev = &serio->dev;
+ for (i = 0; i < 6; i++)
+ input_set_abs_params(input_dev, spaceorb_axes[i], -508, 508, 0, 0);
serio_set_drvdata(serio, spaceorb);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(spaceorb);
- return err;
- }
-
- input_register_device(&spaceorb->dev);
+ if (err)
+ goto fail;
+ input_register_device(spaceorb->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(spaceorb);
+ return err;
}
/*
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
index 6f6e6753d5902d..0a9ed1d306367c 100644
--- a/drivers/input/joystick/stinger.c
+++ b/drivers/input/joystick/stinger.c
@@ -48,14 +48,12 @@ MODULE_LICENSE("GPL");
#define STINGER_MAX_LENGTH 8
-static char *stinger_name = "Gravis Stinger";
-
/*
* Per-Stinger data.
*/
struct stinger {
- struct input_dev dev;
+ struct input_dev *dev;
int idx;
unsigned char data[STINGER_MAX_LENGTH];
char phys[32];
@@ -68,7 +66,7 @@ struct stinger {
static void stinger_process_packet(struct stinger *stinger, struct pt_regs *regs)
{
- struct input_dev *dev = &stinger->dev;
+ struct input_dev *dev = stinger->dev;
unsigned char *data = stinger->data;
if (!stinger->idx) return;
@@ -126,9 +124,9 @@ static void stinger_disconnect(struct serio *serio)
{
struct stinger *stinger = serio_get_drvdata(serio);
- input_unregister_device(&stinger->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(stinger->dev);
kfree(stinger);
}
@@ -141,53 +139,46 @@ static void stinger_disconnect(struct serio *serio)
static int stinger_connect(struct serio *serio, struct serio_driver *drv)
{
struct stinger *stinger;
- int i;
- int err;
-
- if (!(stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(stinger, 0, sizeof(struct stinger));
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
- stinger->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- stinger->dev.keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) | \
- BIT(BTN_Y) | BIT(BTN_Z) | BIT(BTN_TL) | BIT(BTN_TR) | \
- BIT(BTN_START) | BIT(BTN_SELECT);
- stinger->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+ stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!stinger || !input_dev)
+ goto fail;
+ stinger->dev = input_dev;
sprintf(stinger->phys, "%s/serio0", serio->phys);
- init_input_dev(&stinger->dev);
- stinger->dev.name = stinger_name;
- stinger->dev.phys = stinger->phys;
- stinger->dev.id.bustype = BUS_RS232;
- stinger->dev.id.vendor = SERIO_STINGER;
- stinger->dev.id.product = 0x0001;
- stinger->dev.id.version = 0x0100;
- stinger->dev.dev = &serio->dev;
-
- for (i = 0; i < 2; i++) {
- stinger->dev.absmax[ABS_X+i] = 64;
- stinger->dev.absmin[ABS_X+i] = -64;
- stinger->dev.absflat[ABS_X+i] = 4;
- }
-
- stinger->dev.private = stinger;
+ input_dev->name = "Gravis Stinger";
+ input_dev->phys = stinger->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_STINGER;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = stinger;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) |
+ BIT(BTN_Y) | BIT(BTN_Z) | BIT(BTN_TL) | BIT(BTN_TR) |
+ BIT(BTN_START) | BIT(BTN_SELECT);
+ input_set_abs_params(input_dev, ABS_X, -64, 64, 0, 4);
+ input_set_abs_params(input_dev, ABS_Y, -64, 64, 0, 4);
serio_set_drvdata(serio, stinger);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(stinger);
- return err;
- }
-
- input_register_device(&stinger->dev);
-
- printk(KERN_INFO "input: %s on %s\n", stinger_name, serio->phys);
+ if (err)
+ goto fail;
+ input_register_device(stinger->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(stinger);
+ return err;
}
/*
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
index 7431efc4330edb..3a7d1bb46472b7 100644
--- a/drivers/input/joystick/tmdc.c
+++ b/drivers/input/joystick/tmdc.c
@@ -63,37 +63,70 @@ MODULE_LICENSE("GPL");
#define TMDC_ABS_HAT 4
#define TMDC_BTN 16
-static unsigned char tmdc_byte_a[16] = { 0, 1, 3, 4, 6, 7 };
-static unsigned char tmdc_byte_d[16] = { 2, 5, 8, 9 };
+static const unsigned char tmdc_byte_a[16] = { 0, 1, 3, 4, 6, 7 };
+static const unsigned char tmdc_byte_d[16] = { 2, 5, 8, 9 };
-static signed char tmdc_abs[TMDC_ABS] =
+static const signed char tmdc_abs[TMDC_ABS] =
{ ABS_X, ABS_Y, ABS_RUDDER, ABS_THROTTLE, ABS_RX, ABS_RY, ABS_RZ };
-static signed char tmdc_abs_hat[TMDC_ABS_HAT] =
+static const signed char tmdc_abs_hat[TMDC_ABS_HAT] =
{ ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y };
-static signed char tmdc_abs_at[TMDC_ABS] =
+static const signed char tmdc_abs_at[TMDC_ABS] =
{ ABS_X, ABS_Y, ABS_RUDDER, -1, ABS_THROTTLE };
-static signed char tmdc_abs_fm[TMDC_ABS] =
+static const signed char tmdc_abs_fm[TMDC_ABS] =
{ ABS_RX, ABS_RY, ABS_X, ABS_Y };
-static short tmdc_btn_pad[TMDC_BTN] =
+static const short tmdc_btn_pad[TMDC_BTN] =
{ BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR };
-static short tmdc_btn_joy[TMDC_BTN] =
+static const short tmdc_btn_joy[TMDC_BTN] =
{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE,
BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z };
-static short tmdc_btn_fm[TMDC_BTN] =
+static const short tmdc_btn_fm[TMDC_BTN] =
{ BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 };
-static short tmdc_btn_at[TMDC_BTN] =
+static const short tmdc_btn_at[TMDC_BTN] =
{ BTN_TRIGGER, BTN_THUMB2, BTN_PINKIE, BTN_THUMB, BTN_BASE6, BTN_BASE5, BTN_BASE4,
BTN_BASE3, BTN_BASE2, BTN_BASE };
-static struct {
+static const struct {
int x;
int y;
} tmdc_hat_to_axis[] = {{ 0, 0}, { 1, 0}, { 0,-1}, {-1, 0}, { 0, 1}};
+static const struct tmdc_model {
+ unsigned char id;
+ const char *name;
+ char abs;
+ char hats;
+ char btnc[4];
+ char btno[4];
+ const signed char *axes;
+ const short *buttons;
+} tmdc_models[] = {
+ { 1, "ThrustMaster Millenium 3D Inceptor", 6, 2, { 4, 2 }, { 4, 6 }, tmdc_abs, tmdc_btn_joy },
+ { 3, "ThrustMaster Rage 3D Gamepad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
+ { 4, "ThrustMaster Attack Throttle", 5, 2, { 4, 6 }, { 4, 2 }, tmdc_abs_at, tmdc_btn_at },
+ { 8, "ThrustMaster FragMaster", 4, 0, { 8, 2 }, { 0, 0 }, tmdc_abs_fm, tmdc_btn_fm },
+ { 163, "Thrustmaster Fusion GamePad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
+ { 0, "Unknown %d-axis, %d-button TM device %d", 0, 0, { 0, 0 }, { 0, 0 }, tmdc_abs, tmdc_btn_joy }
+};
+
+
+struct tmdc_port {
+ struct input_dev *dev;
+ char name[64];
+ char phys[32];
+ int mode;
+ const signed char *abs;
+ const short *btn;
+ unsigned char absc;
+ unsigned char btnc[4];
+ unsigned char btno[4];
+};
+
struct tmdc {
struct gameport *gameport;
- struct input_dev dev[2];
+ struct tmdc_port *port[2];
+#if 0
+ struct input_dev *dev[2];
char name[2][64];
char phys[2][32];
int mode[2];
@@ -102,6 +135,7 @@ struct tmdc {
unsigned char absc[2];
unsigned char btnc[2][4];
unsigned char btno[2][4];
+#endif
int reads;
int bads;
unsigned char exists;
@@ -156,6 +190,50 @@ static int tmdc_read_packet(struct gameport *gameport, unsigned char data[2][TMD
return (i[0] == TMDC_MAX_LENGTH) | ((i[1] == TMDC_MAX_LENGTH) << 1);
}
+static int tmdc_parse_packet(struct tmdc_port *port, unsigned char *data)
+{
+ int i, k, l;
+
+ if (data[TMDC_BYTE_ID] != port->mode)
+ return -1;
+
+ for (i = 0; i < port->absc; i++) {
+ if (port->abs[i] < 0)
+ return 0;
+
+ input_report_abs(port->dev, port->abs[i], data[tmdc_byte_a[i]]);
+ }
+
+ switch (port->mode) {
+
+ case TMDC_MODE_M3DI:
+
+ i = tmdc_byte_d[0];
+ input_report_abs(port->dev, ABS_HAT0X, ((data[i] >> 3) & 1) - ((data[i] >> 1) & 1));
+ input_report_abs(port->dev, ABS_HAT0Y, ((data[i] >> 2) & 1) - ( data[i] & 1));
+ break;
+
+ case TMDC_MODE_AT:
+
+ i = tmdc_byte_a[3];
+ input_report_abs(port->dev, ABS_HAT0X, tmdc_hat_to_axis[(data[i] - 141) / 25].x);
+ input_report_abs(port->dev, ABS_HAT0Y, tmdc_hat_to_axis[(data[i] - 141) / 25].y);
+ break;
+
+ }
+
+ for (k = l = 0; k < 4; k++) {
+ for (i = 0; i < port->btnc[k]; i++)
+ input_report_key(port->dev, port->btn[i + l],
+ ((data[tmdc_byte_d[k]] >> (i + port->btno[k])) & 1));
+ l += port->btnc[k];
+ }
+
+ input_sync(port->dev);
+
+ return 0;
+}
+
/*
* tmdc_poll() reads and analyzes ThrustMaster joystick data.
*/
@@ -164,57 +242,21 @@ static void tmdc_poll(struct gameport *gameport)
{
unsigned char data[2][TMDC_MAX_LENGTH];
struct tmdc *tmdc = gameport_get_drvdata(gameport);
- struct input_dev *dev;
unsigned char r, bad = 0;
- int i, j, k, l;
+ int i;
tmdc->reads++;
if ((r = tmdc_read_packet(tmdc->gameport, data)) != tmdc->exists)
bad = 1;
- else
-
- for (j = 0; j < 2; j++)
- if (r & (1 << j) & tmdc->exists) {
-
- if (data[j][TMDC_BYTE_ID] != tmdc->mode[j]) {
- bad = 1;
- continue;
- }
-
- dev = tmdc->dev + j;
-
- for (i = 0; i < tmdc->absc[j]; i++) {
- if (tmdc->abs[j][i] < 0) continue;
- input_report_abs(dev, tmdc->abs[j][i], data[j][tmdc_byte_a[i]]);
- }
-
- switch (tmdc->mode[j]) {
+ else {
+ for (i = 0; i < 2; i++) {
+ if (r & (1 << i) & tmdc->exists) {
- case TMDC_MODE_M3DI:
-
- i = tmdc_byte_d[0];
- input_report_abs(dev, ABS_HAT0X, ((data[j][i] >> 3) & 1) - ((data[j][i] >> 1) & 1));
- input_report_abs(dev, ABS_HAT0Y, ((data[j][i] >> 2) & 1) - ( data[j][i] & 1));
- break;
-
- case TMDC_MODE_AT:
-
- i = tmdc_byte_a[3];
- input_report_abs(dev, ABS_HAT0X, tmdc_hat_to_axis[(data[j][i] - 141) / 25].x);
- input_report_abs(dev, ABS_HAT0Y, tmdc_hat_to_axis[(data[j][i] - 141) / 25].y);
- break;
-
- }
-
- for (k = l = 0; k < 4; k++) {
- for (i = 0; i < tmdc->btnc[j][k]; i++)
- input_report_key(dev, tmdc->btn[j][i + l],
- ((data[j][tmdc_byte_d[k]] >> (i + tmdc->btno[j][k])) & 1));
- l += tmdc->btnc[j][k];
+ if (tmdc_parse_packet(tmdc->port[i], data[i]))
+ bad = 1;
}
-
- input_sync(dev);
+ }
}
tmdc->bads += bad;
@@ -235,31 +277,89 @@ static void tmdc_close(struct input_dev *dev)
gameport_stop_polling(tmdc->gameport);
}
+static int tmdc_setup_port(struct tmdc *tmdc, int idx, unsigned char *data)
+{
+ const struct tmdc_model *model;
+ struct tmdc_port *port;
+ struct input_dev *input_dev;
+ int i, j, b = 0;
+
+ tmdc->port[idx] = port = kzalloc(sizeof (struct tmdc_port), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!port || !input_dev) {
+ kfree(port);
+ input_free_device(input_dev);
+ return -ENOMEM;
+ }
+
+ port->mode = data[TMDC_BYTE_ID];
+
+ for (model = tmdc_models; model->id && model->id != port->mode; model++)
+ /* empty */;
+
+ port->abs = model->axes;
+ port->btn = model->buttons;
+
+ if (!model->id) {
+ port->absc = data[TMDC_BYTE_DEF] >> 4;
+ for (i = 0; i < 4; i++)
+ port->btnc[i] = i < (data[TMDC_BYTE_DEF] & 0xf) ? 8 : 0;
+ } else {
+ port->absc = model->abs;
+ for (i = 0; i < 4; i++)
+ port->btnc[i] = model->btnc[i];
+ }
+
+ for (i = 0; i < 4; i++)
+ port->btno[i] = model->btno[i];
+
+ snprintf(port->name, sizeof(port->name), model->name,
+ port->absc, (data[TMDC_BYTE_DEF] & 0xf) << 3, port->mode);
+ snprintf(port->phys, sizeof(port->phys), "%s/input%d", tmdc->gameport->phys, i);
+
+ port->dev = input_dev;
+
+ input_dev->name = port->name;
+ input_dev->phys = port->phys;
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_THRUSTMASTER;
+ input_dev->id.product = model->id;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &tmdc->gameport->dev;
+ input_dev->private = tmdc;
+
+ input_dev->open = tmdc_open;
+ input_dev->close = tmdc_close;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+ for (i = 0; i < port->absc && i < TMDC_ABS; i++)
+ if (port->abs[i] >= 0)
+ input_set_abs_params(input_dev, port->abs[i], 8, 248, 2, 4);
+
+ for (i = 0; i < model->hats && i < TMDC_ABS_HAT; i++)
+ input_set_abs_params(input_dev, tmdc_abs_hat[i], -1, 1, 0, 0);
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < port->btnc[i] && j < TMDC_BTN; j++)
+ set_bit(port->btn[j + b], input_dev->keybit);
+ b += port->btnc[i];
+ }
+
+ input_register_device(port->dev);
+
+ return 0;
+}
+
/*
* tmdc_probe() probes for ThrustMaster type joysticks.
*/
static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv)
{
- static struct models {
- unsigned char id;
- char *name;
- char abs;
- char hats;
- char btnc[4];
- char btno[4];
- signed char *axes;
- short *buttons;
- } models[] = { { 1, "ThrustMaster Millenium 3D Inceptor", 6, 2, { 4, 2 }, { 4, 6 }, tmdc_abs, tmdc_btn_joy },
- { 3, "ThrustMaster Rage 3D Gamepad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
- { 4, "ThrustMaster Attack Throttle", 5, 2, { 4, 6 }, { 4, 2 }, tmdc_abs_at, tmdc_btn_at },
- { 8, "ThrustMaster FragMaster", 4, 0, { 8, 2 }, { 0, 0 }, tmdc_abs_fm, tmdc_btn_fm },
- { 163, "Thrustmaster Fusion GamePad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
- { 0, "Unknown %d-axis, %d-button TM device %d", 0, 0, { 0, 0 }, { 0, 0 }, tmdc_abs, tmdc_btn_joy }};
-
unsigned char data[2][TMDC_MAX_LENGTH];
struct tmdc *tmdc;
- int i, j, k, l, m;
+ int i;
int err;
if (!(tmdc = kzalloc(sizeof(struct tmdc), GFP_KERNEL)))
@@ -281,68 +381,25 @@ static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv)
gameport_set_poll_handler(gameport, tmdc_poll);
gameport_set_poll_interval(gameport, 20);
- for (j = 0; j < 2; j++)
- if (tmdc->exists & (1 << j)) {
+ for (i = 0; i < 2; i++) {
+ if (tmdc->exists & (1 << i)) {
- tmdc->mode[j] = data[j][TMDC_BYTE_ID];
-
- for (m = 0; models[m].id && models[m].id != tmdc->mode[j]; m++);
-
- tmdc->abs[j] = models[m].axes;
- tmdc->btn[j] = models[m].buttons;
-
- if (!models[m].id) {
- models[m].abs = data[j][TMDC_BYTE_DEF] >> 4;
- for (k = 0; k < 4; k++)
- models[m].btnc[k] = k < (data[j][TMDC_BYTE_DEF] & 0xf) ? 8 : 0;
- }
-
- tmdc->absc[j] = models[m].abs;
- for (k = 0; k < 4; k++) {
- tmdc->btnc[j][k] = models[m].btnc[k];
- tmdc->btno[j][k] = models[m].btno[k];
- }
-
- sprintf(tmdc->name[j], models[m].name, models[m].abs,
- (data[j][TMDC_BYTE_DEF] & 0xf) << 3, tmdc->mode[j]);
-
- sprintf(tmdc->phys[j], "%s/input%d", gameport->phys, j);
-
- tmdc->dev[j].private = tmdc;
- tmdc->dev[j].open = tmdc_open;
- tmdc->dev[j].close = tmdc_close;
-
- tmdc->dev[j].name = tmdc->name[j];
- tmdc->dev[j].phys = tmdc->phys[j];
- tmdc->dev[j].id.bustype = BUS_GAMEPORT;
- tmdc->dev[j].id.vendor = GAMEPORT_ID_VENDOR_THRUSTMASTER;
- tmdc->dev[j].id.product = models[m].id;
- tmdc->dev[j].id.version = 0x0100;
-
- tmdc->dev[j].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
- for (i = 0; i < models[m].abs && i < TMDC_ABS; i++)
- if (tmdc->abs[j][i] >= 0)
- input_set_abs_params(&tmdc->dev[j], tmdc->abs[j][i], 8, 248, 2, 4);
-
- for (i = 0; i < models[m].hats && i < TMDC_ABS_HAT; i++)
- input_set_abs_params(&tmdc->dev[j], tmdc_abs_hat[i], -1, 1, 0, 0);
-
-
- for (k = l = 0; k < 4; k++) {
- for (i = 0; i < models[m].btnc[k] && i < TMDC_BTN; i++)
- set_bit(tmdc->btn[j][i + l], tmdc->dev[j].keybit);
- l += models[m].btnc[k];
- }
-
- input_register_device(tmdc->dev + j);
- printk(KERN_INFO "input: %s on %s\n", tmdc->name[j], gameport->phys);
+ err = tmdc_setup_port(tmdc, i, data[i]);
+ if (err)
+ goto fail3;
}
+ }
return 0;
-fail2: gameport_close(gameport);
-fail1: gameport_set_drvdata(gameport, NULL);
+ fail3: while (--i >= 0) {
+ if (tmdc->port[i]) {
+ input_unregister_device(tmdc->port[i]->dev);
+ kfree(tmdc->port[i]);
+ }
+ }
+ fail2: gameport_close(gameport);
+ fail1: gameport_set_drvdata(gameport, NULL);
kfree(tmdc);
return err;
}
@@ -352,9 +409,12 @@ static void tmdc_disconnect(struct gameport *gameport)
struct tmdc *tmdc = gameport_get_drvdata(gameport);
int i;
- for (i = 0; i < 2; i++)
- if (tmdc->exists & (1 << i))
- input_unregister_device(tmdc->dev + i);
+ for (i = 0; i < 2; i++) {
+ if (tmdc->port[i]) {
+ input_unregister_device(tmdc->port[i]->dev);
+ kfree(tmdc->port[i]);
+ }
+ }
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
kfree(tmdc);
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 0c5b9c8297cd4f..7e9764937d064b 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -42,19 +42,21 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("TurboGraFX parallel port interface driver");
MODULE_LICENSE("GPL");
-static int tgfx[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
-static int tgfx_nargs __initdata = 0;
-module_param_array_named(map, tgfx, int, &tgfx_nargs, 0);
-MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>");
+#define TGFX_MAX_PORTS 3
+#define TGFX_MAX_DEVICES 7
-static int tgfx_2[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
-static int tgfx_nargs_2 __initdata = 0;
-module_param_array_named(map2, tgfx_2, int, &tgfx_nargs_2, 0);
-MODULE_PARM_DESC(map2, "Describes second set of devices");
+struct tgfx_config {
+ int args[TGFX_MAX_DEVICES + 1];
+ int nargs;
+};
+
+static struct tgfx_config tgfx[TGFX_MAX_PORTS] __initdata;
-static int tgfx_3[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
-static int tgfx_nargs_3 __initdata = 0;
-module_param_array_named(map3, tgfx_3, int, &tgfx_nargs_3, 0);
+module_param_array_named(map, tgfx[0].args, int, &tgfx[0].nargs, 0);
+MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>");
+module_param_array_named(map2, tgfx[1].args, int, &tgfx[1].nargs, 0);
+MODULE_PARM_DESC(map2, "Describes second set of devices");
+module_param_array_named(map3, tgfx[2].args, int, &tgfx[2].nargs, 0);
MODULE_PARM_DESC(map3, "Describes third set of devices");
__obsolete_setup("tgfx=");
@@ -75,17 +77,17 @@ __obsolete_setup("tgfx_3=");
#define TGFX_TOP2 0x08
static int tgfx_buttons[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2 };
-static char *tgfx_name = "TurboGraFX Multisystem joystick";
static struct tgfx {
struct pardevice *pd;
struct timer_list timer;
- struct input_dev dev[7];
- char phys[7][32];
+ struct input_dev *dev[TGFX_MAX_DEVICES];
+ char name[TGFX_MAX_DEVICES][64];
+ char phys[TGFX_MAX_DEVICES][32];
int sticks;
int used;
struct semaphore sem;
-} *tgfx_base[3];
+} *tgfx_base[TGFX_MAX_PORTS];
/*
* tgfx_timer() reads and analyzes TurboGraFX joystick data.
@@ -100,7 +102,7 @@ static void tgfx_timer(unsigned long private)
for (i = 0; i < 7; i++)
if (tgfx->sticks & (1 << i)) {
- dev = tgfx->dev + i;
+ dev = tgfx->dev[i];
parport_write_data(tgfx->pd->port, ~(1 << i));
data1 = parport_read_status(tgfx->pd->port) ^ 0x7f;
@@ -153,118 +155,165 @@ static void tgfx_close(struct input_dev *dev)
up(&tgfx->sem);
}
+
+
/*
* tgfx_probe() probes for tg gamepads.
*/
-static struct tgfx __init *tgfx_probe(int *config, int nargs)
+static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
{
struct tgfx *tgfx;
+ struct input_dev *input_dev;
struct parport *pp;
+ struct pardevice *pd;
int i, j;
+ int err;
- if (config[0] < 0)
- return NULL;
-
- if (nargs < 2) {
- printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n");
- return NULL;
- }
-
- pp = parport_find_number(config[0]);
-
+ pp = parport_find_number(parport);
if (!pp) {
printk(KERN_ERR "turbografx.c: no such parport\n");
- return NULL;
+ err = -EINVAL;
+ goto err_out;
}
- if (!(tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL))) {
- parport_put_port(pp);
- return NULL;
+ pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+ if (!pd) {
+ printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n");
+ err = -EBUSY;
+ goto err_put_pp;
}
- init_MUTEX(&tgfx->sem);
-
- tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
-
- parport_put_port(pp);
-
- if (!tgfx->pd) {
- printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n");
- kfree(tgfx);
- return NULL;
+ tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL);
+ if (!tgfx) {
+ printk(KERN_ERR "turbografx.c: Not enough memory\n");
+ err = -ENOMEM;
+ goto err_unreg_pardev;
}
+ init_MUTEX(&tgfx->sem);
+ tgfx->pd = pd;
init_timer(&tgfx->timer);
tgfx->timer.data = (long) tgfx;
tgfx->timer.function = tgfx_timer;
- tgfx->sticks = 0;
+ for (i = 0; i < n_devs; i++) {
+ if (n_buttons[i] < 1)
+ continue;
- for (i = 0; i < nargs - 1; i++)
- if (config[i+1] > 0 && config[i+1] < 6) {
-
- tgfx->sticks |= (1 << i);
+ if (n_buttons[i] > 6) {
+ printk(KERN_ERR "turbografx.c: Invalid number of buttons %d\n", n_buttons[i]);
+ err = -EINVAL;
+ goto err_free_devs;
+ }
- tgfx->dev[i].private = tgfx;
- tgfx->dev[i].open = tgfx_open;
- tgfx->dev[i].close = tgfx_close;
+ tgfx->dev[i] = input_dev = input_allocate_device();
+ if (!input_dev) {
+ printk(KERN_ERR "turbografx.c: Not enough memory for input device\n");
+ err = -ENOMEM;
+ goto err_free_devs;
+ }
- sprintf(tgfx->phys[i], "%s/input0", tgfx->pd->port->name);
+ tgfx->sticks |= (1 << i);
+ snprintf(tgfx->name[i], sizeof(tgfx->name[i]),
+ "TurboGraFX %d-button Multisystem joystick", n_buttons[i]);
+ snprintf(tgfx->phys[i], sizeof(tgfx->phys[i]),
+ "%s/input%d", tgfx->pd->port->name, i);
- tgfx->dev[i].name = tgfx_name;
- tgfx->dev[i].phys = tgfx->phys[i];
- tgfx->dev[i].id.bustype = BUS_PARPORT;
- tgfx->dev[i].id.vendor = 0x0003;
- tgfx->dev[i].id.product = config[i+1];
- tgfx->dev[i].id.version = 0x0100;
+ input_dev->name = tgfx->name[i];
+ input_dev->phys = tgfx->phys[i];
+ input_dev->id.bustype = BUS_PARPORT;
+ input_dev->id.vendor = 0x0003;
+ input_dev->id.product = n_buttons[i];
+ input_dev->id.version = 0x0100;
- tgfx->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- tgfx->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+ input_dev->private = tgfx;
+ input_dev->open = tgfx_open;
+ input_dev->close = tgfx_close;
- for (j = 0; j < config[i+1]; j++)
- set_bit(tgfx_buttons[j], tgfx->dev[i].keybit);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_set_abs_params(input_dev, ABS_X, -1, 1, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, -1, 1, 0, 0);
- tgfx->dev[i].absmin[ABS_X] = -1; tgfx->dev[i].absmax[ABS_X] = 1;
- tgfx->dev[i].absmin[ABS_Y] = -1; tgfx->dev[i].absmax[ABS_Y] = 1;
+ for (j = 0; j < n_buttons[i]; j++)
+ set_bit(tgfx_buttons[j], input_dev->keybit);
- input_register_device(tgfx->dev + i);
- printk(KERN_INFO "input: %d-button Multisystem joystick on %s\n",
- config[i+1], tgfx->pd->port->name);
- }
+ input_register_device(tgfx->dev[i]);
+ }
if (!tgfx->sticks) {
- parport_unregister_device(tgfx->pd);
- kfree(tgfx);
- return NULL;
+ printk(KERN_ERR "turbografx.c: No valid devices specified\n");
+ err = -EINVAL;
+ goto err_free_tgfx;
}
return tgfx;
+
+ err_free_devs:
+ while (--i >= 0)
+ input_unregister_device(tgfx->dev[i]);
+ err_free_tgfx:
+ kfree(tgfx);
+ err_unreg_pardev:
+ parport_unregister_device(pd);
+ err_put_pp:
+ parport_put_port(pp);
+ err_out:
+ return ERR_PTR(err);
+}
+
+static void __exit tgfx_remove(struct tgfx *tgfx)
+{
+ int i;
+
+ for (i = 0; i < TGFX_MAX_DEVICES; i++)
+ if (tgfx->dev[i])
+ input_unregister_device(tgfx->dev[i]);
+ parport_unregister_device(tgfx->pd);
+ kfree(tgfx);
}
static int __init tgfx_init(void)
{
- tgfx_base[0] = tgfx_probe(tgfx, tgfx_nargs);
- tgfx_base[1] = tgfx_probe(tgfx_2, tgfx_nargs_2);
- tgfx_base[2] = tgfx_probe(tgfx_3, tgfx_nargs_3);
+ int i;
+ int have_dev = 0;
+ int err = 0;
+
+ for (i = 0; i < TGFX_MAX_PORTS; i++) {
+ if (tgfx[i].nargs == 0 || tgfx[i].args[0] < 0)
+ continue;
+
+ if (tgfx[i].nargs < 2) {
+ printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n");
+ err = -EINVAL;
+ break;
+ }
+
+ tgfx_base[i] = tgfx_probe(tgfx[i].args[0], tgfx[i].args + 1, tgfx[i].nargs - 1);
+ if (IS_ERR(tgfx_base[i])) {
+ err = PTR_ERR(tgfx_base[i]);
+ break;
+ }
+
+ have_dev = 1;
+ }
- if (tgfx_base[0] || tgfx_base[1] || tgfx_base[2])
- return 0;
+ if (err) {
+ while (--i >= 0)
+ tgfx_remove(tgfx_base[i]);
+ return err;
+ }
- return -ENODEV;
+ return have_dev ? 0 : -ENODEV;
}
static void __exit tgfx_exit(void)
{
- int i, j;
+ int i;
- for (i = 0; i < 3; i++)
- if (tgfx_base[i]) {
- for (j = 0; j < 7; j++)
- if (tgfx_base[i]->sticks & (1 << j))
- input_unregister_device(tgfx_base[i]->dev + j);
- parport_unregister_device(tgfx_base[i]->pd);
- }
+ for (i = 0; i < TGFX_MAX_PORTS; i++)
+ if (tgfx_base[i])
+ tgfx_remove(tgfx_base[i]);
}
module_init(tgfx_init);
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
index 0379bc1665252a..cd3a1e742a30ef 100644
--- a/drivers/input/joystick/twidjoy.c
+++ b/drivers/input/joystick/twidjoy.c
@@ -69,8 +69,6 @@ MODULE_LICENSE("GPL");
#define TWIDJOY_MAX_LENGTH 5
-static char *twidjoy_name = "Handykey Twiddler";
-
static struct twidjoy_button_spec {
int bitshift;
int bitmask;
@@ -95,7 +93,7 @@ twidjoy_buttons[] = {
*/
struct twidjoy {
- struct input_dev dev;
+ struct input_dev *dev;
int idx;
unsigned char data[TWIDJOY_MAX_LENGTH];
char phys[32];
@@ -108,37 +106,33 @@ struct twidjoy {
static void twidjoy_process_packet(struct twidjoy *twidjoy, struct pt_regs *regs)
{
- if (twidjoy->idx == TWIDJOY_MAX_LENGTH) {
- struct input_dev *dev = &twidjoy->dev;
- unsigned char *data = twidjoy->data;
- struct twidjoy_button_spec *bp;
- int button_bits, abs_x, abs_y;
-
- button_bits = ((data[1] & 0x7f) << 7) | (data[0] & 0x7f);
+ struct input_dev *dev = twidjoy->dev;
+ unsigned char *data = twidjoy->data;
+ struct twidjoy_button_spec *bp;
+ int button_bits, abs_x, abs_y;
- input_regs(dev, regs);
+ button_bits = ((data[1] & 0x7f) << 7) | (data[0] & 0x7f);
- for (bp = twidjoy_buttons; bp->bitmask; bp++) {
- int value = (button_bits & (bp->bitmask << bp->bitshift)) >> bp->bitshift;
- int i;
+ input_regs(dev, regs);
- for (i = 0; i < bp->bitmask; i++)
- input_report_key(dev, bp->buttons[i], i+1 == value);
- }
+ for (bp = twidjoy_buttons; bp->bitmask; bp++) {
+ int value = (button_bits & (bp->bitmask << bp->bitshift)) >> bp->bitshift;
+ int i;
- abs_x = ((data[4] & 0x07) << 5) | ((data[3] & 0x7C) >> 2);
- if (data[4] & 0x08) abs_x -= 256;
+ for (i = 0; i < bp->bitmask; i++)
+ input_report_key(dev, bp->buttons[i], i+1 == value);
+ }
- abs_y = ((data[3] & 0x01) << 7) | ((data[2] & 0x7F) >> 0);
- if (data[3] & 0x02) abs_y -= 256;
+ abs_x = ((data[4] & 0x07) << 5) | ((data[3] & 0x7C) >> 2);
+ if (data[4] & 0x08) abs_x -= 256;
- input_report_abs(dev, ABS_X, -abs_x);
- input_report_abs(dev, ABS_Y, +abs_y);
+ abs_y = ((data[3] & 0x01) << 7) | ((data[2] & 0x7F) >> 0);
+ if (data[3] & 0x02) abs_y -= 256;
- input_sync(dev);
- }
+ input_report_abs(dev, ABS_X, -abs_x);
+ input_report_abs(dev, ABS_Y, +abs_y);
- return;
+ input_sync(dev);
}
/*
@@ -179,9 +173,9 @@ static void twidjoy_disconnect(struct serio *serio)
{
struct twidjoy *twidjoy = serio_get_drvdata(serio);
- input_unregister_device(&twidjoy->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(twidjoy->dev);
kfree(twidjoy);
}
@@ -195,59 +189,49 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv)
{
struct twidjoy_button_spec *bp;
struct twidjoy *twidjoy;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
int i;
- int err;
-
- if (!(twidjoy = kmalloc(sizeof(struct twidjoy), GFP_KERNEL)))
- return -ENOMEM;
- memset(twidjoy, 0, sizeof(struct twidjoy));
+ twidjoy = kzalloc(sizeof(struct twidjoy), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!twidjoy || !input_dev)
+ goto fail;
+ twidjoy->dev = input_dev;
sprintf(twidjoy->phys, "%s/input0", serio->phys);
- init_input_dev(&twidjoy->dev);
- twidjoy->dev.name = twidjoy_name;
- twidjoy->dev.phys = twidjoy->phys;
- twidjoy->dev.id.bustype = BUS_RS232;
- twidjoy->dev.id.vendor = SERIO_TWIDJOY;
- twidjoy->dev.id.product = 0x0001;
- twidjoy->dev.id.version = 0x0100;
- twidjoy->dev.dev = &serio->dev;
-
- twidjoy->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
- for (bp = twidjoy_buttons; bp->bitmask; bp++) {
+ input_dev->name = "Handykey Twiddler";
+ input_dev->phys = twidjoy->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_TWIDJOY;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = twidjoy;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+ input_set_abs_params(input_dev, ABS_X, -50, 50, 4, 4);
+ input_set_abs_params(input_dev, ABS_Y, -50, 50, 4, 4);
+
+ for (bp = twidjoy_buttons; bp->bitmask; bp++)
for (i = 0; i < bp->bitmask; i++)
- set_bit(bp->buttons[i], twidjoy->dev.keybit);
- }
-
- twidjoy->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
-
- for (i = 0; i < 2; i++) {
- twidjoy->dev.absmax[ABS_X+i] = 50;
- twidjoy->dev.absmin[ABS_X+i] = -50;
-
- /* TODO: arndt 20010708: Are these values appropriate? */
- twidjoy->dev.absfuzz[ABS_X+i] = 4;
- twidjoy->dev.absflat[ABS_X+i] = 4;
- }
-
- twidjoy->dev.private = twidjoy;
+ set_bit(bp->buttons[i], input_dev->keybit);
serio_set_drvdata(serio, twidjoy);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(twidjoy);
- return err;
- }
-
- input_register_device(&twidjoy->dev);
-
- printk(KERN_INFO "input: %s on %s\n", twidjoy_name, serio->phys);
+ if (err)
+ goto fail;
+ input_register_device(twidjoy->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(twidjoy);
+ return err;
}
/*
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
index 6976a219504c5a..99a642d2a1feb1 100644
--- a/drivers/input/joystick/warrior.c
+++ b/drivers/input/joystick/warrior.c
@@ -47,14 +47,13 @@ MODULE_LICENSE("GPL");
#define WARRIOR_MAX_LENGTH 16
static char warrior_lengths[] = { 0, 4, 12, 3, 4, 4, 0, 0 };
-static char *warrior_name = "Logitech WingMan Warrior";
/*
* Per-Warrior data.
*/
struct warrior {
- struct input_dev dev;
+ struct input_dev *dev;
int idx, len;
unsigned char data[WARRIOR_MAX_LENGTH];
char phys[32];
@@ -67,7 +66,7 @@ struct warrior {
static void warrior_process_packet(struct warrior *warrior, struct pt_regs *regs)
{
- struct input_dev *dev = &warrior->dev;
+ struct input_dev *dev = warrior->dev;
unsigned char *data = warrior->data;
if (!warrior->idx) return;
@@ -131,9 +130,9 @@ static void warrior_disconnect(struct serio *serio)
{
struct warrior *warrior = serio_get_drvdata(serio);
- input_unregister_device(&warrior->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(warrior->dev);
kfree(warrior);
}
@@ -146,60 +145,48 @@ static void warrior_disconnect(struct serio *serio)
static int warrior_connect(struct serio *serio, struct serio_driver *drv)
{
struct warrior *warrior;
- int i;
- int err;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
- if (!(warrior = kmalloc(sizeof(struct warrior), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(warrior, 0, sizeof(struct warrior));
-
- warrior->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
- warrior->dev.keybit[LONG(BTN_TRIGGER)] = BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_TOP2);
- warrior->dev.relbit[0] = BIT(REL_DIAL);
- warrior->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y);
+ warrior = kzalloc(sizeof(struct warrior), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!warrior || !input_dev)
+ goto fail;
+ warrior->dev = input_dev;
sprintf(warrior->phys, "%s/input0", serio->phys);
- init_input_dev(&warrior->dev);
- warrior->dev.name = warrior_name;
- warrior->dev.phys = warrior->phys;
- warrior->dev.id.bustype = BUS_RS232;
- warrior->dev.id.vendor = SERIO_WARRIOR;
- warrior->dev.id.product = 0x0001;
- warrior->dev.id.version = 0x0100;
- warrior->dev.dev = &serio->dev;
-
- for (i = 0; i < 2; i++) {
- warrior->dev.absmax[ABS_X+i] = -64;
- warrior->dev.absmin[ABS_X+i] = 64;
- warrior->dev.absflat[ABS_X+i] = 8;
- }
-
- warrior->dev.absmax[ABS_THROTTLE] = -112;
- warrior->dev.absmin[ABS_THROTTLE] = 112;
-
- for (i = 0; i < 2; i++) {
- warrior->dev.absmax[ABS_HAT0X+i] = -1;
- warrior->dev.absmin[ABS_HAT0X+i] = 1;
- }
-
- warrior->dev.private = warrior;
+ input_dev->name = "Logitech WingMan Warrior";
+ input_dev->phys = warrior->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_WARRIOR;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = warrior;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_TRIGGER)] = BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_TOP2);
+ input_dev->relbit[0] = BIT(REL_DIAL);
+ input_set_abs_params(input_dev, ABS_X, -64, 64, 0, 8);
+ input_set_abs_params(input_dev, ABS_Y, -64, 64, 0, 8);
+ input_set_abs_params(input_dev, ABS_THROTTLE, -112, 112, 0, 0);
+ input_set_abs_params(input_dev, ABS_HAT0X, -1, 1, 0, 0);
+ input_set_abs_params(input_dev, ABS_HAT0X, -1, 1, 0, 0);
serio_set_drvdata(serio, warrior);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(warrior);
- return err;
- }
-
- input_register_device(&warrior->dev);
-
- printk(KERN_INFO "input: Logitech WingMan Warrior on %s\n", serio->phys);
+ if (err)
+ goto fail;
+ input_register_device(warrior->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(warrior);
+ return err;
}
/*
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c
index 4e8e8ea214ab2f..3d63bc1ad3220f 100644
--- a/drivers/input/keyboard/amikbd.c
+++ b/drivers/input/keyboard/amikbd.c
@@ -155,10 +155,7 @@ static const char *amikbd_messages[8] = {
[7] = KERN_WARNING "amikbd: keyboard interrupt\n"
};
-static struct input_dev amikbd_dev;
-
-static char *amikbd_name = "Amiga keyboard";
-static char *amikbd_phys = "amikbd/input0";
+static struct input_dev *amikbd_dev;
static irqreturn_t amikbd_interrupt(int irq, void *dummy, struct pt_regs *fp)
{
@@ -176,16 +173,16 @@ static irqreturn_t amikbd_interrupt(int irq, void *dummy, struct pt_regs *fp)
scancode = amikbd_keycode[scancode];
- input_regs(&amikbd_dev, fp);
+ input_regs(amikbd_dev, fp);
if (scancode == KEY_CAPSLOCK) { /* CapsLock is a toggle switch key on Amiga */
- input_report_key(&amikbd_dev, scancode, 1);
- input_report_key(&amikbd_dev, scancode, 0);
- input_sync(&amikbd_dev);
+ input_report_key(amikbd_dev, scancode, 1);
+ input_report_key(amikbd_dev, scancode, 0);
} else {
- input_report_key(&amikbd_dev, scancode, down);
- input_sync(&amikbd_dev);
+ input_report_key(amikbd_dev, scancode, down);
}
+
+ input_sync(amikbd_dev);
} else /* scancodes >= 0x78 are error codes */
printk(amikbd_messages[scancode - 0x78]);
@@ -202,39 +199,41 @@ static int __init amikbd_init(void)
if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb"))
return -EBUSY;
- init_input_dev(&amikbd_dev);
-
- amikbd_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
- amikbd_dev.keycode = amikbd_keycode;
- amikbd_dev.keycodesize = sizeof(unsigned char);
- amikbd_dev.keycodemax = ARRAY_SIZE(amikbd_keycode);
+ amikbd_dev = input_dev_allocate();
+ if (!amikbd_dev) {
+ printk(KERN_ERR "amikbd: not enough memory for input device\n");
+ release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
+ return -ENOMEM;
+ }
+
+ amikbd_dev->name = "Amiga Keyboard";
+ amikbd_dev->phys = "amikbd/input0";
+ amikbd_dev->id.bustype = BUS_AMIGA;
+ amikbd_dev->id.vendor = 0x0001;
+ amikbd_dev->id.product = 0x0001;
+ amikbd_dev->id.version = 0x0100;
+
+ amikbd_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ amikbd_dev->keycode = amikbd_keycode;
+ amikbd_dev->keycodesize = sizeof(unsigned char);
+ amikbd_dev->keycodemax = ARRAY_SIZE(amikbd_keycode);
for (i = 0; i < 0x78; i++)
if (amikbd_keycode[i])
- set_bit(amikbd_keycode[i], amikbd_dev.keybit);
+ set_bit(amikbd_keycode[i], amikbd_dev->keybit);
ciaa.cra &= ~0x41; /* serial data in, turn off TA */
request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", amikbd_interrupt);
- amikbd_dev.name = amikbd_name;
- amikbd_dev.phys = amikbd_phys;
- amikbd_dev.id.bustype = BUS_AMIGA;
- amikbd_dev.id.vendor = 0x0001;
- amikbd_dev.id.product = 0x0001;
- amikbd_dev.id.version = 0x0100;
-
- input_register_device(&amikbd_dev);
-
- printk(KERN_INFO "input: %s\n", amikbd_name);
-
+ input_register_device(amikbd_dev);
return 0;
}
static void __exit amikbd_exit(void)
{
- input_unregister_device(&amikbd_dev);
free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt);
- release_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100);
+ input_unregister_device(amikbd_dev);
+ release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
}
module_init(amikbd_init);
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 1ad8c2ee7dbf33..820c7fd9a6049c 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -185,12 +185,12 @@ static struct {
struct atkbd {
- struct ps2dev ps2dev;
+ struct ps2dev ps2dev;
+ struct input_dev *dev;
/* Written only during init */
char name[64];
char phys[32];
- struct input_dev dev;
unsigned short id;
unsigned char keycode[512];
@@ -290,7 +290,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
if (!atkbd->enabled)
goto out;
- input_event(&atkbd->dev, EV_MSC, MSC_RAW, code);
+ input_event(atkbd->dev, EV_MSC, MSC_RAW, code);
if (atkbd->translated) {
@@ -326,10 +326,10 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
atkbd->release = 1;
goto out;
case ATKBD_RET_HANGUEL:
- atkbd_report_key(&atkbd->dev, regs, KEY_HANGUEL, 3);
+ atkbd_report_key(atkbd->dev, regs, KEY_HANGUEL, 3);
goto out;
case ATKBD_RET_HANJA:
- atkbd_report_key(&atkbd->dev, regs, KEY_HANJA, 3);
+ atkbd_report_key(atkbd->dev, regs, KEY_HANJA, 3);
goto out;
case ATKBD_RET_ERR:
printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys);
@@ -345,7 +345,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
}
if (atkbd->keycode[code] != ATKBD_KEY_NULL)
- input_event(&atkbd->dev, EV_MSC, MSC_SCAN, code);
+ input_event(atkbd->dev, EV_MSC, MSC_SCAN, code);
switch (atkbd->keycode[code]) {
case ATKBD_KEY_NULL:
@@ -365,7 +365,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
"to make it known.\n",
code & 0x80 ? "e0" : "", code & 0x7f);
}
- input_sync(&atkbd->dev);
+ input_sync(atkbd->dev);
break;
case ATKBD_SCR_1:
scroll = 1 - atkbd->release * 2;
@@ -390,7 +390,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
break;
default:
value = atkbd->release ? 0 :
- (1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key)));
+ (1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev->key)));
switch (value) { /* Workaround Toshiba laptop multiple keypress */
case 0:
@@ -398,7 +398,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
break;
case 1:
atkbd->last = code;
- atkbd->time = jiffies + msecs_to_jiffies(atkbd->dev.rep[REP_DELAY]) / 2;
+ atkbd->time = jiffies + msecs_to_jiffies(atkbd->dev->rep[REP_DELAY]) / 2;
break;
case 2:
if (!time_after(jiffies, atkbd->time) && atkbd->last == code)
@@ -406,16 +406,16 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
break;
}
- atkbd_report_key(&atkbd->dev, regs, atkbd->keycode[code], value);
+ atkbd_report_key(atkbd->dev, regs, atkbd->keycode[code], value);
}
if (atkbd->scroll) {
- input_regs(&atkbd->dev, regs);
+ input_regs(atkbd->dev, regs);
if (click != -1)
- input_report_key(&atkbd->dev, BTN_MIDDLE, click);
- input_report_rel(&atkbd->dev, REL_WHEEL, scroll);
- input_report_rel(&atkbd->dev, REL_HWHEEL, hscroll);
- input_sync(&atkbd->dev);
+ input_report_key(atkbd->dev, BTN_MIDDLE, click);
+ input_report_rel(atkbd->dev, REL_WHEEL, scroll);
+ input_report_rel(atkbd->dev, REL_HWHEEL, hscroll);
+ input_sync(atkbd->dev);
}
atkbd->release = 0;
@@ -463,7 +463,6 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
return 0;
-
case EV_REP:
if (atkbd->softrepeat) return 0;
@@ -693,7 +692,7 @@ static void atkbd_disconnect(struct serio *serio)
device_remove_file(&serio->dev, &atkbd_attr_softrepeat);
device_remove_file(&serio->dev, &atkbd_attr_softraw);
- input_unregister_device(&atkbd->dev);
+ input_unregister_device(atkbd->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
kfree(atkbd);
@@ -701,7 +700,7 @@ static void atkbd_disconnect(struct serio *serio)
/*
- * atkbd_set_device_attrs() initializes keyboard's keycode table
+ * atkbd_set_keycode_table() initializes keyboard's keycode table
* according to the selected scancode set
*/
@@ -737,53 +736,58 @@ static void atkbd_set_keycode_table(struct atkbd *atkbd)
static void atkbd_set_device_attrs(struct atkbd *atkbd)
{
+ struct input_dev *input_dev = atkbd->dev;
int i;
- memset(&atkbd->dev, 0, sizeof(struct input_dev));
+ if (atkbd->extra)
+ sprintf(atkbd->name, "AT Set 2 Extra keyboard");
+ else
+ sprintf(atkbd->name, "AT %s Set %d keyboard",
+ atkbd->translated ? "Translated" : "Raw", atkbd->set);
- init_input_dev(&atkbd->dev);
+ sprintf(atkbd->phys, "%s/input0", atkbd->ps2dev.serio->phys);
- atkbd->dev.name = atkbd->name;
- atkbd->dev.phys = atkbd->phys;
- atkbd->dev.id.bustype = BUS_I8042;
- atkbd->dev.id.vendor = 0x0001;
- atkbd->dev.id.product = atkbd->translated ? 1 : atkbd->set;
- atkbd->dev.id.version = atkbd->id;
- atkbd->dev.event = atkbd_event;
- atkbd->dev.private = atkbd;
- atkbd->dev.dev = &atkbd->ps2dev.serio->dev;
+ input_dev->name = atkbd->name;
+ input_dev->phys = atkbd->phys;
+ input_dev->id.bustype = BUS_I8042;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = atkbd->translated ? 1 : atkbd->set;
+ input_dev->id.version = atkbd->id;
+ input_dev->event = atkbd_event;
+ input_dev->private = atkbd;
+ input_dev->cdev.dev = &atkbd->ps2dev.serio->dev;
- atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC);
if (atkbd->write) {
- atkbd->dev.evbit[0] |= BIT(EV_LED);
- atkbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
+ input_dev->evbit[0] |= BIT(EV_LED);
+ input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
}
if (atkbd->extra)
- atkbd->dev.ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) |
+ input_dev->ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) |
BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC);
if (!atkbd->softrepeat) {
- atkbd->dev.rep[REP_DELAY] = 250;
- atkbd->dev.rep[REP_PERIOD] = 33;
+ input_dev->rep[REP_DELAY] = 250;
+ input_dev->rep[REP_PERIOD] = 33;
}
- atkbd->dev.mscbit[0] = atkbd->softraw ? BIT(MSC_SCAN) : BIT(MSC_RAW) | BIT(MSC_SCAN);
+ input_dev->mscbit[0] = atkbd->softraw ? BIT(MSC_SCAN) : BIT(MSC_RAW) | BIT(MSC_SCAN);
if (atkbd->scroll) {
- atkbd->dev.evbit[0] |= BIT(EV_REL);
- atkbd->dev.relbit[0] = BIT(REL_WHEEL) | BIT(REL_HWHEEL);
- set_bit(BTN_MIDDLE, atkbd->dev.keybit);
+ input_dev->evbit[0] |= BIT(EV_REL);
+ input_dev->relbit[0] = BIT(REL_WHEEL) | BIT(REL_HWHEEL);
+ set_bit(BTN_MIDDLE, input_dev->keybit);
}
- atkbd->dev.keycode = atkbd->keycode;
- atkbd->dev.keycodesize = sizeof(unsigned char);
- atkbd->dev.keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
+ input_dev->keycode = atkbd->keycode;
+ input_dev->keycodesize = sizeof(unsigned char);
+ input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
for (i = 0; i < 512; i++)
if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
- set_bit(atkbd->keycode[i], atkbd->dev.keybit);
+ set_bit(atkbd->keycode[i], input_dev->keybit);
}
/*
@@ -796,13 +800,15 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd)
static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
{
struct atkbd *atkbd;
- int err;
-
- if (!(atkbd = kmalloc(sizeof(struct atkbd), GFP_KERNEL)))
- return - ENOMEM;
+ struct input_dev *dev;
+ int err = -ENOMEM;
- memset(atkbd, 0, sizeof(struct atkbd));
+ atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL);
+ dev = input_allocate_device();
+ if (!atkbd || !dev)
+ goto fail;
+ atkbd->dev = dev;
ps2_init(&atkbd->ps2dev, serio);
switch (serio->id.type) {
@@ -828,19 +834,15 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
serio_set_drvdata(serio, atkbd);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(atkbd);
- return err;
- }
+ if (err)
+ goto fail;
if (atkbd->write) {
if (atkbd_probe(atkbd)) {
serio_close(serio);
- serio_set_drvdata(serio, NULL);
- kfree(atkbd);
- return -ENODEV;
+ err = -ENODEV;
+ goto fail;
}
atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
@@ -851,19 +853,9 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd->id = 0xab00;
}
- if (atkbd->extra)
- sprintf(atkbd->name, "AT Set 2 Extra keyboard");
- else
- sprintf(atkbd->name, "AT %s Set %d keyboard",
- atkbd->translated ? "Translated" : "Raw", atkbd->set);
-
- sprintf(atkbd->phys, "%s/input0", serio->phys);
-
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
- input_register_device(&atkbd->dev);
-
device_create_file(&serio->dev, &atkbd_attr_extra);
device_create_file(&serio->dev, &atkbd_attr_scroll);
device_create_file(&serio->dev, &atkbd_attr_set);
@@ -872,9 +864,14 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd_enable(atkbd);
- printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys);
+ input_register_device(atkbd->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(dev);
+ kfree(atkbd);
+ return err;
}
/*
@@ -896,9 +893,9 @@ static int atkbd_reconnect(struct serio *serio)
atkbd_disable(atkbd);
if (atkbd->write) {
- param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0)
- | (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0)
- | (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0);
+ param[0] = (test_bit(LED_SCROLLL, atkbd->dev->led) ? 1 : 0)
+ | (test_bit(LED_NUML, atkbd->dev->led) ? 2 : 0)
+ | (test_bit(LED_CAPSL, atkbd->dev->led) ? 4 : 0);
if (atkbd_probe(atkbd))
return -1;
@@ -1008,6 +1005,7 @@ static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count)
{
+ struct input_dev *new_dev;
unsigned long value;
char *rest;
@@ -1019,12 +1017,19 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun
return -EINVAL;
if (atkbd->extra != value) {
- /* unregister device as it's properties will change */
- input_unregister_device(&atkbd->dev);
+ /*
+ * Since device's properties will change we need to
+ * unregister old device. But allocate new one first
+ * to make sure we have it.
+ */
+ if (!(new_dev = input_allocate_device()))
+ return -ENOMEM;
+ input_unregister_device(atkbd->dev);
+ atkbd->dev = new_dev;
atkbd->set = atkbd_select_set(atkbd, atkbd->set, value);
atkbd_activate(atkbd);
atkbd_set_device_attrs(atkbd);
- input_register_device(&atkbd->dev);
+ input_register_device(atkbd->dev);
}
return count;
}
@@ -1036,6 +1041,7 @@ static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count)
{
+ struct input_dev *new_dev;
unsigned long value;
char *rest;
@@ -1044,12 +1050,14 @@ static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t cou
return -EINVAL;
if (atkbd->scroll != value) {
- /* unregister device as it's properties will change */
- input_unregister_device(&atkbd->dev);
+ if (!(new_dev = input_allocate_device()))
+ return -ENOMEM;
+ input_unregister_device(atkbd->dev);
+ atkbd->dev = new_dev;
atkbd->scroll = value;
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
- input_register_device(&atkbd->dev);
+ input_register_device(atkbd->dev);
}
return count;
}
@@ -1061,6 +1069,7 @@ static ssize_t atkbd_show_set(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
{
+ struct input_dev *new_dev;
unsigned long value;
char *rest;
@@ -1072,13 +1081,15 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
return -EINVAL;
if (atkbd->set != value) {
- /* unregister device as it's properties will change */
- input_unregister_device(&atkbd->dev);
+ if (!(new_dev = input_allocate_device()))
+ return -ENOMEM;
+ input_unregister_device(atkbd->dev);
+ atkbd->dev = new_dev;
atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra);
atkbd_activate(atkbd);
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
- input_register_device(&atkbd->dev);
+ input_register_device(atkbd->dev);
}
return count;
}
@@ -1090,6 +1101,7 @@ static ssize_t atkbd_show_softrepeat(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count)
{
+ struct input_dev *new_dev;
unsigned long value;
char *rest;
@@ -1101,15 +1113,16 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t
return -EINVAL;
if (atkbd->softrepeat != value) {
- /* unregister device as it's properties will change */
- input_unregister_device(&atkbd->dev);
+ if (!(new_dev = input_allocate_device()))
+ return -ENOMEM;
+ input_unregister_device(atkbd->dev);
+ atkbd->dev = new_dev;
atkbd->softrepeat = value;
if (atkbd->softrepeat)
atkbd->softraw = 1;
atkbd_set_device_attrs(atkbd);
- input_register_device(&atkbd->dev);
+ input_register_device(atkbd->dev);
}
-
return count;
}
@@ -1121,6 +1134,7 @@ static ssize_t atkbd_show_softraw(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count)
{
+ struct input_dev *new_dev;
unsigned long value;
char *rest;
@@ -1129,11 +1143,13 @@ static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t co
return -EINVAL;
if (atkbd->softraw != value) {
- /* unregister device as it's properties will change */
- input_unregister_device(&atkbd->dev);
+ if (!(new_dev = input_allocate_device()))
+ return -ENOMEM;
+ input_unregister_device(atkbd->dev);
+ atkbd->dev = new_dev;
atkbd->softraw = value;
atkbd_set_device_attrs(atkbd);
- input_register_device(&atkbd->dev);
+ input_register_device(atkbd->dev);
}
return count;
}
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index cd4b6e795013a8..3210d298b3bc01 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -70,8 +70,7 @@ static unsigned char corgikbd_keycode[NR_SCANCODES] = {
struct corgikbd {
unsigned char keycode[ARRAY_SIZE(corgikbd_keycode)];
- struct input_dev input;
- char phys[32];
+ struct input_dev *input;
spinlock_t lock;
struct timer_list timer;
@@ -147,7 +146,7 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs
spin_lock_irqsave(&corgikbd_data->lock, flags);
if (regs)
- input_regs(&corgikbd_data->input, regs);
+ input_regs(corgikbd_data->input, regs);
num_pressed = 0;
for (col = 0; col < KB_COLS; col++) {
@@ -169,14 +168,14 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs
scancode = SCANCODE(row, col);
pressed = rowd & KB_ROWMASK(row);
- input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], pressed);
+ input_report_key(corgikbd_data->input, corgikbd_data->keycode[scancode], pressed);
if (pressed)
num_pressed++;
if (pressed && (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF)
&& time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) {
- input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
+ input_event(corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
corgikbd_data->suspend_jiffies=jiffies;
}
}
@@ -185,7 +184,7 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs
corgikbd_activate_all();
- input_sync(&corgikbd_data->input);
+ input_sync(corgikbd_data->input);
/* if any keys are pressed, enable the timer */
if (num_pressed)
@@ -249,9 +248,9 @@ static void corgikbd_hinge_timer(unsigned long data)
if (hinge_count >= HINGE_STABLE_COUNT) {
spin_lock_irqsave(&corgikbd_data->lock, flags);
- input_report_switch(&corgikbd_data->input, SW_0, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0));
- input_report_switch(&corgikbd_data->input, SW_1, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0));
- input_sync(&corgikbd_data->input);
+ input_report_switch(corgikbd_data->input, SW_0, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0));
+ input_report_switch(corgikbd_data->input, SW_1, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0));
+ input_sync(corgikbd_data->input);
spin_unlock_irqrestore(&corgikbd_data->lock, flags);
}
@@ -260,24 +259,22 @@ static void corgikbd_hinge_timer(unsigned long data)
}
#ifdef CONFIG_PM
-static int corgikbd_suspend(struct device *dev, pm_message_t state, uint32_t level)
+static int corgikbd_suspend(struct device *dev, pm_message_t state)
{
- if (level == SUSPEND_POWER_DOWN) {
- struct corgikbd *corgikbd = dev_get_drvdata(dev);
- corgikbd->suspended = 1;
- }
+ struct corgikbd *corgikbd = dev_get_drvdata(dev);
+ corgikbd->suspended = 1;
+
return 0;
}
-static int corgikbd_resume(struct device *dev, uint32_t level)
+static int corgikbd_resume(struct device *dev)
{
- if (level == RESUME_POWER_ON) {
- struct corgikbd *corgikbd = dev_get_drvdata(dev);
+ struct corgikbd *corgikbd = dev_get_drvdata(dev);
+
+ /* Upon resume, ignore the suspend key for a short while */
+ corgikbd->suspend_jiffies=jiffies;
+ corgikbd->suspended = 0;
- /* Upon resume, ignore the suspend key for a short while */
- corgikbd->suspend_jiffies=jiffies;
- corgikbd->suspended = 0;
- }
return 0;
}
#else
@@ -287,16 +284,21 @@ static int corgikbd_resume(struct device *dev, uint32_t level)
static int __init corgikbd_probe(struct device *dev)
{
- int i;
struct corgikbd *corgikbd;
+ struct input_dev *input_dev;
+ int i;
corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL);
- if (!corgikbd)
+ input_dev = input_allocate_device();
+ if (!corgikbd || !input_dev) {
+ kfree(corgikbd);
+ input_free_device(input_dev);
return -ENOMEM;
+ }
- dev_set_drvdata(dev,corgikbd);
- strcpy(corgikbd->phys, "corgikbd/input0");
+ dev_set_drvdata(dev, corgikbd);
+ corgikbd->input = input_dev;
spin_lock_init(&corgikbd->lock);
/* Init Keyboard rescan timer */
@@ -311,28 +313,30 @@ static int __init corgikbd_probe(struct device *dev)
corgikbd->suspend_jiffies=jiffies;
- init_input_dev(&corgikbd->input);
- corgikbd->input.private = corgikbd;
- corgikbd->input.name = "Corgi Keyboard";
- corgikbd->input.dev = dev;
- corgikbd->input.phys = corgikbd->phys;
- corgikbd->input.id.bustype = BUS_HOST;
- corgikbd->input.id.vendor = 0x0001;
- corgikbd->input.id.product = 0x0001;
- corgikbd->input.id.version = 0x0100;
- corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
- corgikbd->input.keycode = corgikbd->keycode;
- corgikbd->input.keycodesize = sizeof(unsigned char);
- corgikbd->input.keycodemax = ARRAY_SIZE(corgikbd_keycode);
-
memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode));
+
+ input_dev->name = "Corgi Keyboard";
+ input_dev->phys = "corgikbd/input0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = dev;
+ input_dev->private = corgikbd;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
+ input_dev->keycode = corgikbd->keycode;
+ input_dev->keycodesize = sizeof(unsigned char);
+ input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode);
+
for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
- set_bit(corgikbd->keycode[i], corgikbd->input.keybit);
- clear_bit(0, corgikbd->input.keybit);
- set_bit(SW_0, corgikbd->input.swbit);
- set_bit(SW_1, corgikbd->input.swbit);
+ set_bit(corgikbd->keycode[i], input_dev->keybit);
+ clear_bit(0, input_dev->keybit);
+ set_bit(SW_0, input_dev->swbit);
+ set_bit(SW_1, input_dev->swbit);
+
+ input_register_device(corgikbd->input);
- input_register_device(&corgikbd->input);
mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL);
/* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
@@ -349,8 +353,6 @@ static int __init corgikbd_probe(struct device *dev)
for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)
pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);
- printk(KERN_INFO "input: Corgi Keyboard Registered\n");
-
return 0;
}
@@ -365,7 +367,7 @@ static int corgikbd_remove(struct device *dev)
del_timer_sync(&corgikbd->htimer);
del_timer_sync(&corgikbd->timer);
- input_unregister_device(&corgikbd->input);
+ input_unregister_device(corgikbd->input);
kfree(corgikbd);
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index ef78bffed5e7bd..0a90962c38e7ef 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -204,7 +204,7 @@ static irqreturn_t hil_kbd_interrupt(struct serio *serio,
hil_packet packet;
int idx;
- kbd = (struct hil_kbd *)serio->private;
+ kbd = serio_get_drvdata(serio);
if (kbd == NULL) {
BUG();
return IRQ_HANDLED;
@@ -234,7 +234,7 @@ static void hil_kbd_disconnect(struct serio *serio)
{
struct hil_kbd *kbd;
- kbd = (struct hil_kbd *)serio->private;
+ kbd = serio_get_drvdata(serio);
if (kbd == NULL) {
BUG();
return;
@@ -245,20 +245,20 @@ static void hil_kbd_disconnect(struct serio *serio)
kfree(kbd);
}
-static void hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
+static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
{
struct hil_kbd *kbd;
uint8_t did, *idd;
int i;
- if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return;
-
- if (!(kbd = kmalloc(sizeof(struct hil_kbd), GFP_KERNEL))) return;
+ kbd = kmalloc(sizeof(*kbd), GFP_KERNEL);
+ if (!kbd)
+ return -ENOMEM;
memset(kbd, 0, sizeof(struct hil_kbd));
if (serio_open(serio, drv)) goto bail0;
- serio->private = kbd;
+ serio_set_drvdata(serio, kbd);
kbd->serio = serio;
kbd->dev.private = kbd;
@@ -342,19 +342,31 @@ static void hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
down(&(kbd->sem));
up(&(kbd->sem));
- return;
+ return 0;
bail1:
serio_close(serio);
bail0:
kfree(kbd);
+ serio_set_drvdata(serio, NULL);
+ return -EIO;
}
+static struct serio_device_id hil_kbd_ids[] = {
+ {
+ .type = SERIO_HIL_MLC,
+ .proto = SERIO_HIL,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
struct serio_driver hil_kbd_serio_drv = {
.driver = {
.name = "hil_kbd",
},
.description = "HP HIL keyboard driver",
+ .id_table = hil_kbd_ids,
.connect = hil_kbd_connect,
.disconnect = hil_kbd_disconnect,
.interrupt = hil_kbd_interrupt
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
index eecb77db084771..e95bc052e32a3e 100644
--- a/drivers/input/keyboard/hilkbd.c
+++ b/drivers/input/keyboard/hilkbd.c
@@ -22,7 +22,7 @@
#include <linux/errno.h>
#include <linux/input.h>
#include <linux/init.h>
-#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/hil.h>
#include <linux/spinlock.h>
@@ -278,11 +278,11 @@ static int __init
hil_init_chip(struct parisc_device *dev)
{
if (!dev->irq) {
- printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%08lx\n", dev->hpa);
+ printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%08lx\n", dev->hpa.start);
return -ENODEV;
}
- hil_base = dev->hpa;
+ hil_base = dev->hpa.start;
hil_irq = dev->irq;
hil_dev.dev_id = dev;
@@ -299,7 +299,7 @@ static struct parisc_device_id hil_tbl[] = {
MODULE_DEVICE_TABLE(parisc, hil_tbl);
static struct parisc_driver hil_driver = {
- .name = "HIL",
+ .name = "hil",
.id_table = hil_tbl,
.probe = hil_init_chip,
};
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
index 098963c7cdd6ae..7f06780a437f5d 100644
--- a/drivers/input/keyboard/lkkbd.c
+++ b/drivers/input/keyboard/lkkbd.c
@@ -102,7 +102,7 @@ static int ctrlclick_volume = 100; /* % */
module_param (ctrlclick_volume, int, 0);
MODULE_PARM_DESC (ctrlclick_volume, "Ctrlclick volume (in %), default is 100%");
-static int lk201_compose_is_alt = 0;
+static int lk201_compose_is_alt;
module_param (lk201_compose_is_alt, int, 0);
MODULE_PARM_DESC (lk201_compose_is_alt, "If set non-zero, LK201' Compose key "
"will act as an Alt key");
@@ -274,7 +274,7 @@ static lk_keycode_t lkkbd_keycode[LK_NUM_KEYCODES] = {
};
#define CHECK_LED(LED, BITS) do { \
- if (test_bit (LED, lk->dev.led)) \
+ if (test_bit (LED, lk->dev->led)) \
leds_on |= BITS; \
else \
leds_off |= BITS; \
@@ -287,7 +287,7 @@ struct lkkbd {
lk_keycode_t keycode[LK_NUM_KEYCODES];
int ignore_bytes;
unsigned char id[LK_NUM_IGNORE_BYTES];
- struct input_dev dev;
+ struct input_dev *dev;
struct serio *serio;
struct work_struct tq;
char name[64];
@@ -423,8 +423,7 @@ lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
DBG (KERN_INFO "Got byte 0x%02x\n", data);
if (lk->ignore_bytes > 0) {
- DBG (KERN_INFO "Ignoring a byte on %s\n",
- lk->name);
+ DBG (KERN_INFO "Ignoring a byte on %s\n", lk->name);
lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data;
if (lk->ignore_bytes == 0)
@@ -435,14 +434,14 @@ lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
switch (data) {
case LK_ALL_KEYS_UP:
- input_regs (&lk->dev, regs);
+ input_regs (lk->dev, regs);
for (i = 0; i < ARRAY_SIZE (lkkbd_keycode); i++)
if (lk->keycode[i] != KEY_RESERVED)
- input_report_key (&lk->dev, lk->keycode[i], 0);
- input_sync (&lk->dev);
+ input_report_key (lk->dev, lk->keycode[i], 0);
+ input_sync (lk->dev);
break;
case LK_METRONOME:
- DBG (KERN_INFO "Got LK_METRONOME and don't "
+ DBG (KERN_INFO "Got %#d and don't "
"know how to handle...\n");
break;
case LK_OUTPUT_ERROR:
@@ -482,12 +481,12 @@ lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
default:
if (lk->keycode[data] != KEY_RESERVED) {
- input_regs (&lk->dev, regs);
- if (!test_bit (lk->keycode[data], lk->dev.key))
- input_report_key (&lk->dev, lk->keycode[data], 1);
+ input_regs (lk->dev, regs);
+ if (!test_bit (lk->keycode[data], lk->dev->key))
+ input_report_key (lk->dev, lk->keycode[data], 1);
else
- input_report_key (&lk->dev, lk->keycode[data], 0);
- input_sync (&lk->dev);
+ input_report_key (lk->dev, lk->keycode[data], 0);
+ input_sync (lk->dev);
} else
printk (KERN_WARNING "%s: Unknown key with "
"scancode 0x%02x on %s.\n",
@@ -605,7 +604,7 @@ lkkbd_reinit (void *data)
lk->serio->write (lk->serio, volume_to_hw (lk->bell_volume));
/* Enable/disable keyclick (and possibly set volume) */
- if (test_bit (SND_CLICK, lk->dev.snd)) {
+ if (test_bit (SND_CLICK, lk->dev->snd)) {
lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK);
lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume));
lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK);
@@ -616,7 +615,7 @@ lkkbd_reinit (void *data)
}
/* Sound the bell if needed */
- if (test_bit (SND_BELL, lk->dev.snd))
+ if (test_bit (SND_BELL, lk->dev->snd))
lk->serio->write (lk->serio, LK_CMD_SOUND_BELL);
}
@@ -627,71 +626,70 @@ static int
lkkbd_connect (struct serio *serio, struct serio_driver *drv)
{
struct lkkbd *lk;
+ struct input_dev *input_dev;
int i;
int err;
- if (!(lk = kmalloc (sizeof (struct lkkbd), GFP_KERNEL)))
- return -ENOMEM;
-
- memset (lk, 0, sizeof (struct lkkbd));
-
- init_input_dev (&lk->dev);
- set_bit (EV_KEY, lk->dev.evbit);
- set_bit (EV_LED, lk->dev.evbit);
- set_bit (EV_SND, lk->dev.evbit);
- set_bit (EV_REP, lk->dev.evbit);
- set_bit (LED_CAPSL, lk->dev.ledbit);
- set_bit (LED_SLEEP, lk->dev.ledbit);
- set_bit (LED_COMPOSE, lk->dev.ledbit);
- set_bit (LED_SCROLLL, lk->dev.ledbit);
- set_bit (SND_BELL, lk->dev.sndbit);
- set_bit (SND_CLICK, lk->dev.sndbit);
+ lk = kzalloc (sizeof (struct lkkbd), GFP_KERNEL);
+ input_dev = input_allocate_device ();
+ if (!lk || !input_dev) {
+ err = -ENOMEM;
+ goto fail;
+ }
lk->serio = serio;
-
+ lk->dev = input_dev;
INIT_WORK (&lk->tq, lkkbd_reinit, lk);
-
lk->bell_volume = bell_volume;
lk->keyclick_volume = keyclick_volume;
lk->ctrlclick_volume = ctrlclick_volume;
+ memcpy (lk->keycode, lkkbd_keycode, sizeof (lk_keycode_t) * LK_NUM_KEYCODES);
- lk->dev.keycode = lk->keycode;
- lk->dev.keycodesize = sizeof (lk_keycode_t);
- lk->dev.keycodemax = LK_NUM_KEYCODES;
-
- lk->dev.event = lkkbd_event;
- lk->dev.private = lk;
+ strlcpy (lk->name, "DEC LK keyboard", sizeof(lk->name));
+ snprintf (lk->phys, sizeof(lk->phys), "%s/input0", serio->phys);
+
+ input_dev->name = lk->name;
+ input_dev->phys = lk->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_LKKBD;
+ input_dev->id.product = 0;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->event = lkkbd_event;
+ input_dev->private = lk;
+
+ set_bit (EV_KEY, input_dev->evbit);
+ set_bit (EV_LED, input_dev->evbit);
+ set_bit (EV_SND, input_dev->evbit);
+ set_bit (EV_REP, input_dev->evbit);
+ set_bit (LED_CAPSL, input_dev->ledbit);
+ set_bit (LED_SLEEP, input_dev->ledbit);
+ set_bit (LED_COMPOSE, input_dev->ledbit);
+ set_bit (LED_SCROLLL, input_dev->ledbit);
+ set_bit (SND_BELL, input_dev->sndbit);
+ set_bit (SND_CLICK, input_dev->sndbit);
+
+ input_dev->keycode = lk->keycode;
+ input_dev->keycodesize = sizeof (lk_keycode_t);
+ input_dev->keycodemax = LK_NUM_KEYCODES;
+ for (i = 0; i < LK_NUM_KEYCODES; i++)
+ set_bit (lk->keycode[i], input_dev->keybit);
serio_set_drvdata (serio, lk);
err = serio_open (serio, drv);
- if (err) {
- serio_set_drvdata (serio, NULL);
- kfree (lk);
- return err;
- }
+ if (err)
+ goto fail;
- sprintf (lk->name, "DEC LK keyboard");
- sprintf (lk->phys, "%s/input0", serio->phys);
-
- memcpy (lk->keycode, lkkbd_keycode, sizeof (lk_keycode_t) * LK_NUM_KEYCODES);
- for (i = 0; i < LK_NUM_KEYCODES; i++)
- set_bit (lk->keycode[i], lk->dev.keybit);
-
- lk->dev.name = lk->name;
- lk->dev.phys = lk->phys;
- lk->dev.id.bustype = BUS_RS232;
- lk->dev.id.vendor = SERIO_LKKBD;
- lk->dev.id.product = 0;
- lk->dev.id.version = 0x0100;
- lk->dev.dev = &serio->dev;
-
- input_register_device (&lk->dev);
-
- printk (KERN_INFO "input: %s on %s, initiating reset\n", lk->name, serio->phys);
+ input_register_device (lk->dev);
lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET);
return 0;
+
+ fail: serio_set_drvdata (serio, NULL);
+ input_free_device (input_dev);
+ kfree (lk);
+ return err;
}
/*
@@ -702,9 +700,11 @@ lkkbd_disconnect (struct serio *serio)
{
struct lkkbd *lk = serio_get_drvdata (serio);
- input_unregister_device (&lk->dev);
+ input_get_device (lk->dev);
+ input_unregister_device (lk->dev);
serio_close (serio);
serio_set_drvdata (serio, NULL);
+ input_put_device (lk->dev);
kfree (lk);
}
diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c
index eecbde294f1f09..cc6aaf9e85bef0 100644
--- a/drivers/input/keyboard/maple_keyb.c
+++ b/drivers/input/keyboard/maple_keyb.c
@@ -37,7 +37,7 @@ static unsigned char dc_kbd_keycode[256] = {
struct dc_kbd {
- struct input_dev dev;
+ struct input_dev *dev;
unsigned char new[8];
unsigned char old[8];
};
@@ -46,30 +46,24 @@ struct dc_kbd {
static void dc_scan_kbd(struct dc_kbd *kbd)
{
int i;
- struct input_dev *dev = &kbd->dev;
+ struct input_dev *dev = kbd->dev;
- for(i=0; i<8; i++)
- input_report_key(dev,
- dc_kbd_keycode[i+224],
- (kbd->new[0]>>i)&1);
+ for (i = 0; i < 8; i++)
+ input_report_key(dev, dc_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
- for(i=2; i<8; i++) {
+ for (i = 2; i < 8; i++) {
- if(kbd->old[i]>3&&memscan(kbd->new+2, kbd->old[i], 6)==NULL) {
- if(dc_kbd_keycode[kbd->old[i]])
- input_report_key(dev,
- dc_kbd_keycode[kbd->old[i]],
- 0);
+ if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == NULL) {
+ if (dc_kbd_keycode[kbd->old[i]])
+ input_report_key(dev, dc_kbd_keycode[kbd->old[i]], 0);
else
printk("Unknown key (scancode %#x) released.",
kbd->old[i]);
}
- if(kbd->new[i]>3&&memscan(kbd->old+2, kbd->new[i], 6)!=NULL) {
+ if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) != NULL) {
if(dc_kbd_keycode[kbd->new[i]])
- input_report_key(dev,
- dc_kbd_keycode[kbd->new[i]],
- 1);
+ input_report_key(dev, dc_kbd_keycode[kbd->new[i]], 1);
else
printk("Unknown key (scancode %#x) pressed.",
kbd->new[i]);
@@ -89,43 +83,39 @@ static void dc_kbd_callback(struct mapleq *mq)
unsigned long *buf = mq->recvbuf;
if (buf[1] == mapledev->function) {
- memcpy(kbd->new, buf+2, 8);
+ memcpy(kbd->new, buf + 2, 8);
dc_scan_kbd(kbd);
}
}
static int dc_kbd_connect(struct maple_device *dev)
{
- int i;
- unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
struct dc_kbd *kbd;
+ struct input_dev *input_dev;
+ unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
+ int i;
- if (!(kbd = kmalloc(sizeof(struct dc_kbd), GFP_KERNEL)))
- return -1;
- memset(kbd, 0, sizeof(struct dc_kbd));
-
- dev->private_data = kbd;
-
- kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
-
- init_input_dev(&kbd->dev);
-
- for (i=0; i<255; i++)
- set_bit(dc_kbd_keycode[i], kbd->dev.keybit);
-
- clear_bit(0, kbd->dev.keybit);
+ dev->private_data = kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!kbd || !input_dev) {
+ kfree(kbd);
+ input_free_device(input_dev);
+ return -ENOMEM;
+ }
- kbd->dev.private = kbd;
+ kbd->dev = input_dev;
- kbd->dev.name = dev->product_name;
- kbd->dev.id.bustype = BUS_MAPLE;
+ input_dev->name = dev->product_name;
+ input_dev->id.bustype = BUS_MAPLE;
+ input_dev->private = kbd;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ for (i = 0; i < 255; i++)
+ set_bit(dc_kbd_keycode[i], input_dev->keybit);
+ clear_bit(0, input_dev->keybit);
- input_register_device(&kbd->dev);
+ input_register_device(kbd->dev);
maple_getcond_callback(dev, dc_kbd_callback, 1, MAPLE_FUNC_KEYBOARD);
-
- printk(KERN_INFO "input: keyboard(0x%lx): %s\n", data, kbd->dev.name);
-
return 0;
}
@@ -134,7 +124,7 @@ static void dc_kbd_disconnect(struct maple_device *dev)
{
struct dc_kbd *kbd = dev->private_data;
- input_unregister_device(&kbd->dev);
+ input_unregister_device(kbd->dev);
kfree(kbd);
}
diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c
index 2e8ce1613eec9b..d10983c521e6df 100644
--- a/drivers/input/keyboard/newtonkbd.c
+++ b/drivers/input/keyboard/newtonkbd.c
@@ -57,11 +57,9 @@ static unsigned char nkbd_keycode[128] = {
KEY_LEFT, KEY_RIGHT, KEY_DOWN, KEY_UP, 0
};
-static char *nkbd_name = "Newton Keyboard";
-
struct nkbd {
unsigned char keycode[128];
- struct input_dev dev;
+ struct input_dev *dev;
struct serio *serio;
char phys[32];
};
@@ -73,13 +71,13 @@ static irqreturn_t nkbd_interrupt(struct serio *serio,
/* invalid scan codes are probably the init sequence, so we ignore them */
if (nkbd->keycode[data & NKBD_KEY]) {
- input_regs(&nkbd->dev, regs);
- input_report_key(&nkbd->dev, nkbd->keycode[data & NKBD_KEY], data & NKBD_PRESS);
- input_sync(&nkbd->dev);
+ input_regs(nkbd->dev, regs);
+ input_report_key(nkbd->dev, nkbd->keycode[data & NKBD_KEY], data & NKBD_PRESS);
+ input_sync(nkbd->dev);
}
else if (data == 0xe7) /* end of init sequence */
- printk(KERN_INFO "input: %s on %s\n", nkbd_name, serio->phys);
+ printk(KERN_INFO "input: %s on %s\n", nkbd->dev->name, serio->phys);
return IRQ_HANDLED;
}
@@ -87,62 +85,59 @@ static irqreturn_t nkbd_interrupt(struct serio *serio,
static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
{
struct nkbd *nkbd;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
int i;
- int err;
-
- if (!(nkbd = kmalloc(sizeof(struct nkbd), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(nkbd, 0, sizeof(struct nkbd));
- nkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ nkbd = kzalloc(sizeof(struct nkbd), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!nkbd || !input_dev)
+ goto fail;
nkbd->serio = serio;
+ nkbd->dev = input_dev;
+ sprintf(nkbd->phys, "%s/input0", serio->phys);
+ memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode));
- init_input_dev(&nkbd->dev);
- nkbd->dev.keycode = nkbd->keycode;
- nkbd->dev.keycodesize = sizeof(unsigned char);
- nkbd->dev.keycodemax = ARRAY_SIZE(nkbd_keycode);
- nkbd->dev.private = nkbd;
+ input_dev->name = "Newton Keyboard";
+ input_dev->phys = nkbd->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_NEWTON;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = nkbd;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ input_dev->keycode = nkbd->keycode;
+ input_dev->keycodesize = sizeof(unsigned char);
+ input_dev->keycodemax = ARRAY_SIZE(nkbd_keycode);
+ for (i = 0; i < 128; i++)
+ set_bit(nkbd->keycode[i], input_dev->keybit);
+ clear_bit(0, input_dev->keybit);
serio_set_drvdata(serio, nkbd);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(nkbd);
- return err;
- }
-
- memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode));
- for (i = 0; i < 128; i++)
- set_bit(nkbd->keycode[i], nkbd->dev.keybit);
- clear_bit(0, nkbd->dev.keybit);
-
- sprintf(nkbd->phys, "%s/input0", serio->phys);
-
- nkbd->dev.name = nkbd_name;
- nkbd->dev.phys = nkbd->phys;
- nkbd->dev.id.bustype = BUS_RS232;
- nkbd->dev.id.vendor = SERIO_NEWTON;
- nkbd->dev.id.product = 0x0001;
- nkbd->dev.id.version = 0x0100;
- nkbd->dev.dev = &serio->dev;
-
- input_register_device(&nkbd->dev);
-
- printk(KERN_INFO "input: %s on %s\n", nkbd_name, serio->phys);
+ if (err)
+ goto fail;
+ input_register_device(nkbd->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(nkbd);
+ return err;
}
static void nkbd_disconnect(struct serio *serio)
{
struct nkbd *nkbd = serio_get_drvdata(serio);
- input_unregister_device(&nkbd->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(nkbd->dev);
kfree(nkbd);
}
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
index 344f4600540115..cee9c734a048c9 100644
--- a/drivers/input/keyboard/spitzkbd.c
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -85,7 +85,7 @@ static int spitz_senses[] = {
struct spitzkbd {
unsigned char keycode[ARRAY_SIZE(spitzkbd_keycode)];
- struct input_dev input;
+ struct input_dev *input;
char phys[32];
spinlock_t lock;
@@ -187,8 +187,7 @@ static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs
spin_lock_irqsave(&spitzkbd_data->lock, flags);
- if (regs)
- input_regs(&spitzkbd_data->input, regs);
+ input_regs(spitzkbd_data->input, regs);
num_pressed = 0;
for (col = 0; col < KB_COLS; col++) {
@@ -210,7 +209,7 @@ static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs
scancode = SCANCODE(row, col);
pressed = rowd & KB_ROWMASK(row);
- input_report_key(&spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed);
+ input_report_key(spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed);
if (pressed)
num_pressed++;
@@ -220,15 +219,15 @@ static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs
spitzkbd_activate_all();
- input_report_key(&spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 );
- input_report_key(&spitzkbd_data->input, KEY_SUSPEND, pwrkey);
+ input_report_key(spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 );
+ input_report_key(spitzkbd_data->input, KEY_SUSPEND, pwrkey);
if (pwrkey && time_after(jiffies, spitzkbd_data->suspend_jiffies + msecs_to_jiffies(1000))) {
- input_event(&spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1);
+ input_event(spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1);
spitzkbd_data->suspend_jiffies = jiffies;
}
- input_sync(&spitzkbd_data->input);
+ input_sync(spitzkbd_data->input);
/* if any keys are pressed, enable the timer */
if (num_pressed)
@@ -259,6 +258,7 @@ static irqreturn_t spitzkbd_interrupt(int irq, void *dev_id, struct pt_regs *reg
static void spitzkbd_timer_callback(unsigned long data)
{
struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
+
spitzkbd_scankeyboard(spitzkbd_data, NULL);
}
@@ -298,9 +298,9 @@ static void spitzkbd_hinge_timer(unsigned long data)
if (hinge_count >= HINGE_STABLE_COUNT) {
spin_lock_irqsave(&spitzkbd_data->lock, flags);
- input_report_switch(&spitzkbd_data->input, SW_0, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
- input_report_switch(&spitzkbd_data->input, SW_1, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
- input_sync(&spitzkbd_data->input);
+ input_report_switch(spitzkbd_data->input, SW_0, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
+ input_report_switch(spitzkbd_data->input, SW_1, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
+ input_sync(spitzkbd_data->input);
spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
} else {
@@ -309,34 +309,32 @@ static void spitzkbd_hinge_timer(unsigned long data)
}
#ifdef CONFIG_PM
-static int spitzkbd_suspend(struct device *dev, pm_message_t state, uint32_t level)
+static int spitzkbd_suspend(struct device *dev, pm_message_t state)
{
- if (level == SUSPEND_POWER_DOWN) {
- int i;
- struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
- spitzkbd->suspended = 1;
-
- /* Set Strobe lines as inputs - *except* strobe line 0 leave this
- enabled so we can detect a power button press for resume */
- for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++)
- pxa_gpio_mode(spitz_strobes[i] | GPIO_IN);
- }
+ int i;
+ struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+ spitzkbd->suspended = 1;
+
+ /* Set Strobe lines as inputs - *except* strobe line 0 leave this
+ enabled so we can detect a power button press for resume */
+ for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++)
+ pxa_gpio_mode(spitz_strobes[i] | GPIO_IN);
+
return 0;
}
-static int spitzkbd_resume(struct device *dev, uint32_t level)
+static int spitzkbd_resume(struct device *dev)
{
- if (level == RESUME_POWER_ON) {
- int i;
- struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+ int i;
+ struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
- for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
- pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
+ for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
+ pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
+
+ /* Upon resume, ignore the suspend key for a short while */
+ spitzkbd->suspend_jiffies = jiffies;
+ spitzkbd->suspended = 0;
- /* Upon resume, ignore the suspend key for a short while */
- spitzkbd->suspend_jiffies = jiffies;
- spitzkbd->suspended = 0;
- }
return 0;
}
#else
@@ -346,14 +344,21 @@ static int spitzkbd_resume(struct device *dev, uint32_t level)
static int __init spitzkbd_probe(struct device *dev)
{
- int i;
struct spitzkbd *spitzkbd;
+ struct input_dev *input_dev;
+ int i;
spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL);
if (!spitzkbd)
return -ENOMEM;
- dev_set_drvdata(dev,spitzkbd);
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ kfree(spitzkbd);
+ return -ENOMEM;
+ }
+
+ dev_set_drvdata(dev, spitzkbd);
strcpy(spitzkbd->phys, "spitzkbd/input0");
spin_lock_init(&spitzkbd->lock);
@@ -368,30 +373,34 @@ static int __init spitzkbd_probe(struct device *dev)
spitzkbd->htimer.function = spitzkbd_hinge_timer;
spitzkbd->htimer.data = (unsigned long) spitzkbd;
- spitzkbd->suspend_jiffies=jiffies;
-
- init_input_dev(&spitzkbd->input);
- spitzkbd->input.private = spitzkbd;
- spitzkbd->input.name = "Spitz Keyboard";
- spitzkbd->input.dev = dev;
- spitzkbd->input.phys = spitzkbd->phys;
- spitzkbd->input.id.bustype = BUS_HOST;
- spitzkbd->input.id.vendor = 0x0001;
- spitzkbd->input.id.product = 0x0001;
- spitzkbd->input.id.version = 0x0100;
- spitzkbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
- spitzkbd->input.keycode = spitzkbd->keycode;
- spitzkbd->input.keycodesize = sizeof(unsigned char);
- spitzkbd->input.keycodemax = ARRAY_SIZE(spitzkbd_keycode);
+ spitzkbd->suspend_jiffies = jiffies;
+
+ spitzkbd->input = input_dev;
+
+ input_dev->private = spitzkbd;
+ input_dev->name = "Spitz Keyboard";
+ input_dev->phys = spitzkbd->phys;
+ input_dev->cdev.dev = dev;
+
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
+ input_dev->keycode = spitzkbd->keycode;
+ input_dev->keycodesize = sizeof(unsigned char);
+ input_dev->keycodemax = ARRAY_SIZE(spitzkbd_keycode);
memcpy(spitzkbd->keycode, spitzkbd_keycode, sizeof(spitzkbd->keycode));
for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++)
- set_bit(spitzkbd->keycode[i], spitzkbd->input.keybit);
- clear_bit(0, spitzkbd->input.keybit);
- set_bit(SW_0, spitzkbd->input.swbit);
- set_bit(SW_1, spitzkbd->input.swbit);
+ set_bit(spitzkbd->keycode[i], input_dev->keybit);
+ clear_bit(0, input_dev->keybit);
+ set_bit(SW_0, input_dev->swbit);
+ set_bit(SW_1, input_dev->swbit);
+
+ input_register_device(input_dev);
- input_register_device(&spitzkbd->input);
mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
/* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
@@ -444,7 +453,7 @@ static int spitzkbd_remove(struct device *dev)
del_timer_sync(&spitzkbd->htimer);
del_timer_sync(&spitzkbd->timer);
- input_unregister_device(&spitzkbd->input);
+ input_unregister_device(spitzkbd->input);
kfree(spitzkbd);
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index 4bae5d89348d7d..b15b6d8d4f83c5 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -76,13 +76,14 @@ static unsigned char sunkbd_keycode[128] = {
struct sunkbd {
unsigned char keycode[128];
- struct input_dev dev;
+ struct input_dev *dev;
struct serio *serio;
struct work_struct tq;
wait_queue_head_t wait;
char name[64];
char phys[32];
char type;
+ unsigned char enabled;
volatile s8 reset;
volatile s8 layout;
};
@@ -124,10 +125,13 @@ static irqreturn_t sunkbd_interrupt(struct serio *serio,
break;
default:
+ if (!sunkbd->enabled)
+ break;
+
if (sunkbd->keycode[data & SUNKBD_KEY]) {
- input_regs(&sunkbd->dev, regs);
- input_report_key(&sunkbd->dev, sunkbd->keycode[data & SUNKBD_KEY], !(data & SUNKBD_RELEASE));
- input_sync(&sunkbd->dev);
+ input_regs(sunkbd->dev, regs);
+ input_report_key(sunkbd->dev, sunkbd->keycode[data & SUNKBD_KEY], !(data & SUNKBD_RELEASE));
+ input_sync(sunkbd->dev);
} else {
printk(KERN_WARNING "sunkbd.c: Unknown key (scancode %#x) %s.\n",
data & SUNKBD_KEY, data & SUNKBD_RELEASE ? "released" : "pressed");
@@ -184,7 +188,7 @@ static int sunkbd_initialize(struct sunkbd *sunkbd)
sunkbd->reset = -2;
sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_RESET);
wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
- if (sunkbd->reset <0)
+ if (sunkbd->reset < 0)
return -1;
sunkbd->type = sunkbd->reset;
@@ -213,10 +217,17 @@ static void sunkbd_reinit(void *data)
sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED);
sunkbd->serio->write(sunkbd->serio,
- (!!test_bit(LED_CAPSL, sunkbd->dev.led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev.led) << 2) |
- (!!test_bit(LED_COMPOSE, sunkbd->dev.led) << 1) | !!test_bit(LED_NUML, sunkbd->dev.led));
- sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev.snd));
- sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev.snd));
+ (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev->led) << 2) |
+ (!!test_bit(LED_COMPOSE, sunkbd->dev->led) << 1) | !!test_bit(LED_NUML, sunkbd->dev->led));
+ sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev->snd));
+ sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd));
+}
+
+static void sunkbd_enable(struct sunkbd *sunkbd, int enable)
+{
+ serio_pause_rx(sunkbd->serio);
+ sunkbd->enabled = 1;
+ serio_continue_rx(sunkbd->serio);
}
/*
@@ -226,70 +237,64 @@ static void sunkbd_reinit(void *data)
static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
{
struct sunkbd *sunkbd;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
int i;
- int err;
-
- if (!(sunkbd = kmalloc(sizeof(struct sunkbd), GFP_KERNEL)))
- return -ENOMEM;
- memset(sunkbd, 0, sizeof(struct sunkbd));
-
- init_input_dev(&sunkbd->dev);
- init_waitqueue_head(&sunkbd->wait);
-
- sunkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
- sunkbd->dev.ledbit[0] = BIT(LED_CAPSL) | BIT(LED_COMPOSE) | BIT(LED_SCROLLL) | BIT(LED_NUML);
- sunkbd->dev.sndbit[0] = BIT(SND_CLICK) | BIT(SND_BELL);
+ sunkbd = kzalloc(sizeof(struct sunkbd), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!sunkbd || !input_dev)
+ goto fail;
sunkbd->serio = serio;
-
+ sunkbd->dev = input_dev;
+ init_waitqueue_head(&sunkbd->wait);
INIT_WORK(&sunkbd->tq, sunkbd_reinit, sunkbd);
-
- sunkbd->dev.keycode = sunkbd->keycode;
- sunkbd->dev.keycodesize = sizeof(unsigned char);
- sunkbd->dev.keycodemax = ARRAY_SIZE(sunkbd_keycode);
-
- sunkbd->dev.event = sunkbd_event;
- sunkbd->dev.private = sunkbd;
+ snprintf(sunkbd->phys, sizeof(sunkbd->phys), "%s/input0", serio->phys);
serio_set_drvdata(serio, sunkbd);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(sunkbd);
- return err;
- }
+ if (err)
+ goto fail;
if (sunkbd_initialize(sunkbd) < 0) {
serio_close(serio);
- serio_set_drvdata(serio, NULL);
- kfree(sunkbd);
- return -ENODEV;
+ goto fail;
}
sprintf(sunkbd->name, "Sun Type %d keyboard", sunkbd->type);
-
memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode));
- for (i = 0; i < 128; i++)
- set_bit(sunkbd->keycode[i], sunkbd->dev.keybit);
- clear_bit(0, sunkbd->dev.keybit);
-
- sprintf(sunkbd->phys, "%s/input0", serio->phys);
-
- sunkbd->dev.name = sunkbd->name;
- sunkbd->dev.phys = sunkbd->phys;
- sunkbd->dev.id.bustype = BUS_RS232;
- sunkbd->dev.id.vendor = SERIO_SUNKBD;
- sunkbd->dev.id.product = sunkbd->type;
- sunkbd->dev.id.version = 0x0100;
- sunkbd->dev.dev = &serio->dev;
- input_register_device(&sunkbd->dev);
-
- printk(KERN_INFO "input: %s on %s\n", sunkbd->name, serio->phys);
+ input_dev->name = sunkbd->name;
+ input_dev->phys = sunkbd->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_SUNKBD;
+ input_dev->id.product = sunkbd->type;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = sunkbd;
+ input_dev->event = sunkbd_event;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
+ input_dev->ledbit[0] = BIT(LED_CAPSL) | BIT(LED_COMPOSE) | BIT(LED_SCROLLL) | BIT(LED_NUML);
+ input_dev->sndbit[0] = BIT(SND_CLICK) | BIT(SND_BELL);
+
+ input_dev->keycode = sunkbd->keycode;
+ input_dev->keycodesize = sizeof(unsigned char);
+ input_dev->keycodemax = ARRAY_SIZE(sunkbd_keycode);
+ for (i = 0; i < 128; i++)
+ set_bit(sunkbd->keycode[i], input_dev->keybit);
+ clear_bit(0, input_dev->keybit);
+ sunkbd_enable(sunkbd, 1);
+ input_register_device(sunkbd->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(sunkbd);
+ return err;
}
/*
@@ -299,7 +304,9 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
static void sunkbd_disconnect(struct serio *serio)
{
struct sunkbd *sunkbd = serio_get_drvdata(serio);
- input_unregister_device(&sunkbd->dev);
+
+ sunkbd_enable(sunkbd, 0);
+ input_unregister_device(sunkbd->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
kfree(sunkbd);
diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
index 19eaec7789d1d0..4135e3e16c51dd 100644
--- a/drivers/input/keyboard/xtkbd.c
+++ b/drivers/input/keyboard/xtkbd.c
@@ -56,11 +56,9 @@ static unsigned char xtkbd_keycode[256] = {
106
};
-static char *xtkbd_name = "XT Keyboard";
-
struct xtkbd {
unsigned char keycode[256];
- struct input_dev dev;
+ struct input_dev *dev;
struct serio *serio;
char phys[32];
};
@@ -77,9 +75,9 @@ static irqreturn_t xtkbd_interrupt(struct serio *serio,
default:
if (xtkbd->keycode[data & XTKBD_KEY]) {
- input_regs(&xtkbd->dev, regs);
- input_report_key(&xtkbd->dev, xtkbd->keycode[data & XTKBD_KEY], !(data & XTKBD_RELEASE));
- input_sync(&xtkbd->dev);
+ input_regs(xtkbd->dev, regs);
+ input_report_key(xtkbd->dev, xtkbd->keycode[data & XTKBD_KEY], !(data & XTKBD_RELEASE));
+ input_sync(xtkbd->dev);
} else {
printk(KERN_WARNING "xtkbd.c: Unknown key (scancode %#x) %s.\n",
data & XTKBD_KEY, data & XTKBD_RELEASE ? "released" : "pressed");
@@ -91,62 +89,60 @@ static irqreturn_t xtkbd_interrupt(struct serio *serio,
static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
{
struct xtkbd *xtkbd;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
int i;
- int err;
-
- if (!(xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(xtkbd, 0, sizeof(struct xtkbd));
- xtkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!xtkbd || !input_dev)
+ goto fail;
xtkbd->serio = serio;
+ xtkbd->dev = input_dev;
+ sprintf(xtkbd->phys, "%s/input0", serio->phys);
+ memcpy(xtkbd->keycode, xtkbd_keycode, sizeof(xtkbd->keycode));
- init_input_dev(&xtkbd->dev);
- xtkbd->dev.keycode = xtkbd->keycode;
- xtkbd->dev.keycodesize = sizeof(unsigned char);
- xtkbd->dev.keycodemax = ARRAY_SIZE(xtkbd_keycode);
- xtkbd->dev.private = xtkbd;
-
- serio_set_drvdata(serio, xtkbd);
+ input_dev->name = "XT Keyboard";
+ input_dev->phys = xtkbd->phys;
+ input_dev->id.bustype = BUS_XTKBD;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = xtkbd;
- err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(xtkbd);
- return err;
- }
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ input_dev->keycode = xtkbd->keycode;
+ input_dev->keycodesize = sizeof(unsigned char);
+ input_dev->keycodemax = ARRAY_SIZE(xtkbd_keycode);
- memcpy(xtkbd->keycode, xtkbd_keycode, sizeof(xtkbd->keycode));
for (i = 0; i < 255; i++)
- set_bit(xtkbd->keycode[i], xtkbd->dev.keybit);
- clear_bit(0, xtkbd->dev.keybit);
-
- sprintf(xtkbd->phys, "%s/input0", serio->phys);
-
- xtkbd->dev.name = xtkbd_name;
- xtkbd->dev.phys = xtkbd->phys;
- xtkbd->dev.id.bustype = BUS_XTKBD;
- xtkbd->dev.id.vendor = 0x0001;
- xtkbd->dev.id.product = 0x0001;
- xtkbd->dev.id.version = 0x0100;
- xtkbd->dev.dev = &serio->dev;
+ set_bit(xtkbd->keycode[i], input_dev->keybit);
+ clear_bit(0, input_dev->keybit);
- input_register_device(&xtkbd->dev);
+ serio_set_drvdata(serio, xtkbd);
- printk(KERN_INFO "input: %s on %s\n", xtkbd_name, serio->phys);
+ err = serio_open(serio, drv);
+ if (err)
+ goto fail;
+ input_register_device(xtkbd->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(xtkbd);
+ return err;
}
static void xtkbd_disconnect(struct serio *serio)
{
struct xtkbd *xtkbd = serio_get_drvdata(serio);
- input_unregister_device(&xtkbd->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(xtkbd->dev);
kfree(xtkbd);
}
diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c
index 64abdd98d482f8..04489ad7702a21 100644
--- a/drivers/input/misc/m68kspkr.c
+++ b/drivers/input/misc/m68kspkr.c
@@ -24,9 +24,7 @@ MODULE_AUTHOR("Richard Zidlicky <rz@linux-m68k.org>");
MODULE_DESCRIPTION("m68k beeper driver");
MODULE_LICENSE("GPL");
-static char m68kspkr_name[] = "m68k beeper";
-static char m68kspkr_phys[] = "m68k/generic";
-static struct input_dev m68kspkr_dev;
+static struct input_dev *m68kspkr_dev;
static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
@@ -51,32 +49,34 @@ static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int
static int __init m68kspkr_init(void)
{
- if (!mach_beep){
- printk("%s: no lowlevel beep support\n", m68kspkr_name);
- return -1;
+ if (!mach_beep) {
+ printk(KERN_INFO "m68kspkr: no lowlevel beep support\n");
+ return -ENODEV;
}
- m68kspkr_dev.evbit[0] = BIT(EV_SND);
- m68kspkr_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
- m68kspkr_dev.event = m68kspkr_event;
+ m68kspkr_dev = input_allocate_device();
+ if (!m68kspkr_dev)
+ return -ENOMEM;
- m68kspkr_dev.name = m68kspkr_name;
- m68kspkr_dev.phys = m68kspkr_phys;
- m68kspkr_dev.id.bustype = BUS_HOST;
- m68kspkr_dev.id.vendor = 0x001f;
- m68kspkr_dev.id.product = 0x0001;
- m68kspkr_dev.id.version = 0x0100;
+ m68kspkr_dev->name = "m68k beeper";
+ m68kspkr_dev->phys = "m68k/generic";
+ m68kspkr_dev->id.bustype = BUS_HOST;
+ m68kspkr_dev->id.vendor = 0x001f;
+ m68kspkr_dev->id.product = 0x0001;
+ m68kspkr_dev->id.version = 0x0100;
- input_register_device(&m68kspkr_dev);
+ m68kspkr_dev->evbit[0] = BIT(EV_SND);
+ m68kspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+ m68kspkr_dev->event = m68kspkr_event;
- printk(KERN_INFO "input: %s\n", m68kspkr_name);
+ input_register_device(m68kspkr_dev);
return 0;
}
static void __exit m68kspkr_exit(void)
{
- input_unregister_device(&m68kspkr_dev);
+ input_unregister_device(m68kspkr_dev);
}
module_init(m68kspkr_init);
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index 3013194f462b80..e34633c37fddc5 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -23,9 +23,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("PC Speaker beeper driver");
MODULE_LICENSE("GPL");
-static char pcspkr_name[] = "PC Speaker";
-static char pcspkr_phys[] = "isa0061/input0";
-static struct input_dev pcspkr_dev;
+static struct input_dev *pcspkr_dev;
static DEFINE_SPINLOCK(i8253_beep_lock);
@@ -68,27 +66,29 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c
static int __init pcspkr_init(void)
{
- pcspkr_dev.evbit[0] = BIT(EV_SND);
- pcspkr_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
- pcspkr_dev.event = pcspkr_event;
+ pcspkr_dev = input_allocate_device();
+ if (!pcspkr_dev)
+ return -ENOMEM;
- pcspkr_dev.name = pcspkr_name;
- pcspkr_dev.phys = pcspkr_phys;
- pcspkr_dev.id.bustype = BUS_ISA;
- pcspkr_dev.id.vendor = 0x001f;
- pcspkr_dev.id.product = 0x0001;
- pcspkr_dev.id.version = 0x0100;
+ pcspkr_dev->name = "PC Speaker";
+ pcspkr_dev->name = "isa0061/input0";
+ pcspkr_dev->id.bustype = BUS_ISA;
+ pcspkr_dev->id.vendor = 0x001f;
+ pcspkr_dev->id.product = 0x0001;
+ pcspkr_dev->id.version = 0x0100;
- input_register_device(&pcspkr_dev);
+ pcspkr_dev->evbit[0] = BIT(EV_SND);
+ pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+ pcspkr_dev->event = pcspkr_event;
- printk(KERN_INFO "input: %s\n", pcspkr_name);
+ input_register_device(pcspkr_dev);
return 0;
}
static void __exit pcspkr_exit(void)
{
- input_unregister_device(&pcspkr_dev);
+ input_unregister_device(pcspkr_dev);
/* turn off the speaker */
pcspkr_event(NULL, EV_SND, SND_BELL, 0);
}
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
index cdc3fb3d5f4644..5778220a18d239 100644
--- a/drivers/input/misc/sparcspkr.c
+++ b/drivers/input/misc/sparcspkr.c
@@ -17,28 +17,24 @@
#endif
MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
-MODULE_DESCRIPTION("PC Speaker beeper driver");
+MODULE_DESCRIPTION("Sparc Speaker beeper driver");
MODULE_LICENSE("GPL");
static unsigned long beep_iobase;
-
-static char *sparcspkr_isa_name = "Sparc ISA Speaker";
-static char *sparcspkr_ebus_name = "Sparc EBUS Speaker";
-static char *sparcspkr_phys = "sparc/input0";
-static struct input_dev sparcspkr_dev;
+static struct input_dev *sparcspkr_dev;
DEFINE_SPINLOCK(beep_lock);
static void __init init_sparcspkr_struct(void)
{
- sparcspkr_dev.evbit[0] = BIT(EV_SND);
- sparcspkr_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
-
- sparcspkr_dev.phys = sparcspkr_phys;
- sparcspkr_dev.id.bustype = BUS_ISA;
- sparcspkr_dev.id.vendor = 0x001f;
- sparcspkr_dev.id.product = 0x0001;
- sparcspkr_dev.id.version = 0x0100;
+ sparcspkr_dev->evbit[0] = BIT(EV_SND);
+ sparcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+
+ sparcspkr_dev->phys = "sparc/input0";
+ sparcspkr_dev->id.bustype = BUS_ISA;
+ sparcspkr_dev->id.vendor = 0x001f;
+ sparcspkr_dev->id.product = 0x0001;
+ sparcspkr_dev->id.version = 0x0100;
}
static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
@@ -84,14 +80,15 @@ static int __init init_ebus_beep(struct linux_ebus_device *edev)
{
beep_iobase = edev->resource[0].start;
- init_sparcspkr_struct();
+ sparcspkr_dev = input_allocate_device();
+ if (!sparcspkr_dev)
+ return -ENOMEM;
- sparcspkr_dev.name = sparcspkr_ebus_name;
- sparcspkr_dev.event = ebus_spkr_event;
+ sparcspkr_dev->name = "Sparc EBUS Speaker";
+ sparcspkr_dev->event = ebus_spkr_event;
- input_register_device(&sparcspkr_dev);
+ input_register_device(sparcspkr_dev);
- printk(KERN_INFO "input: %s\n", sparcspkr_ebus_name);
return 0;
}
@@ -137,15 +134,17 @@ static int __init init_isa_beep(struct sparc_isa_device *isa_dev)
{
beep_iobase = isa_dev->resource.start;
+ sparcspkr_dev = input_allocate_device();
+ if (!sparcspkr_dev)
+ return -ENOMEM;
+
init_sparcspkr_struct();
- sparcspkr_dev.name = sparcspkr_isa_name;
- sparcspkr_dev.event = isa_spkr_event;
- sparcspkr_dev.id.bustype = BUS_ISA;
+ sparcspkr_dev->name = "Sparc ISA Speaker";
+ sparcspkr_dev->event = isa_spkr_event;
input_register_device(&sparcspkr_dev);
- printk(KERN_INFO "input: %s\n", sparcspkr_isa_name);
return 0;
}
#endif
@@ -182,7 +181,7 @@ static int __init sparcspkr_init(void)
static void __exit sparcspkr_exit(void)
{
- input_unregister_device(&sparcspkr_dev);
+ input_unregister_device(sparcspkr_dev);
}
module_init(sparcspkr_init);
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index b20783f9748adb..4acc7fd4cd0fdc 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -79,8 +79,8 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
{
struct alps_data *priv = psmouse->private;
unsigned char *packet = psmouse->packet;
- struct input_dev *dev = &psmouse->dev;
- struct input_dev *dev2 = &priv->dev2;
+ struct input_dev *dev = psmouse->dev;
+ struct input_dev *dev2 = priv->dev2;
int x, y, z, ges, fin, left, right, middle;
int back = 0, forward = 0;
@@ -379,20 +379,24 @@ static int alps_reconnect(struct psmouse *psmouse)
static void alps_disconnect(struct psmouse *psmouse)
{
struct alps_data *priv = psmouse->private;
+
psmouse_reset(psmouse);
- input_unregister_device(&priv->dev2);
+ input_unregister_device(priv->dev2);
kfree(priv);
}
int alps_init(struct psmouse *psmouse)
{
struct alps_data *priv;
+ struct input_dev *dev1 = psmouse->dev, *dev2;
int version;
- psmouse->private = priv = kmalloc(sizeof(struct alps_data), GFP_KERNEL);
- if (!priv)
+ psmouse->private = priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
+ dev2 = input_allocate_device();
+ if (!priv || !dev2)
goto init_fail;
- memset(priv, 0, sizeof(struct alps_data));
+
+ priv->dev2 = dev2;
if (!(priv->i = alps_get_model(psmouse, &version)))
goto init_fail;
@@ -411,41 +415,39 @@ int alps_init(struct psmouse *psmouse)
if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 0))
goto init_fail;
- psmouse->dev.evbit[LONG(EV_KEY)] |= BIT(EV_KEY);
- psmouse->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
- psmouse->dev.keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER);
- psmouse->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ dev1->evbit[LONG(EV_KEY)] |= BIT(EV_KEY);
+ dev1->keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
+ dev1->keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER);
+ dev1->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- psmouse->dev.evbit[LONG(EV_ABS)] |= BIT(EV_ABS);
- input_set_abs_params(&psmouse->dev, ABS_X, 0, 1023, 0, 0);
- input_set_abs_params(&psmouse->dev, ABS_Y, 0, 767, 0, 0);
- input_set_abs_params(&psmouse->dev, ABS_PRESSURE, 0, 127, 0, 0);
+ dev1->evbit[LONG(EV_ABS)] |= BIT(EV_ABS);
+ input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0);
+ input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0);
+ input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
if (priv->i->flags & ALPS_WHEEL) {
- psmouse->dev.evbit[LONG(EV_REL)] |= BIT(EV_REL);
- psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL);
+ dev1->evbit[LONG(EV_REL)] |= BIT(EV_REL);
+ dev1->relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL);
}
if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
- psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD);
- psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
+ dev1->keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD);
+ dev1->keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
}
sprintf(priv->phys, "%s/input1", psmouse->ps2dev.serio->phys);
- priv->dev2.phys = priv->phys;
- priv->dev2.name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse";
- priv->dev2.id.bustype = BUS_I8042;
- priv->dev2.id.vendor = 0x0002;
- priv->dev2.id.product = PSMOUSE_ALPS;
- priv->dev2.id.version = 0x0000;
-
- priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
- priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ dev2->phys = priv->phys;
+ dev2->name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse";
+ dev2->id.bustype = BUS_I8042;
+ dev2->id.vendor = 0x0002;
+ dev2->id.product = PSMOUSE_ALPS;
+ dev2->id.version = 0x0000;
- input_register_device(&priv->dev2);
+ dev2->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ dev2->relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
+ dev2->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- printk(KERN_INFO "input: %s on %s\n", priv->dev2.name, psmouse->ps2dev.serio->phys);
+ input_register_device(priv->dev2);
psmouse->protocol_handler = alps_process_byte;
psmouse->disconnect = alps_disconnect;
@@ -455,6 +457,7 @@ int alps_init(struct psmouse *psmouse)
return 0;
init_fail:
+ input_free_device(dev2);
kfree(priv);
return -1;
}
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index aba103dd65b79a..e428f8d5d12ece 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -22,7 +22,7 @@ struct alps_model_info {
};
struct alps_data {
- struct input_dev dev2; /* Relative device */
+ struct input_dev *dev2; /* Relative device */
char name[32]; /* Name */
char phys[32]; /* Phys */
struct alps_model_info *i; /* Info */
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c
index e994849efb8fca..d13d4c8fe3c5b2 100644
--- a/drivers/input/mouse/amimouse.c
+++ b/drivers/input/mouse/amimouse.c
@@ -34,10 +34,7 @@ MODULE_DESCRIPTION("Amiga mouse driver");
MODULE_LICENSE("GPL");
static int amimouse_lastx, amimouse_lasty;
-static struct input_dev amimouse_dev;
-
-static char *amimouse_name = "Amiga mouse";
-static char *amimouse_phys = "amimouse/input0";
+static struct input_dev *amimouse_dev;
static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
{
@@ -62,16 +59,16 @@ static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
potgor = custom.potgor;
- input_regs(&amimouse_dev, fp);
+ input_regs(amimouse_dev, fp);
- input_report_rel(&amimouse_dev, REL_X, dx);
- input_report_rel(&amimouse_dev, REL_Y, dy);
+ input_report_rel(amimouse_dev, REL_X, dx);
+ input_report_rel(amimouse_dev, REL_Y, dy);
- input_report_key(&amimouse_dev, BTN_LEFT, ciaa.pra & 0x40);
- input_report_key(&amimouse_dev, BTN_MIDDLE, potgor & 0x0100);
- input_report_key(&amimouse_dev, BTN_RIGHT, potgor & 0x0400);
+ input_report_key(amimouse_dev, BTN_LEFT, ciaa.pra & 0x40);
+ input_report_key(amimouse_dev, BTN_MIDDLE, potgor & 0x0100);
+ input_report_key(amimouse_dev, BTN_RIGHT, potgor & 0x0400);
- input_sync(&amimouse_dev);
+ input_sync(amimouse_dev);
return IRQ_HANDLED;
}
@@ -103,28 +100,30 @@ static int __init amimouse_init(void)
if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE))
return -ENODEV;
- amimouse_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- amimouse_dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
- amimouse_dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- amimouse_dev.open = amimouse_open;
- amimouse_dev.close = amimouse_close;
+ if (!(amimouse_dev = input_allocate_device()))
+ return -ENOMEM;
+
+ amimouse_dev->name = "Amiga mouse";
+ amimouse_dev->phys = "amimouse/input0";
+ amimouse_dev->id.bustype = BUS_AMIGA;
+ amimouse_dev->id.vendor = 0x0001;
+ amimouse_dev->id.product = 0x0002;
+ amimouse_dev->id.version = 0x0100;
- amimouse_dev.name = amimouse_name;
- amimouse_dev.phys = amimouse_phys;
- amimouse_dev.id.bustype = BUS_AMIGA;
- amimouse_dev.id.vendor = 0x0001;
- amimouse_dev.id.product = 0x0002;
- amimouse_dev.id.version = 0x0100;
+ amimouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ amimouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ amimouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ amimouse_dev->open = amimouse_open;
+ amimouse_dev->close = amimouse_close;
- input_register_device(&amimouse_dev);
+ input_register_device(amimouse_dev);
- printk(KERN_INFO "input: %s at joy0dat\n", amimouse_name);
return 0;
}
static void __exit amimouse_exit(void)
{
- input_unregister_device(&amimouse_dev);
+ input_unregister_device(amimouse_dev);
}
module_init(amimouse_init);
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c
index bc22849c6c79ef..c2bf2ed07dc693 100644
--- a/drivers/input/mouse/hil_ptr.c
+++ b/drivers/input/mouse/hil_ptr.c
@@ -196,7 +196,7 @@ static irqreturn_t hil_ptr_interrupt(struct serio *serio,
hil_packet packet;
int idx;
- ptr = (struct hil_ptr *)serio->private;
+ ptr = serio_get_drvdata(serio);
if (ptr == NULL) {
BUG();
return IRQ_HANDLED;
@@ -227,7 +227,7 @@ static void hil_ptr_disconnect(struct serio *serio)
{
struct hil_ptr *ptr;
- ptr = (struct hil_ptr *)serio->private;
+ ptr = serio_get_drvdata(serio);
if (ptr == NULL) {
BUG();
return;
@@ -238,21 +238,19 @@ static void hil_ptr_disconnect(struct serio *serio)
kfree(ptr);
}
-static void hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
+static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
{
struct hil_ptr *ptr;
char *txt;
unsigned int i, naxsets, btntype;
uint8_t did, *idd;
- if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return;
-
- if (!(ptr = kmalloc(sizeof(struct hil_ptr), GFP_KERNEL))) return;
+ if (!(ptr = kmalloc(sizeof(struct hil_ptr), GFP_KERNEL))) return -ENOMEM;
memset(ptr, 0, sizeof(struct hil_ptr));
if (serio_open(serio, driver)) goto bail0;
- serio->private = ptr;
+ serio_set_drvdata(serio, ptr);
ptr->serio = serio;
ptr->dev.private = ptr;
@@ -380,23 +378,34 @@ static void hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
(btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad",
did);
- return;
+ return 0;
bail1:
serio_close(serio);
bail0:
kfree(ptr);
- return;
+ serio_set_drvdata(serio, NULL);
+ return -ENODEV;
}
+static struct serio_device_id hil_ptr_ids[] = {
+ {
+ .type = SERIO_HIL_MLC,
+ .proto = SERIO_HIL,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
static struct serio_driver hil_ptr_serio_driver = {
.driver = {
.name = "hil_ptr",
},
.description = "HP HIL mouse/tablet driver",
- .connect = hil_ptr_connect,
- .disconnect = hil_ptr_disconnect,
- .interrupt = hil_ptr_interrupt
+ .id_table = hil_ptr_ids,
+ .connect = hil_ptr_connect,
+ .disconnect = hil_ptr_disconnect,
+ .interrupt = hil_ptr_interrupt
};
static int __init hil_ptr_init(void)
diff --git a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c
index 1f62c013401067..afc66f56df43b5 100644
--- a/drivers/input/mouse/inport.c
+++ b/drivers/input/mouse/inport.c
@@ -87,40 +87,7 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)");
__obsolete_setup("inport_irq=");
-static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-
-static int inport_open(struct input_dev *dev)
-{
- if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL))
- return -EBUSY;
- outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
- outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
-
- return 0;
-}
-
-static void inport_close(struct input_dev *dev)
-{
- outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
- outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
- free_irq(inport_irq, NULL);
-}
-
-static struct input_dev inport_dev = {
- .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
- .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
- .relbit = { BIT(REL_X) | BIT(REL_Y) },
- .open = inport_open,
- .close = inport_close,
- .name = INPORT_NAME,
- .phys = "isa023c/input0",
- .id = {
- .bustype = BUS_ISA,
- .vendor = INPORT_VENDOR,
- .product = 0x0001,
- .version = 0x0100,
- },
-};
+static struct input_dev *inport_dev;
static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -129,31 +96,48 @@ static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_HOLD | INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
- input_regs(&inport_dev, regs);
+ input_regs(inport_dev, regs);
outb(INPORT_REG_X, INPORT_CONTROL_PORT);
- input_report_rel(&inport_dev, REL_X, inb(INPORT_DATA_PORT));
+ input_report_rel(inport_dev, REL_X, inb(INPORT_DATA_PORT));
outb(INPORT_REG_Y, INPORT_CONTROL_PORT);
- input_report_rel(&inport_dev, REL_Y, inb(INPORT_DATA_PORT));
+ input_report_rel(inport_dev, REL_Y, inb(INPORT_DATA_PORT));
outb(INPORT_REG_BTNS, INPORT_CONTROL_PORT);
buttons = inb(INPORT_DATA_PORT);
- input_report_key(&inport_dev, BTN_MIDDLE, buttons & 1);
- input_report_key(&inport_dev, BTN_LEFT, buttons & 2);
- input_report_key(&inport_dev, BTN_RIGHT, buttons & 4);
+ input_report_key(inport_dev, BTN_MIDDLE, buttons & 1);
+ input_report_key(inport_dev, BTN_LEFT, buttons & 2);
+ input_report_key(inport_dev, BTN_RIGHT, buttons & 4);
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
- input_sync(&inport_dev);
+ input_sync(inport_dev);
return IRQ_HANDLED;
}
+static int inport_open(struct input_dev *dev)
+{
+ if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL))
+ return -EBUSY;
+ outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
+ outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
+
+ return 0;
+}
+
+static void inport_close(struct input_dev *dev)
+{
+ outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
+ outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
+ free_irq(inport_irq, NULL);
+}
+
static int __init inport_init(void)
{
- unsigned char a,b,c;
+ unsigned char a, b, c;
if (!request_region(INPORT_BASE, INPORT_EXTENT, "inport")) {
printk(KERN_ERR "inport.c: Can't allocate ports at %#x\n", INPORT_BASE);
@@ -163,26 +147,44 @@ static int __init inport_init(void)
a = inb(INPORT_SIGNATURE_PORT);
b = inb(INPORT_SIGNATURE_PORT);
c = inb(INPORT_SIGNATURE_PORT);
- if (( a == b ) || ( a != c )) {
+ if (a == b || a != c) {
release_region(INPORT_BASE, INPORT_EXTENT);
printk(KERN_ERR "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE);
return -ENODEV;
}
+ if (!(inport_dev = input_allocate_device())) {
+ printk(KERN_ERR "inport.c: Not enough memory for input device\n");
+ release_region(INPORT_BASE, INPORT_EXTENT);
+ return -ENOMEM;
+ }
+
+ inport_dev->name = INPORT_NAME;
+ inport_dev->phys = "isa023c/input0";
+ inport_dev->id.bustype = BUS_ISA;
+ inport_dev->id.vendor = INPORT_VENDOR;
+ inport_dev->id.product = 0x0001;
+ inport_dev->id.version = 0x0100;
+
+ inport_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ inport_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ inport_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+
+ inport_dev->open = inport_open;
+ inport_dev->close = inport_close;
+
outb(INPORT_RESET, INPORT_CONTROL_PORT);
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
- input_register_device(&inport_dev);
-
- printk(KERN_INFO "input: " INPORT_NAME " at %#x irq %d\n", INPORT_BASE, inport_irq);
+ input_register_device(inport_dev);
return 0;
}
static void __exit inport_exit(void)
{
- input_unregister_device(&inport_dev);
+ input_unregister_device(inport_dev);
release_region(INPORT_BASE, INPORT_EXTENT);
}
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
index bd9df9b2832599..55991424ac914e 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -34,7 +34,7 @@ static struct dmi_system_id lifebook_dmi_table[] = {
static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
{
unsigned char *packet = psmouse->packet;
- struct input_dev *dev = &psmouse->dev;
+ struct input_dev *dev = psmouse->dev;
if (psmouse->pktcnt != 3)
return PSMOUSE_GOOD_DATA;
@@ -113,15 +113,17 @@ int lifebook_detect(struct psmouse *psmouse, int set_properties)
int lifebook_init(struct psmouse *psmouse)
{
+ struct input_dev *input_dev = psmouse->dev;
+
if (lifebook_absolute_mode(psmouse))
return -1;
- psmouse->dev.evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
- psmouse->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- psmouse->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
- psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
- input_set_abs_params(&psmouse->dev, ABS_X, 0, 1024, 0, 0);
- input_set_abs_params(&psmouse->dev, ABS_Y, 0, 1024, 0, 0);
+ input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
+ input_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ input_set_abs_params(input_dev, ABS_X, 0, 1024, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, 1024, 0, 0);
psmouse->protocol_handler = lifebook_process_byte;
psmouse->set_resolution = lifebook_set_resolution;
diff --git a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c
index 8b5243167227ba..9c7ce38806d7ca 100644
--- a/drivers/input/mouse/logibm.c
+++ b/drivers/input/mouse/logibm.c
@@ -77,39 +77,7 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)");
__obsolete_setup("logibm_irq=");
-static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-
-static int logibm_open(struct input_dev *dev)
-{
- if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) {
- printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq);
- return -EBUSY;
- }
- outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT);
- return 0;
-}
-
-static void logibm_close(struct input_dev *dev)
-{
- outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
- free_irq(logibm_irq, NULL);
-}
-
-static struct input_dev logibm_dev = {
- .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
- .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
- .relbit = { BIT(REL_X) | BIT(REL_Y) },
- .open = logibm_open,
- .close = logibm_close,
- .name = "Logitech bus mouse",
- .phys = "isa023c/input0",
- .id = {
- .bustype = BUS_ISA,
- .vendor = 0x0003,
- .product = 0x0001,
- .version = 0x0100,
- },
-};
+static struct input_dev *logibm_dev;
static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -127,18 +95,34 @@ static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs)
dy |= (buttons & 0xf) << 4;
buttons = ~buttons >> 5;
- input_regs(&logibm_dev, regs);
- input_report_rel(&logibm_dev, REL_X, dx);
- input_report_rel(&logibm_dev, REL_Y, dy);
- input_report_key(&logibm_dev, BTN_RIGHT, buttons & 1);
- input_report_key(&logibm_dev, BTN_MIDDLE, buttons & 2);
- input_report_key(&logibm_dev, BTN_LEFT, buttons & 4);
- input_sync(&logibm_dev);
+ input_regs(logibm_dev, regs);
+ input_report_rel(logibm_dev, REL_X, dx);
+ input_report_rel(logibm_dev, REL_Y, dy);
+ input_report_key(logibm_dev, BTN_RIGHT, buttons & 1);
+ input_report_key(logibm_dev, BTN_MIDDLE, buttons & 2);
+ input_report_key(logibm_dev, BTN_LEFT, buttons & 4);
+ input_sync(logibm_dev);
outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT);
return IRQ_HANDLED;
}
+static int logibm_open(struct input_dev *dev)
+{
+ if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) {
+ printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq);
+ return -EBUSY;
+ }
+ outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT);
+ return 0;
+}
+
+static void logibm_close(struct input_dev *dev)
+{
+ outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
+ free_irq(logibm_irq, NULL);
+}
+
static int __init logibm_init(void)
{
if (!request_region(LOGIBM_BASE, LOGIBM_EXTENT, "logibm")) {
@@ -159,16 +143,34 @@ static int __init logibm_init(void)
outb(LOGIBM_DEFAULT_MODE, LOGIBM_CONFIG_PORT);
outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
- input_register_device(&logibm_dev);
+ if (!(logibm_dev = input_allocate_device())) {
+ printk(KERN_ERR "logibm.c: Not enough memory for input device\n");
+ release_region(LOGIBM_BASE, LOGIBM_EXTENT);
+ return -ENOMEM;
+ }
+
+ logibm_dev->name = "Logitech bus mouse";
+ logibm_dev->phys = "isa023c/input0";
+ logibm_dev->id.bustype = BUS_ISA;
+ logibm_dev->id.vendor = 0x0003;
+ logibm_dev->id.product = 0x0001;
+ logibm_dev->id.version = 0x0100;
+
+ logibm_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ logibm_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ logibm_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+
+ logibm_dev->open = logibm_open;
+ logibm_dev->close = logibm_close;
- printk(KERN_INFO "input: Logitech bus mouse at %#x irq %d\n", LOGIBM_BASE, logibm_irq);
+ input_register_device(logibm_dev);
return 0;
}
static void __exit logibm_exit(void)
{
- input_unregister_device(&logibm_dev);
+ input_unregister_device(logibm_dev);
release_region(LOGIBM_BASE, LOGIBM_EXTENT);
}
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 7df96525222e5d..0f69ff46c1ae1c 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -40,7 +40,7 @@ struct ps2pp_info {
static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
{
- struct input_dev *dev = &psmouse->dev;
+ struct input_dev *dev = psmouse->dev;
unsigned char *packet = psmouse->packet;
if (psmouse->pktcnt < 3)
@@ -257,25 +257,27 @@ static struct ps2pp_info *get_model_info(unsigned char model)
static void ps2pp_set_model_properties(struct psmouse *psmouse, struct ps2pp_info *model_info,
int using_ps2pp)
{
+ struct input_dev *input_dev = psmouse->dev;
+
if (model_info->features & PS2PP_SIDE_BTN)
- set_bit(BTN_SIDE, psmouse->dev.keybit);
+ set_bit(BTN_SIDE, input_dev->keybit);
if (model_info->features & PS2PP_EXTRA_BTN)
- set_bit(BTN_EXTRA, psmouse->dev.keybit);
+ set_bit(BTN_EXTRA, input_dev->keybit);
if (model_info->features & PS2PP_TASK_BTN)
- set_bit(BTN_TASK, psmouse->dev.keybit);
+ set_bit(BTN_TASK, input_dev->keybit);
if (model_info->features & PS2PP_NAV_BTN) {
- set_bit(BTN_FORWARD, psmouse->dev.keybit);
- set_bit(BTN_BACK, psmouse->dev.keybit);
+ set_bit(BTN_FORWARD, input_dev->keybit);
+ set_bit(BTN_BACK, input_dev->keybit);
}
if (model_info->features & PS2PP_WHEEL)
- set_bit(REL_WHEEL, psmouse->dev.relbit);
+ set_bit(REL_WHEEL, input_dev->relbit);
if (model_info->features & PS2PP_HWHEEL)
- set_bit(REL_HWHEEL, psmouse->dev.relbit);
+ set_bit(REL_HWHEEL, input_dev->relbit);
switch (model_info->kind) {
case PS2PP_KIND_WHEEL:
@@ -387,7 +389,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
}
if (buttons < 3)
- clear_bit(BTN_MIDDLE, psmouse->dev.keybit);
+ clear_bit(BTN_MIDDLE, psmouse->dev->keybit);
if (model_info)
ps2pp_set_model_properties(psmouse, model_info, use_ps2pp);
diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c
index e90c60cbbf05a0..b5b34fe4fee89a 100644
--- a/drivers/input/mouse/maplemouse.c
+++ b/drivers/input/mouse/maplemouse.c
@@ -41,13 +41,12 @@ static int dc_mouse_connect(struct maple_device *dev)
unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
struct input_dev *input_dev;
- if (!(input_dev = kmalloc(sizeof(struct input_dev), GFP_KERNEL)))
- return -1;
+ dev->private_data = input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
dev->private_data = input_dev;
- memset(input_dev, 0, sizeof(struct dc_mouse));
- init_input_dev(input_dev);
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
@@ -59,8 +58,6 @@ static int dc_mouse_connect(struct maple_device *dev)
maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE);
- printk(KERN_INFO "input: mouse(0x%lx): %s\n", data, input_dev->name);
-
return 0;
}
@@ -70,7 +67,6 @@ static void dc_mouse_disconnect(struct maple_device *dev)
struct input_dev *input_dev = dev->private_data;
input_unregister_device(input_dev);
- kfree(input_dev);
}
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c
index 93393d5c007800..d284ea7121516c 100644
--- a/drivers/input/mouse/pc110pad.c
+++ b/drivers/input/mouse/pc110pad.c
@@ -53,13 +53,10 @@ MODULE_LICENSE("GPL");
static int pc110pad_irq = 10;
static int pc110pad_io = 0x15e0;
-static struct input_dev pc110pad_dev;
+static struct input_dev *pc110pad_dev;
static int pc110pad_data[3];
static int pc110pad_count;
-static char *pc110pad_name = "IBM PC110 TouchPad";
-static char *pc110pad_phys = "isa15e0/input0";
-
static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs)
{
int value = inb_p(pc110pad_io);
@@ -74,14 +71,14 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs)
if (pc110pad_count < 3)
return IRQ_HANDLED;
- input_regs(&pc110pad_dev, regs);
- input_report_key(&pc110pad_dev, BTN_TOUCH,
+ input_regs(pc110pad_dev, regs);
+ input_report_key(pc110pad_dev, BTN_TOUCH,
pc110pad_data[0] & 0x01);
- input_report_abs(&pc110pad_dev, ABS_X,
+ input_report_abs(pc110pad_dev, ABS_X,
pc110pad_data[1] | ((pc110pad_data[0] << 3) & 0x80) | ((pc110pad_data[0] << 1) & 0x100));
- input_report_abs(&pc110pad_dev, ABS_Y,
+ input_report_abs(pc110pad_dev, ABS_Y,
pc110pad_data[2] | ((pc110pad_data[0] << 4) & 0x80));
- input_sync(&pc110pad_dev);
+ input_sync(pc110pad_dev);
pc110pad_count = 0;
return IRQ_HANDLED;
@@ -94,9 +91,9 @@ static void pc110pad_close(struct input_dev *dev)
static int pc110pad_open(struct input_dev *dev)
{
- pc110pad_interrupt(0,NULL,NULL);
- pc110pad_interrupt(0,NULL,NULL);
- pc110pad_interrupt(0,NULL,NULL);
+ pc110pad_interrupt(0, NULL, NULL);
+ pc110pad_interrupt(0, NULL, NULL);
+ pc110pad_interrupt(0, NULL, NULL);
outb(PC110PAD_ON, pc110pad_io + 2);
pc110pad_count = 0;
@@ -127,45 +124,46 @@ static int __init pc110pad_init(void)
outb(PC110PAD_OFF, pc110pad_io + 2);
- if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", NULL))
- {
+ if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", NULL)) {
release_region(pc110pad_io, 4);
printk(KERN_ERR "pc110pad: Unable to get irq %d.\n", pc110pad_irq);
return -EBUSY;
}
- pc110pad_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- pc110pad_dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
- pc110pad_dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ if (!(pc110pad_dev = input_allocate_device())) {
+ free_irq(pc110pad_irq, NULL);
+ release_region(pc110pad_io, 4);
+ printk(KERN_ERR "pc110pad: Not enough memory.\n");
+ return -ENOMEM;
+ }
- pc110pad_dev.absmax[ABS_X] = 0x1ff;
- pc110pad_dev.absmax[ABS_Y] = 0x0ff;
+ pc110pad_dev->name = "IBM PC110 TouchPad";
+ pc110pad_dev->phys = "isa15e0/input0";
+ pc110pad_dev->id.bustype = BUS_ISA;
+ pc110pad_dev->id.vendor = 0x0003;
+ pc110pad_dev->id.product = 0x0001;
+ pc110pad_dev->id.version = 0x0100;
- pc110pad_dev.open = pc110pad_open;
- pc110pad_dev.close = pc110pad_close;
+ pc110pad_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ pc110pad_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+ pc110pad_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
- pc110pad_dev.name = pc110pad_name;
- pc110pad_dev.phys = pc110pad_phys;
- pc110pad_dev.id.bustype = BUS_ISA;
- pc110pad_dev.id.vendor = 0x0003;
- pc110pad_dev.id.product = 0x0001;
- pc110pad_dev.id.version = 0x0100;
+ pc110pad_dev->absmax[ABS_X] = 0x1ff;
+ pc110pad_dev->absmax[ABS_Y] = 0x0ff;
- input_register_device(&pc110pad_dev);
+ pc110pad_dev->open = pc110pad_open;
+ pc110pad_dev->close = pc110pad_close;
- printk(KERN_INFO "input: %s at %#x irq %d\n",
- pc110pad_name, pc110pad_io, pc110pad_irq);
+ input_register_device(pc110pad_dev);
return 0;
}
static void __exit pc110pad_exit(void)
{
- input_unregister_device(&pc110pad_dev);
-
outb(PC110PAD_OFF, pc110pad_io + 2);
-
free_irq(pc110pad_irq, NULL);
+ input_unregister_device(pc110pad_dev);
release_region(pc110pad_io, 4);
}
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index af24313ff5bb14..6ee9999a2eaa3f 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -114,7 +114,7 @@ struct psmouse_protocol {
static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
{
- struct input_dev *dev = &psmouse->dev;
+ struct input_dev *dev = psmouse->dev;
unsigned char *packet = psmouse->packet;
if (psmouse->pktcnt < psmouse->pktsize)
@@ -333,12 +333,11 @@ static int genius_detect(struct psmouse *psmouse, int set_properties)
return -1;
if (set_properties) {
- set_bit(BTN_EXTRA, psmouse->dev.keybit);
- set_bit(BTN_SIDE, psmouse->dev.keybit);
- set_bit(REL_WHEEL, psmouse->dev.relbit);
+ set_bit(BTN_EXTRA, psmouse->dev->keybit);
+ set_bit(BTN_SIDE, psmouse->dev->keybit);
+ set_bit(REL_WHEEL, psmouse->dev->relbit);
psmouse->vendor = "Genius";
- psmouse->name = "Wheel Mouse";
psmouse->pktsize = 4;
}
@@ -365,8 +364,8 @@ static int intellimouse_detect(struct psmouse *psmouse, int set_properties)
return -1;
if (set_properties) {
- set_bit(BTN_MIDDLE, psmouse->dev.keybit);
- set_bit(REL_WHEEL, psmouse->dev.relbit);
+ set_bit(BTN_MIDDLE, psmouse->dev->keybit);
+ set_bit(REL_WHEEL, psmouse->dev->relbit);
if (!psmouse->vendor) psmouse->vendor = "Generic";
if (!psmouse->name) psmouse->name = "Wheel Mouse";
@@ -398,10 +397,10 @@ static int im_explorer_detect(struct psmouse *psmouse, int set_properties)
return -1;
if (set_properties) {
- set_bit(BTN_MIDDLE, psmouse->dev.keybit);
- set_bit(REL_WHEEL, psmouse->dev.relbit);
- set_bit(BTN_SIDE, psmouse->dev.keybit);
- set_bit(BTN_EXTRA, psmouse->dev.keybit);
+ set_bit(BTN_MIDDLE, psmouse->dev->keybit);
+ set_bit(REL_WHEEL, psmouse->dev->relbit);
+ set_bit(BTN_SIDE, psmouse->dev->keybit);
+ set_bit(BTN_EXTRA, psmouse->dev->keybit);
if (!psmouse->vendor) psmouse->vendor = "Generic";
if (!psmouse->name) psmouse->name = "Explorer Mouse";
@@ -433,7 +432,7 @@ static int thinking_detect(struct psmouse *psmouse, int set_properties)
return -1;
if (set_properties) {
- set_bit(BTN_EXTRA, psmouse->dev.keybit);
+ set_bit(BTN_EXTRA, psmouse->dev->keybit);
psmouse->vendor = "Kensington";
psmouse->name = "ThinkingMouse";
@@ -839,9 +838,9 @@ static void psmouse_disconnect(struct serio *serio)
psmouse_set_state(psmouse, PSMOUSE_IGNORE);
- input_unregister_device(&psmouse->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(psmouse->dev);
kfree(psmouse);
if (parent)
@@ -852,16 +851,14 @@ static void psmouse_disconnect(struct serio *serio)
static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_protocol *proto)
{
- memset(&psmouse->dev, 0, sizeof(struct input_dev));
+ struct input_dev *input_dev = psmouse->dev;
- init_input_dev(&psmouse->dev);
+ input_dev->private = psmouse;
+ input_dev->cdev.dev = &psmouse->ps2dev.serio->dev;
- psmouse->dev.private = psmouse;
- psmouse->dev.dev = &psmouse->ps2dev.serio->dev;
-
- psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
psmouse->set_rate = psmouse_set_rate;
psmouse->set_resolution = psmouse_set_resolution;
@@ -883,12 +880,12 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto
sprintf(psmouse->devname, "%s %s %s",
psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name);
- psmouse->dev.name = psmouse->devname;
- psmouse->dev.phys = psmouse->phys;
- psmouse->dev.id.bustype = BUS_I8042;
- psmouse->dev.id.vendor = 0x0002;
- psmouse->dev.id.product = psmouse->type;
- psmouse->dev.id.version = psmouse->model;
+ input_dev->name = psmouse->devname;
+ input_dev->phys = psmouse->phys;
+ input_dev->id.bustype = BUS_I8042;
+ input_dev->id.vendor = 0x0002;
+ input_dev->id.product = psmouse->type;
+ input_dev->id.version = psmouse->model;
return 0;
}
@@ -900,7 +897,8 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto
static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
{
struct psmouse *psmouse, *parent = NULL;
- int retval;
+ struct input_dev *input_dev;
+ int retval = -ENOMEM;
down(&psmouse_sem);
@@ -913,12 +911,13 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
psmouse_deactivate(parent);
}
- if (!(psmouse = kzalloc(sizeof(struct psmouse), GFP_KERNEL))) {
- retval = -ENOMEM;
+ psmouse = kzalloc(sizeof(struct psmouse), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!psmouse || !input_dev)
goto out;
- }
ps2_init(&psmouse->ps2dev, serio);
+ psmouse->dev = input_dev;
sprintf(psmouse->phys, "%s/input0", serio->phys);
psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
@@ -926,16 +925,11 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
serio_set_drvdata(serio, psmouse);
retval = serio_open(serio, drv);
- if (retval) {
- serio_set_drvdata(serio, NULL);
- kfree(psmouse);
+ if (retval)
goto out;
- }
if (psmouse_probe(psmouse) < 0) {
serio_close(serio);
- serio_set_drvdata(serio, NULL);
- kfree(psmouse);
retval = -ENODEV;
goto out;
}
@@ -947,13 +941,11 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
psmouse_switch_protocol(psmouse, NULL);
- input_register_device(&psmouse->dev);
- printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
-
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
-
psmouse_initialize(psmouse);
+ input_register_device(psmouse->dev);
+
if (parent && parent->pt_activate)
parent->pt_activate(parent);
@@ -964,6 +956,12 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
retval = 0;
out:
+ if (retval) {
+ serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(psmouse);
+ }
+
/* If this is a pass-through port the parent needs to be re-activated */
if (parent)
psmouse_activate(parent);
@@ -1161,6 +1159,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
{
struct serio *serio = psmouse->ps2dev.serio;
struct psmouse *parent = NULL;
+ struct input_dev *new_dev;
struct psmouse_protocol *proto;
int retry = 0;
@@ -1170,9 +1169,13 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
if (psmouse->type == proto->type)
return count;
+ if (!(new_dev = input_allocate_device()))
+ return -ENOMEM;
+
while (serio->child) {
if (++retry > 3) {
printk(KERN_WARNING "psmouse: failed to destroy child port, protocol change aborted.\n");
+ input_free_device(new_dev);
return -EIO;
}
@@ -1182,11 +1185,15 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
serio_pin_driver_uninterruptible(serio);
down(&psmouse_sem);
- if (serio->drv != &psmouse_drv)
+ if (serio->drv != &psmouse_drv) {
+ input_free_device(new_dev);
return -ENODEV;
+ }
- if (psmouse->type == proto->type)
+ if (psmouse->type == proto->type) {
+ input_free_device(new_dev);
return count; /* switched by other thread */
+ }
}
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
@@ -1199,8 +1206,9 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
psmouse->disconnect(psmouse);
psmouse_set_state(psmouse, PSMOUSE_IGNORE);
- input_unregister_device(&psmouse->dev);
+ input_unregister_device(psmouse->dev);
+ psmouse->dev = new_dev;
psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
if (psmouse_switch_protocol(psmouse, proto) < 0) {
@@ -1212,8 +1220,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
psmouse_initialize(psmouse);
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
- input_register_device(&psmouse->dev);
- printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
+ input_register_device(psmouse->dev);
if (parent && parent->pt_activate)
parent->pt_activate(parent);
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 45d2bd774f00f0..7c4192bd1279c6 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -36,7 +36,7 @@ typedef enum {
struct psmouse {
void *private;
- struct input_dev dev;
+ struct input_dev *dev;
struct ps2dev ps2dev;
char *vendor;
char *name;
diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c
index 8fe1212b8fd73f..09b6ffdb7582b1 100644
--- a/drivers/input/mouse/rpcmouse.c
+++ b/drivers/input/mouse/rpcmouse.c
@@ -34,20 +34,7 @@ MODULE_DESCRIPTION("Acorn RiscPC mouse driver");
MODULE_LICENSE("GPL");
static short rpcmouse_lastx, rpcmouse_lasty;
-
-static struct input_dev rpcmouse_dev = {
- .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
- .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
- .relbit = { BIT(REL_X) | BIT(REL_Y) },
- .name = "Acorn RiscPC Mouse",
- .phys = "rpcmouse/input0",
- .id = {
- .bustype = BUS_HOST,
- .vendor = 0x0005,
- .product = 0x0001,
- .version = 0x0100,
- },
-};
+static struct input_dev *rpcmouse_dev;
static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -78,29 +65,41 @@ static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
+
static int __init rpcmouse_init(void)
{
- init_input_dev(&rpcmouse_dev);
+ if (!(rpcmouse_dev = input_allocate_device()))
+ return -ENOMEM;
+
+ rpcmouse_dev->name = "Acorn RiscPC Mouse";
+ rpcmouse_dev->phys = "rpcmouse/input0";
+ rpcmouse_dev->id.bustype = BUS_HOST;
+ rpcmouse_dev->id.vendor = 0x0005;
+ rpcmouse_dev->id.product = 0x0001;
+ rpcmouse_dev->id.version = 0x0100;
+
+ rpcmouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ rpcmouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ rpcmouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
rpcmouse_lastx = (short) iomd_readl(IOMD_MOUSEX);
rpcmouse_lasty = (short) iomd_readl(IOMD_MOUSEY);
- if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, SA_SHIRQ, "rpcmouse", &rpcmouse_dev)) {
+ if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, SA_SHIRQ, "rpcmouse", rpcmouse_dev)) {
printk(KERN_ERR "rpcmouse: unable to allocate VSYNC interrupt\n");
- return -1;
+ input_free_device(rpcmouse_dev);
+ return -EBUSY;
}
- input_register_device(&rpcmouse_dev);
-
- printk(KERN_INFO "input: Acorn RiscPC mouse\n");
+ input_register_device(rpcmouse_dev);
return 0;
}
static void __exit rpcmouse_exit(void)
{
- input_unregister_device(&rpcmouse_dev);
- free_irq(IRQ_VSYNCPULSE, &rpcmouse_dev);
+ free_irq(IRQ_VSYNCPULSE, rpcmouse_dev);
+ input_unregister_device(rpcmouse_dev);
}
module_init(rpcmouse_init);
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
index d12b93ae390074..4bf584364d2830 100644
--- a/drivers/input/mouse/sermouse.c
+++ b/drivers/input/mouse/sermouse.c
@@ -48,7 +48,7 @@ static char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse"
"Logitech MZ++ Mouse"};
struct sermouse {
- struct input_dev dev;
+ struct input_dev *dev;
signed char buf[8];
unsigned char count;
unsigned char type;
@@ -64,7 +64,7 @@ struct sermouse {
static void sermouse_process_msc(struct sermouse *sermouse, signed char data, struct pt_regs *regs)
{
- struct input_dev *dev = &sermouse->dev;
+ struct input_dev *dev = sermouse->dev;
signed char *buf = sermouse->buf;
input_regs(dev, regs);
@@ -107,7 +107,7 @@ static void sermouse_process_msc(struct sermouse *sermouse, signed char data, st
static void sermouse_process_ms(struct sermouse *sermouse, signed char data, struct pt_regs *regs)
{
- struct input_dev *dev = &sermouse->dev;
+ struct input_dev *dev = sermouse->dev;
signed char *buf = sermouse->buf;
if (data & 0x40) sermouse->count = 0;
@@ -230,9 +230,9 @@ static void sermouse_disconnect(struct serio *serio)
{
struct sermouse *sermouse = serio_get_drvdata(serio);
- input_unregister_device(&sermouse->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(sermouse->dev);
kfree(sermouse);
}
@@ -244,56 +244,52 @@ static void sermouse_disconnect(struct serio *serio)
static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
{
struct sermouse *sermouse;
- unsigned char c;
- int err;
+ struct input_dev *input_dev;
+ unsigned char c = serio->id.extra;
+ int err = -ENOMEM;
- if (!serio->id.proto || serio->id.proto > SERIO_MZPP)
- return -ENODEV;
-
- if (!(sermouse = kmalloc(sizeof(struct sermouse), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(sermouse, 0, sizeof(struct sermouse));
-
- init_input_dev(&sermouse->dev);
- sermouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- sermouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
- sermouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
- sermouse->dev.private = sermouse;
-
- sermouse->type = serio->id.proto;
- c = serio->id.extra;
-
- if (c & 0x01) set_bit(BTN_MIDDLE, sermouse->dev.keybit);
- if (c & 0x02) set_bit(BTN_SIDE, sermouse->dev.keybit);
- if (c & 0x04) set_bit(BTN_EXTRA, sermouse->dev.keybit);
- if (c & 0x10) set_bit(REL_WHEEL, sermouse->dev.relbit);
- if (c & 0x20) set_bit(REL_HWHEEL, sermouse->dev.relbit);
+ sermouse = kzalloc(sizeof(struct sermouse), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!sermouse || !input_dev)
+ goto fail;
+ sermouse->dev = input_dev;
sprintf(sermouse->phys, "%s/input0", serio->phys);
+ sermouse->type = serio->id.proto;
- sermouse->dev.name = sermouse_protocols[sermouse->type];
- sermouse->dev.phys = sermouse->phys;
- sermouse->dev.id.bustype = BUS_RS232;
- sermouse->dev.id.vendor = sermouse->type;
- sermouse->dev.id.product = c;
- sermouse->dev.id.version = 0x0100;
- sermouse->dev.dev = &serio->dev;
+ input_dev->name = sermouse_protocols[sermouse->type];
+ input_dev->phys = sermouse->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = sermouse->type;
+ input_dev->id.product = c;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
+ input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ input_dev->private = sermouse;
+
+ if (c & 0x01) set_bit(BTN_MIDDLE, input_dev->keybit);
+ if (c & 0x02) set_bit(BTN_SIDE, input_dev->keybit);
+ if (c & 0x04) set_bit(BTN_EXTRA, input_dev->keybit);
+ if (c & 0x10) set_bit(REL_WHEEL, input_dev->relbit);
+ if (c & 0x20) set_bit(REL_HWHEEL, input_dev->relbit);
serio_set_drvdata(serio, sermouse);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(sermouse);
- return err;
- }
-
- input_register_device(&sermouse->dev);
+ if (err)
+ goto fail;
- printk(KERN_INFO "input: %s on %s\n", sermouse_protocols[sermouse->type], serio->phys);
+ input_register_device(sermouse->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(sermouse);
+ return err;
}
static struct serio_device_id sermouse_serio_ids[] = {
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 0293094224098b..97cdfd6acaca03 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -342,7 +342,7 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data
*/
static void synaptics_process_packet(struct psmouse *psmouse)
{
- struct input_dev *dev = &psmouse->dev;
+ struct input_dev *dev = psmouse->dev;
struct synaptics_data *priv = psmouse->private;
struct synaptics_hw_state hw;
int num_fingers;
@@ -473,7 +473,7 @@ static unsigned char synaptics_detect_pkt_type(struct psmouse *psmouse)
static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
{
- struct input_dev *dev = &psmouse->dev;
+ struct input_dev *dev = psmouse->dev;
struct synaptics_data *priv = psmouse->private;
input_regs(dev, regs);
@@ -645,7 +645,7 @@ int synaptics_init(struct psmouse *psmouse)
SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
priv->model_id, priv->capabilities, priv->ext_cap);
- set_input_params(&psmouse->dev, priv);
+ set_input_params(psmouse->dev, priv);
psmouse->protocol_handler = synaptics_process_byte;
psmouse->set_rate = synaptics_set_rate;
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c
index f024be9b44d2f1..36e9442a16b296 100644
--- a/drivers/input/mouse/vsxxxaa.c
+++ b/drivers/input/mouse/vsxxxaa.c
@@ -112,7 +112,7 @@ MODULE_LICENSE ("GPL");
struct vsxxxaa {
- struct input_dev dev;
+ struct input_dev *dev;
struct serio *serio;
#define BUFLEN 15 /* At least 5 is needed for a full tablet packet */
unsigned char buf[BUFLEN];
@@ -211,7 +211,7 @@ vsxxxaa_smells_like_packet (struct vsxxxaa *mouse, unsigned char type, size_t le
static void
vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
{
- struct input_dev *dev = &mouse->dev;
+ struct input_dev *dev = mouse->dev;
unsigned char *buf = mouse->buf;
int left, middle, right;
int dx, dy;
@@ -269,7 +269,7 @@ vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
static void
vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
{
- struct input_dev *dev = &mouse->dev;
+ struct input_dev *dev = mouse->dev;
unsigned char *buf = mouse->buf;
int left, middle, right, touch;
int x, y;
@@ -323,7 +323,7 @@ vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
static void
vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
{
- struct input_dev *dev = &mouse->dev;
+ struct input_dev *dev = mouse->dev;
unsigned char *buf = mouse->buf;
int left, middle, right;
unsigned char error;
@@ -483,9 +483,9 @@ vsxxxaa_disconnect (struct serio *serio)
{
struct vsxxxaa *mouse = serio_get_drvdata (serio);
- input_unregister_device (&mouse->dev);
serio_close (serio);
serio_set_drvdata (serio, NULL);
+ input_unregister_device (mouse->dev);
kfree (mouse);
}
@@ -493,61 +493,57 @@ static int
vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
{
struct vsxxxaa *mouse;
- int err;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
- if (!(mouse = kmalloc (sizeof (struct vsxxxaa), GFP_KERNEL)))
- return -ENOMEM;
-
- memset (mouse, 0, sizeof (struct vsxxxaa));
-
- init_input_dev (&mouse->dev);
- set_bit (EV_KEY, mouse->dev.evbit); /* We have buttons */
- set_bit (EV_REL, mouse->dev.evbit);
- set_bit (EV_ABS, mouse->dev.evbit);
- set_bit (BTN_LEFT, mouse->dev.keybit); /* We have 3 buttons */
- set_bit (BTN_MIDDLE, mouse->dev.keybit);
- set_bit (BTN_RIGHT, mouse->dev.keybit);
- set_bit (BTN_TOUCH, mouse->dev.keybit); /* ...and Tablet */
- set_bit (REL_X, mouse->dev.relbit);
- set_bit (REL_Y, mouse->dev.relbit);
- set_bit (ABS_X, mouse->dev.absbit);
- set_bit (ABS_Y, mouse->dev.absbit);
-
- mouse->dev.absmin[ABS_X] = 0;
- mouse->dev.absmax[ABS_X] = 1023;
- mouse->dev.absmin[ABS_Y] = 0;
- mouse->dev.absmax[ABS_Y] = 1023;
-
- mouse->dev.private = mouse;
+ mouse = kzalloc (sizeof (struct vsxxxaa), GFP_KERNEL);
+ input_dev = input_allocate_device ();
+ if (!mouse || !input_dev)
+ goto fail;
+ mouse->dev = input_dev;
+ mouse->serio = serio;
sprintf (mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer");
sprintf (mouse->phys, "%s/input0", serio->phys);
- mouse->dev.name = mouse->name;
- mouse->dev.phys = mouse->phys;
- mouse->dev.id.bustype = BUS_RS232;
- mouse->dev.dev = &serio->dev;
- mouse->serio = serio;
+
+ input_dev->name = mouse->name;
+ input_dev->phys = mouse->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = mouse;
+
+ set_bit (EV_KEY, input_dev->evbit); /* We have buttons */
+ set_bit (EV_REL, input_dev->evbit);
+ set_bit (EV_ABS, input_dev->evbit);
+ set_bit (BTN_LEFT, input_dev->keybit); /* We have 3 buttons */
+ set_bit (BTN_MIDDLE, input_dev->keybit);
+ set_bit (BTN_RIGHT, input_dev->keybit);
+ set_bit (BTN_TOUCH, input_dev->keybit); /* ...and Tablet */
+ set_bit (REL_X, input_dev->relbit);
+ set_bit (REL_Y, input_dev->relbit);
+ input_set_abs_params (input_dev, ABS_X, 0, 1023, 0, 0);
+ input_set_abs_params (input_dev, ABS_Y, 0, 1023, 0, 0);
serio_set_drvdata (serio, mouse);
err = serio_open (serio, drv);
- if (err) {
- serio_set_drvdata (serio, NULL);
- kfree (mouse);
- return err;
- }
+ if (err)
+ goto fail;
/*
* Request selftest. Standard packet format and differential
* mode will be requested after the device ID'ed successfully.
*/
- mouse->serio->write (mouse->serio, 'T'); /* Test */
-
- input_register_device (&mouse->dev);
+ serio->write (serio, 'T'); /* Test */
- printk (KERN_INFO "input: %s on %s\n", mouse->name, mouse->phys);
+ input_register_device (input_dev);
return 0;
+
+ fail: serio_set_drvdata (serio, NULL);
+ input_free_device (input_dev);
+ kfree (mouse);
+ return err;
}
static struct serio_device_id vsxxaa_serio_ids[] = {
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index c6194a9dd174be..2d0af44ac4b965 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -9,7 +9,7 @@
* the Free Software Foundation.
*/
-#define MOUSEDEV_MINOR_BASE 32
+#define MOUSEDEV_MINOR_BASE 32
#define MOUSEDEV_MINORS 32
#define MOUSEDEV_MIX 31
@@ -24,7 +24,6 @@
#include <linux/random.h>
#include <linux/major.h>
#include <linux/device.h>
-#include <linux/devfs_fs_kernel.h>
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
#include <linux/miscdevice.h>
#endif
@@ -621,6 +620,7 @@ static struct file_operations mousedev_fops = {
static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
{
struct mousedev *mousedev;
+ struct class_device *cdev;
int minor = 0;
for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
@@ -649,11 +649,13 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru
mousedev_table[minor] = mousedev;
- devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
- S_IFCHR|S_IRUGO|S_IWUSR, "input/mouse%d", minor);
- class_device_create(input_class,
+ cdev = class_device_create(&input_class, &dev->cdev,
MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
- dev->dev, "mouse%d", minor);
+ dev->cdev.dev, mousedev->name);
+
+ /* temporary symlink to keep userspace happy */
+ sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
+ mousedev->name);
return &mousedev->handle;
}
@@ -663,9 +665,9 @@ static void mousedev_disconnect(struct input_handle *handle)
struct mousedev *mousedev = handle->private;
struct mousedev_list *list;
- class_device_destroy(input_class,
+ sysfs_remove_link(&input_class.subsys.kset.kobj, mousedev->name);
+ class_device_destroy(&input_class,
MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
- devfs_remove("input/mouse%d", mousedev->minor);
mousedev->exist = 0;
if (mousedev->open) {
@@ -738,9 +740,7 @@ static int __init mousedev_init(void)
mousedev_mix.exist = 1;
mousedev_mix.minor = MOUSEDEV_MIX;
- devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX),
- S_IFCHR|S_IRUGO|S_IWUSR, "input/mice");
- class_device_create(input_class,
+ class_device_create(&input_class, NULL,
MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
@@ -759,8 +759,7 @@ static void __exit mousedev_exit(void)
if (psaux_registered)
misc_deregister(&psaux_mouse);
#endif
- devfs_remove("input/mice");
- class_device_destroy(input_class,
+ class_device_destroy(&input_class,
MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
input_unregister_handler(&mousedev_handler);
}
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
index 897e4c12b64271..a7b0de0f92b2ab 100644
--- a/drivers/input/serio/gscps2.c
+++ b/drivers/input/serio/gscps2.c
@@ -211,9 +211,6 @@ static void gscps2_reset(struct gscps2port *ps2port)
writeb(0xff, addr+GSC_RESET);
gscps2_flush(ps2port);
spin_unlock_irqrestore(&ps2port->lock, flags);
-
- /* enable it */
- gscps2_enable(ps2port, ENABLE);
}
static LIST_HEAD(ps2port_list);
@@ -307,6 +304,9 @@ static int gscps2_open(struct serio *port)
gscps2_reset(ps2port);
+ /* enable it */
+ gscps2_enable(ps2port, ENABLE);
+
gscps2_interrupt(0, NULL, NULL);
return 0;
@@ -331,7 +331,7 @@ static int __init gscps2_probe(struct parisc_device *dev)
{
struct gscps2port *ps2port;
struct serio *serio;
- unsigned long hpa = dev->hpa;
+ unsigned long hpa = dev->hpa.start;
int ret;
if (!dev->irq)
@@ -370,8 +370,6 @@ static int __init gscps2_probe(struct parisc_device *dev)
serio->port_data = ps2port;
serio->dev.parent = &dev->dev;
- list_add_tail(&ps2port->node, &ps2port_list);
-
ret = -EBUSY;
if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->port->name, ps2port))
goto fail_miserably;
@@ -396,15 +394,16 @@ static int __init gscps2_probe(struct parisc_device *dev)
serio_register_port(ps2port->port);
+ list_add_tail(&ps2port->node, &ps2port_list);
+
return 0;
fail:
free_irq(dev->irq, ps2port);
fail_miserably:
- list_del(&ps2port->node);
iounmap(ps2port->addr);
- release_mem_region(dev->hpa, GSC_STATUS + 4);
+ release_mem_region(dev->hpa.start, GSC_STATUS + 4);
fail_nomem:
kfree(ps2port);
@@ -444,7 +443,7 @@ static struct parisc_device_id gscps2_device_tbl[] = {
};
static struct parisc_driver parisc_ps2_driver = {
- .name = "GSC PS2",
+ .name = "gsc_ps2",
.id_table = gscps2_device_tbl,
.probe = gscps2_probe,
.remove = gscps2_remove,
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index c243cb6fdfc4a7..5704204964a354 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -801,7 +801,8 @@ static int hil_mlc_serio_open(struct serio *serio) {
struct hil_mlc_serio_map *map;
struct hil_mlc *mlc;
- if (serio->private != NULL) return -EBUSY;
+ if (serio_get_drvdata(serio) != NULL)
+ return -EBUSY;
map = serio->port_data;
if (map == NULL) {
@@ -832,11 +833,18 @@ static void hil_mlc_serio_close(struct serio *serio) {
return;
}
- serio->private = NULL;
+ serio_set_drvdata(serio, NULL);
serio->drv = NULL;
/* TODO wake up interruptable */
}
+static struct serio_device_id hil_mlc_serio_id = {
+ .type = SERIO_HIL_MLC,
+ .proto = SERIO_HIL,
+ .extra = SERIO_ANY,
+ .id = SERIO_ANY,
+};
+
int hil_mlc_register(hil_mlc *mlc) {
int i;
unsigned long flags;
@@ -867,7 +875,7 @@ int hil_mlc_register(hil_mlc *mlc) {
mlc_serio = kmalloc(sizeof(*mlc_serio), GFP_KERNEL);
mlc->serio[i] = mlc_serio;
memset(mlc_serio, 0, sizeof(*mlc_serio));
- mlc_serio->type = SERIO_HIL | SERIO_HIL_MLC;
+ mlc_serio->id = hil_mlc_serio_id;
mlc_serio->write = hil_mlc_serio_write;
mlc_serio->open = hil_mlc_serio_open;
mlc_serio->close = hil_mlc_serio_close;
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index 7629452dd64b0d..a10348bb25e983 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -764,7 +764,7 @@ MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl);
static int __init hp_sdc_init_hppa(struct parisc_device *d);
static struct parisc_driver hp_sdc_driver = {
- .name = "HP SDC",
+ .name = "hp_sdc",
.id_table = hp_sdc_tbl,
.probe = hp_sdc_init_hppa,
};
@@ -875,9 +875,9 @@ static int __init hp_sdc_init_hppa(struct parisc_device *d)
hp_sdc.dev = d;
hp_sdc.irq = d->irq;
hp_sdc.nmi = d->aux_irq;
- hp_sdc.base_io = d->hpa;
- hp_sdc.data_io = d->hpa + 0x800;
- hp_sdc.status_io = d->hpa + 0x801;
+ hp_sdc.base_io = d->hpa.start;
+ hp_sdc.data_io = d->hpa.start + 0x800;
+ hp_sdc.status_io = d->hpa.start + 0x801;
return hp_sdc_init();
}
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 40d451ce07ffec..4bc40f15999603 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -911,12 +911,10 @@ static long i8042_panic_blink(long count)
* Here we try to restore the original BIOS settings
*/
-static int i8042_suspend(struct device *dev, pm_message_t state, u32 level)
+static int i8042_suspend(struct device *dev, pm_message_t state)
{
- if (level == SUSPEND_DISABLE) {
- del_timer_sync(&i8042_timer);
- i8042_controller_reset();
- }
+ del_timer_sync(&i8042_timer);
+ i8042_controller_reset();
return 0;
}
@@ -926,13 +924,10 @@ static int i8042_suspend(struct device *dev, pm_message_t state, u32 level)
* Here we try to reset everything back to a state in which suspended
*/
-static int i8042_resume(struct device *dev, u32 level)
+static int i8042_resume(struct device *dev)
{
int i;
- if (level != RESUME_ENABLE)
- return 0;
-
if (i8042_ctl_test())
return -1;
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index 4c7fbe55036540..0ba3e6562bffeb 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -41,8 +41,7 @@ struct ts_event {
};
struct corgi_ts {
- char phys[32];
- struct input_dev input;
+ struct input_dev *input;
struct timer_list timer;
struct ts_event tc;
int pendown;
@@ -182,14 +181,12 @@ static void new_data(struct corgi_ts *corgi_ts, struct pt_regs *regs)
if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0)
return;
- if (regs)
- input_regs(&corgi_ts->input, regs);
-
- input_report_abs(&corgi_ts->input, ABS_X, corgi_ts->tc.x);
- input_report_abs(&corgi_ts->input, ABS_Y, corgi_ts->tc.y);
- input_report_abs(&corgi_ts->input, ABS_PRESSURE, corgi_ts->tc.pressure);
- input_report_key(&corgi_ts->input, BTN_TOUCH, (corgi_ts->pendown != 0));
- input_sync(&corgi_ts->input);
+ input_regs(corgi_ts->input, regs);
+ input_report_abs(corgi_ts->input, ABS_X, corgi_ts->tc.x);
+ input_report_abs(corgi_ts->input, ABS_Y, corgi_ts->tc.y);
+ input_report_abs(corgi_ts->input, ABS_PRESSURE, corgi_ts->tc.pressure);
+ input_report_key(corgi_ts->input, BTN_TOUCH, (corgi_ts->pendown != 0));
+ input_sync(corgi_ts->input);
}
static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_regs *regs)
@@ -234,34 +231,32 @@ static irqreturn_t ts_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
#ifdef CONFIG_PM
-static int corgits_suspend(struct device *dev, pm_message_t state, uint32_t level)
+static int corgits_suspend(struct device *dev, pm_message_t state)
{
- if (level == SUSPEND_POWER_DOWN) {
- struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
-
- if (corgi_ts->pendown) {
- del_timer_sync(&corgi_ts->timer);
- corgi_ts->tc.pressure = 0;
- new_data(corgi_ts, NULL);
- corgi_ts->pendown = 0;
- }
- corgi_ts->power_mode = PWR_MODE_SUSPEND;
+ struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
- corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+ if (corgi_ts->pendown) {
+ del_timer_sync(&corgi_ts->timer);
+ corgi_ts->tc.pressure = 0;
+ new_data(corgi_ts, NULL);
+ corgi_ts->pendown = 0;
}
+ corgi_ts->power_mode = PWR_MODE_SUSPEND;
+
+ corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+
return 0;
}
-static int corgits_resume(struct device *dev, uint32_t level)
+static int corgits_resume(struct device *dev)
{
- if (level == RESUME_POWER_ON) {
- struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
+ struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
+
+ corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+ /* Enable Falling Edge */
+ set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
+ corgi_ts->power_mode = PWR_MODE_ACTIVE;
- corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
- /* Enable Falling Edge */
- set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
- corgi_ts->power_mode = PWR_MODE_ACTIVE;
- }
return 0;
}
#else
@@ -273,39 +268,44 @@ static int __init corgits_probe(struct device *dev)
{
struct corgi_ts *corgi_ts;
struct platform_device *pdev = to_platform_device(dev);
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
- if (!(corgi_ts = kmalloc(sizeof(struct corgi_ts), GFP_KERNEL)))
- return -ENOMEM;
+ corgi_ts = kzalloc(sizeof(struct corgi_ts), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!corgi_ts || !input_dev)
+ goto fail;
dev_set_drvdata(dev, corgi_ts);
- memset(corgi_ts, 0, sizeof(struct corgi_ts));
-
corgi_ts->machinfo = dev->platform_data;
corgi_ts->irq_gpio = platform_get_irq(pdev, 0);
if (corgi_ts->irq_gpio < 0) {
- kfree(corgi_ts);
- return -ENODEV;
+ err = -ENODEV;
+ goto fail;
}
- init_input_dev(&corgi_ts->input);
- corgi_ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- corgi_ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
- input_set_abs_params(&corgi_ts->input, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
- input_set_abs_params(&corgi_ts->input, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
- input_set_abs_params(&corgi_ts->input, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0);
+ corgi_ts->input = input_dev;
- strcpy(corgi_ts->phys, "corgits/input0");
+ init_timer(&corgi_ts->timer);
+ corgi_ts->timer.data = (unsigned long) corgi_ts;
+ corgi_ts->timer.function = corgi_ts_timer;
- corgi_ts->input.private = corgi_ts;
- corgi_ts->input.name = "Corgi Touchscreen";
- corgi_ts->input.dev = dev;
- corgi_ts->input.phys = corgi_ts->phys;
- corgi_ts->input.id.bustype = BUS_HOST;
- corgi_ts->input.id.vendor = 0x0001;
- corgi_ts->input.id.product = 0x0002;
- corgi_ts->input.id.version = 0x0100;
+ input_dev->name = "Corgi Touchscreen";
+ input_dev->phys = "corgits/input0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0002;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = dev;
+ input_dev->private = corgi_ts;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0);
pxa_gpio_mode(IRQ_TO_GPIO(corgi_ts->irq_gpio) | GPIO_IN);
@@ -319,25 +319,24 @@ static int __init corgits_probe(struct device *dev)
corgi_ssp_ads7846_putget((5u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
mdelay(5);
- init_timer(&corgi_ts->timer);
- corgi_ts->timer.data = (unsigned long) corgi_ts;
- corgi_ts->timer.function = corgi_ts_timer;
-
- input_register_device(&corgi_ts->input);
- corgi_ts->power_mode = PWR_MODE_ACTIVE;
-
if (request_irq(corgi_ts->irq_gpio, ts_interrupt, SA_INTERRUPT, "ts", corgi_ts)) {
- input_unregister_device(&corgi_ts->input);
- kfree(corgi_ts);
- return -EBUSY;
+ err = -EBUSY;
+ goto fail;
}
+ input_register_device(corgi_ts->input);
+
+ corgi_ts->power_mode = PWR_MODE_ACTIVE;
+
/* Enable Falling Edge */
set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
- printk(KERN_INFO "input: Corgi Touchscreen Registered\n");
-
return 0;
+
+ fail: input_free_device(input_dev);
+ kfree(corgi_ts);
+ return err;
+
}
static int corgits_remove(struct device *dev)
@@ -347,7 +346,7 @@ static int corgits_remove(struct device *dev)
free_irq(corgi_ts->irq_gpio, NULL);
del_timer_sync(&corgi_ts->timer);
corgi_ts->machinfo->put_hsync();
- input_unregister_device(&corgi_ts->input);
+ input_unregister_device(corgi_ts->input);
kfree(corgi_ts);
return 0;
}
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
index 3cdc9cab688d84..c86a2eb310fd93 100644
--- a/drivers/input/touchscreen/elo.c
+++ b/drivers/input/touchscreen/elo.c
@@ -36,14 +36,12 @@ MODULE_LICENSE("GPL");
#define ELO_MAX_LENGTH 10
-static char *elo_name = "Elo Serial TouchScreen";
-
/*
* Per-touchscreen data.
*/
struct elo {
- struct input_dev dev;
+ struct input_dev *dev;
struct serio *serio;
int id;
int idx;
@@ -54,7 +52,7 @@ struct elo {
static void elo_process_data_10(struct elo* elo, unsigned char data, struct pt_regs *regs)
{
- struct input_dev *dev = &elo->dev;
+ struct input_dev *dev = elo->dev;
elo->csum += elo->data[elo->idx] = data;
@@ -80,7 +78,7 @@ static void elo_process_data_10(struct elo* elo, unsigned char data, struct pt_r
input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]);
input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]);
input_report_abs(dev, ABS_PRESSURE, (elo->data[8] << 8) | elo->data[7]);
- input_report_key(dev, BTN_TOUCH, elo->data[2] & 3);
+ input_report_key(dev, BTN_TOUCH, elo->data[8] || elo->data[7]);
input_sync(dev);
}
elo->idx = 0;
@@ -91,7 +89,7 @@ static void elo_process_data_10(struct elo* elo, unsigned char data, struct pt_r
static void elo_process_data_6(struct elo* elo, unsigned char data, struct pt_regs *regs)
{
- struct input_dev *dev = &elo->dev;
+ struct input_dev *dev = elo->dev;
elo->data[elo->idx] = data;
@@ -129,7 +127,7 @@ static void elo_process_data_6(struct elo* elo, unsigned char data, struct pt_re
case 5:
if ((data & 0xf0) == 0) {
input_report_abs(dev, ABS_PRESSURE, elo->data[5]);
- input_report_key(dev, BTN_TOUCH, elo->data[5]);
+ input_report_key(dev, BTN_TOUCH, !!elo->data[5]);
}
input_sync(dev);
elo->idx = 0;
@@ -139,7 +137,7 @@ static void elo_process_data_6(struct elo* elo, unsigned char data, struct pt_re
static void elo_process_data_3(struct elo* elo, unsigned char data, struct pt_regs *regs)
{
- struct input_dev *dev = &elo->dev;
+ struct input_dev *dev = elo->dev;
elo->data[elo->idx] = data;
@@ -191,7 +189,7 @@ static void elo_disconnect(struct serio *serio)
{
struct elo* elo = serio_get_drvdata(serio);
- input_unregister_device(&elo->dev);
+ input_unregister_device(elo->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
kfree(elo);
@@ -206,67 +204,68 @@ static void elo_disconnect(struct serio *serio)
static int elo_connect(struct serio *serio, struct serio_driver *drv)
{
struct elo *elo;
+ struct input_dev *input_dev;
int err;
- if (!(elo = kmalloc(sizeof(struct elo), GFP_KERNEL)))
- return -ENOMEM;
+ elo = kzalloc(sizeof(struct elo), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!elo || !input_dev) {
+ err = -ENOMEM;
+ goto fail;
+ }
- memset(elo, 0, sizeof(struct elo));
+ elo->serio = serio;
+ elo->id = serio->id.id;
+ elo->dev = input_dev;
+ snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys);
- init_input_dev(&elo->dev);
- elo->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- elo->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_dev->private = elo;
+ input_dev->name = "Elo Serial TouchScreen";
+ input_dev->phys = elo->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_ELO;
+ input_dev->id.product = elo->id;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
- elo->id = serio->id.id;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
switch (elo->id) {
case 0: /* 10-byte protocol */
- input_set_abs_params(&elo->dev, ABS_X, 96, 4000, 0, 0);
- input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0);
- input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 255, 0, 0);
+ input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0);
break;
case 1: /* 6-byte protocol */
- input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 15, 0, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0);
case 2: /* 4-byte protocol */
- input_set_abs_params(&elo->dev, ABS_X, 96, 4000, 0, 0);
- input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0);
+ input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0);
break;
case 3: /* 3-byte protocol */
- input_set_abs_params(&elo->dev, ABS_X, 0, 255, 0, 0);
- input_set_abs_params(&elo->dev, ABS_Y, 0, 255, 0, 0);
+ input_set_abs_params(input_dev, ABS_X, 0, 255, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, 255, 0, 0);
break;
}
- elo->serio = serio;
-
- sprintf(elo->phys, "%s/input0", serio->phys);
-
- elo->dev.private = elo;
- elo->dev.name = elo_name;
- elo->dev.phys = elo->phys;
- elo->dev.id.bustype = BUS_RS232;
- elo->dev.id.vendor = SERIO_ELO;
- elo->dev.id.product = elo->id;
- elo->dev.id.version = 0x0100;
-
serio_set_drvdata(serio, elo);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(elo);
- return err;
- }
-
- input_register_device(&elo->dev);
-
- printk(KERN_INFO "input: %s on %s\n", elo_name, serio->phys);
+ if (err)
+ goto fail;
+ input_register_device(elo->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(elo);
+ return err;
}
/*
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
index 53a27e43dd2352..466da190ceeccc 100644
--- a/drivers/input/touchscreen/gunze.c
+++ b/drivers/input/touchscreen/gunze.c
@@ -48,14 +48,12 @@ MODULE_LICENSE("GPL");
#define GUNZE_MAX_LENGTH 10
-static char *gunze_name = "Gunze AHL-51S TouchScreen";
-
/*
* Per-touchscreen data.
*/
struct gunze {
- struct input_dev dev;
+ struct input_dev *dev;
struct serio *serio;
int idx;
unsigned char data[GUNZE_MAX_LENGTH];
@@ -64,7 +62,7 @@ struct gunze {
static void gunze_process_packet(struct gunze* gunze, struct pt_regs *regs)
{
- struct input_dev *dev = &gunze->dev;
+ struct input_dev *dev = gunze->dev;
if (gunze->idx != GUNZE_MAX_LENGTH || gunze->data[5] != ',' ||
(gunze->data[0] != 'T' && gunze->data[0] != 'R')) {
@@ -100,11 +98,13 @@ static irqreturn_t gunze_interrupt(struct serio *serio,
static void gunze_disconnect(struct serio *serio)
{
- struct gunze* gunze = serio_get_drvdata(serio);
+ struct gunze *gunze = serio_get_drvdata(serio);
- input_unregister_device(&gunze->dev);
+ input_get_device(gunze->dev);
+ input_unregister_device(gunze->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_put_device(gunze->dev);
kfree(gunze);
}
@@ -117,45 +117,45 @@ static void gunze_disconnect(struct serio *serio)
static int gunze_connect(struct serio *serio, struct serio_driver *drv)
{
struct gunze *gunze;
+ struct input_dev *input_dev;
int err;
- if (!(gunze = kmalloc(sizeof(struct gunze), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(gunze, 0, sizeof(struct gunze));
-
- init_input_dev(&gunze->dev);
- gunze->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- gunze->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
- input_set_abs_params(&gunze->dev, ABS_X, 24, 1000, 0, 0);
- input_set_abs_params(&gunze->dev, ABS_Y, 24, 1000, 0, 0);
+ gunze = kzalloc(sizeof(struct gunze), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!gunze || !input_dev) {
+ err = -ENOMEM;
+ goto fail;
+ }
gunze->serio = serio;
-
+ gunze->dev = input_dev;
sprintf(gunze->phys, "%s/input0", serio->phys);
- gunze->dev.private = gunze;
- gunze->dev.name = gunze_name;
- gunze->dev.phys = gunze->phys;
- gunze->dev.id.bustype = BUS_RS232;
- gunze->dev.id.vendor = SERIO_GUNZE;
- gunze->dev.id.product = 0x0051;
- gunze->dev.id.version = 0x0100;
+ input_dev->private = gunze;
+ input_dev->name = "Gunze AHL-51S TouchScreen";
+ input_dev->phys = gunze->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_GUNZE;
+ input_dev->id.product = 0x0051;
+ input_dev->id.version = 0x0100;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(input_dev, ABS_X, 24, 1000, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 24, 1000, 0, 0);
serio_set_drvdata(serio, gunze);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(gunze);
- return err;
- }
-
- input_register_device(&gunze->dev);
-
- printk(KERN_INFO "input: %s on %s\n", gunze_name, serio->phys);
+ if (err)
+ goto fail;
+ input_register_device(gunze->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(gunze);
+ return err;
}
/*
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
index bcfa1e36f957f4..a18d56bdafd931 100644
--- a/drivers/input/touchscreen/h3600_ts_input.c
+++ b/drivers/input/touchscreen/h3600_ts_input.c
@@ -39,7 +39,6 @@
#include <linux/serio.h>
#include <linux/init.h>
#include <linux/delay.h>
-#include <linux/pm.h>
/* SA1100 serial defines */
#include <asm/arch/hardware.h>
@@ -93,16 +92,12 @@ MODULE_LICENSE("GPL");
#define H3600_SCANCODE_LEFT 8 /* 8 -> left */
#define H3600_SCANCODE_DOWN 9 /* 9 -> down */
-static char *h3600_name = "H3600 TouchScreen";
-
/*
* Per-touchscreen data.
*/
struct h3600_dev {
- struct input_dev dev;
- struct pm_dev *pm_dev;
+ struct input_dev *dev;
struct serio *serio;
- struct pm_dev *pm_dev;
unsigned char event; /* event ID from packet */
unsigned char chksum;
unsigned char len;
@@ -163,33 +158,6 @@ unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr)
return 0;
}
-static int suspended = 0;
-static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req,
- void *data)
-{
- struct input_dev *dev = (struct input_dev *) data;
-
- switch (req) {
- case PM_SUSPEND: /* enter D1-D3 */
- suspended = 1;
- h3600_flite_power(dev, FLITE_PWR_OFF);
- break;
- case PM_BLANK:
- if (!suspended)
- h3600_flite_power(dev, FLITE_PWR_OFF);
- break;
- case PM_RESUME: /* enter D0 */
- /* same as unblank */
- case PM_UNBLANK:
- if (suspended) {
- //initSerial();
- suspended = 0;
- }
- h3600_flite_power(dev, FLITE_PWR_ON);
- break;
- }
- return 0;
-}
#endif
/*
@@ -199,7 +167,7 @@ static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req,
*/
static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs)
{
- struct input_dev *dev = &ts->dev;
+ struct input_dev *dev = ts->dev;
static int touched = 0;
int key, down = 0;
@@ -295,6 +263,7 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs)
static int h3600ts_event(struct input_dev *dev, unsigned int type,
unsigned int code, int value)
{
+#if 0
struct h3600_dev *ts = dev->private;
switch (type) {
@@ -304,6 +273,8 @@ static int h3600ts_event(struct input_dev *dev, unsigned int type,
}
}
return -1;
+#endif
+ return 0;
}
/*
@@ -380,14 +351,48 @@ static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data,
static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
{
struct h3600_dev *ts;
+ struct input_dev *input_dev;
int err;
- if (!(ts = kmalloc(sizeof(struct h3600_dev), GFP_KERNEL)))
- return -ENOMEM;
+ ts = kzalloc(sizeof(struct h3600_dev), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ts || !input_dev) {
+ err = -ENOMEM;
+ goto fail1;
+ }
- memset(ts, 0, sizeof(struct h3600_dev));
+ ts->serio = serio;
+ ts->dev = input_dev;
+ sprintf(ts->phys, "%s/input0", serio->phys);
- init_input_dev(&ts->dev);
+ input_dev->name = "H3600 TouchScreen";
+ input_dev->phys = ts->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_H3600;
+ input_dev->id.product = 0x0666; /* FIXME !!! We can ask the hardware */
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = ts;
+
+ input_dev->event = h3600ts_event;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_LED) | BIT(EV_PWR);
+ input_dev->ledbit[0] = BIT(LED_SLEEP);
+ input_set_abs_params(input_dev, ABS_X, 60, 985, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 35, 1024, 0, 0);
+
+ set_bit(KEY_RECORD, input_dev->keybit);
+ set_bit(KEY_Q, input_dev->keybit);
+ set_bit(KEY_PROG1, input_dev->keybit);
+ set_bit(KEY_PROG2, input_dev->keybit);
+ set_bit(KEY_PROG3, input_dev->keybit);
+ set_bit(KEY_UP, input_dev->keybit);
+ set_bit(KEY_RIGHT, input_dev->keybit);
+ set_bit(KEY_LEFT, input_dev->keybit);
+ set_bit(KEY_DOWN, input_dev->keybit);
+ set_bit(KEY_ENTER, input_dev->keybit);
+ set_bit(KEY_SUSPEND, input_dev->keybit);
+ set_bit(BTN_TOUCH, input_dev->keybit);
/* Device specific stuff */
set_GPIO_IRQ_edge(GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES);
@@ -397,73 +402,35 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM,
"h3600_action", &ts->dev)) {
printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n");
- kfree(ts);
- return -EBUSY;
+ err = -EBUSY;
+ goto fail2;
}
if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM,
"h3600_suspend", &ts->dev)) {
- free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev);
printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n");
- kfree(ts);
- return -EBUSY;
+ err = -EBUSY;
+ goto fail3;
}
- /* Now we have things going we setup our input device */
- ts->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_LED) | BIT(EV_PWR);
- ts->dev.ledbit[0] = BIT(LED_SLEEP);
- input_set_abs_params(&ts->dev, ABS_X, 60, 985, 0, 0);
- input_set_abs_params(&ts->dev, ABS_Y, 35, 1024, 0, 0);
-
- set_bit(KEY_RECORD, ts->dev.keybit);
- set_bit(KEY_Q, ts->dev.keybit);
- set_bit(KEY_PROG1, ts->dev.keybit);
- set_bit(KEY_PROG2, ts->dev.keybit);
- set_bit(KEY_PROG3, ts->dev.keybit);
- set_bit(KEY_UP, ts->dev.keybit);
- set_bit(KEY_RIGHT, ts->dev.keybit);
- set_bit(KEY_LEFT, ts->dev.keybit);
- set_bit(KEY_DOWN, ts->dev.keybit);
- set_bit(KEY_ENTER, ts->dev.keybit);
- ts->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
- ts->dev.keybit[LONG(KEY_SUSPEND)] |= BIT(KEY_SUSPEND);
-
- ts->serio = serio;
-
- sprintf(ts->phys, "%s/input0", serio->phys);
-
- ts->dev.event = h3600ts_event;
- ts->dev.private = ts;
- ts->dev.name = h3600_name;
- ts->dev.phys = ts->phys;
- ts->dev.id.bustype = BUS_RS232;
- ts->dev.id.vendor = SERIO_H3600;
- ts->dev.id.product = 0x0666; /* FIXME !!! We can ask the hardware */
- ts->dev.id.version = 0x0100;
-
serio_set_drvdata(serio, ts);
err = serio_open(serio, drv);
- if (err) {
- free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts);
- free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts);
- serio_set_drvdata(serio, NULL);
- kfree(ts);
+ if (err)
return err;
- }
//h3600_flite_control(1, 25); /* default brightness */
-#ifdef CONFIG_PM
- ts->pm_dev = pm_register(PM_ILLUMINATION_DEV, PM_SYS_LIGHT,
- h3600ts_pm_callback);
- printk("registered pm callback\n");
-#endif
- input_register_device(&ts->dev);
-
- printk(KERN_INFO "input: %s on %s\n", h3600_name, serio->phys);
+ input_register_device(ts->dev);
return 0;
+
+fail3: free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev);
+fail2: free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts->dev);
+fail1: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(ts);
+ return err;
}
/*
@@ -476,9 +443,11 @@ static void h3600ts_disconnect(struct serio *serio)
free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev);
free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, &ts->dev);
- input_unregister_device(&ts->dev);
+ input_get_device(ts->dev);
+ input_unregister_device(ts->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_put_device(ts->dev);
kfree(ts);
}
diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c
index 7e1404441ecaa5..957dd5a1b15ea4 100644
--- a/drivers/input/touchscreen/hp680_ts_input.c
+++ b/drivers/input/touchscreen/hp680_ts_input.c
@@ -21,10 +21,8 @@
static void do_softint(void *data);
-static struct input_dev hp680_ts_dev;
+static struct input_dev *hp680_ts_dev;
static DECLARE_WORK(work, do_softint, 0);
-static char *hp680_ts_name = "HP Jornada touchscreen";
-static char *hp680_ts_phys = "input0";
static void do_softint(void *data)
{
@@ -58,14 +56,14 @@ static void do_softint(void *data)
}
if (touched) {
- input_report_key(&hp680_ts_dev, BTN_TOUCH, 1);
- input_report_abs(&hp680_ts_dev, ABS_X, absx);
- input_report_abs(&hp680_ts_dev, ABS_Y, absy);
+ input_report_key(hp680_ts_dev, BTN_TOUCH, 1);
+ input_report_abs(hp680_ts_dev, ABS_X, absx);
+ input_report_abs(hp680_ts_dev, ABS_Y, absy);
} else {
- input_report_key(&hp680_ts_dev, BTN_TOUCH, 0);
+ input_report_key(hp680_ts_dev, BTN_TOUCH, 0);
}
- input_sync(&hp680_ts_dev);
+ input_sync(hp680_ts_dev);
enable_irq(HP680_TS_IRQ);
}
@@ -92,27 +90,29 @@ static int __init hp680_ts_init(void)
scpcr |= SCPCR_TS_ENABLE;
ctrl_outw(scpcr, SCPCR);
- memset(&hp680_ts_dev, 0, sizeof(hp680_ts_dev));
- init_input_dev(&hp680_ts_dev);
+ hp680_ts_dev = input_allocate_device();
+ if (!hp680_ts_dev)
+ return -ENOMEM;
- hp680_ts_dev.evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
- hp680_ts_dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
- hp680_ts_dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ hp680_ts_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
+ hp680_ts_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+ hp680_ts_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
- hp680_ts_dev.absmin[ABS_X] = HP680_TS_ABS_X_MIN;
- hp680_ts_dev.absmin[ABS_Y] = HP680_TS_ABS_Y_MIN;
- hp680_ts_dev.absmax[ABS_X] = HP680_TS_ABS_X_MAX;
- hp680_ts_dev.absmax[ABS_Y] = HP680_TS_ABS_Y_MAX;
+ hp680_ts_dev->absmin[ABS_X] = HP680_TS_ABS_X_MIN;
+ hp680_ts_dev->absmin[ABS_Y] = HP680_TS_ABS_Y_MIN;
+ hp680_ts_dev->absmax[ABS_X] = HP680_TS_ABS_X_MAX;
+ hp680_ts_dev->absmax[ABS_Y] = HP680_TS_ABS_Y_MAX;
- hp680_ts_dev.name = hp680_ts_name;
- hp680_ts_dev.phys = hp680_ts_phys;
- input_register_device(&hp680_ts_dev);
+ hp680_ts_dev->name = "HP Jornada touchscreen";
+ hp680_ts_dev->phys = "hp680_ts/input0";
- if (request_irq
- (HP680_TS_IRQ, hp680_ts_interrupt, SA_INTERRUPT, MODNAME, 0) < 0) {
- printk(KERN_ERR "hp680_touchscreen.c : Can't allocate irq %d\n",
+ input_register_device(hp680_ts_dev);
+
+ if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt,
+ SA_INTERRUPT, MODNAME, 0) < 0) {
+ printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n",
HP680_TS_IRQ);
- input_unregister_device(&hp680_ts_dev);
+ input_unregister_device(hp680_ts_dev);
return -EBUSY;
}
@@ -124,7 +124,7 @@ static void __exit hp680_ts_exit(void)
free_irq(HP680_TS_IRQ, 0);
cancel_delayed_work(&work);
flush_scheduled_work();
- input_unregister_device(&hp680_ts_dev);
+ input_unregister_device(hp680_ts_dev);
}
module_init(hp680_ts_init);
diff --git a/drivers/input/touchscreen/mk712.c b/drivers/input/touchscreen/mk712.c
index afaaebe5225bee..4844d250a5ebc7 100644
--- a/drivers/input/touchscreen/mk712.c
+++ b/drivers/input/touchscreen/mk712.c
@@ -77,7 +77,7 @@ MODULE_PARM_DESC(irq, "IRQ of MK712 touchscreen controller");
#define MK712_READ_ONE_POINT 0x20
#define MK712_POWERUP 0x40
-static struct input_dev mk712_dev;
+static struct input_dev *mk712_dev;
static DEFINE_SPINLOCK(mk712_lock);
static irqreturn_t mk712_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -88,7 +88,7 @@ static irqreturn_t mk712_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static unsigned short last_y;
spin_lock(&mk712_lock);
- input_regs(&mk712_dev, regs);
+ input_regs(mk712_dev, regs);
status = inb(mk712_io + MK712_STATUS);
@@ -100,7 +100,7 @@ static irqreturn_t mk712_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (~status & MK712_STATUS_TOUCH)
{
debounce = 1;
- input_report_key(&mk712_dev, BTN_TOUCH, 0);
+ input_report_key(mk712_dev, BTN_TOUCH, 0);
goto end;
}
@@ -110,15 +110,15 @@ static irqreturn_t mk712_interrupt(int irq, void *dev_id, struct pt_regs *regs)
goto end;
}
- input_report_key(&mk712_dev, BTN_TOUCH, 1);
- input_report_abs(&mk712_dev, ABS_X, last_x);
- input_report_abs(&mk712_dev, ABS_Y, last_y);
+ input_report_key(mk712_dev, BTN_TOUCH, 1);
+ input_report_abs(mk712_dev, ABS_X, last_x);
+ input_report_abs(mk712_dev, ABS_Y, last_y);
end:
last_x = inw(mk712_io + MK712_X) & 0x0fff;
last_y = inw(mk712_io + MK712_Y) & 0x0fff;
- input_sync(&mk712_dev);
+ input_sync(mk712_dev);
spin_unlock(&mk712_lock);
return IRQ_HANDLED;
}
@@ -154,30 +154,11 @@ static void mk712_close(struct input_dev *dev)
spin_unlock_irqrestore(&mk712_lock, flags);
}
-static struct input_dev mk712_dev = {
- .evbit = { BIT(EV_KEY) | BIT(EV_ABS) },
- .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
- .absbit = { BIT(ABS_X) | BIT(ABS_Y) },
- .open = mk712_open,
- .close = mk712_close,
- .name = "ICS MicroClock MK712 TouchScreen",
- .phys = "isa0260/input0",
- .absmin = { [ABS_X] = 0, [ABS_Y] = 0 },
- .absmax = { [ABS_X] = 0xfff, [ABS_Y] = 0xfff },
- .absfuzz = { [ABS_X] = 88, [ABS_Y] = 88 },
- .id = {
- .bustype = BUS_ISA,
- .vendor = 0x0005,
- .product = 0x0001,
- .version = 0x0100,
- },
-};
-
int __init mk712_init(void)
{
+ int err;
- if(!request_region(mk712_io, 8, "mk712"))
- {
+ if (!request_region(mk712_io, 8, "mk712")) {
printk(KERN_WARNING "mk712: unable to get IO region\n");
return -ENODEV;
}
@@ -188,28 +169,49 @@ int __init mk712_init(void)
(inw(mk712_io + MK712_Y) & 0xf000) ||
(inw(mk712_io + MK712_STATUS) & 0xf333)) {
printk(KERN_WARNING "mk712: device not present\n");
- release_region(mk712_io, 8);
- return -ENODEV;
+ err = -ENODEV;
+ goto fail;
}
- if(request_irq(mk712_irq, mk712_interrupt, 0, "mk712", &mk712_dev))
- {
- printk(KERN_WARNING "mk712: unable to get IRQ\n");
- release_region(mk712_io, 8);
- return -EBUSY;
+ if (!(mk712_dev = input_allocate_device())) {
+ printk(KERN_ERR "mk712: not enough memory\n");
+ err = -ENOMEM;
+ goto fail;
}
- input_register_device(&mk712_dev);
+ mk712_dev->name = "ICS MicroClock MK712 TouchScreen";
+ mk712_dev->phys = "isa0260/input0";
+ mk712_dev->id.bustype = BUS_ISA;
+ mk712_dev->id.vendor = 0x0005;
+ mk712_dev->id.product = 0x0001;
+ mk712_dev->id.version = 0x0100;
+
+ mk712_dev->open = mk712_open;
+ mk712_dev->close = mk712_close;
- printk(KERN_INFO "input: ICS MicroClock MK712 TouchScreen at %#x irq %d\n", mk712_io, mk712_irq);
+ mk712_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ mk712_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(mk712_dev, ABS_X, 0, 0xfff, 88, 0);
+ input_set_abs_params(mk712_dev, ABS_Y, 0, 0xfff, 88, 0);
+ if (request_irq(mk712_irq, mk712_interrupt, 0, "mk712", mk712_dev)) {
+ printk(KERN_WARNING "mk712: unable to get IRQ\n");
+ err = -EBUSY;
+ goto fail;
+ }
+
+ input_register_device(mk712_dev);
return 0;
+
+ fail: input_free_device(mk712_dev);
+ release_region(mk712_io, 8);
+ return err;
}
static void __exit mk712_exit(void)
{
- input_unregister_device(&mk712_dev);
- free_irq(mk712_irq, &mk712_dev);
+ input_unregister_device(mk712_dev);
+ free_irq(mk712_irq, mk712_dev);
release_region(mk712_io, 8);
}
diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c
index aa8ee7842179c6..1d0d37eeef6e63 100644
--- a/drivers/input/touchscreen/mtouch.c
+++ b/drivers/input/touchscreen/mtouch.c
@@ -51,14 +51,12 @@ MODULE_LICENSE("GPL");
#define MTOUCH_GET_YC(data) (((data[4])<<7) | data[3])
#define MTOUCH_GET_TOUCHED(data) (MTOUCH_FORMAT_TABLET_TOUCH_BIT & data[0])
-static char *mtouch_name = "MicroTouch Serial TouchScreen";
-
/*
* Per-touchscreen data.
*/
struct mtouch {
- struct input_dev dev;
+ struct input_dev *dev;
struct serio *serio;
int idx;
unsigned char data[MTOUCH_MAX_LENGTH];
@@ -67,7 +65,7 @@ struct mtouch {
static void mtouch_process_format_tablet(struct mtouch *mtouch, struct pt_regs *regs)
{
- struct input_dev *dev = &mtouch->dev;
+ struct input_dev *dev = mtouch->dev;
if (MTOUCH_FORMAT_TABLET_LENGTH == ++mtouch->idx) {
input_regs(dev, regs);
@@ -116,9 +114,11 @@ static void mtouch_disconnect(struct serio *serio)
{
struct mtouch* mtouch = serio_get_drvdata(serio);
- input_unregister_device(&mtouch->dev);
+ input_get_device(mtouch->dev);
+ input_unregister_device(mtouch->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_put_device(mtouch->dev);
kfree(mtouch);
}
@@ -131,46 +131,46 @@ static void mtouch_disconnect(struct serio *serio)
static int mtouch_connect(struct serio *serio, struct serio_driver *drv)
{
struct mtouch *mtouch;
+ struct input_dev *input_dev;
int err;
- if (!(mtouch = kmalloc(sizeof(*mtouch), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(mtouch, 0, sizeof(*mtouch));
-
- init_input_dev(&mtouch->dev);
- mtouch->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- mtouch->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-
- input_set_abs_params(&mtouch->dev, ABS_X, MTOUCH_MIN_XC, MTOUCH_MAX_XC, 0, 0);
- input_set_abs_params(&mtouch->dev, ABS_Y, MTOUCH_MIN_YC, MTOUCH_MAX_YC, 0, 0);
+ mtouch = kzalloc(sizeof(struct mtouch), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!mtouch || !input_dev) {
+ err = -ENOMEM;
+ goto fail;
+ }
mtouch->serio = serio;
-
+ mtouch->dev = input_dev;
sprintf(mtouch->phys, "%s/input0", serio->phys);
- mtouch->dev.private = mtouch;
- mtouch->dev.name = mtouch_name;
- mtouch->dev.phys = mtouch->phys;
- mtouch->dev.id.bustype = BUS_RS232;
- mtouch->dev.id.vendor = SERIO_MICROTOUCH;
- mtouch->dev.id.product = 0;
- mtouch->dev.id.version = 0x0100;
+ input_dev->private = mtouch;
+ input_dev->name = "MicroTouch Serial TouchScreen";
+ input_dev->phys = mtouch->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_MICROTOUCH;
+ input_dev->id.product = 0;
+ input_dev->id.version = 0x0100;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(mtouch->dev, ABS_X, MTOUCH_MIN_XC, MTOUCH_MAX_XC, 0, 0);
+ input_set_abs_params(mtouch->dev, ABS_Y, MTOUCH_MIN_YC, MTOUCH_MAX_YC, 0, 0);
serio_set_drvdata(serio, mtouch);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(mtouch);
- return err;
- }
-
- input_register_device(&mtouch->dev);
+ if (err)
+ goto fail;
- printk(KERN_INFO "input: %s on %s\n", mtouch->dev.name, serio->phys);
+ input_register_device(mtouch->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(mtouch);
+ return err;
}
/*
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index 50c63a155156a3..ca1547929d62e0 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -53,7 +53,6 @@
#include <linux/random.h>
#include <linux/time.h>
#include <linux/device.h>
-#include <linux/devfs_fs_kernel.h>
#ifndef CONFIG_INPUT_TSDEV_SCREEN_X
#define CONFIG_INPUT_TSDEV_SCREEN_X 240
@@ -369,6 +368,7 @@ static struct input_handle *tsdev_connect(struct input_handler *handler,
struct input_device_id *id)
{
struct tsdev *tsdev;
+ struct class_device *cdev;
int minor, delta;
for (minor = 0; minor < TSDEV_MINORS/2 && tsdev_table[minor];
@@ -410,13 +410,13 @@ static struct input_handle *tsdev_connect(struct input_handler *handler,
tsdev_table[minor] = tsdev;
- devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
- S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor);
- devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor + TSDEV_MINORS/2),
- S_IFCHR|S_IRUGO|S_IWUSR, "input/tsraw%d", minor);
- class_device_create(input_class,
+ cdev = class_device_create(&input_class, &dev->cdev,
MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
- dev->dev, "ts%d", minor);
+ dev->cdev.dev, tsdev->name);
+
+ /* temporary symlink to keep userspace happy */
+ sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
+ tsdev->name);
return &tsdev->handle;
}
@@ -426,10 +426,9 @@ static void tsdev_disconnect(struct input_handle *handle)
struct tsdev *tsdev = handle->private;
struct tsdev_list *list;
- class_device_destroy(input_class,
+ sysfs_remove_link(&input_class.subsys.kset.kobj, tsdev->name);
+ class_device_destroy(&input_class,
MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
- devfs_remove("input/ts%d", tsdev->minor);
- devfs_remove("input/tsraw%d", tsdev->minor);
tsdev->exist = 0;
if (tsdev->open) {
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 04fb606b5ddd85..11ae0fddea04bd 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -1505,7 +1505,7 @@ static int __init capi_init(void)
return PTR_ERR(capi_class);
}
- class_device_create(capi_class, MKDEV(capi_major, 0), NULL, "capi");
+ class_device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi");
devfs_mk_cdev(MKDEV(capi_major, 0), S_IFCHR | S_IRUSR | S_IWUSR,
"isdn/capi20");
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index c0dc1e3fa58bfa..d2ead1776c1607 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -905,5 +905,5 @@ adbdev_init(void)
adb_dev_class = class_create(THIS_MODULE, "adb");
if (IS_ERR(adb_dev_class))
return;
- class_device_create(adb_dev_class, MKDEV(ADB_MAJOR, 0), NULL, "adb");
+ class_device_create(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), NULL, "adb");
}
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index db654e8bd67e26..cdb6d028319577 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -206,7 +206,7 @@ u8 adb_to_linux_keycodes[128] = {
};
struct adbhid {
- struct input_dev input;
+ struct input_dev *input;
int id;
int default_id;
int original_handler_id;
@@ -291,10 +291,10 @@ adbhid_input_keycode(int id, int keycode, int repeat, struct pt_regs *regs)
switch (keycode) {
case ADB_KEY_CAPSLOCK: /* Generate down/up events for CapsLock everytime. */
- input_regs(&ahid->input, regs);
- input_report_key(&ahid->input, KEY_CAPSLOCK, 1);
- input_report_key(&ahid->input, KEY_CAPSLOCK, 0);
- input_sync(&ahid->input);
+ input_regs(ahid->input, regs);
+ input_report_key(ahid->input, KEY_CAPSLOCK, 1);
+ input_report_key(ahid->input, KEY_CAPSLOCK, 0);
+ input_sync(ahid->input);
return;
#ifdef CONFIG_PPC_PMAC
case ADB_KEY_POWER_OLD: /* Power key on PBook 3400 needs remapping */
@@ -347,10 +347,10 @@ adbhid_input_keycode(int id, int keycode, int repeat, struct pt_regs *regs)
}
if (adbhid[id]->keycode[keycode]) {
- input_regs(&adbhid[id]->input, regs);
- input_report_key(&adbhid[id]->input,
+ input_regs(adbhid[id]->input, regs);
+ input_report_key(adbhid[id]->input,
adbhid[id]->keycode[keycode], !up_flag);
- input_sync(&adbhid[id]->input);
+ input_sync(adbhid[id]->input);
} else
printk(KERN_INFO "Unhandled ADB key (scancode %#02x) %s.\n", keycode,
up_flag ? "released" : "pressed");
@@ -441,20 +441,20 @@ adbhid_mouse_input(unsigned char *data, int nb, struct pt_regs *regs, int autopo
break;
}
- input_regs(&adbhid[id]->input, regs);
+ input_regs(adbhid[id]->input, regs);
- input_report_key(&adbhid[id]->input, BTN_LEFT, !((data[1] >> 7) & 1));
- input_report_key(&adbhid[id]->input, BTN_MIDDLE, !((data[2] >> 7) & 1));
+ input_report_key(adbhid[id]->input, BTN_LEFT, !((data[1] >> 7) & 1));
+ input_report_key(adbhid[id]->input, BTN_MIDDLE, !((data[2] >> 7) & 1));
if (nb >= 4 && adbhid[id]->mouse_kind != ADBMOUSE_TRACKPAD)
- input_report_key(&adbhid[id]->input, BTN_RIGHT, !((data[3] >> 7) & 1));
+ input_report_key(adbhid[id]->input, BTN_RIGHT, !((data[3] >> 7) & 1));
- input_report_rel(&adbhid[id]->input, REL_X,
+ input_report_rel(adbhid[id]->input, REL_X,
((data[2]&0x7f) < 64 ? (data[2]&0x7f) : (data[2]&0x7f)-128 ));
- input_report_rel(&adbhid[id]->input, REL_Y,
+ input_report_rel(adbhid[id]->input, REL_Y,
((data[1]&0x7f) < 64 ? (data[1]&0x7f) : (data[1]&0x7f)-128 ));
- input_sync(&adbhid[id]->input);
+ input_sync(adbhid[id]->input);
}
static void
@@ -467,7 +467,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
return;
}
- input_regs(&adbhid[id]->input, regs);
+ input_regs(adbhid[id]->input, regs);
switch (adbhid[id]->original_handler_id) {
default:
@@ -477,19 +477,19 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
switch (data[1] & 0x0f) {
case 0x0: /* microphone */
- input_report_key(&adbhid[id]->input, KEY_SOUND, down);
+ input_report_key(adbhid[id]->input, KEY_SOUND, down);
break;
case 0x1: /* mute */
- input_report_key(&adbhid[id]->input, KEY_MUTE, down);
+ input_report_key(adbhid[id]->input, KEY_MUTE, down);
break;
case 0x2: /* volume decrease */
- input_report_key(&adbhid[id]->input, KEY_VOLUMEDOWN, down);
+ input_report_key(adbhid[id]->input, KEY_VOLUMEDOWN, down);
break;
case 0x3: /* volume increase */
- input_report_key(&adbhid[id]->input, KEY_VOLUMEUP, down);
+ input_report_key(adbhid[id]->input, KEY_VOLUMEUP, down);
break;
default:
@@ -513,19 +513,19 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
switch (data[1] & 0x0f) {
case 0x8: /* mute */
- input_report_key(&adbhid[id]->input, KEY_MUTE, down);
+ input_report_key(adbhid[id]->input, KEY_MUTE, down);
break;
case 0x7: /* volume decrease */
- input_report_key(&adbhid[id]->input, KEY_VOLUMEDOWN, down);
+ input_report_key(adbhid[id]->input, KEY_VOLUMEDOWN, down);
break;
case 0x6: /* volume increase */
- input_report_key(&adbhid[id]->input, KEY_VOLUMEUP, down);
+ input_report_key(adbhid[id]->input, KEY_VOLUMEUP, down);
break;
case 0xb: /* eject */
- input_report_key(&adbhid[id]->input, KEY_EJECTCD, down);
+ input_report_key(adbhid[id]->input, KEY_EJECTCD, down);
break;
case 0xa: /* brightness decrease */
@@ -539,7 +539,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
}
}
#endif /* CONFIG_PMAC_BACKLIGHT */
- input_report_key(&adbhid[id]->input, KEY_BRIGHTNESSDOWN, down);
+ input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down);
break;
case 0x9: /* brightness increase */
@@ -553,19 +553,19 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
}
}
#endif /* CONFIG_PMAC_BACKLIGHT */
- input_report_key(&adbhid[id]->input, KEY_BRIGHTNESSUP, down);
+ input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down);
break;
case 0xc: /* videomode switch */
- input_report_key(&adbhid[id]->input, KEY_SWITCHVIDEOMODE, down);
+ input_report_key(adbhid[id]->input, KEY_SWITCHVIDEOMODE, down);
break;
case 0xd: /* keyboard illumination toggle */
- input_report_key(&adbhid[id]->input, KEY_KBDILLUMTOGGLE, down);
+ input_report_key(adbhid[id]->input, KEY_KBDILLUMTOGGLE, down);
break;
case 0xe: /* keyboard illumination decrease */
- input_report_key(&adbhid[id]->input, KEY_KBDILLUMDOWN, down);
+ input_report_key(adbhid[id]->input, KEY_KBDILLUMDOWN, down);
break;
case 0xf:
@@ -573,7 +573,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
case 0x8f:
case 0x0f:
/* keyboard illumination increase */
- input_report_key(&adbhid[id]->input, KEY_KBDILLUMUP, down);
+ input_report_key(adbhid[id]->input, KEY_KBDILLUMUP, down);
break;
case 0x7f:
@@ -596,7 +596,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
break;
}
- input_sync(&adbhid[id]->input);
+ input_sync(adbhid[id]->input);
}
static struct adb_request led_request;
@@ -683,7 +683,7 @@ adb_message_handler(struct notifier_block *this, unsigned long code, void *x)
int i;
for (i = 1; i < 16; i++) {
if (adbhid[i])
- del_timer_sync(&adbhid[i]->input.timer);
+ del_timer_sync(&adbhid[i]->input->timer);
}
}
@@ -699,153 +699,163 @@ adb_message_handler(struct notifier_block *this, unsigned long code, void *x)
return NOTIFY_DONE;
}
-static void
+static int
adbhid_input_register(int id, int default_id, int original_handler_id,
int current_handler_id, int mouse_kind)
{
+ struct adbhid *hid;
+ struct input_dev *input_dev;
+ int err;
int i;
if (adbhid[id]) {
printk(KERN_ERR "Trying to reregister ADB HID on ID %d\n", id);
- return;
+ return -EEXIST;
}
- if (!(adbhid[id] = kmalloc(sizeof(struct adbhid), GFP_KERNEL)))
- return;
-
- memset(adbhid[id], 0, sizeof(struct adbhid));
- sprintf(adbhid[id]->phys, "adb%d:%d.%02x/input", id, default_id, original_handler_id);
+ adbhid[id] = hid = kzalloc(sizeof(struct adbhid), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!hid || !input_dev) {
+ err = -ENOMEM;
+ goto fail;
- init_input_dev(&adbhid[id]->input);
+ }
- adbhid[id]->id = default_id;
- adbhid[id]->original_handler_id = original_handler_id;
- adbhid[id]->current_handler_id = current_handler_id;
- adbhid[id]->mouse_kind = mouse_kind;
- adbhid[id]->flags = 0;
- adbhid[id]->input.private = adbhid[id];
- adbhid[id]->input.name = adbhid[id]->name;
- adbhid[id]->input.phys = adbhid[id]->phys;
- adbhid[id]->input.id.bustype = BUS_ADB;
- adbhid[id]->input.id.vendor = 0x0001;
- adbhid[id]->input.id.product = (id << 12) | (default_id << 8) | original_handler_id;
- adbhid[id]->input.id.version = 0x0100;
+ sprintf(hid->phys, "adb%d:%d.%02x/input", id, default_id, original_handler_id);
+
+ hid->id = default_id;
+ hid->original_handler_id = original_handler_id;
+ hid->current_handler_id = current_handler_id;
+ hid->mouse_kind = mouse_kind;
+ hid->flags = 0;
+ input_dev->private = hid;
+ input_dev->name = hid->name;
+ input_dev->phys = hid->phys;
+ input_dev->id.bustype = BUS_ADB;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = (id << 12) | (default_id << 8) | original_handler_id;
+ input_dev->id.version = 0x0100;
switch (default_id) {
case ADB_KEYBOARD:
- if (!(adbhid[id]->keycode = kmalloc(sizeof(adb_to_linux_keycodes), GFP_KERNEL))) {
- kfree(adbhid[id]);
- return;
+ hid->keycode = kmalloc(sizeof(adb_to_linux_keycodes), GFP_KERNEL);
+ if (!hid->keycode) {
+ err = -ENOMEM;
+ goto fail;
}
- sprintf(adbhid[id]->name, "ADB keyboard");
+ sprintf(hid->name, "ADB keyboard");
- memcpy(adbhid[id]->keycode, adb_to_linux_keycodes, sizeof(adb_to_linux_keycodes));
+ memcpy(hid->keycode, adb_to_linux_keycodes, sizeof(adb_to_linux_keycodes));
printk(KERN_INFO "Detected ADB keyboard, type ");
switch (original_handler_id) {
default:
printk("<unknown>.\n");
- adbhid[id]->input.id.version = ADB_KEYBOARD_UNKNOWN;
+ input_dev->id.version = ADB_KEYBOARD_UNKNOWN;
break;
case 0x01: case 0x02: case 0x03: case 0x06: case 0x08:
case 0x0C: case 0x10: case 0x18: case 0x1B: case 0x1C:
case 0xC0: case 0xC3: case 0xC6:
printk("ANSI.\n");
- adbhid[id]->input.id.version = ADB_KEYBOARD_ANSI;
+ input_dev->id.version = ADB_KEYBOARD_ANSI;
break;
case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D:
case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1:
case 0xC4: case 0xC7:
printk("ISO, swapping keys.\n");
- adbhid[id]->input.id.version = ADB_KEYBOARD_ISO;
- i = adbhid[id]->keycode[10];
- adbhid[id]->keycode[10] = adbhid[id]->keycode[50];
- adbhid[id]->keycode[50] = i;
+ input_dev->id.version = ADB_KEYBOARD_ISO;
+ i = hid->keycode[10];
+ hid->keycode[10] = hid->keycode[50];
+ hid->keycode[50] = i;
break;
case 0x12: case 0x15: case 0x16: case 0x17: case 0x1A:
case 0x1E: case 0xC2: case 0xC5: case 0xC8: case 0xC9:
printk("JIS.\n");
- adbhid[id]->input.id.version = ADB_KEYBOARD_JIS;
+ input_dev->id.version = ADB_KEYBOARD_JIS;
break;
}
for (i = 0; i < 128; i++)
- if (adbhid[id]->keycode[i])
- set_bit(adbhid[id]->keycode[i], adbhid[id]->input.keybit);
-
- adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
- adbhid[id]->input.ledbit[0] = BIT(LED_SCROLLL) | BIT(LED_CAPSL) | BIT(LED_NUML);
- adbhid[id]->input.event = adbhid_kbd_event;
- adbhid[id]->input.keycodemax = 127;
- adbhid[id]->input.keycodesize = 1;
+ if (hid->keycode[i])
+ set_bit(hid->keycode[i], input_dev->keybit);
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
+ input_dev->ledbit[0] = BIT(LED_SCROLLL) | BIT(LED_CAPSL) | BIT(LED_NUML);
+ input_dev->event = adbhid_kbd_event;
+ input_dev->keycodemax = 127;
+ input_dev->keycodesize = 1;
break;
case ADB_MOUSE:
- sprintf(adbhid[id]->name, "ADB mouse");
+ sprintf(hid->name, "ADB mouse");
- adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- adbhid[id]->input.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- adbhid[id]->input.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
break;
case ADB_MISC:
switch (original_handler_id) {
case 0x02: /* Adjustable keyboard button device */
- sprintf(adbhid[id]->name, "ADB adjustable keyboard buttons");
- adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
- set_bit(KEY_SOUND, adbhid[id]->input.keybit);
- set_bit(KEY_MUTE, adbhid[id]->input.keybit);
- set_bit(KEY_VOLUMEUP, adbhid[id]->input.keybit);
- set_bit(KEY_VOLUMEDOWN, adbhid[id]->input.keybit);
+ sprintf(hid->name, "ADB adjustable keyboard buttons");
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ set_bit(KEY_SOUND, input_dev->keybit);
+ set_bit(KEY_MUTE, input_dev->keybit);
+ set_bit(KEY_VOLUMEUP, input_dev->keybit);
+ set_bit(KEY_VOLUMEDOWN, input_dev->keybit);
break;
case 0x1f: /* Powerbook button device */
- sprintf(adbhid[id]->name, "ADB Powerbook buttons");
- adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
- set_bit(KEY_MUTE, adbhid[id]->input.keybit);
- set_bit(KEY_VOLUMEUP, adbhid[id]->input.keybit);
- set_bit(KEY_VOLUMEDOWN, adbhid[id]->input.keybit);
- set_bit(KEY_BRIGHTNESSUP, adbhid[id]->input.keybit);
- set_bit(KEY_BRIGHTNESSDOWN, adbhid[id]->input.keybit);
- set_bit(KEY_EJECTCD, adbhid[id]->input.keybit);
- set_bit(KEY_SWITCHVIDEOMODE, adbhid[id]->input.keybit);
- set_bit(KEY_KBDILLUMTOGGLE, adbhid[id]->input.keybit);
- set_bit(KEY_KBDILLUMDOWN, adbhid[id]->input.keybit);
- set_bit(KEY_KBDILLUMUP, adbhid[id]->input.keybit);
+ sprintf(hid->name, "ADB Powerbook buttons");
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ set_bit(KEY_MUTE, input_dev->keybit);
+ set_bit(KEY_VOLUMEUP, input_dev->keybit);
+ set_bit(KEY_VOLUMEDOWN, input_dev->keybit);
+ set_bit(KEY_BRIGHTNESSUP, input_dev->keybit);
+ set_bit(KEY_BRIGHTNESSDOWN, input_dev->keybit);
+ set_bit(KEY_EJECTCD, input_dev->keybit);
+ set_bit(KEY_SWITCHVIDEOMODE, input_dev->keybit);
+ set_bit(KEY_KBDILLUMTOGGLE, input_dev->keybit);
+ set_bit(KEY_KBDILLUMDOWN, input_dev->keybit);
+ set_bit(KEY_KBDILLUMUP, input_dev->keybit);
break;
}
- if (adbhid[id]->name[0])
+ if (hid->name[0])
break;
/* else fall through */
default:
printk(KERN_INFO "Trying to register unknown ADB device to input layer.\n");
- kfree(adbhid[id]);
- return;
+ err = -ENODEV;
+ goto fail;
}
- adbhid[id]->input.keycode = adbhid[id]->keycode;
-
- input_register_device(&adbhid[id]->input);
+ input_dev->keycode = hid->keycode;
- printk(KERN_INFO "input: %s on %s\n",
- adbhid[id]->name, adbhid[id]->phys);
+ input_register_device(input_dev);
if (default_id == ADB_KEYBOARD) {
/* HACK WARNING!! This should go away as soon there is an utility
* to control that for event devices.
*/
- adbhid[id]->input.rep[REP_DELAY] = 500; /* input layer default: 250 */
- adbhid[id]->input.rep[REP_PERIOD] = 66; /* input layer default: 33 */
+ input_dev->rep[REP_DELAY] = 500; /* input layer default: 250 */
+ input_dev->rep[REP_PERIOD] = 66; /* input layer default: 33 */
}
+
+ return 0;
+
+ fail: input_free_device(input_dev);
+ kfree(hid);
+ adbhid[id] = NULL;
+ return err;
}
static void adbhid_input_unregister(int id)
{
- input_unregister_device(&adbhid[id]->input);
+ input_unregister_device(adbhid[id]->input);
if (adbhid[id]->keycode)
kfree(adbhid[id]->keycode);
kfree(adbhid[id]);
@@ -858,7 +868,7 @@ adbhid_input_reregister(int id, int default_id, int org_handler_id,
int cur_handler_id, int mk)
{
if (adbhid[id]) {
- if (adbhid[id]->input.id.product !=
+ if (adbhid[id]->input->id.product !=
((id << 12)|(default_id << 8)|org_handler_id)) {
adbhid_input_unregister(id);
adbhid_input_register(id, default_id, org_handler_id,
diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
index 5ad3a5a9eb7f21..a66636116f0b4f 100644
--- a/drivers/macintosh/mac_hid.c
+++ b/drivers/macintosh/mac_hid.c
@@ -16,8 +16,8 @@
#include <linux/module.h>
-static struct input_dev emumousebtn;
-static void emumousebtn_input_register(void);
+static struct input_dev *emumousebtn;
+static int emumousebtn_input_register(void);
static int mouse_emulate_buttons = 0;
static int mouse_button2_keycode = KEY_RIGHTCTRL; /* right control key */
static int mouse_button3_keycode = KEY_RIGHTALT; /* right option key */
@@ -90,10 +90,10 @@ int mac_hid_mouse_emulate_buttons(int caller, unsigned int keycode, int down)
&& (keycode == mouse_button2_keycode
|| keycode == mouse_button3_keycode)) {
if (mouse_emulate_buttons == 1) {
- input_report_key(&emumousebtn,
+ input_report_key(emumousebtn,
keycode == mouse_button2_keycode ? BTN_MIDDLE : BTN_RIGHT,
down);
- input_sync(&emumousebtn);
+ input_sync(emumousebtn);
return 1;
}
mouse_last_keycode = down ? keycode : 0;
@@ -105,30 +105,34 @@ int mac_hid_mouse_emulate_buttons(int caller, unsigned int keycode, int down)
EXPORT_SYMBOL(mac_hid_mouse_emulate_buttons);
-static void emumousebtn_input_register(void)
+static int emumousebtn_input_register(void)
{
- emumousebtn.name = "Macintosh mouse button emulation";
+ emumousebtn = input_allocate_device();
+ if (!emumousebtn)
+ return -ENOMEM;
- init_input_dev(&emumousebtn);
+ emumousebtn->name = "Macintosh mouse button emulation";
+ emumousebtn->id.bustype = BUS_ADB;
+ emumousebtn->id.vendor = 0x0001;
+ emumousebtn->id.product = 0x0001;
+ emumousebtn->id.version = 0x0100;
- emumousebtn.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- emumousebtn.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- emumousebtn.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ emumousebtn->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ emumousebtn->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ emumousebtn->relbit[0] = BIT(REL_X) | BIT(REL_Y);
- emumousebtn.id.bustype = BUS_ADB;
- emumousebtn.id.vendor = 0x0001;
- emumousebtn.id.product = 0x0001;
- emumousebtn.id.version = 0x0100;
+ input_register_device(emumousebtn);
- input_register_device(&emumousebtn);
-
- printk(KERN_INFO "input: Macintosh mouse button emulation\n");
+ return 0;
}
int __init mac_hid_init(void)
{
+ int err;
- emumousebtn_input_register();
+ err = emumousebtn_input_register();
+ if (err)
+ return err;
#if defined(CONFIG_SYSCTL)
mac_hid_sysctl_header = register_sysctl_table(mac_hid_root_dir, 1);
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 2fba2bbe72d8f6..01654fcabc5212 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -91,7 +91,7 @@ int bitmap_active(struct bitmap *bitmap)
#define WRITE_POOL_SIZE 256
/* mempool for queueing pending writes on the bitmap file */
-static void *write_pool_alloc(unsigned int gfp_flags, void *data)
+static void *write_pool_alloc(gfp_t gfp_flags, void *data)
{
return kmalloc(sizeof(struct page_list), gfp_flags);
}
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index b6148f6f783672..28c1a628621fa2 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -331,7 +331,7 @@ crypt_alloc_buffer(struct crypt_config *cc, unsigned int size,
{
struct bio *bio;
unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
- int gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
+ gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
unsigned int i;
/*
diff --git a/drivers/md/md.c b/drivers/md/md.c
index e9476075aa13df..2a8a5696bf8aec 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -3568,7 +3568,8 @@ static void md_do_sync(mddev_t *mddev)
mddev->curr_resync = 2;
try_again:
- if (signal_pending(current)) {
+ if (signal_pending(current) ||
+ kthread_should_stop()) {
flush_signals(current);
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
goto skip;
@@ -3590,8 +3591,9 @@ static void md_do_sync(mddev_t *mddev)
*/
continue;
prepare_to_wait(&resync_wait, &wq, TASK_INTERRUPTIBLE);
- if (!signal_pending(current)
- && mddev2->curr_resync >= mddev->curr_resync) {
+ if (!signal_pending(current) &&
+ !kthread_should_stop() &&
+ mddev2->curr_resync >= mddev->curr_resync) {
printk(KERN_INFO "md: delaying resync of %s"
" until %s has finished resync (they"
" share one or more physical units)\n",
@@ -3697,7 +3699,7 @@ static void md_do_sync(mddev_t *mddev)
}
- if (signal_pending(current)) {
+ if (signal_pending(current) || kthread_should_stop()) {
/*
* got a signal, exit.
*/
diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c
index a0e700d7a4a4ad..06f4d4686a6c71 100644
--- a/drivers/media/common/ir-common.c
+++ b/drivers/media/common/ir-common.c
@@ -252,7 +252,6 @@ void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
if (ir_codes)
memcpy(ir->ir_codes, ir_codes, sizeof(ir->ir_codes));
- init_input_dev(dev);
dev->keycode = ir->ir_codes;
dev->keycodesize = sizeof(IR_KEYTAB_TYPE);
dev->keycodemax = IR_KEYTAB_SIZE;
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index 6db0929ef53dbf..a1607e7d6d6bfb 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -137,7 +137,8 @@ struct cinergyt2 {
struct urb *stream_urb [STREAM_URB_COUNT];
#ifdef ENABLE_RC
- struct input_dev rc_input_dev;
+ struct input_dev *rc_input_dev;
+ char phys[64];
struct work_struct rc_query_work;
int rc_input_event;
u32 rc_last_code;
@@ -683,6 +684,7 @@ static struct dvb_device cinergyt2_fe_template = {
};
#ifdef ENABLE_RC
+
static void cinergyt2_query_rc (void *data)
{
struct cinergyt2 *cinergyt2 = data;
@@ -703,7 +705,7 @@ static void cinergyt2_query_rc (void *data)
/* stop key repeat */
if (cinergyt2->rc_input_event != KEY_MAX) {
dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event);
- input_report_key(&cinergyt2->rc_input_dev,
+ input_report_key(cinergyt2->rc_input_dev,
cinergyt2->rc_input_event, 0);
cinergyt2->rc_input_event = KEY_MAX;
}
@@ -722,7 +724,7 @@ static void cinergyt2_query_rc (void *data)
/* keyrepeat bit -> just repeat last rc_input_event */
} else {
cinergyt2->rc_input_event = KEY_MAX;
- for (i = 0; i < sizeof(rc_keys) / sizeof(rc_keys[0]); i += 3) {
+ for (i = 0; i < ARRAY_SIZE(rc_keys); i += 3) {
if (rc_keys[i + 0] == rc_events[n].type &&
rc_keys[i + 1] == le32_to_cpu(rc_events[n].value)) {
cinergyt2->rc_input_event = rc_keys[i + 2];
@@ -736,11 +738,11 @@ static void cinergyt2_query_rc (void *data)
cinergyt2->rc_last_code != ~0) {
/* emit a key-up so the double event is recognized */
dprintk(1, "rc_input_event=%d UP\n", cinergyt2->rc_input_event);
- input_report_key(&cinergyt2->rc_input_dev,
+ input_report_key(cinergyt2->rc_input_dev,
cinergyt2->rc_input_event, 0);
}
dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event);
- input_report_key(&cinergyt2->rc_input_dev,
+ input_report_key(cinergyt2->rc_input_dev,
cinergyt2->rc_input_event, 1);
cinergyt2->rc_last_code = rc_events[n].value;
}
@@ -752,7 +754,59 @@ out:
up(&cinergyt2->sem);
}
-#endif
+
+static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
+{
+ struct input_dev *input_dev;
+ int i;
+
+ cinergyt2->rc_input_dev = input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
+
+ usb_make_path(cinergyt2->udev, cinergyt2->phys, sizeof(cinergyt2->phys));
+ strlcat(cinergyt2->phys, "/input0", sizeof(cinergyt2->phys));
+ cinergyt2->rc_input_event = KEY_MAX;
+ cinergyt2->rc_last_code = ~0;
+ INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2);
+
+ input_dev->name = DRIVER_NAME " remote control";
+ input_dev->phys = cinergyt2->phys;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ for (i = 0; ARRAY_SIZE(rc_keys); i += 3)
+ set_bit(rc_keys[i + 2], input_dev->keybit);
+ input_dev->keycodesize = 0;
+ input_dev->keycodemax = 0;
+
+ input_register_device(cinergyt2->rc_input_dev);
+ schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
+}
+
+static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2)
+{
+ cancel_delayed_work(&cinergyt2->rc_query_work);
+ flush_scheduled_work();
+ input_unregister_device(cinergyt2->rc_input_dev);
+}
+
+static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2)
+{
+ cancel_delayed_work(&cinergyt2->rc_query_work);
+}
+
+static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2)
+{
+ schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
+}
+
+#else
+
+static inline int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) { return 0; }
+static inline void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2) { }
+static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2) { }
+static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) { }
+
+#endif /* ENABLE_RC */
static void cinergyt2_query (void *data)
{
@@ -789,9 +843,6 @@ static int cinergyt2_probe (struct usb_interface *intf,
{
struct cinergyt2 *cinergyt2;
int err;
-#ifdef ENABLE_RC
- int i;
-#endif
if (!(cinergyt2 = kmalloc (sizeof(struct cinergyt2), GFP_KERNEL))) {
dprintk(1, "out of memory?!?\n");
@@ -846,30 +897,17 @@ static int cinergyt2_probe (struct usb_interface *intf,
&cinergyt2_fe_template, cinergyt2,
DVB_DEVICE_FRONTEND);
-#ifdef ENABLE_RC
- cinergyt2->rc_input_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
- cinergyt2->rc_input_dev.keycodesize = 0;
- cinergyt2->rc_input_dev.keycodemax = 0;
- cinergyt2->rc_input_dev.name = DRIVER_NAME " remote control";
-
- for (i = 0; i < sizeof(rc_keys) / sizeof(rc_keys[0]); i += 3)
- set_bit(rc_keys[i + 2], cinergyt2->rc_input_dev.keybit);
-
- input_register_device(&cinergyt2->rc_input_dev);
-
- cinergyt2->rc_input_event = KEY_MAX;
- cinergyt2->rc_last_code = ~0;
+ err = cinergyt2_register_rc(cinergyt2);
+ if (err)
+ goto bailout;
- INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2);
- schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
-#endif
return 0;
bailout:
dvb_dmxdev_release(&cinergyt2->dmxdev);
dvb_dmx_release(&cinergyt2->demux);
- dvb_unregister_adapter (&cinergyt2->adapter);
- cinergyt2_free_stream_urbs (cinergyt2);
+ dvb_unregister_adapter(&cinergyt2->adapter);
+ cinergyt2_free_stream_urbs(cinergyt2);
kfree(cinergyt2);
return -ENOMEM;
}
@@ -881,11 +919,7 @@ static void cinergyt2_disconnect (struct usb_interface *intf)
if (down_interruptible(&cinergyt2->sem))
return;
-#ifdef ENABLE_RC
- cancel_delayed_work(&cinergyt2->rc_query_work);
- flush_scheduled_work();
- input_unregister_device(&cinergyt2->rc_input_dev);
-#endif
+ cinergyt2_unregister_rc(cinergyt2);
cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx);
dvb_net_release(&cinergyt2->dvbnet);
@@ -908,9 +942,8 @@ static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state)
if (state.event > PM_EVENT_ON) {
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
-#ifdef ENABLE_RC
- cancel_delayed_work(&cinergyt2->rc_query_work);
-#endif
+
+ cinergyt2_suspend_rc(cinergyt2);
cancel_delayed_work(&cinergyt2->query_work);
if (cinergyt2->streaming)
cinergyt2_stop_stream_xfer(cinergyt2);
@@ -938,9 +971,8 @@ static int cinergyt2_resume (struct usb_interface *intf)
schedule_delayed_work(&cinergyt2->query_work, HZ/2);
}
-#ifdef ENABLE_RC
- schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
-#endif
+ cinergyt2_resume_rc(cinergyt2);
+
up(&cinergyt2->sem);
return 0;
}
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 4b7adca3e286d2..477b4fa56430ab 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -235,7 +235,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
S_IFCHR | S_IRUSR | S_IWUSR,
"dvb/adapter%d/%s%d", adap->num, dnames[type], id);
- class_device_create(dvb_class, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
+ class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
index fc7800f1743ee5..e5c6d9835e06d2 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
@@ -39,9 +39,9 @@ static void dvb_usb_read_remote_control(void *data)
d->last_event = event;
case REMOTE_KEY_REPEAT:
deb_rc("key repeated\n");
- input_event(&d->rc_input_dev, EV_KEY, d->last_event, 1);
- input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0);
- input_sync(&d->rc_input_dev);
+ input_event(d->rc_input_dev, EV_KEY, event, 1);
+ input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
+ input_sync(d->rc_input_dev);
break;
default:
break;
@@ -53,8 +53,8 @@ static void dvb_usb_read_remote_control(void *data)
deb_rc("NO KEY PRESSED\n");
if (d->last_state != REMOTE_NO_KEY_PRESSED) {
deb_rc("releasing event %d\n",d->last_event);
- input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0);
- input_sync(&d->rc_input_dev);
+ input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
+ input_sync(d->rc_input_dev);
}
d->last_state = REMOTE_NO_KEY_PRESSED;
d->last_event = 0;
@@ -63,8 +63,8 @@ static void dvb_usb_read_remote_control(void *data)
deb_rc("KEY PRESSED\n");
deb_rc("pressing event %d\n",event);
- input_event(&d->rc_input_dev, EV_KEY, event, 1);
- input_sync(&d->rc_input_dev);
+ input_event(d->rc_input_dev, EV_KEY, event, 1);
+ input_sync(d->rc_input_dev);
d->last_event = event;
d->last_state = REMOTE_KEY_PRESSED;
@@ -73,8 +73,8 @@ static void dvb_usb_read_remote_control(void *data)
deb_rc("KEY_REPEAT\n");
if (d->last_state != REMOTE_NO_KEY_PRESSED) {
deb_rc("repeating event %d\n",d->last_event);
- input_event(&d->rc_input_dev, EV_KEY, d->last_event, 2);
- input_sync(&d->rc_input_dev);
+ input_event(d->rc_input_dev, EV_KEY, d->last_event, 2);
+ input_sync(d->rc_input_dev);
d->last_state = REMOTE_KEY_REPEAT;
}
default:
@@ -89,24 +89,30 @@ schedule:
int dvb_usb_remote_init(struct dvb_usb_device *d)
{
int i;
+
if (d->props.rc_key_map == NULL ||
d->props.rc_query == NULL ||
dvb_usb_disable_rc_polling)
return 0;
- /* Initialise the remote-control structures.*/
- init_input_dev(&d->rc_input_dev);
+ usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
+ strlcpy(d->rc_phys, "/ir0", sizeof(d->rc_phys));
+
+ d->rc_input_dev = input_allocate_device();
+ if (!d->rc_input_dev)
+ return -ENOMEM;
- d->rc_input_dev.evbit[0] = BIT(EV_KEY);
- d->rc_input_dev.keycodesize = sizeof(unsigned char);
- d->rc_input_dev.keycodemax = KEY_MAX;
- d->rc_input_dev.name = "IR-receiver inside an USB DVB receiver";
+ d->rc_input_dev->evbit[0] = BIT(EV_KEY);
+ d->rc_input_dev->keycodesize = sizeof(unsigned char);
+ d->rc_input_dev->keycodemax = KEY_MAX;
+ d->rc_input_dev->name = "IR-receiver inside an USB DVB receiver";
+ d->rc_input_dev->phys = d->rc_phys;
/* set the bits for the keys */
- deb_rc("key map size: %d\n",d->props.rc_key_map_size);
+ deb_rc("key map size: %d\n", d->props.rc_key_map_size);
for (i = 0; i < d->props.rc_key_map_size; i++) {
deb_rc("setting bit for event %d item %d\n",d->props.rc_key_map[i].event, i);
- set_bit(d->props.rc_key_map[i].event, d->rc_input_dev.keybit);
+ set_bit(d->props.rc_key_map[i].event, d->rc_input_dev->keybit);
}
/* Start the remote-control polling. */
@@ -114,14 +120,14 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
d->props.rc_interval = 100; /* default */
/* setting these two values to non-zero, we have to manage key repeats */
- d->rc_input_dev.rep[REP_PERIOD] = d->props.rc_interval;
- d->rc_input_dev.rep[REP_DELAY] = d->props.rc_interval + 150;
+ d->rc_input_dev->rep[REP_PERIOD] = d->props.rc_interval;
+ d->rc_input_dev->rep[REP_DELAY] = d->props.rc_interval + 150;
- input_register_device(&d->rc_input_dev);
+ input_register_device(d->rc_input_dev);
INIT_WORK(&d->rc_query_work, dvb_usb_read_remote_control, d);
- info("schedule remote query interval to %d msecs.",d->props.rc_interval);
+ info("schedule remote query interval to %d msecs.", d->props.rc_interval);
schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
d->state |= DVB_USB_STATE_REMOTE;
@@ -134,7 +140,7 @@ int dvb_usb_remote_exit(struct dvb_usb_device *d)
if (d->state & DVB_USB_STATE_REMOTE) {
cancel_delayed_work(&d->rc_query_work);
flush_scheduled_work();
- input_unregister_device(&d->rc_input_dev);
+ input_unregister_device(d->rc_input_dev);
}
d->state &= ~DVB_USB_STATE_REMOTE;
return 0;
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index 0e4f1035b0dd56..b4a1a98006c7d9 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -300,7 +300,8 @@ struct dvb_usb_device {
int (*fe_init) (struct dvb_frontend *);
/* remote control */
- struct input_dev rc_input_dev;
+ struct input_dev *rc_input_dev;
+ char rc_phys[64];
struct work_struct rc_query_work;
u32 last_event;
int last_state;
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index 357a3728ec68fe..f5e59fc924afea 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -15,7 +15,7 @@
static int av_cnt;
static struct av7110 *av_list[4];
-static struct input_dev input_dev;
+static struct input_dev *input_dev;
static u16 key_map [256] = {
KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7,
@@ -43,10 +43,10 @@ static u16 key_map [256] = {
static void av7110_emit_keyup(unsigned long data)
{
- if (!data || !test_bit(data, input_dev.key))
+ if (!data || !test_bit(data, input_dev->key))
return;
- input_event(&input_dev, EV_KEY, data, !!0);
+ input_event(input_dev, EV_KEY, data, !!0);
}
@@ -112,13 +112,13 @@ static void av7110_emit_key(unsigned long parm)
if (timer_pending(&keyup_timer)) {
del_timer(&keyup_timer);
if (keyup_timer.data != keycode || new_toggle != old_toggle) {
- input_event(&input_dev, EV_KEY, keyup_timer.data, !!0);
- input_event(&input_dev, EV_KEY, keycode, !0);
+ input_event(input_dev, EV_KEY, keyup_timer.data, !!0);
+ input_event(input_dev, EV_KEY, keycode, !0);
} else
- input_event(&input_dev, EV_KEY, keycode, 2);
+ input_event(input_dev, EV_KEY, keycode, 2);
} else
- input_event(&input_dev, EV_KEY, keycode, !0);
+ input_event(input_dev, EV_KEY, keycode, !0);
keyup_timer.expires = jiffies + UP_TIMEOUT;
keyup_timer.data = keycode;
@@ -132,13 +132,13 @@ static void input_register_keys(void)
{
int i;
- memset(input_dev.keybit, 0, sizeof(input_dev.keybit));
+ memset(input_dev->keybit, 0, sizeof(input_dev->keybit));
- for (i = 0; i < sizeof(key_map) / sizeof(key_map[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(key_map); i++) {
if (key_map[i] > KEY_MAX)
key_map[i] = 0;
else if (key_map[i] > KEY_RESERVED)
- set_bit(key_map[i], input_dev.keybit);
+ set_bit(key_map[i], input_dev->keybit);
}
}
@@ -216,12 +216,17 @@ int __init av7110_ir_init(struct av7110 *av7110)
init_timer(&keyup_timer);
keyup_timer.data = 0;
- input_dev.name = "DVB on-card IR receiver";
- set_bit(EV_KEY, input_dev.evbit);
- set_bit(EV_REP, input_dev.evbit);
+ input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
+
+ input_dev->name = "DVB on-card IR receiver";
+
+ set_bit(EV_KEY, input_dev->evbit);
+ set_bit(EV_REP, input_dev->evbit);
input_register_keys();
- input_register_device(&input_dev);
- input_dev.timer.function = input_repeat_key;
+ input_register_device(input_dev);
+ input_dev->timer.function = input_repeat_key;
e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL);
if (e) {
@@ -256,7 +261,7 @@ void __exit av7110_ir_exit(struct av7110 *av7110)
if (av_cnt == 1) {
del_timer_sync(&keyup_timer);
remove_proc_entry("av7110_ir", NULL);
- input_unregister_device(&input_dev);
+ input_unregister_device(input_dev);
}
av_cnt--;
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 2980db3ef22f8c..51c30ba68140ac 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -64,7 +64,7 @@
struct budget_ci {
struct budget budget;
- struct input_dev input_dev;
+ struct input_dev *input_dev;
struct tasklet_struct msp430_irq_tasklet;
struct tasklet_struct ciintf_irq_tasklet;
int slot_status;
@@ -145,7 +145,7 @@ static void msp430_ir_debounce(unsigned long data)
static void msp430_ir_interrupt(unsigned long data)
{
struct budget_ci *budget_ci = (struct budget_ci *) data;
- struct input_dev *dev = &budget_ci->input_dev;
+ struct input_dev *dev = budget_ci->input_dev;
unsigned int code =
ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
@@ -181,25 +181,27 @@ static void msp430_ir_interrupt(unsigned long data)
static int msp430_ir_init(struct budget_ci *budget_ci)
{
struct saa7146_dev *saa = budget_ci->budget.dev;
+ struct input_dev *input_dev;
int i;
- memset(&budget_ci->input_dev, 0, sizeof(struct input_dev));
+ budget_ci->input_dev = input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
sprintf(budget_ci->ir_dev_name, "Budget-CI dvb ir receiver %s", saa->name);
- budget_ci->input_dev.name = budget_ci->ir_dev_name;
- set_bit(EV_KEY, budget_ci->input_dev.evbit);
+ input_dev->name = budget_ci->ir_dev_name;
- for (i = 0; i < sizeof(key_map) / sizeof(*key_map); i++)
+ set_bit(EV_KEY, input_dev->evbit);
+ for (i = 0; i < ARRAY_SIZE(key_map); i++)
if (key_map[i])
- set_bit(key_map[i], budget_ci->input_dev.keybit);
+ set_bit(key_map[i], input_dev->keybit);
- input_register_device(&budget_ci->input_dev);
+ input_register_device(budget_ci->input_dev);
- budget_ci->input_dev.timer.function = msp430_ir_debounce;
+ input_dev->timer.function = msp430_ir_debounce;
saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06);
-
saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
return 0;
@@ -208,7 +210,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
static void msp430_ir_deinit(struct budget_ci *budget_ci)
{
struct saa7146_dev *saa = budget_ci->budget.dev;
- struct input_dev *dev = &budget_ci->input_dev;
+ struct input_dev *dev = budget_ci->input_dev;
saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06);
saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 3d08fc83a7541a..832d179f26fa41 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -152,7 +152,8 @@ struct ttusb_dec {
struct list_head filter_info_list;
spinlock_t filter_info_list_lock;
- struct input_dev rc_input_dev;
+ struct input_dev *rc_input_dev;
+ char rc_phys[64];
int active; /* Loaded successfully */
};
@@ -235,9 +236,9 @@ static void ttusb_dec_handle_irq( struct urb *urb, struct pt_regs *regs)
* this should/could be added later ...
* for now lets report each signal as a key down and up*/
dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]);
- input_report_key(&dec->rc_input_dev,rc_keys[buffer[4]-1],1);
- input_report_key(&dec->rc_input_dev,rc_keys[buffer[4]-1],0);
- input_sync(&dec->rc_input_dev);
+ input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1);
+ input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0);
+ input_sync(dec->rc_input_dev);
}
exit: retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -1181,29 +1182,38 @@ static void ttusb_dec_init_tasklet(struct ttusb_dec *dec)
(unsigned long)dec);
}
-static void ttusb_init_rc( struct ttusb_dec *dec)
+static int ttusb_init_rc(struct ttusb_dec *dec)
{
+ struct input_dev *input_dev;
u8 b[] = { 0x00, 0x01 };
int i;
- init_input_dev(&dec->rc_input_dev);
+ usb_make_path(dec->udev, dec->rc_phys, sizeof(dec->rc_phys));
+ strlcpy(dec->rc_phys, "/input0", sizeof(dec->rc_phys));
- dec->rc_input_dev.name = "ttusb_dec remote control";
- dec->rc_input_dev.evbit[0] = BIT(EV_KEY);
- dec->rc_input_dev.keycodesize = sizeof(u16);
- dec->rc_input_dev.keycodemax = 0x1a;
- dec->rc_input_dev.keycode = rc_keys;
+ dec->rc_input_dev = input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
+
+ input_dev->name = "ttusb_dec remote control";
+ input_dev->phys = dec->rc_phys;
+ input_dev->evbit[0] = BIT(EV_KEY);
+ input_dev->keycodesize = sizeof(u16);
+ input_dev->keycodemax = 0x1a;
+ input_dev->keycode = rc_keys;
- for (i = 0; i < sizeof(rc_keys)/sizeof(rc_keys[0]); i++)
- set_bit(rc_keys[i], dec->rc_input_dev.keybit);
+ for (i = 0; i < ARRAY_SIZE(rc_keys); i++)
+ set_bit(rc_keys[i], input_dev->keybit);
- input_register_device(&dec->rc_input_dev);
+ input_register_device(input_dev);
- if(usb_submit_urb(dec->irq_urb,GFP_KERNEL)) {
+ if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
printk("%s: usb_submit_urb failed\n",__FUNCTION__);
- }
+
/* enable irq pipe */
ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL);
+
+ return 0;
}
static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
@@ -1513,7 +1523,7 @@ static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
* As the irq is submitted after the interface is changed,
* this is the best method i figured out.
* Any others?*/
- if(dec->interface == TTUSB_DEC_INTERFACE_IN)
+ if (dec->interface == TTUSB_DEC_INTERFACE_IN)
usb_kill_urb(dec->irq_urb);
usb_free_urb(dec->irq_urb);
@@ -1521,7 +1531,10 @@ static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
usb_buffer_free(dec->udev,IRQ_PACKET_SIZE,
dec->irq_buffer, dec->irq_dma_handle);
- input_unregister_device(&dec->rc_input_dev);
+ if (dec->rc_input_dev) {
+ input_unregister_device(dec->rc_input_dev);
+ dec->rc_input_dev = NULL;
+ }
}
@@ -1659,7 +1672,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
ttusb_dec_set_interface(dec, TTUSB_DEC_INTERFACE_IN);
- if(enable_rc)
+ if (enable_rc)
ttusb_init_rc(dec);
return 0;
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
index 7a312f79340aa3..e0e7c7a84bc530 100644
--- a/drivers/media/video/bttvp.h
+++ b/drivers/media/video/bttvp.h
@@ -240,7 +240,7 @@ struct bttv_pll_info {
/* for gpio-connected remote control */
struct bttv_input {
- struct input_dev dev;
+ struct input_dev *dev;
struct ir_input_state ir;
char name[32];
char phys[32];
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index d81b21d6e05d0d..c27fe4c36f69f0 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -260,7 +260,7 @@ static IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = {
struct cx88_IR {
struct cx88_core *core;
- struct input_dev input;
+ struct input_dev *input;
struct ir_input_state ir;
char name[32];
char phys[32];
@@ -315,23 +315,23 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
if (ir->mask_keydown) {
/* bit set on keydown */
if (gpio & ir->mask_keydown) {
- ir_input_keydown(&ir->input, &ir->ir, data, data);
+ ir_input_keydown(ir->input, &ir->ir, data, data);
} else {
- ir_input_nokey(&ir->input, &ir->ir);
+ ir_input_nokey(ir->input, &ir->ir);
}
} else if (ir->mask_keyup) {
/* bit cleared on keydown */
if (0 == (gpio & ir->mask_keyup)) {
- ir_input_keydown(&ir->input, &ir->ir, data, data);
+ ir_input_keydown(ir->input, &ir->ir, data, data);
} else {
- ir_input_nokey(&ir->input, &ir->ir);
+ ir_input_nokey(ir->input, &ir->ir);
}
} else {
/* can't distinguish keydown/up :-/ */
- ir_input_keydown(&ir->input, &ir->ir, data, data);
- ir_input_nokey(&ir->input, &ir->ir);
+ ir_input_keydown(ir->input, &ir->ir, data, data);
+ ir_input_nokey(ir->input, &ir->ir);
}
}
@@ -357,13 +357,19 @@ static void cx88_ir_work(void *data)
int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
{
struct cx88_IR *ir;
+ struct input_dev *input_dev;
IR_KEYTAB_TYPE *ir_codes = NULL;
int ir_type = IR_TYPE_OTHER;
- ir = kmalloc(sizeof(*ir), GFP_KERNEL);
- if (NULL == ir)
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ir || !input_dev) {
+ kfree(ir);
+ input_free_device(input_dev);
return -ENOMEM;
- memset(ir, 0, sizeof(*ir));
+ }
+
+ ir->input = input_dev;
/* detect & configure */
switch (core->board) {
@@ -425,6 +431,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
if (NULL == ir_codes) {
kfree(ir);
+ input_free_device(input_dev);
return -ENODEV;
}
@@ -433,19 +440,19 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
cx88_boards[core->board].name);
snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci));
- ir_input_init(&ir->input, &ir->ir, ir_type, ir_codes);
- ir->input.name = ir->name;
- ir->input.phys = ir->phys;
- ir->input.id.bustype = BUS_PCI;
- ir->input.id.version = 1;
+ ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
+ input_dev->name = ir->name;
+ input_dev->phys = ir->phys;
+ input_dev->id.bustype = BUS_PCI;
+ input_dev->id.version = 1;
if (pci->subsystem_vendor) {
- ir->input.id.vendor = pci->subsystem_vendor;
- ir->input.id.product = pci->subsystem_device;
+ input_dev->id.vendor = pci->subsystem_vendor;
+ input_dev->id.product = pci->subsystem_device;
} else {
- ir->input.id.vendor = pci->vendor;
- ir->input.id.product = pci->device;
+ input_dev->id.vendor = pci->vendor;
+ input_dev->id.product = pci->device;
}
- ir->input.dev = &pci->dev;
+ input_dev->cdev.dev = &pci->dev;
/* record handles to ourself */
ir->core = core;
@@ -465,8 +472,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
}
/* all done */
- input_register_device(&ir->input);
- printk("%s: registered IR remote control\n", core->name);
+ input_register_device(ir->input);
return 0;
}
@@ -484,7 +490,7 @@ int cx88_ir_fini(struct cx88_core *core)
flush_scheduled_work();
}
- input_unregister_device(&ir->input);
+ input_unregister_device(ir->input);
kfree(ir);
/* done */
@@ -515,7 +521,7 @@ void cx88_ir_irq(struct cx88_core *core)
if (!ir->scount) {
/* nothing to sample */
if (ir->ir.keypressed && time_after(jiffies, ir->release))
- ir_input_nokey(&ir->input, &ir->ir);
+ ir_input_nokey(ir->input, &ir->ir);
return;
}
@@ -557,7 +563,7 @@ void cx88_ir_irq(struct cx88_core *core)
ir_dprintk("Key Code: %x\n", (ircode >> 16) & 0x7f);
- ir_input_keydown(&ir->input, &ir->ir, (ircode >> 16) & 0x7f, (ircode >> 16) & 0xff);
+ ir_input_keydown(ir->input, &ir->ir, (ircode >> 16) & 0x7f, (ircode >> 16) & 0xff);
ir->release = jiffies + msecs_to_jiffies(120);
break;
case CX88_BOARD_HAUPPAUGE:
@@ -566,7 +572,7 @@ void cx88_ir_irq(struct cx88_core *core)
ir_dprintk("biphase decoded: %x\n", ircode);
if ((ircode & 0xfffff000) != 0x3000)
break;
- ir_input_keydown(&ir->input, &ir->ir, ircode & 0x3f, ircode);
+ ir_input_keydown(ir->input, &ir->ir, ircode & 0x3f, ircode);
ir->release = jiffies + msecs_to_jiffies(120);
break;
}
diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c
index cf292da8fdd575..234151e48edc40 100644
--- a/drivers/media/video/ir-kbd-gpio.c
+++ b/drivers/media/video/ir-kbd-gpio.c
@@ -158,7 +158,7 @@ static IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = {
struct IR {
struct bttv_sub_device *sub;
- struct input_dev input;
+ struct input_dev *input;
struct ir_input_state ir;
char name[32];
char phys[32];
@@ -217,23 +217,23 @@ static void ir_handle_key(struct IR *ir)
if (ir->mask_keydown) {
/* bit set on keydown */
if (gpio & ir->mask_keydown) {
- ir_input_keydown(&ir->input,&ir->ir,data,data);
+ ir_input_keydown(ir->input, &ir->ir, data, data);
} else {
- ir_input_nokey(&ir->input,&ir->ir);
+ ir_input_nokey(ir->input, &ir->ir);
}
} else if (ir->mask_keyup) {
/* bit cleared on keydown */
if (0 == (gpio & ir->mask_keyup)) {
- ir_input_keydown(&ir->input,&ir->ir,data,data);
+ ir_input_keydown(ir->input, &ir->ir, data, data);
} else {
- ir_input_nokey(&ir->input,&ir->ir);
+ ir_input_nokey(ir->input, &ir->ir);
}
} else {
/* can't disturgissh keydown/up :-/ */
- ir_input_keydown(&ir->input,&ir->ir,data,data);
- ir_input_nokey(&ir->input,&ir->ir);
+ ir_input_keydown(ir->input, &ir->ir, data, data);
+ ir_input_nokey(ir->input, &ir->ir);
}
}
@@ -268,13 +268,17 @@ static int ir_probe(struct device *dev)
{
struct bttv_sub_device *sub = to_bttv_sub_dev(dev);
struct IR *ir;
+ struct input_dev *input_dev;
IR_KEYTAB_TYPE *ir_codes = NULL;
int ir_type = IR_TYPE_OTHER;
- ir = kmalloc(sizeof(*ir),GFP_KERNEL);
- if (NULL == ir)
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ir || !input_dev) {
+ kfree(ir);
+ input_free_device(input_dev);
return -ENOMEM;
- memset(ir,0,sizeof(*ir));
+ }
/* detect & configure */
switch (sub->core->type) {
@@ -328,6 +332,7 @@ static int ir_probe(struct device *dev)
}
if (NULL == ir_codes) {
kfree(ir);
+ input_free_device(input_dev);
return -ENODEV;
}
@@ -341,19 +346,19 @@ static int ir_probe(struct device *dev)
snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
pci_name(sub->core->pci));
- ir_input_init(&ir->input, &ir->ir, ir_type, ir_codes);
- ir->input.name = ir->name;
- ir->input.phys = ir->phys;
- ir->input.id.bustype = BUS_PCI;
- ir->input.id.version = 1;
+ ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
+ input_dev->name = ir->name;
+ input_dev->phys = ir->phys;
+ input_dev->id.bustype = BUS_PCI;
+ input_dev->id.version = 1;
if (sub->core->pci->subsystem_vendor) {
- ir->input.id.vendor = sub->core->pci->subsystem_vendor;
- ir->input.id.product = sub->core->pci->subsystem_device;
+ input_dev->id.vendor = sub->core->pci->subsystem_vendor;
+ input_dev->id.product = sub->core->pci->subsystem_device;
} else {
- ir->input.id.vendor = sub->core->pci->vendor;
- ir->input.id.product = sub->core->pci->device;
+ input_dev->id.vendor = sub->core->pci->vendor;
+ input_dev->id.product = sub->core->pci->device;
}
- ir->input.dev = &sub->core->pci->dev;
+ input_dev->cdev.dev = &sub->core->pci->dev;
if (ir->polling) {
INIT_WORK(&ir->work, ir_work, ir);
@@ -364,9 +369,8 @@ static int ir_probe(struct device *dev)
}
/* all done */
- dev_set_drvdata(dev,ir);
- input_register_device(&ir->input);
- printk(DEVNAME ": %s detected at %s\n",ir->input.name,ir->input.phys);
+ dev_set_drvdata(dev, ir);
+ input_register_device(ir->input);
return 0;
}
@@ -380,7 +384,7 @@ static int ir_remove(struct device *dev)
flush_scheduled_work();
}
- input_unregister_device(&ir->input);
+ input_unregister_device(ir->input);
kfree(ir);
return 0;
}
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 67105b9804a238..9703d3d351f943 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -121,10 +121,9 @@ static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = {
};
-struct IR;
struct IR {
struct i2c_client c;
- struct input_dev input;
+ struct input_dev *input;
struct ir_input_state ir;
struct work_struct work;
@@ -271,9 +270,9 @@ static void ir_key_poll(struct IR *ir)
}
if (0 == rc) {
- ir_input_nokey(&ir->input,&ir->ir);
+ ir_input_nokey(ir->input, &ir->ir);
} else {
- ir_input_keydown(&ir->input,&ir->ir, ir_key, ir_raw);
+ ir_input_keydown(ir->input, &ir->ir, ir_key, ir_raw);
}
}
@@ -318,11 +317,18 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
char *name;
int ir_type;
struct IR *ir;
+ struct input_dev *input_dev;
- if (NULL == (ir = kmalloc(sizeof(struct IR),GFP_KERNEL)))
+ ir = kzalloc(sizeof(struct IR), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ir || !input_dev) {
+ kfree(ir);
+ input_free_device(input_dev);
return -ENOMEM;
- memset(ir,0,sizeof(*ir));
+ }
+
ir->c = client_template;
+ ir->input = input_dev;
i2c_set_clientdata(&ir->c, ir);
ir->c.adapter = adap;
@@ -375,13 +381,12 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
ir->c.dev.bus_id);
/* init + register input device */
- ir_input_init(&ir->input,&ir->ir,ir_type,ir_codes);
- ir->input.id.bustype = BUS_I2C;
- ir->input.name = ir->c.name;
- ir->input.phys = ir->phys;
- input_register_device(&ir->input);
- printk(DEVNAME ": %s detected at %s [%s]\n",
- ir->input.name,ir->input.phys,adap->name);
+ ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->name = ir->c.name;
+ input_dev->phys = ir->phys;
+
+ input_register_device(ir->input);
/* start polling via eventd */
INIT_WORK(&ir->work, ir_work, ir);
@@ -402,7 +407,7 @@ static int ir_detach(struct i2c_client *client)
flush_scheduled_work();
/* unregister devices */
- input_unregister_device(&ir->input);
+ input_unregister_device(ir->input);
i2c_detach_client(&ir->c);
/* free memory */
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
index f0d43fc2632f35..262890cb20a7da 100644
--- a/drivers/media/video/msp3400.c
+++ b/drivers/media/video/msp3400.c
@@ -1420,8 +1420,8 @@ static int msp_detach(struct i2c_client *client);
static int msp_probe(struct i2c_adapter *adap);
static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg);
-static int msp_suspend(struct device * dev, pm_message_t state, u32 level);
-static int msp_resume(struct device * dev, u32 level);
+static int msp_suspend(struct device * dev, pm_message_t state);
+static int msp_resume(struct device * dev);
static void msp_wake_thread(struct i2c_client *client);
@@ -1821,7 +1821,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
}
-static int msp_suspend(struct device * dev, pm_message_t state, u32 level)
+static int msp_suspend(struct device * dev, pm_message_t state)
{
struct i2c_client *c = container_of(dev, struct i2c_client, dev);
@@ -1830,7 +1830,7 @@ static int msp_suspend(struct device * dev, pm_message_t state, u32 level)
return 0;
}
-static int msp_resume(struct device * dev, u32 level)
+static int msp_resume(struct device * dev)
{
struct i2c_client *c = container_of(dev, struct i2c_client, dev);
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index 1f456c4d76f2dd..242cb235cf9262 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -425,9 +425,9 @@ static int build_key(struct saa7134_dev *dev)
if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
(ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
- ir_input_keydown(&ir->dev,&ir->ir,data,data);
+ ir_input_keydown(ir->dev, &ir->ir, data, data);
} else {
- ir_input_nokey(&ir->dev,&ir->ir);
+ ir_input_nokey(ir->dev, &ir->ir);
}
return 0;
}
@@ -456,6 +456,7 @@ static void saa7134_input_timer(unsigned long data)
int saa7134_input_init1(struct saa7134_dev *dev)
{
struct saa7134_ir *ir;
+ struct input_dev *input_dev;
IR_KEYTAB_TYPE *ir_codes = NULL;
u32 mask_keycode = 0;
u32 mask_keydown = 0;
@@ -535,10 +536,13 @@ int saa7134_input_init1(struct saa7134_dev *dev)
return -ENODEV;
}
- ir = kmalloc(sizeof(*ir),GFP_KERNEL);
- if (NULL == ir)
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ir || !input_dev) {
+ kfree(ir);
+ input_free_device(input_dev);
return -ENOMEM;
- memset(ir,0,sizeof(*ir));
+ }
/* init hardware-specific stuff */
ir->mask_keycode = mask_keycode;
@@ -552,19 +556,19 @@ int saa7134_input_init1(struct saa7134_dev *dev)
snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
pci_name(dev->pci));
- ir_input_init(&ir->dev, &ir->ir, ir_type, ir_codes);
- ir->dev.name = ir->name;
- ir->dev.phys = ir->phys;
- ir->dev.id.bustype = BUS_PCI;
- ir->dev.id.version = 1;
+ ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
+ input_dev->name = ir->name;
+ input_dev->phys = ir->phys;
+ input_dev->id.bustype = BUS_PCI;
+ input_dev->id.version = 1;
if (dev->pci->subsystem_vendor) {
- ir->dev.id.vendor = dev->pci->subsystem_vendor;
- ir->dev.id.product = dev->pci->subsystem_device;
+ input_dev->id.vendor = dev->pci->subsystem_vendor;
+ input_dev->id.product = dev->pci->subsystem_device;
} else {
- ir->dev.id.vendor = dev->pci->vendor;
- ir->dev.id.product = dev->pci->device;
+ input_dev->id.vendor = dev->pci->vendor;
+ input_dev->id.product = dev->pci->device;
}
- ir->dev.dev = &dev->pci->dev;
+ input_dev->cdev.dev = &dev->pci->dev;
/* all done */
dev->remote = ir;
@@ -576,8 +580,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
add_timer(&ir->timer);
}
- input_register_device(&dev->remote->dev);
- printk("%s: registered input device for IR\n",dev->name);
+ input_register_device(ir->dev);
return 0;
}
@@ -586,9 +589,9 @@ void saa7134_input_fini(struct saa7134_dev *dev)
if (NULL == dev->remote)
return;
- input_unregister_device(&dev->remote->dev);
if (dev->remote->polling)
del_timer_sync(&dev->remote->timer);
+ input_unregister_device(dev->remote->dev);
kfree(dev->remote);
dev->remote = NULL;
}
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 3ea09142ec9c44..860b89530e2a45 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -351,7 +351,7 @@ struct saa7134_oss {
/* IR input */
struct saa7134_ir {
- struct input_dev dev;
+ struct input_dev *dev;
struct ir_input_state ir;
char name[32];
char phys[32];
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 0456dda2624ddc..94053f149ddf57 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -784,13 +784,13 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
}
-static int tda9887_suspend(struct device * dev, pm_message_t state, u32 level)
+static int tda9887_suspend(struct device * dev, pm_message_t state)
{
dprintk("tda9887: suspend\n");
return 0;
}
-static int tda9887_resume(struct device * dev, u32 level)
+static int tda9887_resume(struct device * dev)
{
struct i2c_client *c = container_of(dev, struct i2c_client, dev);
struct tda9887 *t = i2c_get_clientdata(c);
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 05572020af4d03..ad85bef1c3d5d2 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -697,7 +697,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
}
-static int tuner_suspend(struct device *dev, pm_message_t state, u32 level)
+static int tuner_suspend(struct device *dev, pm_message_t state)
{
struct i2c_client *c = container_of (dev, struct i2c_client, dev);
struct tuner *t = i2c_get_clientdata (c);
@@ -707,7 +707,7 @@ static int tuner_suspend(struct device *dev, pm_message_t state, u32 level)
return 0;
}
-static int tuner_resume(struct device *dev, u32 level)
+static int tuner_resume(struct device *dev)
{
struct i2c_client *c = container_of (dev, struct i2c_client, dev);
struct tuner *t = i2c_get_clientdata (c);
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h
index c5bcfd70f71151..9eefedb1621120 100644
--- a/drivers/message/i2o/core.h
+++ b/drivers/message/i2o/core.h
@@ -36,9 +36,6 @@ extern void __exit i2o_pci_exit(void);
extern void i2o_device_remove(struct i2o_device *);
extern int i2o_device_parse_lct(struct i2o_controller *);
-extern int i2o_device_init(void);
-extern void i2o_device_exit(void);
-
/* IOP */
extern struct i2o_controller *i2o_iop_alloc(void);
extern void i2o_iop_free(struct i2o_controller *);
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index 21f16ba3ac38a5..d9879965eb5096 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -45,10 +45,10 @@ static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd,
writel(type, &msg->body[0]);
return i2o_msg_post_wait(dev->iop, m, 60);
-};
+}
/**
- * i2o_device_claim - claim a device for use by an OSM
+ * i2o_device_claim - claim a device for use by an OSM
* @dev: I2O device to claim
* @drv: I2O driver which wants to claim the device
*
@@ -73,7 +73,7 @@ int i2o_device_claim(struct i2o_device *dev)
up(&dev->lock);
return rc;
-};
+}
/**
* i2o_device_claim_release - release a device that the OSM is using
@@ -119,7 +119,8 @@ int i2o_device_claim_release(struct i2o_device *dev)
up(&dev->lock);
return rc;
-};
+}
+
/**
* i2o_device_release - release the memory for a I2O device
@@ -135,39 +136,47 @@ static void i2o_device_release(struct device *dev)
pr_debug("i2o: device %s released\n", dev->bus_id);
kfree(i2o_dev);
-};
+}
+
/**
- * i2o_device_class_release - Remove I2O device attributes
- * @cd: I2O class device which is added to the I2O device class
+ * i2o_device_class_show_class_id - Displays class id of I2O device
+ * @cd: class device of which the class id should be displayed
+ * @buf: buffer into which the class id should be printed
*
- * Removes attributes from the I2O device again. Also search each device
- * on the controller for I2O devices which refert to this device as parent
- * or user and remove this links also.
+ * Returns the number of bytes which are printed into the buffer.
*/
-static void i2o_device_class_release(struct class_device *cd)
+static ssize_t i2o_device_show_class_id(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
- struct i2o_device *i2o_dev, *tmp;
- struct i2o_controller *c;
+ struct i2o_device *i2o_dev = to_i2o_device(dev);
- i2o_dev = to_i2o_device(cd->dev);
- c = i2o_dev->iop;
+ sprintf(buf, "0x%03x\n", i2o_dev->lct_data.class_id);
+ return strlen(buf) + 1;
+}
- sysfs_remove_link(&i2o_dev->device.kobj, "parent");
- sysfs_remove_link(&i2o_dev->device.kobj, "user");
+/**
+ * i2o_device_class_show_tid - Displays TID of I2O device
+ * @cd: class device of which the TID should be displayed
+ * @buf: buffer into which the class id should be printed
+ *
+ * Returns the number of bytes which are printed into the buffer.
+ */
+static ssize_t i2o_device_show_tid(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct i2o_device *i2o_dev = to_i2o_device(dev);
- list_for_each_entry(tmp, &c->devices, list) {
- if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
- sysfs_remove_link(&tmp->device.kobj, "parent");
- if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
- sysfs_remove_link(&tmp->device.kobj, "user");
- }
-};
+ sprintf(buf, "0x%03x\n", i2o_dev->lct_data.tid);
+ return strlen(buf) + 1;
+}
-/* I2O device class */
-static struct class i2o_device_class = {
- .name = "i2o_device",
- .release = i2o_device_class_release
+struct device_attribute i2o_device_attrs[] = {
+ __ATTR(class_id, S_IRUGO, i2o_device_show_class_id, NULL),
+ __ATTR(tid, S_IRUGO, i2o_device_show_tid, NULL),
+ __ATTR_NULL
};
/**
@@ -193,11 +202,69 @@ static struct i2o_device *i2o_device_alloc(void)
dev->device.bus = &i2o_bus_type;
dev->device.release = &i2o_device_release;
- dev->classdev.class = &i2o_device_class;
- dev->classdev.dev = &dev->device;
return dev;
-};
+}
+
+/**
+ * i2o_setup_sysfs_links - Adds attributes to the I2O device
+ * @cd: I2O class device which is added to the I2O device class
+ *
+ * This function get called when a I2O device is added to the class. It
+ * creates the attributes for each device and creates user/parent symlink
+ * if necessary.
+ *
+ * Returns 0 on success or negative error code on failure.
+ */
+static void i2o_setup_sysfs_links(struct i2o_device *i2o_dev)
+{
+ struct i2o_controller *c = i2o_dev->iop;
+ struct i2o_device *tmp;
+
+ /* create user entries for this device */
+ tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
+ if (tmp && tmp != i2o_dev)
+ sysfs_create_link(&i2o_dev->device.kobj,
+ &tmp->device.kobj, "user");
+
+ /* create user entries refering to this device */
+ list_for_each_entry(tmp, &c->devices, list)
+ if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid &&
+ tmp != i2o_dev)
+ sysfs_create_link(&tmp->device.kobj,
+ &i2o_dev->device.kobj, "user");
+
+ /* create parent entries for this device */
+ tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
+ if (tmp && tmp != i2o_dev)
+ sysfs_create_link(&i2o_dev->device.kobj,
+ &tmp->device.kobj, "parent");
+
+ /* create parent entries refering to this device */
+ list_for_each_entry(tmp, &c->devices, list)
+ if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid &&
+ tmp != i2o_dev)
+ sysfs_create_link(&tmp->device.kobj,
+ &i2o_dev->device.kobj, "parent");
+}
+
+static void i2o_remove_sysfs_links(struct i2o_device *i2o_dev)
+{
+ struct i2o_controller *c = i2o_dev->iop;
+ struct i2o_device *tmp;
+
+ sysfs_remove_link(&i2o_dev->device.kobj, "parent");
+ sysfs_remove_link(&i2o_dev->device.kobj, "user");
+
+ list_for_each_entry(tmp, &c->devices, list) {
+ if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+ sysfs_remove_link(&tmp->device.kobj, "parent");
+ if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+ sysfs_remove_link(&tmp->device.kobj, "user");
+ }
+}
+
+
/**
* i2o_device_add - allocate a new I2O device and add it to the IOP
@@ -222,28 +289,25 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c,
}
dev->lct_data = *entry;
+ dev->iop = c;
snprintf(dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit,
dev->lct_data.tid);
- snprintf(dev->classdev.class_id, BUS_ID_SIZE, "%d:%03x", c->unit,
- dev->lct_data.tid);
-
- dev->iop = c;
dev->device.parent = &c->device;
device_register(&dev->device);
list_add_tail(&dev->list, &c->devices);
- class_device_register(&dev->classdev);
+ i2o_setup_sysfs_links(dev);
i2o_driver_notify_device_add_all(dev);
pr_debug("i2o: device %s added\n", dev->device.bus_id);
return dev;
-};
+}
/**
* i2o_device_remove - remove an I2O device from the I2O core
@@ -256,10 +320,10 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c,
void i2o_device_remove(struct i2o_device *i2o_dev)
{
i2o_driver_notify_device_remove_all(i2o_dev);
- class_device_unregister(&i2o_dev->classdev);
+ i2o_remove_sysfs_links(i2o_dev);
list_del(&i2o_dev->list);
device_unregister(&i2o_dev->device);
-};
+}
/**
* i2o_device_parse_lct - Parse a previously fetched LCT and create devices
@@ -337,99 +401,8 @@ int i2o_device_parse_lct(struct i2o_controller *c)
up(&c->lct_lock);
return 0;
-};
-
-/**
- * i2o_device_class_show_class_id - Displays class id of I2O device
- * @cd: class device of which the class id should be displayed
- * @buf: buffer into which the class id should be printed
- *
- * Returns the number of bytes which are printed into the buffer.
- */
-static ssize_t i2o_device_class_show_class_id(struct class_device *cd,
- char *buf)
-{
- struct i2o_device *dev = to_i2o_device(cd->dev);
-
- sprintf(buf, "0x%03x\n", dev->lct_data.class_id);
- return strlen(buf) + 1;
-};
-
-/**
- * i2o_device_class_show_tid - Displays TID of I2O device
- * @cd: class device of which the TID should be displayed
- * @buf: buffer into which the class id should be printed
- *
- * Returns the number of bytes which are printed into the buffer.
- */
-static ssize_t i2o_device_class_show_tid(struct class_device *cd, char *buf)
-{
- struct i2o_device *dev = to_i2o_device(cd->dev);
-
- sprintf(buf, "0x%03x\n", dev->lct_data.tid);
- return strlen(buf) + 1;
-};
-
-/* I2O device class attributes */
-static CLASS_DEVICE_ATTR(class_id, S_IRUGO, i2o_device_class_show_class_id,
- NULL);
-static CLASS_DEVICE_ATTR(tid, S_IRUGO, i2o_device_class_show_tid, NULL);
-
-/**
- * i2o_device_class_add - Adds attributes to the I2O device
- * @cd: I2O class device which is added to the I2O device class
- *
- * This function get called when a I2O device is added to the class. It
- * creates the attributes for each device and creates user/parent symlink
- * if necessary.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_device_class_add(struct class_device *cd)
-{
- struct i2o_device *i2o_dev, *tmp;
- struct i2o_controller *c;
-
- i2o_dev = to_i2o_device(cd->dev);
- c = i2o_dev->iop;
-
- class_device_create_file(cd, &class_device_attr_class_id);
- class_device_create_file(cd, &class_device_attr_tid);
-
- /* create user entries for this device */
- tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
- if (tmp && (tmp != i2o_dev))
- sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
- "user");
-
- /* create user entries refering to this device */
- list_for_each_entry(tmp, &c->devices, list)
- if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
- && (tmp != i2o_dev))
- sysfs_create_link(&tmp->device.kobj,
- &i2o_dev->device.kobj, "user");
-
- /* create parent entries for this device */
- tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
- if (tmp && (tmp != i2o_dev))
- sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
- "parent");
-
- /* create parent entries refering to this device */
- list_for_each_entry(tmp, &c->devices, list)
- if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
- && (tmp != i2o_dev))
- sysfs_create_link(&tmp->device.kobj,
- &i2o_dev->device.kobj, "parent");
-
- return 0;
-};
+}
-/* I2O device class interface */
-static struct class_interface i2o_device_class_interface = {
- .class = &i2o_device_class,
- .add = i2o_device_class_add
-};
/*
* Run time support routines
@@ -553,11 +526,11 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field,
}
/*
- * if oper == I2O_PARAMS_TABLE_GET, get from all rows
- * if fieldcount == -1 return all fields
+ * if oper == I2O_PARAMS_TABLE_GET, get from all rows
+ * if fieldcount == -1 return all fields
* ibuf and ibuflen are unused (use NULL, 0)
- * else return specific fields
- * ibuf contains fieldindexes
+ * else return specific fields
+ * ibuf contains fieldindexes
*
* if oper == I2O_PARAMS_LIST_GET, get from specific rows
* if fieldcount == -1 return all fields
@@ -602,35 +575,6 @@ int i2o_parm_table_get(struct i2o_device *dev, int oper, int group,
return size;
}
-/**
- * i2o_device_init - Initialize I2O devices
- *
- * Registers the I2O device class.
- *
- * Returns 0 on success or negative error code on failure.
- */
-int i2o_device_init(void)
-{
- int rc;
-
- rc = class_register(&i2o_device_class);
- if (rc)
- return rc;
-
- return class_interface_register(&i2o_device_class_interface);
-};
-
-/**
- * i2o_device_exit - I2O devices exit function
- *
- * Unregisters the I2O device class.
- */
-void i2o_device_exit(void)
-{
- class_interface_register(&i2o_device_class_interface);
- class_unregister(&i2o_device_class);
-};
-
EXPORT_SYMBOL(i2o_device_claim);
EXPORT_SYMBOL(i2o_device_claim_release);
EXPORT_SYMBOL(i2o_parm_field_get);
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
index 739bfdef0c6d04..0079a4be0af28a 100644
--- a/drivers/message/i2o/driver.c
+++ b/drivers/message/i2o/driver.c
@@ -58,9 +58,12 @@ static int i2o_bus_match(struct device *dev, struct device_driver *drv)
};
/* I2O bus type */
+extern struct device_attribute i2o_device_attrs[];
+
struct bus_type i2o_bus_type = {
.name = "i2o",
.match = i2o_bus_match,
+ .dev_attrs = i2o_device_attrs,
};
/**
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 42f8b810d6e57f..361da8d1d5e766 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -833,6 +833,7 @@ void i2o_iop_remove(struct i2o_controller *c)
list_for_each_entry_safe(dev, tmp, &c->devices, list)
i2o_device_remove(dev);
+ class_device_unregister(c->classdev);
device_del(&c->device);
/* Ask the IOP to switch to RESET state */
@@ -1077,9 +1078,7 @@ static void i2o_iop_release(struct device *dev)
};
/* I2O controller class */
-static struct class i2o_controller_class = {
- .name = "i2o_controller",
-};
+static struct class *i2o_controller_class;
/**
* i2o_iop_alloc - Allocate and initialize a i2o_controller struct
@@ -1110,14 +1109,10 @@ struct i2o_controller *i2o_iop_alloc(void)
sprintf(c->name, "iop%d", c->unit);
device_initialize(&c->device);
- class_device_initialize(&c->classdev);
c->device.release = &i2o_iop_release;
- c->classdev.class = &i2o_controller_class;
- c->classdev.dev = &c->device;
snprintf(c->device.bus_id, BUS_ID_SIZE, "iop%d", c->unit);
- snprintf(c->classdev.class_id, BUS_ID_SIZE, "iop%d", c->unit);
#if BITS_PER_LONG == 64
spin_lock_init(&c->context_list_lock);
@@ -1146,7 +1141,9 @@ int i2o_iop_add(struct i2o_controller *c)
goto iop_reset;
}
- if ((rc = class_device_add(&c->classdev))) {
+ c->classdev = class_device_create(i2o_controller_class, NULL, MKDEV(0,0),
+ &c->device, "iop%d", c->unit);
+ if (IS_ERR(c->classdev)) {
osm_err("%s: could not add controller class\n", c->name);
goto device_del;
}
@@ -1184,7 +1181,7 @@ int i2o_iop_add(struct i2o_controller *c)
return 0;
class_del:
- class_device_del(&c->classdev);
+ class_device_unregister(c->classdev);
device_del:
device_del(&c->device);
@@ -1246,13 +1243,10 @@ static int __init i2o_iop_init(void)
printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
- rc = i2o_device_init();
- if (rc)
- goto exit;
-
- if ((rc = class_register(&i2o_controller_class))) {
+ i2o_controller_class = class_create(THIS_MODULE, "i2o_controller");
+ if (IS_ERR(i2o_controller_class)) {
osm_err("can't register class i2o_controller\n");
- goto device_exit;
+ goto exit;
}
if ((rc = i2o_driver_init()))
@@ -1273,10 +1267,7 @@ static int __init i2o_iop_init(void)
i2o_driver_exit();
class_exit:
- class_unregister(&i2o_controller_class);
-
- device_exit:
- i2o_device_exit();
+ class_destroy(i2o_controller_class);
exit:
return rc;
@@ -1292,8 +1283,7 @@ static void __exit i2o_iop_exit(void)
i2o_pci_exit();
i2o_exec_exit();
i2o_driver_exit();
- class_unregister(&i2o_controller_class);
- i2o_device_exit();
+ class_destroy(i2o_controller_class);
};
module_init(i2o_iop_init);
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c
index e9806fbbe69630..720e7a3263088b 100644
--- a/drivers/mfd/mcp-sa11x0.c
+++ b/drivers/mfd/mcp-sa11x0.c
@@ -219,26 +219,24 @@ static int mcp_sa11x0_remove(struct device *dev)
return 0;
}
-static int mcp_sa11x0_suspend(struct device *dev, pm_message_t state, u32 level)
+static int mcp_sa11x0_suspend(struct device *dev, pm_message_t state)
{
struct mcp *mcp = dev_get_drvdata(dev);
- if (level == SUSPEND_DISABLE) {
- priv(mcp)->mccr0 = Ser4MCCR0;
- priv(mcp)->mccr1 = Ser4MCCR1;
- Ser4MCCR0 &= ~MCCR0_MCE;
- }
+ priv(mcp)->mccr0 = Ser4MCCR0;
+ priv(mcp)->mccr1 = Ser4MCCR1;
+ Ser4MCCR0 &= ~MCCR0_MCE;
+
return 0;
}
-static int mcp_sa11x0_resume(struct device *dev, u32 level)
+static int mcp_sa11x0_resume(struct device *dev)
{
struct mcp *mcp = dev_get_drvdata(dev);
- if (level == RESUME_RESTORE_STATE) {
- Ser4MCCR1 = priv(mcp)->mccr1;
- Ser4MCCR0 = priv(mcp)->mccr0;
- }
+ Ser4MCCR1 = priv(mcp)->mccr1;
+ Ser4MCCR0 = priv(mcp)->mccr0;
+
return 0;
}
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
index a260f83bcb0210..585cded3d365bf 100644
--- a/drivers/mfd/ucb1x00-ts.c
+++ b/drivers/mfd/ucb1x00-ts.c
@@ -40,7 +40,7 @@
struct ucb1x00_ts {
- struct input_dev idev;
+ struct input_dev *idev;
struct ucb1x00 *ucb;
wait_queue_head_t irq_wait;
@@ -56,16 +56,16 @@ static int adcsync;
static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
{
- input_report_abs(&ts->idev, ABS_X, x);
- input_report_abs(&ts->idev, ABS_Y, y);
- input_report_abs(&ts->idev, ABS_PRESSURE, pressure);
- input_sync(&ts->idev);
+ input_report_abs(ts->idev, ABS_X, x);
+ input_report_abs(ts->idev, ABS_Y, y);
+ input_report_abs(ts->idev, ABS_PRESSURE, pressure);
+ input_sync(ts->idev);
}
static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
{
- input_report_abs(&ts->idev, ABS_PRESSURE, 0);
- input_sync(&ts->idev);
+ input_report_abs(ts->idev, ABS_PRESSURE, 0);
+ input_sync(ts->idev);
}
/*
@@ -341,26 +341,30 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
{
struct ucb1x00_ts *ts;
- ts = kmalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL);
+ ts = kzalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL);
if (!ts)
return -ENOMEM;
- memset(ts, 0, sizeof(struct ucb1x00_ts));
+ ts->idev = input_allocate_device();
+ if (!ts->idev) {
+ kfree(ts);
+ return -ENOMEM;
+ }
ts->ucb = dev->ucb;
ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
- ts->idev.name = "Touchscreen panel";
- ts->idev.id.product = ts->ucb->id;
- ts->idev.open = ucb1x00_ts_open;
- ts->idev.close = ucb1x00_ts_close;
+ ts->idev->name = "Touchscreen panel";
+ ts->idev->id.product = ts->ucb->id;
+ ts->idev->open = ucb1x00_ts_open;
+ ts->idev->close = ucb1x00_ts_close;
- __set_bit(EV_ABS, ts->idev.evbit);
- __set_bit(ABS_X, ts->idev.absbit);
- __set_bit(ABS_Y, ts->idev.absbit);
- __set_bit(ABS_PRESSURE, ts->idev.absbit);
+ __set_bit(EV_ABS, ts->idev->evbit);
+ __set_bit(ABS_X, ts->idev->absbit);
+ __set_bit(ABS_Y, ts->idev->absbit);
+ __set_bit(ABS_PRESSURE, ts->idev->absbit);
- input_register_device(&ts->idev);
+ input_register_device(ts->idev);
dev->priv = ts;
@@ -370,7 +374,8 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
static void ucb1x00_ts_remove(struct ucb1x00_dev *dev)
{
struct ucb1x00_ts *ts = dev->priv;
- input_unregister_device(&ts->idev);
+
+ input_unregister_device(ts->idev);
kfree(ts);
}
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index 91c74843dc0d8c..1e6bdba2675639 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -24,6 +24,7 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/scatterlist.h>
+#include <asm/sizes.h>
#include <asm/hardware/amba.h>
#include <asm/hardware/clock.h>
#include <asm/mach/mmc.h>
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
index b53af57074e329..8eba373d42d70f 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -571,23 +571,23 @@ static int pxamci_remove(struct device *dev)
}
#ifdef CONFIG_PM
-static int pxamci_suspend(struct device *dev, pm_message_t state, u32 level)
+static int pxamci_suspend(struct device *dev, pm_message_t state)
{
struct mmc_host *mmc = dev_get_drvdata(dev);
int ret = 0;
- if (mmc && level == SUSPEND_DISABLE)
+ if (mmc)
ret = mmc_suspend_host(mmc, state);
return ret;
}
-static int pxamci_resume(struct device *dev, u32 level)
+static int pxamci_resume(struct device *dev)
{
struct mmc_host *mmc = dev_get_drvdata(dev);
int ret = 0;
- if (mmc && level == RESUME_ENABLE)
+ if (mmc)
ret = mmc_resume_host(mmc);
return ret;
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index 3cbca7cbea8017..25f7ce7b3bc08e 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -1955,14 +1955,14 @@ static void __devexit wbsd_pnp_remove(struct pnp_dev * dev)
*/
#ifdef CONFIG_PM
-static int wbsd_suspend(struct device *dev, pm_message_t state, u32 level)
+static int wbsd_suspend(struct device *dev, pm_message_t state)
{
DBGF("Not yet supported\n");
return 0;
}
-static int wbsd_resume(struct device *dev, u32 level)
+static int wbsd_resume(struct device *dev)
{
DBGF("Not yet supported\n");
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index 8dcaa357b4bb13..6a8e0caf9fdca3 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -21,6 +21,7 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/concat.h>
+#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/sizes.h>
#include <asm/mach/flash.h>
@@ -402,21 +403,21 @@ static int __exit sa1100_mtd_remove(struct device *dev)
}
#ifdef CONFIG_PM
-static int sa1100_mtd_suspend(struct device *dev, pm_message_t state, u32 level)
+static int sa1100_mtd_suspend(struct device *dev, pm_message_t state)
{
struct sa_info *info = dev_get_drvdata(dev);
int ret = 0;
- if (info && level == SUSPEND_SAVE_STATE)
+ if (info)
ret = info->mtd->suspend(info->mtd);
return ret;
}
-static int sa1100_mtd_resume(struct device *dev, u32 level)
+static int sa1100_mtd_resume(struct device *dev)
{
struct sa_info *info = dev_get_drvdata(dev);
- if (info && level == RESUME_RESTORE_STATE)
+ if (info)
info->mtd->resume(info->mtd);
return 0;
}
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 1ed602a0f24cb6..c534fd5d95cb97 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -24,10 +24,10 @@ static void mtd_notify_add(struct mtd_info* mtd)
if (!mtd)
return;
- class_device_create(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
+ class_device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
NULL, "mtd%d", mtd->index);
- class_device_create(mtd_class,
+ class_device_create(mtd_class, NULL,
MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
NULL, "mtd%dro", mtd->index);
}
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index bc537440ca0259..f822cd3025ff07 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -1027,8 +1027,7 @@ static void cp_reset_hw (struct cp_private *cp)
if (!(cpr8(Cmd) & CmdReset))
return;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(10);
+ schedule_timeout_uninterruptible(10);
}
printk(KERN_ERR "%s: hardware reset timeout\n", cp->dev->name);
@@ -1575,6 +1574,7 @@ static struct ethtool_ops cp_ethtool_ops = {
.set_wol = cp_set_wol,
.get_strings = cp_get_strings,
.get_ethtool_stats = cp_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1773,6 +1773,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
for (i = 0; i < 3; i++)
((u16 *) (dev->dev_addr))[i] =
le16_to_cpu (read_eeprom (regs, i + 7, addr_len));
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
dev->open = cp_open;
dev->stop = cp_close;
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 4c2cf7bbd25292..30bee11c48bd2d 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -552,7 +552,8 @@ const static struct {
{ "RTL-8100B/8139D",
HW_REVID(1, 1, 1, 0, 1, 0, 1),
- HasLWake,
+ HasHltClk /* XXX undocumented? */
+ | HasLWake,
},
{ "RTL-8101",
@@ -970,6 +971,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
for (i = 0; i < 3; i++)
((u16 *) (dev->dev_addr))[i] =
le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len));
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
/* The Rtl8139-specific entries in the device structure. */
dev->open = rtl8139_open;
@@ -2465,6 +2467,7 @@ static struct ethtool_ops rtl8139_ethtool_ops = {
.get_strings = rtl8139_get_strings,
.get_stats_count = rtl8139_get_stats_count,
.get_ethtool_stats = rtl8139_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index c748b0e1641921..fee8c5cf1f3a8e 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -475,6 +475,14 @@ config SGI_IOC3_ETH_HW_TX_CSUM
the moment only acceleration of IPv4 is supported. This option
enables offloading for checksums on transmit. If unsure, say Y.
+config MIPS_SIM_NET
+ tristate "MIPS simulator Network device (EXPERIMENTAL)"
+ depends on NETDEVICES && MIPS_SIM && EXPERIMENTAL
+ help
+ The MIPSNET device is a simple Ethernet network device which is
+ emulated by the MIPS Simulator.
+ If you are not using a MIPSsim or are unsure, say N.
+
config SGI_O2MACE_ETH
tristate "SGI O2 MACE Fast Ethernet support"
depends on NET_ETHERNET && SGI_IP32=y
@@ -1330,7 +1338,7 @@ config FORCEDETH
config CS89x0
tristate "CS89x0 support"
- depends on (NET_PCI && (ISA || ARCH_IXDP2X01)) || ARCH_PNX0105
+ depends on (NET_PCI && (ISA || ARCH_IXDP2X01)) || ARCH_PNX0105 || MACH_MP1000
---help---
Support for CS89x0 chipset based Ethernet cards. If you have a
network (Ethernet) card of this type, say Y and read the
@@ -2083,6 +2091,7 @@ config SPIDER_NET
config GIANFAR
tristate "Gianfar Ethernet"
depends on 85xx || 83xx
+ select PHYLIB
help
This driver supports the Gigabit TSEC on the MPC85xx
family of chips, and the FEC on the 8540
@@ -2243,6 +2252,20 @@ config ISERIES_VETH
tristate "iSeries Virtual Ethernet driver support"
depends on PPC_ISERIES
+config RIONET
+ tristate "RapidIO Ethernet over messaging driver support"
+ depends on NETDEVICES && RAPIDIO
+
+config RIONET_TX_SIZE
+ int "Number of outbound queue entries"
+ depends on RIONET
+ default "128"
+
+config RIONET_RX_SIZE
+ int "Number of inbound queue entries"
+ depends on RIONET
+ default "128"
+
config FDDI
bool "FDDI driver support"
depends on (PCI || EISA)
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 8aeec9f2495b5e..1a84e0435f64b5 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -13,7 +13,7 @@ obj-$(CONFIG_CHELSIO_T1) += chelsio/
obj-$(CONFIG_BONDING) += bonding/
obj-$(CONFIG_GIANFAR) += gianfar_driver.o
-gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_phy.o
+gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_mii.o
#
# link order important here
@@ -64,6 +64,7 @@ obj-$(CONFIG_SKFP) += skfp/
obj-$(CONFIG_VIA_RHINE) += via-rhine.o
obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
+obj-$(CONFIG_RIONET) += rionet.o
#
# end link order section
@@ -166,6 +167,7 @@ obj-$(CONFIG_EQUALIZER) += eql.o
obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
obj-$(CONFIG_MIPS_GT96100ETH) += gt96100eth.o
obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
+obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
obj-$(CONFIG_DECLANCE) += declance.o
obj-$(CONFIG_ATARILANCE) += atarilance.o
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index c56d86d371a9c6..3d50e953faaaba 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -29,6 +29,7 @@
#include <asm/system.h>
#include <asm/irq.h>
+#include <asm/hardware.h>
#include <asm/io.h>
#define TX_BUFFERS 15
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index c82b9cd1c9246c..78506911d6566d 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -151,13 +151,6 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES];
SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
SUPPORTED_Autoneg
-static char *phy_link[] =
-{ "unknown",
- "10Base2", "10BaseT",
- "AUI",
- "100BaseT", "100BaseTX", "100BaseFX"
-};
-
int bcm_5201_init(struct net_device *dev, int phy_addr)
{
s16 data;
@@ -785,6 +778,7 @@ static struct mii_chip_info {
{"Broadcom BCM5201 10/100 BaseT PHY",0x0040,0x6212, &bcm_5201_ops,0},
{"Broadcom BCM5221 10/100 BaseT PHY",0x0040,0x61e4, &bcm_5201_ops,0},
{"Broadcom BCM5222 10/100 BaseT PHY",0x0040,0x6322, &bcm_5201_ops,1},
+ {"NS DP83847 PHY", 0x2000, 0x5c30, &bcm_5201_ops ,0},
{"AMD 79C901 HomePNA PHY",0x0000,0x35c8, &am79c901_ops,0},
{"AMD 79C874 10/100 BaseT PHY",0x0022,0x561b, &am79c874_ops,0},
{"LSI 80227 10/100 BaseT PHY",0x0016,0xf840, &lsi_80227_ops,0},
@@ -1045,7 +1039,7 @@ found:
#endif
if (aup->mii->chip_info == NULL) {
- printk(KERN_ERR "%s: Au1x No MII transceivers found!\n",
+ printk(KERN_ERR "%s: Au1x No known MII transceivers found!\n",
dev->name);
return -1;
}
@@ -1546,6 +1540,9 @@ au1000_probe(u32 ioaddr, int irq, int port_num)
printk(KERN_ERR "%s: out of memory\n", dev->name);
goto err_out;
}
+ aup->mii->next = NULL;
+ aup->mii->chip_info = NULL;
+ aup->mii->status = 0;
aup->mii->mii_control_reg = 0;
aup->mii->mii_data_reg = 0;
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 94939f570f7898..282ebd15f0115a 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -106,6 +106,29 @@ static int b44_poll(struct net_device *dev, int *budget);
static void b44_poll_controller(struct net_device *dev);
#endif
+static int dma_desc_align_mask;
+static int dma_desc_sync_size;
+
+static inline void b44_sync_dma_desc_for_device(struct pci_dev *pdev,
+ dma_addr_t dma_base,
+ unsigned long offset,
+ enum dma_data_direction dir)
+{
+ dma_sync_single_range_for_device(&pdev->dev, dma_base,
+ offset & dma_desc_align_mask,
+ dma_desc_sync_size, dir);
+}
+
+static inline void b44_sync_dma_desc_for_cpu(struct pci_dev *pdev,
+ dma_addr_t dma_base,
+ unsigned long offset,
+ enum dma_data_direction dir)
+{
+ dma_sync_single_range_for_cpu(&pdev->dev, dma_base,
+ offset & dma_desc_align_mask,
+ dma_desc_sync_size, dir);
+}
+
static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
{
return readl(bp->regs + reg);
@@ -668,6 +691,11 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
dp->ctrl = cpu_to_le32(ctrl);
dp->addr = cpu_to_le32((u32) mapping + bp->rx_offset + bp->dma_offset);
+ if (bp->flags & B44_FLAG_RX_RING_HACK)
+ b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
+ dest_idx * sizeof(dp),
+ DMA_BIDIRECTIONAL);
+
return RX_PKT_BUF_SZ;
}
@@ -692,6 +720,11 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
pci_unmap_addr_set(dest_map, mapping,
pci_unmap_addr(src_map, mapping));
+ if (bp->flags & B44_FLAG_RX_RING_HACK)
+ b44_sync_dma_desc_for_cpu(bp->pdev, bp->rx_ring_dma,
+ src_idx * sizeof(src_desc),
+ DMA_BIDIRECTIONAL);
+
ctrl = src_desc->ctrl;
if (dest_idx == (B44_RX_RING_SIZE - 1))
ctrl |= cpu_to_le32(DESC_CTRL_EOT);
@@ -700,8 +733,14 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
dest_desc->ctrl = ctrl;
dest_desc->addr = src_desc->addr;
+
src_map->skb = NULL;
+ if (bp->flags & B44_FLAG_RX_RING_HACK)
+ b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
+ dest_idx * sizeof(dest_desc),
+ DMA_BIDIRECTIONAL);
+
pci_dma_sync_single_for_device(bp->pdev, src_desc->addr,
RX_PKT_BUF_SZ,
PCI_DMA_FROMDEVICE);
@@ -959,6 +998,11 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
bp->tx_ring[entry].ctrl = cpu_to_le32(ctrl);
bp->tx_ring[entry].addr = cpu_to_le32((u32) mapping+bp->dma_offset);
+ if (bp->flags & B44_FLAG_TX_RING_HACK)
+ b44_sync_dma_desc_for_device(bp->pdev, bp->tx_ring_dma,
+ entry * sizeof(bp->tx_ring[0]),
+ DMA_TO_DEVICE);
+
entry = NEXT_TX(entry);
bp->tx_prod = entry;
@@ -1064,6 +1108,16 @@ static void b44_init_rings(struct b44 *bp)
memset(bp->rx_ring, 0, B44_RX_RING_BYTES);
memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
+ if (bp->flags & B44_FLAG_RX_RING_HACK)
+ dma_sync_single_for_device(&bp->pdev->dev, bp->rx_ring_dma,
+ DMA_TABLE_BYTES,
+ PCI_DMA_BIDIRECTIONAL);
+
+ if (bp->flags & B44_FLAG_TX_RING_HACK)
+ dma_sync_single_for_device(&bp->pdev->dev, bp->tx_ring_dma,
+ DMA_TABLE_BYTES,
+ PCI_DMA_TODEVICE);
+
for (i = 0; i < bp->rx_pending; i++) {
if (b44_alloc_rx_skb(bp, -1, i) < 0)
break;
@@ -1085,14 +1139,28 @@ static void b44_free_consistent(struct b44 *bp)
bp->tx_buffers = NULL;
}
if (bp->rx_ring) {
- pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
- bp->rx_ring, bp->rx_ring_dma);
+ if (bp->flags & B44_FLAG_RX_RING_HACK) {
+ dma_unmap_single(&bp->pdev->dev, bp->rx_ring_dma,
+ DMA_TABLE_BYTES,
+ DMA_BIDIRECTIONAL);
+ kfree(bp->rx_ring);
+ } else
+ pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
+ bp->rx_ring, bp->rx_ring_dma);
bp->rx_ring = NULL;
+ bp->flags &= ~B44_FLAG_RX_RING_HACK;
}
if (bp->tx_ring) {
- pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
- bp->tx_ring, bp->tx_ring_dma);
+ if (bp->flags & B44_FLAG_TX_RING_HACK) {
+ dma_unmap_single(&bp->pdev->dev, bp->tx_ring_dma,
+ DMA_TABLE_BYTES,
+ DMA_TO_DEVICE);
+ kfree(bp->tx_ring);
+ } else
+ pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
+ bp->tx_ring, bp->tx_ring_dma);
bp->tx_ring = NULL;
+ bp->flags &= ~B44_FLAG_TX_RING_HACK;
}
}
@@ -1118,12 +1186,56 @@ static int b44_alloc_consistent(struct b44 *bp)
size = DMA_TABLE_BYTES;
bp->rx_ring = pci_alloc_consistent(bp->pdev, size, &bp->rx_ring_dma);
- if (!bp->rx_ring)
- goto out_err;
+ if (!bp->rx_ring) {
+ /* Allocation may have failed due to pci_alloc_consistent
+ insisting on use of GFP_DMA, which is more restrictive
+ than necessary... */
+ struct dma_desc *rx_ring;
+ dma_addr_t rx_ring_dma;
+
+ if (!(rx_ring = (struct dma_desc *)kmalloc(size, GFP_KERNEL)))
+ goto out_err;
+
+ memset(rx_ring, 0, size);
+ rx_ring_dma = dma_map_single(&bp->pdev->dev, rx_ring,
+ DMA_TABLE_BYTES,
+ DMA_BIDIRECTIONAL);
+
+ if (rx_ring_dma + size > B44_DMA_MASK) {
+ kfree(rx_ring);
+ goto out_err;
+ }
+
+ bp->rx_ring = rx_ring;
+ bp->rx_ring_dma = rx_ring_dma;
+ bp->flags |= B44_FLAG_RX_RING_HACK;
+ }
bp->tx_ring = pci_alloc_consistent(bp->pdev, size, &bp->tx_ring_dma);
- if (!bp->tx_ring)
- goto out_err;
+ if (!bp->tx_ring) {
+ /* Allocation may have failed due to pci_alloc_consistent
+ insisting on use of GFP_DMA, which is more restrictive
+ than necessary... */
+ struct dma_desc *tx_ring;
+ dma_addr_t tx_ring_dma;
+
+ if (!(tx_ring = (struct dma_desc *)kmalloc(size, GFP_KERNEL)))
+ goto out_err;
+
+ memset(tx_ring, 0, size);
+ tx_ring_dma = dma_map_single(&bp->pdev->dev, tx_ring,
+ DMA_TABLE_BYTES,
+ DMA_TO_DEVICE);
+
+ if (tx_ring_dma + size > B44_DMA_MASK) {
+ kfree(tx_ring);
+ goto out_err;
+ }
+
+ bp->tx_ring = tx_ring;
+ bp->tx_ring_dma = tx_ring_dma;
+ bp->flags |= B44_FLAG_TX_RING_HACK;
+ }
return 0;
@@ -1676,6 +1788,7 @@ static struct ethtool_ops b44_ethtool_ops = {
.set_pauseparam = b44_set_pauseparam,
.get_msglevel = b44_get_msglevel,
.set_msglevel = b44_set_msglevel,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -1718,6 +1831,7 @@ static int __devinit b44_get_invariants(struct b44 *bp)
bp->dev->dev_addr[3] = eeprom[80];
bp->dev->dev_addr[4] = eeprom[83];
bp->dev->dev_addr[5] = eeprom[82];
+ memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len);
bp->phy_addr = eeprom[90] & 0x1f;
@@ -1971,6 +2085,12 @@ static struct pci_driver b44_driver = {
static int __init b44_init(void)
{
+ unsigned int dma_desc_align_size = dma_get_cache_alignment();
+
+ /* Setup paramaters for syncing RX/TX DMA descriptors */
+ dma_desc_align_mask = ~(dma_desc_align_size - 1);
+ dma_desc_sync_size = max(dma_desc_align_size, sizeof(struct dma_desc));
+
return pci_module_init(&b44_driver);
}
diff --git a/drivers/net/b44.h b/drivers/net/b44.h
index 11c40a2e71c70a..593cb0ad4100c6 100644
--- a/drivers/net/b44.h
+++ b/drivers/net/b44.h
@@ -400,6 +400,8 @@ struct b44 {
#define B44_FLAG_ADV_100HALF 0x04000000
#define B44_FLAG_ADV_100FULL 0x08000000
#define B44_FLAG_INTERNAL_PHY 0x10000000
+#define B44_FLAG_RX_RING_HACK 0x20000000
+#define B44_FLAG_TX_RING_HACK 0x40000000
u32 rx_offset;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index f264ff162979f5..8032126fd58918 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4241,6 +4241,43 @@ out:
return 0;
}
+static void bond_activebackup_xmit_copy(struct sk_buff *skb,
+ struct bonding *bond,
+ struct slave *slave)
+{
+ struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
+ struct ethhdr *eth_data;
+ u8 *hwaddr;
+ int res;
+
+ if (!skb2) {
+ printk(KERN_ERR DRV_NAME ": Error: "
+ "bond_activebackup_xmit_copy(): skb_copy() failed\n");
+ return;
+ }
+
+ skb2->mac.raw = (unsigned char *)skb2->data;
+ eth_data = eth_hdr(skb2);
+
+ /* Pick an appropriate source MAC address
+ * -- use slave's perm MAC addr, unless used by bond
+ * -- otherwise, borrow active slave's perm MAC addr
+ * since that will not be used
+ */
+ hwaddr = slave->perm_hwaddr;
+ if (!memcmp(eth_data->h_source, hwaddr, ETH_ALEN))
+ hwaddr = bond->curr_active_slave->perm_hwaddr;
+
+ /* Set source MAC address appropriately */
+ memcpy(eth_data->h_source, hwaddr, ETH_ALEN);
+
+ res = bond_dev_queue_xmit(bond, skb2, slave->dev);
+ if (res)
+ dev_kfree_skb(skb2);
+
+ return;
+}
+
/*
* in active-backup mode, we know that bond->curr_active_slave is always valid if
* the bond has a usable interface.
@@ -4257,10 +4294,26 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d
goto out;
}
- if (bond->curr_active_slave) { /* one usable interface */
- res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
+ if (!bond->curr_active_slave)
+ goto out;
+
+ /* Xmit IGMP frames on all slaves to ensure rapid fail-over
+ for multicast traffic on snooping switches */
+ if (skb->protocol == __constant_htons(ETH_P_IP) &&
+ skb->nh.iph->protocol == IPPROTO_IGMP) {
+ struct slave *slave, *active_slave;
+ int i;
+
+ active_slave = bond->curr_active_slave;
+ bond_for_each_slave_from_to(bond, slave, i, active_slave->next,
+ active_slave->prev)
+ if (IS_UP(slave->dev) &&
+ (slave->link == BOND_LINK_UP))
+ bond_activebackup_xmit_copy(skb, bond, slave);
}
+ res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
+
out:
if (res) {
/* no suitable interface, frame not sent */
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 2e617424d3fbf6..50f43dbf31aed4 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -489,7 +489,7 @@ static int cas_page_free(struct cas *cp, cas_page_t *page)
/* local page allocation routines for the receive buffers. jumbo pages
* require at least 8K contiguous and 8K aligned buffers.
*/
-static cas_page_t *cas_page_alloc(struct cas *cp, const int flags)
+static cas_page_t *cas_page_alloc(struct cas *cp, const gfp_t flags)
{
cas_page_t *page;
@@ -561,7 +561,7 @@ static void cas_spare_free(struct cas *cp)
}
/* replenish spares if needed */
-static void cas_spare_recover(struct cas *cp, const int flags)
+static void cas_spare_recover(struct cas *cp, const gfp_t flags)
{
struct list_head list, *elem, *tmp;
int needed, i;
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index a6078ad9b654ff..bfdae10036ed86 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -182,6 +182,10 @@ static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
#define CIRRUS_DEFAULT_IRQ VH_INTC_INT_NUM_CASCADED_INTERRUPT_1 /* Event inputs bank 1 - ID 35/bit 3 */
static unsigned int netcard_portlist[] __initdata = {CIRRUS_DEFAULT_BASE, 0};
static unsigned int cs8900_irq_map[] = {CIRRUS_DEFAULT_IRQ, 0, 0, 0};
+#elif defined(CONFIG_MACH_MP1000)
+#include <asm/arch/mp1000-seprom.h>
+static unsigned int netcard_portlist[] __initdata = {MP1000_EIO_BASE+0x300, 0};
+static unsigned int cs8900_irq_map[] = {IRQ_EINT3,0,0,0};
#else
static unsigned int netcard_portlist[] __initdata =
{ 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
@@ -590,6 +594,10 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
cnt -= j;
}
} else
+#elif defined(CONFIG_MACH_MP1000)
+ if (1) {
+ memcpy(dev->dev_addr, get_eeprom_mac_address(), ETH_ALEN);
+ } else
#endif
if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) ==
@@ -649,6 +657,10 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
if (1) {
printk(KERN_NOTICE "cs89x0: No EEPROM on HiCO.SH4\n");
} else
+#elif defined(CONFIG_MACH_MP1000)
+ if (1) {
+ lp->force |= FORCE_RJ45;
+ } else
#endif
if ((readreg(dev, PP_SelfST) & EEPROM_PRESENT) == 0)
printk(KERN_WARNING "cs89x0: No EEPROM, relying on command line....\n");
@@ -1231,7 +1243,7 @@ net_open(struct net_device *dev)
else
#endif
{
-#if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX0105)
+#if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX0105) && !defined(CONFIG_MACH_MP1000)
if (((1 << dev->irq) & lp->irq_map) == 0) {
printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
dev->name, dev->irq, lp->irq_map);
diff --git a/drivers/net/cs89x0.h b/drivers/net/cs89x0.h
index decea264f1214c..f19d1ebe018374 100644
--- a/drivers/net/cs89x0.h
+++ b/drivers/net/cs89x0.h
@@ -16,7 +16,7 @@
#include <linux/config.h>
-#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105)
+#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105) || defined (CONFIG_MACH_MP1000)
/* IXDP2401/IXDP2801 uses dword-aligned register addressing */
#define CS89x0_PORT(reg) ((reg) * 2)
#else
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index 521c83137bf67f..f130bdab3fd319 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -5,7 +5,7 @@
*
* adopted from sunlance.c by Richard van den Berg
*
- * Copyright (C) 2002, 2003 Maciej W. Rozycki
+ * Copyright (C) 2002, 2003, 2005 Maciej W. Rozycki
*
* additional sources:
* - PMAD-AA TURBOchannel Ethernet Module Functional Specification,
@@ -57,13 +57,15 @@
#include <linux/string.h>
#include <asm/addrspace.h>
+#include <asm/system.h>
+
#include <asm/dec/interrupts.h>
#include <asm/dec/ioasic.h>
#include <asm/dec/ioasic_addrs.h>
#include <asm/dec/kn01.h>
#include <asm/dec/machtype.h>
+#include <asm/dec/system.h>
#include <asm/dec/tc.h>
-#include <asm/system.h>
static char version[] __devinitdata =
"declance.c: v0.009 by Linux MIPS DECstation task force\n";
@@ -79,10 +81,6 @@ MODULE_LICENSE("GPL");
#define PMAD_LANCE 2
#define PMAX_LANCE 3
-#ifndef CONFIG_TC
-unsigned long system_base;
-unsigned long dmaptr;
-#endif
#define LE_CSR0 0
#define LE_CSR1 1
@@ -237,7 +235,7 @@ struct lance_init_block {
/*
* This works *only* for the ring descriptors
*/
-#define LANCE_ADDR(x) (PHYSADDR(x) >> 1)
+#define LANCE_ADDR(x) (CPHYSADDR(x) >> 1)
struct lance_private {
struct net_device *next;
@@ -697,12 +695,13 @@ out:
spin_unlock(&lp->lock);
}
-static void lance_dma_merr_int(const int irq, void *dev_id,
- struct pt_regs *regs)
+static irqreturn_t lance_dma_merr_int(const int irq, void *dev_id,
+ struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_id;
printk("%s: DMA error\n", dev->name);
+ return IRQ_HANDLED;
}
static irqreturn_t
@@ -1026,10 +1025,6 @@ static int __init dec_lance_init(const int type, const int slot)
unsigned long esar_base;
unsigned char *esar;
-#ifndef CONFIG_TC
- system_base = KN01_LANCE_BASE;
-#endif
-
if (dec_lance_debug && version_printed++ == 0)
printk(version);
@@ -1062,16 +1057,16 @@ static int __init dec_lance_init(const int type, const int slot)
switch (type) {
#ifdef CONFIG_TC
case ASIC_LANCE:
- dev->base_addr = system_base + IOASIC_LANCE;
+ dev->base_addr = CKSEG1ADDR(dec_kn_slot_base + IOASIC_LANCE);
/* buffer space for the on-board LANCE shared memory */
/*
* FIXME: ugly hack!
*/
- dev->mem_start = KSEG1ADDR(0x00020000);
+ dev->mem_start = CKSEG1ADDR(0x00020000);
dev->mem_end = dev->mem_start + 0x00020000;
dev->irq = dec_interrupt[DEC_IRQ_LANCE];
- esar_base = system_base + IOASIC_ESAR;
+ esar_base = CKSEG1ADDR(dec_kn_slot_base + IOASIC_ESAR);
/* Workaround crash with booting KN04 2.1k from Disk */
memset((void *)dev->mem_start, 0,
@@ -1101,14 +1096,14 @@ static int __init dec_lance_init(const int type, const int slot)
/* Setup I/O ASIC LANCE DMA. */
lp->dma_irq = dec_interrupt[DEC_IRQ_LANCE_MERR];
ioasic_write(IO_REG_LANCE_DMA_P,
- PHYSADDR(dev->mem_start) << 3);
+ CPHYSADDR(dev->mem_start) << 3);
break;
case PMAD_LANCE:
claim_tc_card(slot);
- dev->mem_start = get_tc_base_addr(slot);
+ dev->mem_start = CKSEG1ADDR(get_tc_base_addr(slot));
dev->base_addr = dev->mem_start + 0x100000;
dev->irq = get_tc_irq_nr(slot);
esar_base = dev->mem_start + 0x1c0002;
@@ -1137,9 +1132,9 @@ static int __init dec_lance_init(const int type, const int slot)
case PMAX_LANCE:
dev->irq = dec_interrupt[DEC_IRQ_LANCE];
- dev->base_addr = KN01_LANCE_BASE;
- dev->mem_start = KN01_LANCE_BASE + 0x01000000;
- esar_base = KN01_RTC_BASE + 1;
+ dev->base_addr = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE);
+ dev->mem_start = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE_MEM);
+ esar_base = CKSEG1ADDR(KN01_SLOT_BASE + KN01_ESAR + 1);
lp->dma_irq = -1;
/*
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index e54fc10f68467c..abce1f730d00b3 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -1140,11 +1140,11 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
}
static int
-dm9000_drv_suspend(struct device *dev, pm_message_t state, u32 level)
+dm9000_drv_suspend(struct device *dev, pm_message_t state)
{
struct net_device *ndev = dev_get_drvdata(dev);
- if (ndev && level == SUSPEND_DISABLE) {
+ if (ndev) {
if (netif_running(ndev)) {
netif_device_detach(ndev);
dm9000_shutdown(ndev);
@@ -1154,12 +1154,12 @@ dm9000_drv_suspend(struct device *dev, pm_message_t state, u32 level)
}
static int
-dm9000_drv_resume(struct device *dev, u32 level)
+dm9000_drv_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
board_info_t *db = (board_info_t *) ndev->priv;
- if (ndev && level == RESUME_ENABLE) {
+ if (ndev) {
if (netif_running(ndev)) {
dm9000_reset(db);
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 40887f09b681ac..eb169a8e877316 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -2201,6 +2201,7 @@ static struct ethtool_ops e100_ethtool_ops = {
.phys_id = e100_phys_id,
.get_stats_count = e100_get_stats_count,
.get_ethtool_stats = e100_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
@@ -2351,7 +2352,8 @@ static int __devinit e100_probe(struct pci_dev *pdev,
e100_phy_init(nic);
memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN);
- if(!is_valid_ether_addr(netdev->dev_addr)) {
+ memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN);
+ if(!is_valid_ether_addr(netdev->perm_addr)) {
DPRINTK(PROBE, ERR, "Invalid MAC address from "
"EEPROM, aborting.\n");
err = -EAGAIN;
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 092757bc721f0a..3f653a93e1bc78 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -72,6 +72,10 @@
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
+#ifdef CONFIG_E1000_MQ
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#endif
#define BAR_0 0
#define BAR_1 1
@@ -165,10 +169,33 @@ struct e1000_buffer {
uint16_t next_to_watch;
};
-struct e1000_ps_page { struct page *ps_page[MAX_PS_BUFFERS]; };
-struct e1000_ps_page_dma { uint64_t ps_page_dma[MAX_PS_BUFFERS]; };
+struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; };
+struct e1000_ps_page_dma { uint64_t ps_page_dma[PS_PAGE_BUFFERS]; };
+
+struct e1000_tx_ring {
+ /* pointer to the descriptor ring memory */
+ void *desc;
+ /* physical address of the descriptor ring */
+ dma_addr_t dma;
+ /* length of descriptor ring in bytes */
+ unsigned int size;
+ /* number of descriptors in the ring */
+ unsigned int count;
+ /* next descriptor to associate a buffer with */
+ unsigned int next_to_use;
+ /* next descriptor to check for DD status bit */
+ unsigned int next_to_clean;
+ /* array of buffer information structs */
+ struct e1000_buffer *buffer_info;
+
+ struct e1000_buffer previous_buffer_info;
+ spinlock_t tx_lock;
+ uint16_t tdh;
+ uint16_t tdt;
+ uint64_t pkt;
+};
-struct e1000_desc_ring {
+struct e1000_rx_ring {
/* pointer to the descriptor ring memory */
void *desc;
/* physical address of the descriptor ring */
@@ -186,6 +213,10 @@ struct e1000_desc_ring {
/* arrays of page information for packet split */
struct e1000_ps_page *ps_page;
struct e1000_ps_page_dma *ps_page_dma;
+
+ uint16_t rdh;
+ uint16_t rdt;
+ uint64_t pkt;
};
#define E1000_DESC_UNUSED(R) \
@@ -227,9 +258,10 @@ struct e1000_adapter {
unsigned long led_status;
/* TX */
- struct e1000_desc_ring tx_ring;
- struct e1000_buffer previous_buffer_info;
- spinlock_t tx_lock;
+ struct e1000_tx_ring *tx_ring; /* One per active queue */
+#ifdef CONFIG_E1000_MQ
+ struct e1000_tx_ring **cpu_tx_ring; /* per-cpu */
+#endif
uint32_t txd_cmd;
uint32_t tx_int_delay;
uint32_t tx_abs_int_delay;
@@ -246,19 +278,33 @@ struct e1000_adapter {
/* RX */
#ifdef CONFIG_E1000_NAPI
- boolean_t (*clean_rx) (struct e1000_adapter *adapter, int *work_done,
- int work_to_do);
+ boolean_t (*clean_rx) (struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int *work_done, int work_to_do);
#else
- boolean_t (*clean_rx) (struct e1000_adapter *adapter);
+ boolean_t (*clean_rx) (struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring);
#endif
- void (*alloc_rx_buf) (struct e1000_adapter *adapter);
- struct e1000_desc_ring rx_ring;
+ void (*alloc_rx_buf) (struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring);
+ struct e1000_rx_ring *rx_ring; /* One per active queue */
+#ifdef CONFIG_E1000_NAPI
+ struct net_device *polling_netdev; /* One per active queue */
+#endif
+#ifdef CONFIG_E1000_MQ
+ struct net_device **cpu_netdev; /* per-cpu */
+ struct call_async_data_struct rx_sched_call_data;
+ int cpu_for_queue[4];
+#endif
+ int num_queues;
+
uint64_t hw_csum_err;
uint64_t hw_csum_good;
+ uint64_t rx_hdr_split;
uint32_t rx_int_delay;
uint32_t rx_abs_int_delay;
boolean_t rx_csum;
- boolean_t rx_ps;
+ unsigned int rx_ps_pages;
uint32_t gorcl;
uint64_t gorcl_old;
uint16_t rx_ps_bsize0;
@@ -278,8 +324,8 @@ struct e1000_adapter {
struct e1000_phy_stats phy_stats;
uint32_t test_icr;
- struct e1000_desc_ring test_tx_ring;
- struct e1000_desc_ring test_rx_ring;
+ struct e1000_tx_ring test_tx_ring;
+ struct e1000_rx_ring test_rx_ring;
int msg_enable;
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index f133ff0b0b947c..6b9acc7f94a32e 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -39,10 +39,10 @@ extern int e1000_up(struct e1000_adapter *adapter);
extern void e1000_down(struct e1000_adapter *adapter);
extern void e1000_reset(struct e1000_adapter *adapter);
extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
-extern int e1000_setup_rx_resources(struct e1000_adapter *adapter);
-extern int e1000_setup_tx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_rx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_tx_resources(struct e1000_adapter *adapter);
+extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
extern void e1000_update_stats(struct e1000_adapter *adapter);
struct e1000_stats {
@@ -91,7 +91,8 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
{ "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
{ "rx_long_byte_count", E1000_STAT(stats.gorcl) },
{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
- { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }
+ { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
+ { "rx_header_split", E1000_STAT(rx_hdr_split) },
};
#define E1000_STATS_LEN \
sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
@@ -546,8 +547,10 @@ e1000_set_eeprom(struct net_device *netdev,
ret_val = e1000_write_eeprom(hw, first_word,
last_word - first_word + 1, eeprom_buff);
- /* Update the checksum over the first part of the EEPROM if needed */
- if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG)
+ /* Update the checksum over the first part of the EEPROM if needed
+ * and flush shadow RAM for 82573 conrollers */
+ if((ret_val == 0) && ((first_word <= EEPROM_CHECKSUM_REG) ||
+ (hw->mac_type == e1000_82573)))
e1000_update_eeprom_checksum(hw);
kfree(eeprom_buff);
@@ -576,8 +579,8 @@ e1000_get_ringparam(struct net_device *netdev,
{
struct e1000_adapter *adapter = netdev_priv(netdev);
e1000_mac_type mac_type = adapter->hw.mac_type;
- struct e1000_desc_ring *txdr = &adapter->tx_ring;
- struct e1000_desc_ring *rxdr = &adapter->rx_ring;
+ struct e1000_tx_ring *txdr = adapter->tx_ring;
+ struct e1000_rx_ring *rxdr = adapter->rx_ring;
ring->rx_max_pending = (mac_type < e1000_82544) ? E1000_MAX_RXD :
E1000_MAX_82544_RXD;
@@ -597,20 +600,40 @@ e1000_set_ringparam(struct net_device *netdev,
{
struct e1000_adapter *adapter = netdev_priv(netdev);
e1000_mac_type mac_type = adapter->hw.mac_type;
- struct e1000_desc_ring *txdr = &adapter->tx_ring;
- struct e1000_desc_ring *rxdr = &adapter->rx_ring;
- struct e1000_desc_ring tx_old, tx_new, rx_old, rx_new;
- int err;
+ struct e1000_tx_ring *txdr, *tx_old, *tx_new;
+ struct e1000_rx_ring *rxdr, *rx_old, *rx_new;
+ int i, err, tx_ring_size, rx_ring_size;
+
+ tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_queues;
+ rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_queues;
+
+ if (netif_running(adapter->netdev))
+ e1000_down(adapter);
tx_old = adapter->tx_ring;
rx_old = adapter->rx_ring;
+ adapter->tx_ring = kmalloc(tx_ring_size, GFP_KERNEL);
+ if (!adapter->tx_ring) {
+ err = -ENOMEM;
+ goto err_setup_rx;
+ }
+ memset(adapter->tx_ring, 0, tx_ring_size);
+
+ adapter->rx_ring = kmalloc(rx_ring_size, GFP_KERNEL);
+ if (!adapter->rx_ring) {
+ kfree(adapter->tx_ring);
+ err = -ENOMEM;
+ goto err_setup_rx;
+ }
+ memset(adapter->rx_ring, 0, rx_ring_size);
+
+ txdr = adapter->tx_ring;
+ rxdr = adapter->rx_ring;
+
if((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
- if(netif_running(adapter->netdev))
- e1000_down(adapter);
-
rxdr->count = max(ring->rx_pending,(uint32_t)E1000_MIN_RXD);
rxdr->count = min(rxdr->count,(uint32_t)(mac_type < e1000_82544 ?
E1000_MAX_RXD : E1000_MAX_82544_RXD));
@@ -621,11 +644,16 @@ e1000_set_ringparam(struct net_device *netdev,
E1000_MAX_TXD : E1000_MAX_82544_TXD));
E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE);
+ for (i = 0; i < adapter->num_queues; i++) {
+ txdr[i].count = txdr->count;
+ rxdr[i].count = rxdr->count;
+ }
+
if(netif_running(adapter->netdev)) {
/* Try to get new resources before deleting old */
- if((err = e1000_setup_rx_resources(adapter)))
+ if ((err = e1000_setup_all_rx_resources(adapter)))
goto err_setup_rx;
- if((err = e1000_setup_tx_resources(adapter)))
+ if ((err = e1000_setup_all_tx_resources(adapter)))
goto err_setup_tx;
/* save the new, restore the old in order to free it,
@@ -635,8 +663,10 @@ e1000_set_ringparam(struct net_device *netdev,
tx_new = adapter->tx_ring;
adapter->rx_ring = rx_old;
adapter->tx_ring = tx_old;
- e1000_free_rx_resources(adapter);
- e1000_free_tx_resources(adapter);
+ e1000_free_all_rx_resources(adapter);
+ e1000_free_all_tx_resources(adapter);
+ kfree(tx_old);
+ kfree(rx_old);
adapter->rx_ring = rx_new;
adapter->tx_ring = tx_new;
if((err = e1000_up(adapter)))
@@ -645,7 +675,7 @@ e1000_set_ringparam(struct net_device *netdev,
return 0;
err_setup_tx:
- e1000_free_rx_resources(adapter);
+ e1000_free_all_rx_resources(adapter);
err_setup_rx:
adapter->rx_ring = rx_old;
adapter->tx_ring = tx_old;
@@ -696,6 +726,11 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
* Some bits that get toggled are ignored.
*/
switch (adapter->hw.mac_type) {
+ /* there are several bits on newer hardware that are r/w */
+ case e1000_82571:
+ case e1000_82572:
+ toggle = 0x7FFFF3FF;
+ break;
case e1000_82573:
toggle = 0x7FFFF033;
break;
@@ -898,8 +933,8 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
static void
e1000_free_desc_rings(struct e1000_adapter *adapter)
{
- struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
- struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+ struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
+ struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
struct pci_dev *pdev = adapter->pdev;
int i;
@@ -941,8 +976,8 @@ e1000_free_desc_rings(struct e1000_adapter *adapter)
static int
e1000_setup_desc_rings(struct e1000_adapter *adapter)
{
- struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
- struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+ struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
+ struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
struct pci_dev *pdev = adapter->pdev;
uint32_t rctl;
int size, i, ret_val;
@@ -1245,6 +1280,8 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
case e1000_82541_rev_2:
case e1000_82547:
case e1000_82547_rev_2:
+ case e1000_82571:
+ case e1000_82572:
case e1000_82573:
return e1000_integrated_phy_loopback(adapter);
break;
@@ -1340,8 +1377,8 @@ e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
static int
e1000_run_loopback_test(struct e1000_adapter *adapter)
{
- struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
- struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+ struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
+ struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
struct pci_dev *pdev = adapter->pdev;
int i, j, k, l, lc, good_cnt, ret_val=0;
unsigned long time;
@@ -1509,6 +1546,7 @@ e1000_diag_test(struct net_device *netdev,
data[2] = 0;
data[3] = 0;
}
+ msleep_interruptible(4 * 1000);
}
static void
@@ -1625,7 +1663,7 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
- if(adapter->hw.mac_type < e1000_82573) {
+ if(adapter->hw.mac_type < e1000_82571) {
if(!adapter->blink_timer.function) {
init_timer(&adapter->blink_timer);
adapter->blink_timer.function = e1000_led_blink_callback;
@@ -1739,6 +1777,7 @@ struct ethtool_ops e1000_ethtool_ops = {
.phys_id = e1000_phys_id,
.get_stats_count = e1000_get_stats_count,
.get_ethtool_stats = e1000_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
void e1000_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 045f5426ab9a68..8fc876da43b43f 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -83,14 +83,14 @@ uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
static const
uint16_t e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
- { 8, 13, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43,
- 22, 24, 27, 30, 32, 35, 37, 40, 42, 44, 47, 49, 51, 54, 56, 58,
- 32, 35, 38, 41, 44, 47, 50, 53, 55, 58, 61, 63, 66, 69, 71, 74,
- 43, 47, 51, 54, 58, 61, 64, 67, 71, 74, 77, 80, 82, 85, 88, 90,
- 57, 62, 66, 70, 74, 77, 81, 85, 88, 91, 94, 97, 100, 103, 106, 108,
- 73, 78, 82, 87, 91, 95, 98, 102, 105, 109, 112, 114, 117, 119, 122, 124,
- 91, 96, 101, 105, 109, 113, 116, 119, 122, 125, 127, 128, 128, 128, 128, 128,
- 108, 113, 117, 121, 124, 127, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128};
+ { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,
+ 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41,
+ 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61,
+ 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82,
+ 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104,
+ 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121,
+ 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124,
+ 104, 109, 114, 118, 121, 124};
/******************************************************************************
@@ -286,7 +286,6 @@ e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82546GB_FIBER:
case E1000_DEV_ID_82546GB_SERDES:
case E1000_DEV_ID_82546GB_PCIE:
- case E1000_DEV_ID_82546GB_QUAD_COPPER:
hw->mac_type = e1000_82546_rev_3;
break;
case E1000_DEV_ID_82541EI:
@@ -305,8 +304,19 @@ e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82547GI:
hw->mac_type = e1000_82547_rev_2;
break;
+ case E1000_DEV_ID_82571EB_COPPER:
+ case E1000_DEV_ID_82571EB_FIBER:
+ case E1000_DEV_ID_82571EB_SERDES:
+ hw->mac_type = e1000_82571;
+ break;
+ case E1000_DEV_ID_82572EI_COPPER:
+ case E1000_DEV_ID_82572EI_FIBER:
+ case E1000_DEV_ID_82572EI_SERDES:
+ hw->mac_type = e1000_82572;
+ break;
case E1000_DEV_ID_82573E:
case E1000_DEV_ID_82573E_IAMT:
+ case E1000_DEV_ID_82573L:
hw->mac_type = e1000_82573;
break;
default:
@@ -315,6 +325,8 @@ e1000_set_mac_type(struct e1000_hw *hw)
}
switch(hw->mac_type) {
+ case e1000_82571:
+ case e1000_82572:
case e1000_82573:
hw->eeprom_semaphore_present = TRUE;
/* fall through */
@@ -351,6 +363,8 @@ e1000_set_media_type(struct e1000_hw *hw)
switch (hw->device_id) {
case E1000_DEV_ID_82545GM_SERDES:
case E1000_DEV_ID_82546GB_SERDES:
+ case E1000_DEV_ID_82571EB_SERDES:
+ case E1000_DEV_ID_82572EI_SERDES:
hw->media_type = e1000_media_type_internal_serdes;
break;
default:
@@ -523,6 +537,8 @@ e1000_reset_hw(struct e1000_hw *hw)
E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
E1000_WRITE_FLUSH(hw);
/* fall through */
+ case e1000_82571:
+ case e1000_82572:
ret_val = e1000_get_auto_rd_done(hw);
if(ret_val)
/* We don't want to continue accessing MAC registers. */
@@ -683,6 +699,9 @@ e1000_init_hw(struct e1000_hw *hw)
switch (hw->mac_type) {
default:
break;
+ case e1000_82571:
+ case e1000_82572:
+ ctrl |= (1 << 22);
case e1000_82573:
ctrl |= E1000_TXDCTL_COUNT_DESC;
break;
@@ -694,6 +713,26 @@ e1000_init_hw(struct e1000_hw *hw)
e1000_enable_tx_pkt_filtering(hw);
}
+ switch (hw->mac_type) {
+ default:
+ break;
+ case e1000_82571:
+ case e1000_82572:
+ ctrl = E1000_READ_REG(hw, TXDCTL1);
+ ctrl &= ~E1000_TXDCTL_WTHRESH;
+ ctrl |= E1000_TXDCTL_COUNT_DESC | E1000_TXDCTL_FULL_TX_DESC_WB;
+ ctrl |= (1 << 22);
+ E1000_WRITE_REG(hw, TXDCTL1, ctrl);
+ break;
+ }
+
+
+
+ if (hw->mac_type == e1000_82573) {
+ uint32_t gcr = E1000_READ_REG(hw, GCR);
+ gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
+ E1000_WRITE_REG(hw, GCR, gcr);
+ }
/* Clear all of the statistics registers (clear on read). It is
* important that we do this after we have tried to establish link
@@ -878,6 +917,14 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
DEBUGFUNC("e1000_setup_fiber_serdes_link");
+ /* On 82571 and 82572 Fiber connections, SerDes loopback mode persists
+ * until explicitly turned off or a power cycle is performed. A read to
+ * the register does not indicate its status. Therefore, we ensure
+ * loopback mode is disabled during initialization.
+ */
+ if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572)
+ E1000_WRITE_REG(hw, SCTL, E1000_DISABLE_SERDES_LOOPBACK);
+
/* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be
* set when the optics detect a signal. On older adapters, it will be
* cleared when there is a signal. This applies to fiber media only.
@@ -2943,6 +2990,8 @@ e1000_phy_reset(struct e1000_hw *hw)
switch (hw->mac_type) {
case e1000_82541_rev_2:
+ case e1000_82571:
+ case e1000_82572:
ret_val = e1000_phy_hw_reset(hw);
if(ret_val)
return ret_val;
@@ -2981,6 +3030,16 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
DEBUGFUNC("e1000_detect_gig_phy");
+ /* The 82571 firmware may still be configuring the PHY. In this
+ * case, we cannot access the PHY until the configuration is done. So
+ * we explicitly set the PHY values. */
+ if(hw->mac_type == e1000_82571 ||
+ hw->mac_type == e1000_82572) {
+ hw->phy_id = IGP01E1000_I_PHY_ID;
+ hw->phy_type = e1000_phy_igp_2;
+ return E1000_SUCCESS;
+ }
+
/* Read the PHY ID Registers to identify which PHY is onboard. */
ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high);
if(ret_val)
@@ -3334,6 +3393,21 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
eeprom->use_eerd = FALSE;
eeprom->use_eewr = FALSE;
break;
+ case e1000_82571:
+ case e1000_82572:
+ eeprom->type = e1000_eeprom_spi;
+ eeprom->opcode_bits = 8;
+ eeprom->delay_usec = 1;
+ if (eecd & E1000_EECD_ADDR_BITS) {
+ eeprom->page_size = 32;
+ eeprom->address_bits = 16;
+ } else {
+ eeprom->page_size = 8;
+ eeprom->address_bits = 8;
+ }
+ eeprom->use_eerd = FALSE;
+ eeprom->use_eewr = FALSE;
+ break;
case e1000_82573:
eeprom->type = e1000_eeprom_spi;
eeprom->opcode_bits = 8;
@@ -3543,25 +3617,26 @@ e1000_acquire_eeprom(struct e1000_hw *hw)
eecd = E1000_READ_REG(hw, EECD);
if (hw->mac_type != e1000_82573) {
- /* Request EEPROM Access */
- if(hw->mac_type > e1000_82544) {
- eecd |= E1000_EECD_REQ;
- E1000_WRITE_REG(hw, EECD, eecd);
- eecd = E1000_READ_REG(hw, EECD);
- while((!(eecd & E1000_EECD_GNT)) &&
- (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
- i++;
- udelay(5);
- eecd = E1000_READ_REG(hw, EECD);
- }
- if(!(eecd & E1000_EECD_GNT)) {
- eecd &= ~E1000_EECD_REQ;
+ /* Request EEPROM Access */
+ if(hw->mac_type > e1000_82544) {
+ eecd |= E1000_EECD_REQ;
E1000_WRITE_REG(hw, EECD, eecd);
- DEBUGOUT("Could not acquire EEPROM grant\n");
- return -E1000_ERR_EEPROM;
+ eecd = E1000_READ_REG(hw, EECD);
+ while((!(eecd & E1000_EECD_GNT)) &&
+ (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
+ i++;
+ udelay(5);
+ eecd = E1000_READ_REG(hw, EECD);
+ }
+ if(!(eecd & E1000_EECD_GNT)) {
+ eecd &= ~E1000_EECD_REQ;
+ E1000_WRITE_REG(hw, EECD, eecd);
+ DEBUGOUT("Could not acquire EEPROM grant\n");
+ e1000_put_hw_eeprom_semaphore(hw);
+ return -E1000_ERR_EEPROM;
+ }
}
}
- }
/* Setup EEPROM for Read/Write */
@@ -4064,7 +4139,7 @@ e1000_write_eeprom(struct e1000_hw *hw,
return -E1000_ERR_EEPROM;
}
- /* 82573 reads only through eerd */
+ /* 82573 writes only through eewr */
if(eeprom->use_eewr == TRUE)
return e1000_write_eeprom_eewr(hw, offset, words, data);
@@ -4353,9 +4428,16 @@ e1000_read_mac_addr(struct e1000_hw * hw)
hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF);
hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8);
}
- if(((hw->mac_type == e1000_82546) || (hw->mac_type == e1000_82546_rev_3)) &&
- (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1))
+ switch (hw->mac_type) {
+ default:
+ break;
+ case e1000_82546:
+ case e1000_82546_rev_3:
+ case e1000_82571:
+ if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
hw->perm_mac_addr[5] ^= 0x01;
+ break;
+ }
for(i = 0; i < NODE_ADDRESS_SIZE; i++)
hw->mac_addr[i] = hw->perm_mac_addr[i];
@@ -4385,6 +4467,12 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
e1000_rar_set(hw, hw->mac_addr, 0);
rar_num = E1000_RAR_ENTRIES;
+
+ /* Reserve a spot for the Locally Administered Address to work around
+ * an 82571 issue in which a reset on one port will reload the MAC on
+ * the other port. */
+ if ((hw->mac_type == e1000_82571) && (hw->laa_is_present == TRUE))
+ rar_num -= 1;
/* Zero out the other 15 receive addresses. */
DEBUGOUT("Clearing RAR[1-15]\n");
for(i = 1; i < rar_num; i++) {
@@ -4427,6 +4515,12 @@ e1000_mc_addr_list_update(struct e1000_hw *hw,
/* Clear RAR[1-15] */
DEBUGOUT(" Clearing RAR[1-15]\n");
num_rar_entry = E1000_RAR_ENTRIES;
+ /* Reserve a spot for the Locally Administered Address to work around
+ * an 82571 issue in which a reset on one port will reload the MAC on
+ * the other port. */
+ if ((hw->mac_type == e1000_82571) && (hw->laa_is_present == TRUE))
+ num_rar_entry -= 1;
+
for(i = rar_used_count; i < num_rar_entry; i++) {
E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
@@ -4984,7 +5078,6 @@ e1000_clear_hw_cntrs(struct e1000_hw *hw)
temp = E1000_READ_REG(hw, ICTXQEC);
temp = E1000_READ_REG(hw, ICTXQMTC);
temp = E1000_READ_REG(hw, ICRXDMTC);
-
}
/******************************************************************************
@@ -5151,6 +5244,8 @@ e1000_get_bus_info(struct e1000_hw *hw)
hw->bus_speed = e1000_bus_speed_unknown;
hw->bus_width = e1000_bus_width_unknown;
break;
+ case e1000_82571:
+ case e1000_82572:
case e1000_82573:
hw->bus_type = e1000_bus_type_pci_express;
hw->bus_speed = e1000_bus_speed_2500;
@@ -5250,6 +5345,7 @@ e1000_get_cable_length(struct e1000_hw *hw,
int32_t ret_val;
uint16_t agc_value = 0;
uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
+ uint16_t max_agc = 0;
uint16_t i, phy_data;
uint16_t cable_length;
@@ -5338,6 +5434,40 @@ e1000_get_cable_length(struct e1000_hw *hw,
IGP01E1000_AGC_RANGE) : 0;
*max_length = e1000_igp_cable_length_table[agc_value] +
IGP01E1000_AGC_RANGE;
+ } else if (hw->phy_type == e1000_phy_igp_2) {
+ uint16_t agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
+ {IGP02E1000_PHY_AGC_A,
+ IGP02E1000_PHY_AGC_B,
+ IGP02E1000_PHY_AGC_C,
+ IGP02E1000_PHY_AGC_D};
+ /* Read the AGC registers for all channels */
+ for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
+ ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* Getting bits 15:9, which represent the combination of course and
+ * fine gain values. The result is a number that can be put into
+ * the lookup table to obtain the approximate cable length. */
+ cur_agc = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
+ IGP02E1000_AGC_LENGTH_MASK;
+
+ /* Remove min & max AGC values from calculation. */
+ if (e1000_igp_2_cable_length_table[min_agc] > e1000_igp_2_cable_length_table[cur_agc])
+ min_agc = cur_agc;
+ if (e1000_igp_2_cable_length_table[max_agc] < e1000_igp_2_cable_length_table[cur_agc])
+ max_agc = cur_agc;
+
+ agc_value += e1000_igp_2_cable_length_table[cur_agc];
+ }
+
+ agc_value -= (e1000_igp_2_cable_length_table[min_agc] + e1000_igp_2_cable_length_table[max_agc]);
+ agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2);
+
+ /* Calculate cable length with the error range of +/- 10 meters. */
+ *min_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
+ (agc_value - IGP02E1000_AGC_RANGE) : 0;
+ *max_length = agc_value + IGP02E1000_AGC_RANGE;
}
return E1000_SUCCESS;
@@ -6465,6 +6595,8 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
default:
msec_delay(5);
break;
+ case e1000_82571:
+ case e1000_82572:
case e1000_82573:
while(timeout) {
if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) break;
@@ -6494,10 +6626,31 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
int32_t
e1000_get_phy_cfg_done(struct e1000_hw *hw)
{
+ int32_t timeout = PHY_CFG_TIMEOUT;
+ uint32_t cfg_mask = E1000_EEPROM_CFG_DONE;
+
DEBUGFUNC("e1000_get_phy_cfg_done");
- /* Simply wait for 10ms */
- msec_delay(10);
+ switch (hw->mac_type) {
+ default:
+ msec_delay(10);
+ break;
+ case e1000_82571:
+ case e1000_82572:
+ while (timeout) {
+ if (E1000_READ_REG(hw, EEMNGCTL) & cfg_mask)
+ break;
+ else
+ msec_delay(1);
+ timeout--;
+ }
+
+ if (!timeout) {
+ DEBUGOUT("MNG configuration cycle has not completed.\n");
+ return -E1000_ERR_RESET;
+ }
+ break;
+ }
return E1000_SUCCESS;
}
@@ -6569,8 +6722,7 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
return;
swsm = E1000_READ_REG(hw, SWSM);
- /* Release both semaphores. */
- swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
+ swsm &= ~(E1000_SWSM_SWESMBI);
E1000_WRITE_REG(hw, SWSM, swsm);
}
@@ -6606,6 +6758,8 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
* if this is the case. We read FWSM to determine the manageability mode.
*/
switch (hw->mac_type) {
+ case e1000_82571:
+ case e1000_82572:
case e1000_82573:
fwsm = E1000_READ_REG(hw, FWSM);
if((fwsm & E1000_FWSM_MODE_MASK) != 0)
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index 51c2b3a18b6f38..4f2c196dc314cd 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -57,6 +57,8 @@ typedef enum {
e1000_82541_rev_2,
e1000_82547,
e1000_82547_rev_2,
+ e1000_82571,
+ e1000_82572,
e1000_82573,
e1000_num_macs
} e1000_mac_type;
@@ -478,10 +480,16 @@ uint8_t e1000_arc_subsystem_valid(struct e1000_hw *hw);
#define E1000_DEV_ID_82546GB_SERDES 0x107B
#define E1000_DEV_ID_82546GB_PCIE 0x108A
#define E1000_DEV_ID_82547EI 0x1019
+#define E1000_DEV_ID_82571EB_COPPER 0x105E
+#define E1000_DEV_ID_82571EB_FIBER 0x105F
+#define E1000_DEV_ID_82571EB_SERDES 0x1060
+#define E1000_DEV_ID_82572EI_COPPER 0x107D
+#define E1000_DEV_ID_82572EI_FIBER 0x107E
+#define E1000_DEV_ID_82572EI_SERDES 0x107F
#define E1000_DEV_ID_82573E 0x108B
#define E1000_DEV_ID_82573E_IAMT 0x108C
+#define E1000_DEV_ID_82573L 0x109A
-#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
#define NODE_ADDRESS_SIZE 6
#define ETH_LENGTH_OF_ADDRESS 6
@@ -833,6 +841,8 @@ struct e1000_ffvt_entry {
#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
+#define E1000_DISABLE_SERDES_LOOPBACK 0x0400
+
/* Register Set. (82543, 82544)
*
* Registers are defined to be 32 bits and should be accessed as 32 bit values.
@@ -853,6 +863,7 @@ struct e1000_ffvt_entry {
#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */
#define E1000_FLA 0x0001C /* Flash Access - RW */
#define E1000_MDIC 0x00020 /* MDI Control - RW */
+#define E1000_SCTL 0x00024 /* SerDes Control - RW */
#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */
#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */
#define E1000_FCT 0x00030 /* Flow Control Type - RW */
@@ -864,6 +875,12 @@ struct e1000_ffvt_entry {
#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
#define E1000_RCTL 0x00100 /* RX Control - RW */
+#define E1000_RDTR1 0x02820 /* RX Delay Timer (1) - RW */
+#define E1000_RDBAL1 0x02900 /* RX Descriptor Base Address Low (1) - RW */
+#define E1000_RDBAH1 0x02904 /* RX Descriptor Base Address High (1) - RW */
+#define E1000_RDLEN1 0x02908 /* RX Descriptor Length (1) - RW */
+#define E1000_RDH1 0x02910 /* RX Descriptor Head (1) - RW */
+#define E1000_RDT1 0x02918 /* RX Descriptor Tail (1) - RW */
#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
#define E1000_TXCW 0x00178 /* TX Configuration Word - RW */
#define E1000_RXCW 0x00180 /* RX Configuration Word - RO */
@@ -895,6 +912,12 @@ struct e1000_ffvt_entry {
#define E1000_RDH 0x02810 /* RX Descriptor Head - RW */
#define E1000_RDT 0x02818 /* RX Descriptor Tail - RW */
#define E1000_RDTR 0x02820 /* RX Delay Timer - RW */
+#define E1000_RDBAL0 E1000_RDBAL /* RX Desc Base Address Low (0) - RW */
+#define E1000_RDBAH0 E1000_RDBAH /* RX Desc Base Address High (0) - RW */
+#define E1000_RDLEN0 E1000_RDLEN /* RX Desc Length (0) - RW */
+#define E1000_RDH0 E1000_RDH /* RX Desc Head (0) - RW */
+#define E1000_RDT0 E1000_RDT /* RX Desc Tail (0) - RW */
+#define E1000_RDTR0 E1000_RDTR /* RX Delay Timer (0) - RW */
#define E1000_RXDCTL 0x02828 /* RX Descriptor Control - RW */
#define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */
#define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */
@@ -980,15 +1003,15 @@ struct e1000_ffvt_entry {
#define E1000_BPTC 0x040F4 /* Broadcast Packets TX Count - R/clr */
#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context TX - R/clr */
#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context TX Fail - R/clr */
-#define E1000_IAC 0x4100 /* Interrupt Assertion Count */
-#define E1000_ICRXPTC 0x4104 /* Interrupt Cause Rx Packet Timer Expire Count */
-#define E1000_ICRXATC 0x4108 /* Interrupt Cause Rx Absolute Timer Expire Count */
-#define E1000_ICTXPTC 0x410C /* Interrupt Cause Tx Packet Timer Expire Count */
-#define E1000_ICTXATC 0x4110 /* Interrupt Cause Tx Absolute Timer Expire Count */
-#define E1000_ICTXQEC 0x4118 /* Interrupt Cause Tx Queue Empty Count */
-#define E1000_ICTXQMTC 0x411C /* Interrupt Cause Tx Queue Minimum Threshold Count */
-#define E1000_ICRXDMTC 0x4120 /* Interrupt Cause Rx Descriptor Minimum Threshold Count */
-#define E1000_ICRXOC 0x4124 /* Interrupt Cause Receiver Overrun Count */
+#define E1000_IAC 0x04100 /* Interrupt Assertion Count */
+#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Packet Timer Expire Count */
+#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Absolute Timer Expire Count */
+#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Packet Timer Expire Count */
+#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Absolute Timer Expire Count */
+#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */
+#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Minimum Threshold Count */
+#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Descriptor Minimum Threshold Count */
+#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */
#define E1000_RXCSUM 0x05000 /* RX Checksum Control - RW */
#define E1000_RFCTL 0x05008 /* Receive Filter Control*/
#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
@@ -1018,6 +1041,14 @@ struct e1000_ffvt_entry {
#define E1000_FWSM 0x05B54 /* FW Semaphore */
#define E1000_FFLT_DBG 0x05F04 /* Debug Register */
#define E1000_HICR 0x08F00 /* Host Inteface Control */
+
+/* RSS registers */
+#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */
+#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */
+#define E1000_RETA 0x05C00 /* Redirection Table - RW Array */
+#define E1000_RSSRK 0x05C80 /* RSS Random Key - RW Array */
+#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */
+#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */
/* Register Set (82542)
*
* Some of the 82542 registers are located at different offsets than they are
@@ -1032,6 +1063,7 @@ struct e1000_ffvt_entry {
#define E1000_82542_CTRL_EXT E1000_CTRL_EXT
#define E1000_82542_FLA E1000_FLA
#define E1000_82542_MDIC E1000_MDIC
+#define E1000_82542_SCTL E1000_SCTL
#define E1000_82542_FCAL E1000_FCAL
#define E1000_82542_FCAH E1000_FCAH
#define E1000_82542_FCT E1000_FCT
@@ -1049,6 +1081,18 @@ struct e1000_ffvt_entry {
#define E1000_82542_RDLEN 0x00118
#define E1000_82542_RDH 0x00120
#define E1000_82542_RDT 0x00128
+#define E1000_82542_RDTR0 E1000_82542_RDTR
+#define E1000_82542_RDBAL0 E1000_82542_RDBAL
+#define E1000_82542_RDBAH0 E1000_82542_RDBAH
+#define E1000_82542_RDLEN0 E1000_82542_RDLEN
+#define E1000_82542_RDH0 E1000_82542_RDH
+#define E1000_82542_RDT0 E1000_82542_RDT
+#define E1000_82542_RDTR1 0x00130
+#define E1000_82542_RDBAL1 0x00138
+#define E1000_82542_RDBAH1 0x0013C
+#define E1000_82542_RDLEN1 0x00140
+#define E1000_82542_RDH1 0x00148
+#define E1000_82542_RDT1 0x00150
#define E1000_82542_FCRTH 0x00160
#define E1000_82542_FCRTL 0x00168
#define E1000_82542_FCTTV E1000_FCTTV
@@ -1197,6 +1241,13 @@ struct e1000_ffvt_entry {
#define E1000_82542_ICRXOC E1000_ICRXOC
#define E1000_82542_HICR E1000_HICR
+#define E1000_82542_CPUVEC E1000_CPUVEC
+#define E1000_82542_MRQC E1000_MRQC
+#define E1000_82542_RETA E1000_RETA
+#define E1000_82542_RSSRK E1000_RSSRK
+#define E1000_82542_RSSIM E1000_RSSIM
+#define E1000_82542_RSSIR E1000_RSSIR
+
/* Statistics counters collected by the MAC */
struct e1000_hw_stats {
uint64_t crcerrs;
@@ -1336,6 +1387,7 @@ struct e1000_hw {
boolean_t serdes_link_down;
boolean_t tbi_compatibility_en;
boolean_t tbi_compatibility_on;
+ boolean_t laa_is_present;
boolean_t phy_reset_disable;
boolean_t fc_send_xon;
boolean_t fc_strict_ieee;
@@ -1374,6 +1426,7 @@ struct e1000_hw {
#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */
#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */
#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */
+#define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */
#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */
#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */
#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */
@@ -1491,6 +1544,8 @@ struct e1000_hw {
#define E1000_CTRL_EXT_WR_WMARK_320 0x01000000
#define E1000_CTRL_EXT_WR_WMARK_384 0x02000000
#define E1000_CTRL_EXT_WR_WMARK_448 0x03000000
+#define E1000_CTRL_EXT_CANC 0x04000000 /* Interrupt delay cancellation */
+#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */
#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */
#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */
@@ -1524,6 +1579,7 @@ struct e1000_hw {
#define E1000_LEDCTL_LED2_BLINK 0x00800000
#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000
#define E1000_LEDCTL_LED3_MODE_SHIFT 24
+#define E1000_LEDCTL_LED3_BLINK_RATE 0x20000000
#define E1000_LEDCTL_LED3_IVRT 0x40000000
#define E1000_LEDCTL_LED3_BLINK 0x80000000
@@ -1784,6 +1840,16 @@ struct e1000_hw {
#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */
#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
+/* Multiple Receive Queue Control */
+#define E1000_MRQC_ENABLE_MASK 0x00000003
+#define E1000_MRQC_ENABLE_RSS_2Q 0x00000001
+#define E1000_MRQC_ENABLE_RSS_INT 0x00000004
+#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000
+#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
+#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000
+#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00040000
+#define E1000_MRQC_RSS_FIELD_IPV6_EX 0x00080000
+#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000
/* Definitions for power management and wakeup registers */
/* Wake Up Control */
@@ -1928,6 +1994,7 @@ struct e1000_host_command_info {
#define E1000_MDALIGN 4096
#define E1000_GCR_BEM32 0x00400000
+#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
/* Function Active and Power State to MNG */
#define E1000_FACTPS_FUNC0_POWER_STATE_MASK 0x00000003
#define E1000_FACTPS_LAN0_VALID 0x00000004
@@ -1980,6 +2047,7 @@ struct e1000_host_command_info {
/* EEPROM Word Offsets */
#define EEPROM_COMPAT 0x0003
#define EEPROM_ID_LED_SETTINGS 0x0004
+#define EEPROM_VERSION 0x0005
#define EEPROM_SERDES_AMPLITUDE 0x0006 /* For SERDES output amplitude adjustment. */
#define EEPROM_PHY_CLASS_WORD 0x0007
#define EEPROM_INIT_CONTROL1_REG 0x000A
@@ -1990,6 +2058,8 @@ struct e1000_host_command_info {
#define EEPROM_FLASH_VERSION 0x0032
#define EEPROM_CHECKSUM_REG 0x003F
+#define E1000_EEPROM_CFG_DONE 0x00040000 /* MNG config cycle done */
+
/* Word definitions for ID LED Settings */
#define ID_LED_RESERVED_0000 0x0000
#define ID_LED_RESERVED_FFFF 0xFFFF
@@ -2108,6 +2178,8 @@ struct e1000_host_command_info {
#define E1000_PBA_22K 0x0016
#define E1000_PBA_24K 0x0018
#define E1000_PBA_30K 0x001E
+#define E1000_PBA_32K 0x0020
+#define E1000_PBA_38K 0x0026
#define E1000_PBA_40K 0x0028
#define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */
@@ -2592,11 +2664,11 @@ struct e1000_host_command_info {
/* 7 bits (3 Coarse + 4 Fine) --> 128 optional values */
#define IGP01E1000_AGC_LENGTH_TABLE_SIZE 128
-#define IGP02E1000_AGC_LENGTH_TABLE_SIZE 128
+#define IGP02E1000_AGC_LENGTH_TABLE_SIZE 113
/* The precision error of the cable length is +/- 10 meters */
#define IGP01E1000_AGC_RANGE 10
-#define IGP02E1000_AGC_RANGE 10
+#define IGP02E1000_AGC_RANGE 15
/* IGP01E1000 PCS Initialization register */
/* bits 3:6 in the PCS registers stores the channels polarity */
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index ee687c902a20be..6b72f6acdd54ec 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -43,7 +43,7 @@ char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-#define DRV_VERSION "6.0.60-k2"DRIVERNAPI
+#define DRV_VERSION "6.1.16-k2"DRIVERNAPI
char e1000_driver_version[] = DRV_VERSION;
char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
@@ -80,6 +80,9 @@ static struct pci_device_id e1000_pci_tbl[] = {
INTEL_E1000_ETHERNET_DEVICE(0x1026),
INTEL_E1000_ETHERNET_DEVICE(0x1027),
INTEL_E1000_ETHERNET_DEVICE(0x1028),
+ INTEL_E1000_ETHERNET_DEVICE(0x105E),
+ INTEL_E1000_ETHERNET_DEVICE(0x105F),
+ INTEL_E1000_ETHERNET_DEVICE(0x1060),
INTEL_E1000_ETHERNET_DEVICE(0x1075),
INTEL_E1000_ETHERNET_DEVICE(0x1076),
INTEL_E1000_ETHERNET_DEVICE(0x1077),
@@ -88,10 +91,13 @@ static struct pci_device_id e1000_pci_tbl[] = {
INTEL_E1000_ETHERNET_DEVICE(0x107A),
INTEL_E1000_ETHERNET_DEVICE(0x107B),
INTEL_E1000_ETHERNET_DEVICE(0x107C),
+ INTEL_E1000_ETHERNET_DEVICE(0x107D),
+ INTEL_E1000_ETHERNET_DEVICE(0x107E),
+ INTEL_E1000_ETHERNET_DEVICE(0x107F),
INTEL_E1000_ETHERNET_DEVICE(0x108A),
INTEL_E1000_ETHERNET_DEVICE(0x108B),
INTEL_E1000_ETHERNET_DEVICE(0x108C),
- INTEL_E1000_ETHERNET_DEVICE(0x1099),
+ INTEL_E1000_ETHERNET_DEVICE(0x109A),
/* required last entry */
{0,}
};
@@ -102,10 +108,18 @@ int e1000_up(struct e1000_adapter *adapter);
void e1000_down(struct e1000_adapter *adapter);
void e1000_reset(struct e1000_adapter *adapter);
int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
-int e1000_setup_tx_resources(struct e1000_adapter *adapter);
-int e1000_setup_rx_resources(struct e1000_adapter *adapter);
-void e1000_free_tx_resources(struct e1000_adapter *adapter);
-void e1000_free_rx_resources(struct e1000_adapter *adapter);
+int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
+void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
+int e1000_setup_tx_resources(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *txdr);
+int e1000_setup_rx_resources(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rxdr);
+void e1000_free_tx_resources(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring);
+void e1000_free_rx_resources(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring);
void e1000_update_stats(struct e1000_adapter *adapter);
/* Local Function Prototypes */
@@ -114,14 +128,22 @@ static int e1000_init_module(void);
static void e1000_exit_module(void);
static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
static void __devexit e1000_remove(struct pci_dev *pdev);
+static int e1000_alloc_queues(struct e1000_adapter *adapter);
+#ifdef CONFIG_E1000_MQ
+static void e1000_setup_queue_mapping(struct e1000_adapter *adapter);
+#endif
static int e1000_sw_init(struct e1000_adapter *adapter);
static int e1000_open(struct net_device *netdev);
static int e1000_close(struct net_device *netdev);
static void e1000_configure_tx(struct e1000_adapter *adapter);
static void e1000_configure_rx(struct e1000_adapter *adapter);
static void e1000_setup_rctl(struct e1000_adapter *adapter);
-static void e1000_clean_tx_ring(struct e1000_adapter *adapter);
-static void e1000_clean_rx_ring(struct e1000_adapter *adapter);
+static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter);
+static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter);
+static void e1000_clean_tx_ring(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring);
+static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring);
static void e1000_set_multi(struct net_device *netdev);
static void e1000_update_phy_info(unsigned long data);
static void e1000_watchdog(unsigned long data);
@@ -132,19 +154,26 @@ static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
static int e1000_set_mac(struct net_device *netdev, void *p);
static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs);
-static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter);
+static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring);
#ifdef CONFIG_E1000_NAPI
-static int e1000_clean(struct net_device *netdev, int *budget);
+static int e1000_clean(struct net_device *poll_dev, int *budget);
static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
int *work_done, int work_to_do);
static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
int *work_done, int work_to_do);
#else
-static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter);
-static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter);
+static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring);
+static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring);
#endif
-static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter);
-static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter);
+static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring);
+static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring);
static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
int cmd);
@@ -172,6 +201,11 @@ static int e1000_resume(struct pci_dev *pdev);
static void e1000_netpoll (struct net_device *netdev);
#endif
+#ifdef CONFIG_E1000_MQ
+/* for multiple Rx queues */
+void e1000_rx_schedule(void *data);
+#endif
+
/* Exported from other modules */
extern void e1000_check_options(struct e1000_adapter *adapter);
@@ -289,7 +323,7 @@ int
e1000_up(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- int err;
+ int i, err;
/* hardware has been reset, we need to reload some things */
@@ -308,7 +342,8 @@ e1000_up(struct e1000_adapter *adapter)
e1000_configure_tx(adapter);
e1000_setup_rctl(adapter);
e1000_configure_rx(adapter);
- adapter->alloc_rx_buf(adapter);
+ for (i = 0; i < adapter->num_queues; i++)
+ adapter->alloc_rx_buf(adapter, &adapter->rx_ring[i]);
#ifdef CONFIG_PCI_MSI
if(adapter->hw.mac_type > e1000_82547_rev_2) {
@@ -344,6 +379,9 @@ e1000_down(struct e1000_adapter *adapter)
struct net_device *netdev = adapter->netdev;
e1000_irq_disable(adapter);
+#ifdef CONFIG_E1000_MQ
+ while (atomic_read(&adapter->rx_sched_call_data.count) != 0);
+#endif
free_irq(adapter->pdev->irq, netdev);
#ifdef CONFIG_PCI_MSI
if(adapter->hw.mac_type > e1000_82547_rev_2 &&
@@ -363,11 +401,10 @@ e1000_down(struct e1000_adapter *adapter)
netif_stop_queue(netdev);
e1000_reset(adapter);
- e1000_clean_tx_ring(adapter);
- e1000_clean_rx_ring(adapter);
+ e1000_clean_all_tx_rings(adapter);
+ e1000_clean_all_rx_rings(adapter);
- /* If WoL is not enabled
- * and management mode is not IAMT
+ /* If WoL is not enabled and management mode is not IAMT
* Power down the PHY so no link is implied when interface is down */
if(!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
adapter->hw.media_type == e1000_media_type_copper &&
@@ -398,6 +435,10 @@ e1000_reset(struct e1000_adapter *adapter)
case e1000_82547_rev_2:
pba = E1000_PBA_30K;
break;
+ case e1000_82571:
+ case e1000_82572:
+ pba = E1000_PBA_38K;
+ break;
case e1000_82573:
pba = E1000_PBA_12K;
break;
@@ -475,6 +516,7 @@ e1000_probe(struct pci_dev *pdev,
struct net_device *netdev;
struct e1000_adapter *adapter;
unsigned long mmio_start, mmio_len;
+ uint32_t ctrl_ext;
uint32_t swsm;
static int cards_found = 0;
@@ -614,8 +656,9 @@ e1000_probe(struct pci_dev *pdev,
if(e1000_read_mac_addr(&adapter->hw))
DPRINTK(PROBE, ERR, "EEPROM Read Error\n");
memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
+ memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
- if(!is_valid_ether_addr(netdev->dev_addr)) {
+ if(!is_valid_ether_addr(netdev->perm_addr)) {
DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
err = -EIO;
goto err_eeprom;
@@ -687,6 +730,12 @@ e1000_probe(struct pci_dev *pdev,
/* Let firmware know the driver has taken over */
switch(adapter->hw.mac_type) {
+ case e1000_82571:
+ case e1000_82572:
+ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+ E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+ ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
+ break;
case e1000_82573:
swsm = E1000_READ_REG(&adapter->hw, SWSM);
E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -731,7 +780,11 @@ e1000_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
+ uint32_t ctrl_ext;
uint32_t manc, swsm;
+#ifdef CONFIG_E1000_NAPI
+ int i;
+#endif
flush_scheduled_work();
@@ -745,6 +798,12 @@ e1000_remove(struct pci_dev *pdev)
}
switch(adapter->hw.mac_type) {
+ case e1000_82571:
+ case e1000_82572:
+ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+ E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+ ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
+ break;
case e1000_82573:
swsm = E1000_READ_REG(&adapter->hw, SWSM);
E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -756,13 +815,27 @@ e1000_remove(struct pci_dev *pdev)
}
unregister_netdev(netdev);
+#ifdef CONFIG_E1000_NAPI
+ for (i = 0; i < adapter->num_queues; i++)
+ __dev_put(&adapter->polling_netdev[i]);
+#endif
if(!e1000_check_phy_reset_block(&adapter->hw))
e1000_phy_hw_reset(&adapter->hw);
+ kfree(adapter->tx_ring);
+ kfree(adapter->rx_ring);
+#ifdef CONFIG_E1000_NAPI
+ kfree(adapter->polling_netdev);
+#endif
+
iounmap(adapter->hw.hw_addr);
pci_release_regions(pdev);
+#ifdef CONFIG_E1000_MQ
+ free_percpu(adapter->cpu_netdev);
+ free_percpu(adapter->cpu_tx_ring);
+#endif
free_netdev(netdev);
pci_disable_device(pdev);
@@ -783,6 +856,9 @@ e1000_sw_init(struct e1000_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
+#ifdef CONFIG_E1000_NAPI
+ int i;
+#endif
/* PCI config space info */
@@ -840,14 +916,123 @@ e1000_sw_init(struct e1000_adapter *adapter)
hw->master_slave = E1000_MASTER_SLAVE;
}
+#ifdef CONFIG_E1000_MQ
+ /* Number of supported queues */
+ switch (hw->mac_type) {
+ case e1000_82571:
+ case e1000_82572:
+ adapter->num_queues = 2;
+ break;
+ default:
+ adapter->num_queues = 1;
+ break;
+ }
+ adapter->num_queues = min(adapter->num_queues, num_online_cpus());
+#else
+ adapter->num_queues = 1;
+#endif
+
+ if (e1000_alloc_queues(adapter)) {
+ DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n");
+ return -ENOMEM;
+ }
+
+#ifdef CONFIG_E1000_NAPI
+ for (i = 0; i < adapter->num_queues; i++) {
+ adapter->polling_netdev[i].priv = adapter;
+ adapter->polling_netdev[i].poll = &e1000_clean;
+ adapter->polling_netdev[i].weight = 64;
+ dev_hold(&adapter->polling_netdev[i]);
+ set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state);
+ }
+#endif
+
+#ifdef CONFIG_E1000_MQ
+ e1000_setup_queue_mapping(adapter);
+#endif
+
atomic_set(&adapter->irq_sem, 1);
spin_lock_init(&adapter->stats_lock);
- spin_lock_init(&adapter->tx_lock);
return 0;
}
/**
+ * e1000_alloc_queues - Allocate memory for all rings
+ * @adapter: board private structure to initialize
+ *
+ * We allocate one ring per queue at run-time since we don't know the
+ * number of queues at compile-time. The polling_netdev array is
+ * intended for Multiqueue, but should work fine with a single queue.
+ **/
+
+static int __devinit
+e1000_alloc_queues(struct e1000_adapter *adapter)
+{
+ int size;
+
+ size = sizeof(struct e1000_tx_ring) * adapter->num_queues;
+ adapter->tx_ring = kmalloc(size, GFP_KERNEL);
+ if (!adapter->tx_ring)
+ return -ENOMEM;
+ memset(adapter->tx_ring, 0, size);
+
+ size = sizeof(struct e1000_rx_ring) * adapter->num_queues;
+ adapter->rx_ring = kmalloc(size, GFP_KERNEL);
+ if (!adapter->rx_ring) {
+ kfree(adapter->tx_ring);
+ return -ENOMEM;
+ }
+ memset(adapter->rx_ring, 0, size);
+
+#ifdef CONFIG_E1000_NAPI
+ size = sizeof(struct net_device) * adapter->num_queues;
+ adapter->polling_netdev = kmalloc(size, GFP_KERNEL);
+ if (!adapter->polling_netdev) {
+ kfree(adapter->tx_ring);
+ kfree(adapter->rx_ring);
+ return -ENOMEM;
+ }
+ memset(adapter->polling_netdev, 0, size);
+#endif
+
+ return E1000_SUCCESS;
+}
+
+#ifdef CONFIG_E1000_MQ
+static void __devinit
+e1000_setup_queue_mapping(struct e1000_adapter *adapter)
+{
+ int i, cpu;
+
+ adapter->rx_sched_call_data.func = e1000_rx_schedule;
+ adapter->rx_sched_call_data.info = adapter->netdev;
+ cpus_clear(adapter->rx_sched_call_data.cpumask);
+
+ adapter->cpu_netdev = alloc_percpu(struct net_device *);
+ adapter->cpu_tx_ring = alloc_percpu(struct e1000_tx_ring *);
+
+ lock_cpu_hotplug();
+ i = 0;
+ for_each_online_cpu(cpu) {
+ *per_cpu_ptr(adapter->cpu_tx_ring, cpu) = &adapter->tx_ring[i % adapter->num_queues];
+ /* This is incomplete because we'd like to assign separate
+ * physical cpus to these netdev polling structures and
+ * avoid saturating a subset of cpus.
+ */
+ if (i < adapter->num_queues) {
+ *per_cpu_ptr(adapter->cpu_netdev, cpu) = &adapter->polling_netdev[i];
+ adapter->cpu_for_queue[i] = cpu;
+ } else
+ *per_cpu_ptr(adapter->cpu_netdev, cpu) = NULL;
+
+ i++;
+ }
+ unlock_cpu_hotplug();
+}
+#endif
+
+/**
* e1000_open - Called when a network interface is made active
* @netdev: network interface device structure
*
@@ -868,12 +1053,12 @@ e1000_open(struct net_device *netdev)
/* allocate transmit descriptors */
- if((err = e1000_setup_tx_resources(adapter)))
+ if ((err = e1000_setup_all_tx_resources(adapter)))
goto err_setup_tx;
/* allocate receive descriptors */
- if((err = e1000_setup_rx_resources(adapter)))
+ if ((err = e1000_setup_all_rx_resources(adapter)))
goto err_setup_rx;
if((err = e1000_up(adapter)))
@@ -887,9 +1072,9 @@ e1000_open(struct net_device *netdev)
return E1000_SUCCESS;
err_up:
- e1000_free_rx_resources(adapter);
+ e1000_free_all_rx_resources(adapter);
err_setup_rx:
- e1000_free_tx_resources(adapter);
+ e1000_free_all_tx_resources(adapter);
err_setup_tx:
e1000_reset(adapter);
@@ -915,8 +1100,8 @@ e1000_close(struct net_device *netdev)
e1000_down(adapter);
- e1000_free_tx_resources(adapter);
- e1000_free_rx_resources(adapter);
+ e1000_free_all_tx_resources(adapter);
+ e1000_free_all_rx_resources(adapter);
if((adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
@@ -951,14 +1136,15 @@ e1000_check_64k_bound(struct e1000_adapter *adapter,
/**
* e1000_setup_tx_resources - allocate Tx resources (Descriptors)
* @adapter: board private structure
+ * @txdr: tx descriptor ring (for a specific queue) to setup
*
* Return 0 on success, negative on failure
**/
int
-e1000_setup_tx_resources(struct e1000_adapter *adapter)
+e1000_setup_tx_resources(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *txdr)
{
- struct e1000_desc_ring *txdr = &adapter->tx_ring;
struct pci_dev *pdev = adapter->pdev;
int size;
@@ -970,6 +1156,7 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter)
return -ENOMEM;
}
memset(txdr->buffer_info, 0, size);
+ memset(&txdr->previous_buffer_info, 0, sizeof(struct e1000_buffer));
/* round up to nearest 4K */
@@ -1018,11 +1205,41 @@ setup_tx_desc_die:
txdr->next_to_use = 0;
txdr->next_to_clean = 0;
+ spin_lock_init(&txdr->tx_lock);
return 0;
}
/**
+ * e1000_setup_all_tx_resources - wrapper to allocate Tx resources
+ * (Descriptors) for all queues
+ * @adapter: board private structure
+ *
+ * If this function returns with an error, then it's possible one or
+ * more of the rings is populated (while the rest are not). It is the
+ * callers duty to clean those orphaned rings.
+ *
+ * Return 0 on success, negative on failure
+ **/
+
+int
+e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
+{
+ int i, err = 0;
+
+ for (i = 0; i < adapter->num_queues; i++) {
+ err = e1000_setup_tx_resources(adapter, &adapter->tx_ring[i]);
+ if (err) {
+ DPRINTK(PROBE, ERR,
+ "Allocation for Tx Queue %u failed\n", i);
+ break;
+ }
+ }
+
+ return err;
+}
+
+/**
* e1000_configure_tx - Configure 8254x Transmit Unit after Reset
* @adapter: board private structure
*
@@ -1032,23 +1249,43 @@ setup_tx_desc_die:
static void
e1000_configure_tx(struct e1000_adapter *adapter)
{
- uint64_t tdba = adapter->tx_ring.dma;
- uint32_t tdlen = adapter->tx_ring.count * sizeof(struct e1000_tx_desc);
- uint32_t tctl, tipg;
-
- E1000_WRITE_REG(&adapter->hw, TDBAL, (tdba & 0x00000000ffffffffULL));
- E1000_WRITE_REG(&adapter->hw, TDBAH, (tdba >> 32));
-
- E1000_WRITE_REG(&adapter->hw, TDLEN, tdlen);
+ uint64_t tdba;
+ struct e1000_hw *hw = &adapter->hw;
+ uint32_t tdlen, tctl, tipg, tarc;
/* Setup the HW Tx Head and Tail descriptor pointers */
- E1000_WRITE_REG(&adapter->hw, TDH, 0);
- E1000_WRITE_REG(&adapter->hw, TDT, 0);
+ switch (adapter->num_queues) {
+ case 2:
+ tdba = adapter->tx_ring[1].dma;
+ tdlen = adapter->tx_ring[1].count *
+ sizeof(struct e1000_tx_desc);
+ E1000_WRITE_REG(hw, TDBAL1, (tdba & 0x00000000ffffffffULL));
+ E1000_WRITE_REG(hw, TDBAH1, (tdba >> 32));
+ E1000_WRITE_REG(hw, TDLEN1, tdlen);
+ E1000_WRITE_REG(hw, TDH1, 0);
+ E1000_WRITE_REG(hw, TDT1, 0);
+ adapter->tx_ring[1].tdh = E1000_TDH1;
+ adapter->tx_ring[1].tdt = E1000_TDT1;
+ /* Fall Through */
+ case 1:
+ default:
+ tdba = adapter->tx_ring[0].dma;
+ tdlen = adapter->tx_ring[0].count *
+ sizeof(struct e1000_tx_desc);
+ E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
+ E1000_WRITE_REG(hw, TDBAH, (tdba >> 32));
+ E1000_WRITE_REG(hw, TDLEN, tdlen);
+ E1000_WRITE_REG(hw, TDH, 0);
+ E1000_WRITE_REG(hw, TDT, 0);
+ adapter->tx_ring[0].tdh = E1000_TDH;
+ adapter->tx_ring[0].tdt = E1000_TDT;
+ break;
+ }
/* Set the default values for the Tx Inter Packet Gap timer */
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_82542_rev2_0:
case e1000_82542_rev2_1:
tipg = DEFAULT_82542_TIPG_IPGT;
@@ -1056,67 +1293,81 @@ e1000_configure_tx(struct e1000_adapter *adapter)
tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
break;
default:
- if(adapter->hw.media_type == e1000_media_type_fiber ||
- adapter->hw.media_type == e1000_media_type_internal_serdes)
+ if (hw->media_type == e1000_media_type_fiber ||
+ hw->media_type == e1000_media_type_internal_serdes)
tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
else
tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
}
- E1000_WRITE_REG(&adapter->hw, TIPG, tipg);
+ E1000_WRITE_REG(hw, TIPG, tipg);
/* Set the Tx Interrupt Delay register */
- E1000_WRITE_REG(&adapter->hw, TIDV, adapter->tx_int_delay);
- if(adapter->hw.mac_type >= e1000_82540)
- E1000_WRITE_REG(&adapter->hw, TADV, adapter->tx_abs_int_delay);
+ E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay);
+ if (hw->mac_type >= e1000_82540)
+ E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay);
/* Program the Transmit Control Register */
- tctl = E1000_READ_REG(&adapter->hw, TCTL);
+ tctl = E1000_READ_REG(hw, TCTL);
tctl &= ~E1000_TCTL_CT;
- tctl |= E1000_TCTL_EN | E1000_TCTL_PSP |
+ tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | E1000_TCTL_RTLC |
(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
- E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
+ E1000_WRITE_REG(hw, TCTL, tctl);
- e1000_config_collision_dist(&adapter->hw);
+ if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572) {
+ tarc = E1000_READ_REG(hw, TARC0);
+ tarc |= ((1 << 25) | (1 << 21));
+ E1000_WRITE_REG(hw, TARC0, tarc);
+ tarc = E1000_READ_REG(hw, TARC1);
+ tarc |= (1 << 25);
+ if (tctl & E1000_TCTL_MULR)
+ tarc &= ~(1 << 28);
+ else
+ tarc |= (1 << 28);
+ E1000_WRITE_REG(hw, TARC1, tarc);
+ }
+
+ e1000_config_collision_dist(hw);
/* Setup Transmit Descriptor Settings for eop descriptor */
adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP |
E1000_TXD_CMD_IFCS;
- if(adapter->hw.mac_type < e1000_82543)
+ if (hw->mac_type < e1000_82543)
adapter->txd_cmd |= E1000_TXD_CMD_RPS;
else
adapter->txd_cmd |= E1000_TXD_CMD_RS;
/* Cache if we're 82544 running in PCI-X because we'll
* need this to apply a workaround later in the send path. */
- if(adapter->hw.mac_type == e1000_82544 &&
- adapter->hw.bus_type == e1000_bus_type_pcix)
+ if (hw->mac_type == e1000_82544 &&
+ hw->bus_type == e1000_bus_type_pcix)
adapter->pcix_82544 = 1;
}
/**
* e1000_setup_rx_resources - allocate Rx resources (Descriptors)
* @adapter: board private structure
+ * @rxdr: rx descriptor ring (for a specific queue) to setup
*
* Returns 0 on success, negative on failure
**/
int
-e1000_setup_rx_resources(struct e1000_adapter *adapter)
+e1000_setup_rx_resources(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rxdr)
{
- struct e1000_desc_ring *rxdr = &adapter->rx_ring;
struct pci_dev *pdev = adapter->pdev;
int size, desc_len;
size = sizeof(struct e1000_buffer) * rxdr->count;
rxdr->buffer_info = vmalloc(size);
- if(!rxdr->buffer_info) {
+ if (!rxdr->buffer_info) {
DPRINTK(PROBE, ERR,
"Unable to allocate memory for the receive descriptor ring\n");
return -ENOMEM;
@@ -1156,13 +1407,13 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter)
rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
- if(!rxdr->desc) {
+ if (!rxdr->desc) {
+ DPRINTK(PROBE, ERR,
+ "Unable to allocate memory for the receive descriptor ring\n");
setup_rx_desc_die:
vfree(rxdr->buffer_info);
kfree(rxdr->ps_page);
kfree(rxdr->ps_page_dma);
- DPRINTK(PROBE, ERR,
- "Unable to allocate memory for the receive descriptor ring\n");
return -ENOMEM;
}
@@ -1174,9 +1425,12 @@ setup_rx_desc_die:
"at %p\n", rxdr->size, rxdr->desc);
/* Try again, without freeing the previous */
rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
- if(!rxdr->desc) {
/* Failed allocation, critical failure */
+ if (!rxdr->desc) {
pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
+ DPRINTK(PROBE, ERR,
+ "Unable to allocate memory "
+ "for the receive descriptor ring\n");
goto setup_rx_desc_die;
}
@@ -1188,10 +1442,7 @@ setup_rx_desc_die:
DPRINTK(PROBE, ERR,
"Unable to allocate aligned memory "
"for the receive descriptor ring\n");
- vfree(rxdr->buffer_info);
- kfree(rxdr->ps_page);
- kfree(rxdr->ps_page_dma);
- return -ENOMEM;
+ goto setup_rx_desc_die;
} else {
/* Free old allocation, new allocation was successful */
pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
@@ -1206,15 +1457,48 @@ setup_rx_desc_die:
}
/**
+ * e1000_setup_all_rx_resources - wrapper to allocate Rx resources
+ * (Descriptors) for all queues
+ * @adapter: board private structure
+ *
+ * If this function returns with an error, then it's possible one or
+ * more of the rings is populated (while the rest are not). It is the
+ * callers duty to clean those orphaned rings.
+ *
+ * Return 0 on success, negative on failure
+ **/
+
+int
+e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
+{
+ int i, err = 0;
+
+ for (i = 0; i < adapter->num_queues; i++) {
+ err = e1000_setup_rx_resources(adapter, &adapter->rx_ring[i]);
+ if (err) {
+ DPRINTK(PROBE, ERR,
+ "Allocation for Rx Queue %u failed\n", i);
+ break;
+ }
+ }
+
+ return err;
+}
+
+/**
* e1000_setup_rctl - configure the receive control registers
* @adapter: Board private structure
**/
-
+#define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \
+ (((S) & (PAGE_SIZE - 1)) ? 1 : 0))
static void
e1000_setup_rctl(struct e1000_adapter *adapter)
{
uint32_t rctl, rfctl;
uint32_t psrctl = 0;
+#ifdef CONFIG_E1000_PACKET_SPLIT
+ uint32_t pages = 0;
+#endif
rctl = E1000_READ_REG(&adapter->hw, RCTL);
@@ -1235,7 +1519,7 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
rctl |= E1000_RCTL_LPE;
/* Setup buffer sizes */
- if(adapter->hw.mac_type == e1000_82573) {
+ if(adapter->hw.mac_type >= e1000_82571) {
/* We can now specify buffers in 1K increments.
* BSIZE and BSEX are ignored in this case. */
rctl |= adapter->rx_buffer_len << 0x11;
@@ -1268,11 +1552,14 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
* followed by the page buffers. Therefore, skb->data is
* sized to hold the largest protocol header.
*/
- adapter->rx_ps = (adapter->hw.mac_type > e1000_82547_rev_2)
- && (adapter->netdev->mtu
- < ((3 * PAGE_SIZE) + adapter->rx_ps_bsize0));
+ pages = PAGE_USE_COUNT(adapter->netdev->mtu);
+ if ((adapter->hw.mac_type > e1000_82547_rev_2) && (pages <= 3) &&
+ PAGE_SIZE <= 16384)
+ adapter->rx_ps_pages = pages;
+ else
+ adapter->rx_ps_pages = 0;
#endif
- if(adapter->rx_ps) {
+ if (adapter->rx_ps_pages) {
/* Configure extra packet-split registers */
rfctl = E1000_READ_REG(&adapter->hw, RFCTL);
rfctl |= E1000_RFCTL_EXTEN;
@@ -1284,12 +1571,19 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
psrctl |= adapter->rx_ps_bsize0 >>
E1000_PSRCTL_BSIZE0_SHIFT;
- psrctl |= PAGE_SIZE >>
- E1000_PSRCTL_BSIZE1_SHIFT;
- psrctl |= PAGE_SIZE <<
- E1000_PSRCTL_BSIZE2_SHIFT;
- psrctl |= PAGE_SIZE <<
- E1000_PSRCTL_BSIZE3_SHIFT;
+
+ switch (adapter->rx_ps_pages) {
+ case 3:
+ psrctl |= PAGE_SIZE <<
+ E1000_PSRCTL_BSIZE3_SHIFT;
+ case 2:
+ psrctl |= PAGE_SIZE <<
+ E1000_PSRCTL_BSIZE2_SHIFT;
+ case 1:
+ psrctl |= PAGE_SIZE >>
+ E1000_PSRCTL_BSIZE1_SHIFT;
+ break;
+ }
E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl);
}
@@ -1307,91 +1601,181 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
static void
e1000_configure_rx(struct e1000_adapter *adapter)
{
- uint64_t rdba = adapter->rx_ring.dma;
- uint32_t rdlen, rctl, rxcsum;
+ uint64_t rdba;
+ struct e1000_hw *hw = &adapter->hw;
+ uint32_t rdlen, rctl, rxcsum, ctrl_ext;
+#ifdef CONFIG_E1000_MQ
+ uint32_t reta, mrqc;
+ int i;
+#endif
- if(adapter->rx_ps) {
- rdlen = adapter->rx_ring.count *
+ if (adapter->rx_ps_pages) {
+ rdlen = adapter->rx_ring[0].count *
sizeof(union e1000_rx_desc_packet_split);
adapter->clean_rx = e1000_clean_rx_irq_ps;
adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps;
} else {
- rdlen = adapter->rx_ring.count * sizeof(struct e1000_rx_desc);
+ rdlen = adapter->rx_ring[0].count *
+ sizeof(struct e1000_rx_desc);
adapter->clean_rx = e1000_clean_rx_irq;
adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
}
/* disable receives while setting up the descriptors */
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN);
+ rctl = E1000_READ_REG(hw, RCTL);
+ E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
/* set the Receive Delay Timer Register */
- E1000_WRITE_REG(&adapter->hw, RDTR, adapter->rx_int_delay);
+ E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay);
- if(adapter->hw.mac_type >= e1000_82540) {
- E1000_WRITE_REG(&adapter->hw, RADV, adapter->rx_abs_int_delay);
+ if (hw->mac_type >= e1000_82540) {
+ E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay);
if(adapter->itr > 1)
- E1000_WRITE_REG(&adapter->hw, ITR,
+ E1000_WRITE_REG(hw, ITR,
1000000000 / (adapter->itr * 256));
}
- /* Setup the Base and Length of the Rx Descriptor Ring */
- E1000_WRITE_REG(&adapter->hw, RDBAL, (rdba & 0x00000000ffffffffULL));
- E1000_WRITE_REG(&adapter->hw, RDBAH, (rdba >> 32));
+ if (hw->mac_type >= e1000_82571) {
+ /* Reset delay timers after every interrupt */
+ ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext |= E1000_CTRL_EXT_CANC;
+ E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH(hw);
+ }
+
+ /* Setup the HW Rx Head and Tail Descriptor Pointers and
+ * the Base and Length of the Rx Descriptor Ring */
+ switch (adapter->num_queues) {
+#ifdef CONFIG_E1000_MQ
+ case 2:
+ rdba = adapter->rx_ring[1].dma;
+ E1000_WRITE_REG(hw, RDBAL1, (rdba & 0x00000000ffffffffULL));
+ E1000_WRITE_REG(hw, RDBAH1, (rdba >> 32));
+ E1000_WRITE_REG(hw, RDLEN1, rdlen);
+ E1000_WRITE_REG(hw, RDH1, 0);
+ E1000_WRITE_REG(hw, RDT1, 0);
+ adapter->rx_ring[1].rdh = E1000_RDH1;
+ adapter->rx_ring[1].rdt = E1000_RDT1;
+ /* Fall Through */
+#endif
+ case 1:
+ default:
+ rdba = adapter->rx_ring[0].dma;
+ E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
+ E1000_WRITE_REG(hw, RDBAH, (rdba >> 32));
+ E1000_WRITE_REG(hw, RDLEN, rdlen);
+ E1000_WRITE_REG(hw, RDH, 0);
+ E1000_WRITE_REG(hw, RDT, 0);
+ adapter->rx_ring[0].rdh = E1000_RDH;
+ adapter->rx_ring[0].rdt = E1000_RDT;
+ break;
+ }
+
+#ifdef CONFIG_E1000_MQ
+ if (adapter->num_queues > 1) {
+ uint32_t random[10];
+
+ get_random_bytes(&random[0], 40);
+
+ if (hw->mac_type <= e1000_82572) {
+ E1000_WRITE_REG(hw, RSSIR, 0);
+ E1000_WRITE_REG(hw, RSSIM, 0);
+ }
+
+ switch (adapter->num_queues) {
+ case 2:
+ default:
+ reta = 0x00800080;
+ mrqc = E1000_MRQC_ENABLE_RSS_2Q;
+ break;
+ }
+
+ /* Fill out redirection table */
+ for (i = 0; i < 32; i++)
+ E1000_WRITE_REG_ARRAY(hw, RETA, i, reta);
+ /* Fill out hash function seeds */
+ for (i = 0; i < 10; i++)
+ E1000_WRITE_REG_ARRAY(hw, RSSRK, i, random[i]);
+
+ mrqc |= (E1000_MRQC_RSS_FIELD_IPV4 |
+ E1000_MRQC_RSS_FIELD_IPV4_TCP);
+ E1000_WRITE_REG(hw, MRQC, mrqc);
+ }
- E1000_WRITE_REG(&adapter->hw, RDLEN, rdlen);
+ /* Multiqueue and packet checksumming are mutually exclusive. */
+ if (hw->mac_type >= e1000_82571) {
+ rxcsum = E1000_READ_REG(hw, RXCSUM);
+ rxcsum |= E1000_RXCSUM_PCSD;
+ E1000_WRITE_REG(hw, RXCSUM, rxcsum);
+ }
- /* Setup the HW Rx Head and Tail Descriptor Pointers */
- E1000_WRITE_REG(&adapter->hw, RDH, 0);
- E1000_WRITE_REG(&adapter->hw, RDT, 0);
+#else
/* Enable 82543 Receive Checksum Offload for TCP and UDP */
- if(adapter->hw.mac_type >= e1000_82543) {
- rxcsum = E1000_READ_REG(&adapter->hw, RXCSUM);
+ if (hw->mac_type >= e1000_82543) {
+ rxcsum = E1000_READ_REG(hw, RXCSUM);
if(adapter->rx_csum == TRUE) {
rxcsum |= E1000_RXCSUM_TUOFL;
- /* Enable 82573 IPv4 payload checksum for UDP fragments
+ /* Enable 82571 IPv4 payload checksum for UDP fragments
* Must be used in conjunction with packet-split. */
- if((adapter->hw.mac_type > e1000_82547_rev_2) &&
- (adapter->rx_ps)) {
+ if ((hw->mac_type >= e1000_82571) &&
+ (adapter->rx_ps_pages)) {
rxcsum |= E1000_RXCSUM_IPPCSE;
}
} else {
rxcsum &= ~E1000_RXCSUM_TUOFL;
/* don't need to clear IPPCSE as it defaults to 0 */
}
- E1000_WRITE_REG(&adapter->hw, RXCSUM, rxcsum);
+ E1000_WRITE_REG(hw, RXCSUM, rxcsum);
}
+#endif /* CONFIG_E1000_MQ */
- if (adapter->hw.mac_type == e1000_82573)
- E1000_WRITE_REG(&adapter->hw, ERT, 0x0100);
+ if (hw->mac_type == e1000_82573)
+ E1000_WRITE_REG(hw, ERT, 0x0100);
/* Enable Receives */
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ E1000_WRITE_REG(hw, RCTL, rctl);
}
/**
- * e1000_free_tx_resources - Free Tx Resources
+ * e1000_free_tx_resources - Free Tx Resources per Queue
* @adapter: board private structure
+ * @tx_ring: Tx descriptor ring for a specific queue
*
* Free all transmit software resources
**/
void
-e1000_free_tx_resources(struct e1000_adapter *adapter)
+e1000_free_tx_resources(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring)
{
struct pci_dev *pdev = adapter->pdev;
- e1000_clean_tx_ring(adapter);
+ e1000_clean_tx_ring(adapter, tx_ring);
+
+ vfree(tx_ring->buffer_info);
+ tx_ring->buffer_info = NULL;
- vfree(adapter->tx_ring.buffer_info);
- adapter->tx_ring.buffer_info = NULL;
+ pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma);
+
+ tx_ring->desc = NULL;
+}
- pci_free_consistent(pdev, adapter->tx_ring.size,
- adapter->tx_ring.desc, adapter->tx_ring.dma);
+/**
+ * e1000_free_all_tx_resources - Free Tx Resources for All Queues
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ **/
+
+void
+e1000_free_all_tx_resources(struct e1000_adapter *adapter)
+{
+ int i;
- adapter->tx_ring.desc = NULL;
+ for (i = 0; i < adapter->num_queues; i++)
+ e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
}
static inline void
@@ -1414,21 +1798,22 @@ e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
/**
* e1000_clean_tx_ring - Free Tx Buffers
* @adapter: board private structure
+ * @tx_ring: ring to be cleaned
**/
static void
-e1000_clean_tx_ring(struct e1000_adapter *adapter)
+e1000_clean_tx_ring(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring)
{
- struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
struct e1000_buffer *buffer_info;
unsigned long size;
unsigned int i;
/* Free all the Tx ring sk_buffs */
- if (likely(adapter->previous_buffer_info.skb != NULL)) {
+ if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
e1000_unmap_and_free_tx_resource(adapter,
- &adapter->previous_buffer_info);
+ &tx_ring->previous_buffer_info);
}
for(i = 0; i < tx_ring->count; i++) {
@@ -1446,24 +1831,39 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter)
tx_ring->next_to_use = 0;
tx_ring->next_to_clean = 0;
- E1000_WRITE_REG(&adapter->hw, TDH, 0);
- E1000_WRITE_REG(&adapter->hw, TDT, 0);
+ writel(0, adapter->hw.hw_addr + tx_ring->tdh);
+ writel(0, adapter->hw.hw_addr + tx_ring->tdt);
+}
+
+/**
+ * e1000_clean_all_tx_rings - Free Tx Buffers for all queues
+ * @adapter: board private structure
+ **/
+
+static void
+e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
+{
+ int i;
+
+ for (i = 0; i < adapter->num_queues; i++)
+ e1000_clean_tx_ring(adapter, &adapter->tx_ring[i]);
}
/**
* e1000_free_rx_resources - Free Rx Resources
* @adapter: board private structure
+ * @rx_ring: ring to clean the resources from
*
* Free all receive software resources
**/
void
-e1000_free_rx_resources(struct e1000_adapter *adapter)
+e1000_free_rx_resources(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring)
{
- struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct pci_dev *pdev = adapter->pdev;
- e1000_clean_rx_ring(adapter);
+ e1000_clean_rx_ring(adapter, rx_ring);
vfree(rx_ring->buffer_info);
rx_ring->buffer_info = NULL;
@@ -1478,14 +1878,31 @@ e1000_free_rx_resources(struct e1000_adapter *adapter)
}
/**
- * e1000_clean_rx_ring - Free Rx Buffers
+ * e1000_free_all_rx_resources - Free Rx Resources for All Queues
+ * @adapter: board private structure
+ *
+ * Free all receive software resources
+ **/
+
+void
+e1000_free_all_rx_resources(struct e1000_adapter *adapter)
+{
+ int i;
+
+ for (i = 0; i < adapter->num_queues; i++)
+ e1000_free_rx_resources(adapter, &adapter->rx_ring[i]);
+}
+
+/**
+ * e1000_clean_rx_ring - Free Rx Buffers per Queue
* @adapter: board private structure
+ * @rx_ring: ring to free buffers from
**/
static void
-e1000_clean_rx_ring(struct e1000_adapter *adapter)
+e1000_clean_rx_ring(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring)
{
- struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct e1000_buffer *buffer_info;
struct e1000_ps_page *ps_page;
struct e1000_ps_page_dma *ps_page_dma;
@@ -1508,7 +1925,7 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter)
dev_kfree_skb(buffer_info->skb);
buffer_info->skb = NULL;
- for(j = 0; j < PS_PAGE_BUFFERS; j++) {
+ for(j = 0; j < adapter->rx_ps_pages; j++) {
if(!ps_page->ps_page[j]) break;
pci_unmap_single(pdev,
ps_page_dma->ps_page_dma[j],
@@ -1534,8 +1951,22 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter)
rx_ring->next_to_clean = 0;
rx_ring->next_to_use = 0;
- E1000_WRITE_REG(&adapter->hw, RDH, 0);
- E1000_WRITE_REG(&adapter->hw, RDT, 0);
+ writel(0, adapter->hw.hw_addr + rx_ring->rdh);
+ writel(0, adapter->hw.hw_addr + rx_ring->rdt);
+}
+
+/**
+ * e1000_clean_all_rx_rings - Free Rx Buffers for all queues
+ * @adapter: board private structure
+ **/
+
+static void
+e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
+{
+ int i;
+
+ for (i = 0; i < adapter->num_queues; i++)
+ e1000_clean_rx_ring(adapter, &adapter->rx_ring[i]);
}
/* The 82542 2.0 (revision 2) needs to have the receive unit in reset
@@ -1556,7 +1987,7 @@ e1000_enter_82542_rst(struct e1000_adapter *adapter)
mdelay(5);
if(netif_running(netdev))
- e1000_clean_rx_ring(adapter);
+ e1000_clean_all_rx_rings(adapter);
}
static void
@@ -1576,7 +2007,7 @@ e1000_leave_82542_rst(struct e1000_adapter *adapter)
if(netif_running(netdev)) {
e1000_configure_rx(adapter);
- e1000_alloc_rx_buffers(adapter);
+ e1000_alloc_rx_buffers(adapter, &adapter->rx_ring[0]);
}
}
@@ -1607,6 +2038,22 @@ e1000_set_mac(struct net_device *netdev, void *p)
e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
+ /* With 82571 controllers, LAA may be overwritten (with the default)
+ * due to controller reset from the other port. */
+ if (adapter->hw.mac_type == e1000_82571) {
+ /* activate the work around */
+ adapter->hw.laa_is_present = 1;
+
+ /* Hold a copy of the LAA in RAR[14] This is done so that
+ * between the time RAR[0] gets clobbered and the time it
+ * gets fixed (in e1000_watchdog), the actual LAA is in one
+ * of the RARs and no incoming packets directed to this port
+ * are dropped. Eventaully the LAA will be in RAR[0] and
+ * RAR[14] */
+ e1000_rar_set(&adapter->hw, adapter->hw.mac_addr,
+ E1000_RAR_ENTRIES - 1);
+ }
+
if(adapter->hw.mac_type == e1000_82542_rev2_0)
e1000_leave_82542_rst(adapter);
@@ -1629,12 +2076,13 @@ e1000_set_multi(struct net_device *netdev)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
struct dev_mc_list *mc_ptr;
- unsigned long flags;
uint32_t rctl;
uint32_t hash_value;
- int i;
+ int i, rar_entries = E1000_RAR_ENTRIES;
- spin_lock_irqsave(&adapter->tx_lock, flags);
+ /* reserve RAR[14] for LAA over-write work-around */
+ if (adapter->hw.mac_type == e1000_82571)
+ rar_entries--;
/* Check for Promiscuous and All Multicast modes */
@@ -1659,11 +2107,12 @@ e1000_set_multi(struct net_device *netdev)
/* load the first 14 multicast address into the exact filters 1-14
* RAR 0 is used for the station MAC adddress
* if there are not 14 addresses, go ahead and clear the filters
+ * -- with 82571 controllers only 0-13 entries are filled here
*/
mc_ptr = netdev->mc_list;
- for(i = 1; i < E1000_RAR_ENTRIES; i++) {
- if(mc_ptr) {
+ for(i = 1; i < rar_entries; i++) {
+ if (mc_ptr) {
e1000_rar_set(hw, mc_ptr->dmi_addr, i);
mc_ptr = mc_ptr->next;
} else {
@@ -1686,8 +2135,6 @@ e1000_set_multi(struct net_device *netdev)
if(hw->mac_type == e1000_82542_rev2_0)
e1000_leave_82542_rst(adapter);
-
- spin_unlock_irqrestore(&adapter->tx_lock, flags);
}
/* Need to wait a few seconds after link up to get diagnostic information from
@@ -1759,7 +2206,7 @@ static void
e1000_watchdog_task(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- struct e1000_desc_ring *txdr = &adapter->tx_ring;
+ struct e1000_tx_ring *txdr = &adapter->tx_ring[0];
uint32_t link;
e1000_check_for_link(&adapter->hw);
@@ -1818,8 +2265,8 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
e1000_update_adaptive(&adapter->hw);
- if(!netif_carrier_ok(netdev)) {
- if(E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
+ if (adapter->num_queues == 1 && !netif_carrier_ok(netdev)) {
+ if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
/* We've lost link, so the controller stops DMA,
* but we've got queued Tx work that's never going
* to get done, so reset controller to flush Tx.
@@ -1847,6 +2294,11 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
/* Force detection of hung controller every watchdog period */
adapter->detect_tx_hung = TRUE;
+ /* With 82571 controllers, LAA may be overwritten due to controller
+ * reset from the other port. Set the appropriate LAA in RAR[0] */
+ if (adapter->hw.mac_type == e1000_82571 && adapter->hw.laa_is_present)
+ e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
+
/* Reset the timer */
mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
}
@@ -1859,7 +2311,8 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
#define E1000_TX_FLAGS_VLAN_SHIFT 16
static inline int
-e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
+e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ struct sk_buff *skb)
{
#ifdef NETIF_F_TSO
struct e1000_context_desc *context_desc;
@@ -1910,8 +2363,8 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
E1000_TXD_CMD_TCP | (skb->len - (hdr_len)));
- i = adapter->tx_ring.next_to_use;
- context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
+ i = tx_ring->next_to_use;
+ context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
context_desc->lower_setup.ip_fields.ipcss = ipcss;
context_desc->lower_setup.ip_fields.ipcso = ipcso;
@@ -1923,8 +2376,8 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
context_desc->cmd_and_length = cpu_to_le32(cmd_length);
- if(++i == adapter->tx_ring.count) i = 0;
- adapter->tx_ring.next_to_use = i;
+ if (++i == tx_ring->count) i = 0;
+ tx_ring->next_to_use = i;
return 1;
}
@@ -1934,7 +2387,8 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
}
static inline boolean_t
-e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
+e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ struct sk_buff *skb)
{
struct e1000_context_desc *context_desc;
unsigned int i;
@@ -1943,8 +2397,8 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
if(likely(skb->ip_summed == CHECKSUM_HW)) {
css = skb->h.raw - skb->data;
- i = adapter->tx_ring.next_to_use;
- context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
+ i = tx_ring->next_to_use;
+ context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
context_desc->upper_setup.tcp_fields.tucss = css;
context_desc->upper_setup.tcp_fields.tucso = css + skb->csum;
@@ -1952,8 +2406,8 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
context_desc->tcp_seg_setup.data = 0;
context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
- if(unlikely(++i == adapter->tx_ring.count)) i = 0;
- adapter->tx_ring.next_to_use = i;
+ if (unlikely(++i == tx_ring->count)) i = 0;
+ tx_ring->next_to_use = i;
return TRUE;
}
@@ -1965,11 +2419,10 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
#define E1000_MAX_DATA_PER_TXD (1<<E1000_MAX_TXD_PWR)
static inline int
-e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
- unsigned int first, unsigned int max_per_txd,
- unsigned int nr_frags, unsigned int mss)
+e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ struct sk_buff *skb, unsigned int first, unsigned int max_per_txd,
+ unsigned int nr_frags, unsigned int mss)
{
- struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
struct e1000_buffer *buffer_info;
unsigned int len = skb->len;
unsigned int offset = 0, size, count = 0, i;
@@ -2065,9 +2518,9 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
}
static inline void
-e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags)
+e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ int tx_flags, int count)
{
- struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
struct e1000_tx_desc *tx_desc = NULL;
struct e1000_buffer *buffer_info;
uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
@@ -2113,7 +2566,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags)
wmb();
tx_ring->next_to_use = i;
- E1000_WRITE_REG(&adapter->hw, TDT, i);
+ writel(i, adapter->hw.hw_addr + tx_ring->tdt);
}
/**
@@ -2206,6 +2659,7 @@ static int
e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_tx_ring *tx_ring;
unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
unsigned int tx_flags = 0;
@@ -2218,7 +2672,13 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
unsigned int f;
len -= skb->data_len;
- if(unlikely(skb->len <= 0)) {
+#ifdef CONFIG_E1000_MQ
+ tx_ring = *per_cpu_ptr(adapter->cpu_tx_ring, smp_processor_id());
+#else
+ tx_ring = adapter->tx_ring;
+#endif
+
+ if (unlikely(skb->len <= 0)) {
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
@@ -2262,21 +2722,42 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if(adapter->pcix_82544)
count += nr_frags;
- local_irq_save(flags);
- if (!spin_trylock(&adapter->tx_lock)) {
- /* Collision - tell upper layer to requeue */
- local_irq_restore(flags);
- return NETDEV_TX_LOCKED;
- }
+#ifdef NETIF_F_TSO
+ /* TSO Workaround for 82571/2 Controllers -- if skb->data
+ * points to just header, pull a few bytes of payload from
+ * frags into skb->data */
+ if (skb_shinfo(skb)->tso_size) {
+ uint8_t hdr_len;
+ hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
+ if (skb->data_len && (hdr_len < (skb->len - skb->data_len)) &&
+ (adapter->hw.mac_type == e1000_82571 ||
+ adapter->hw.mac_type == e1000_82572)) {
+ unsigned int pull_size;
+ pull_size = min((unsigned int)4, skb->data_len);
+ if (!__pskb_pull_tail(skb, pull_size)) {
+ printk(KERN_ERR "__pskb_pull_tail failed.\n");
+ dev_kfree_skb_any(skb);
+ return -EFAULT;
+ }
+ }
+ }
+#endif
+
if(adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) )
e1000_transfer_dhcp_info(adapter, skb);
+ local_irq_save(flags);
+ if (!spin_trylock(&tx_ring->tx_lock)) {
+ /* Collision - tell upper layer to requeue */
+ local_irq_restore(flags);
+ return NETDEV_TX_LOCKED;
+ }
/* need: count + 2 desc gap to keep tail from touching
* head, otherwise try next time */
- if(unlikely(E1000_DESC_UNUSED(&adapter->tx_ring) < count + 2)) {
+ if (unlikely(E1000_DESC_UNUSED(tx_ring) < count + 2)) {
netif_stop_queue(netdev);
- spin_unlock_irqrestore(&adapter->tx_lock, flags);
+ spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
return NETDEV_TX_BUSY;
}
@@ -2284,7 +2765,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if(unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
netif_stop_queue(netdev);
mod_timer(&adapter->tx_fifo_stall_timer, jiffies);
- spin_unlock_irqrestore(&adapter->tx_lock, flags);
+ spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
return NETDEV_TX_BUSY;
}
}
@@ -2294,37 +2775,37 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
}
- first = adapter->tx_ring.next_to_use;
+ first = tx_ring->next_to_use;
- tso = e1000_tso(adapter, skb);
+ tso = e1000_tso(adapter, tx_ring, skb);
if (tso < 0) {
dev_kfree_skb_any(skb);
- spin_unlock_irqrestore(&adapter->tx_lock, flags);
+ spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
return NETDEV_TX_OK;
}
if (likely(tso))
tx_flags |= E1000_TX_FLAGS_TSO;
- else if(likely(e1000_tx_csum(adapter, skb)))
+ else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
tx_flags |= E1000_TX_FLAGS_CSUM;
/* Old method was to assume IPv4 packet by default if TSO was enabled.
- * 82573 hardware supports TSO capabilities for IPv6 as well...
+ * 82571 hardware supports TSO capabilities for IPv6 as well...
* no longer assume, we must. */
- if(likely(skb->protocol == ntohs(ETH_P_IP)))
+ if (likely(skb->protocol == ntohs(ETH_P_IP)))
tx_flags |= E1000_TX_FLAGS_IPV4;
- e1000_tx_queue(adapter,
- e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss),
- tx_flags);
+ e1000_tx_queue(adapter, tx_ring, tx_flags,
+ e1000_tx_map(adapter, tx_ring, skb, first,
+ max_per_txd, nr_frags, mss));
netdev->trans_start = jiffies;
/* Make sure there is space in the ring for the next send. */
- if(unlikely(E1000_DESC_UNUSED(&adapter->tx_ring) < MAX_SKB_FRAGS + 2))
+ if (unlikely(E1000_DESC_UNUSED(tx_ring) < MAX_SKB_FRAGS + 2))
netif_stop_queue(netdev);
- spin_unlock_irqrestore(&adapter->tx_lock, flags);
+ spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
return NETDEV_TX_OK;
}
@@ -2388,9 +2869,18 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
return -EINVAL;
}
-#define MAX_STD_JUMBO_FRAME_SIZE 9216
+#define MAX_STD_JUMBO_FRAME_SIZE 9234
/* might want this to be bigger enum check... */
- if (adapter->hw.mac_type == e1000_82573 &&
+ /* 82571 controllers limit jumbo frame size to 10500 bytes */
+ if ((adapter->hw.mac_type == e1000_82571 ||
+ adapter->hw.mac_type == e1000_82572) &&
+ max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
+ DPRINTK(PROBE, ERR, "MTU > 9216 bytes not supported "
+ "on 82571 and 82572 controllers.\n");
+ return -EINVAL;
+ }
+
+ if(adapter->hw.mac_type == e1000_82573 &&
max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
"on 82573\n");
@@ -2578,6 +3068,29 @@ e1000_update_stats(struct e1000_adapter *adapter)
spin_unlock_irqrestore(&adapter->stats_lock, flags);
}
+#ifdef CONFIG_E1000_MQ
+void
+e1000_rx_schedule(void *data)
+{
+ struct net_device *poll_dev, *netdev = data;
+ struct e1000_adapter *adapter = netdev->priv;
+ int this_cpu = get_cpu();
+
+ poll_dev = *per_cpu_ptr(adapter->cpu_netdev, this_cpu);
+ if (poll_dev == NULL) {
+ put_cpu();
+ return;
+ }
+
+ if (likely(netif_rx_schedule_prep(poll_dev)))
+ __netif_rx_schedule(poll_dev);
+ else
+ e1000_irq_enable(adapter);
+
+ put_cpu();
+}
+#endif
+
/**
* e1000_intr - Interrupt Handler
* @irq: interrupt number
@@ -2592,8 +3105,8 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
uint32_t icr = E1000_READ_REG(hw, ICR);
-#ifndef CONFIG_E1000_NAPI
- unsigned int i;
+#if defined(CONFIG_E1000_NAPI) && defined(CONFIG_E1000_MQ) || !defined(CONFIG_E1000_NAPI)
+ int i;
#endif
if(unlikely(!icr))
@@ -2605,17 +3118,31 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
}
#ifdef CONFIG_E1000_NAPI
- if(likely(netif_rx_schedule_prep(netdev))) {
-
- /* Disable interrupts and register for poll. The flush
- of the posted write is intentionally left out.
- */
-
- atomic_inc(&adapter->irq_sem);
- E1000_WRITE_REG(hw, IMC, ~0);
- __netif_rx_schedule(netdev);
+ atomic_inc(&adapter->irq_sem);
+ E1000_WRITE_REG(hw, IMC, ~0);
+ E1000_WRITE_FLUSH(hw);
+#ifdef CONFIG_E1000_MQ
+ if (atomic_read(&adapter->rx_sched_call_data.count) == 0) {
+ cpu_set(adapter->cpu_for_queue[0],
+ adapter->rx_sched_call_data.cpumask);
+ for (i = 1; i < adapter->num_queues; i++) {
+ cpu_set(adapter->cpu_for_queue[i],
+ adapter->rx_sched_call_data.cpumask);
+ atomic_inc(&adapter->irq_sem);
+ }
+ atomic_set(&adapter->rx_sched_call_data.count, i);
+ smp_call_async_mask(&adapter->rx_sched_call_data);
+ } else {
+ printk("call_data.count == %u\n", atomic_read(&adapter->rx_sched_call_data.count));
}
-#else
+#else /* if !CONFIG_E1000_MQ */
+ if (likely(netif_rx_schedule_prep(&adapter->polling_netdev[0])))
+ __netif_rx_schedule(&adapter->polling_netdev[0]);
+ else
+ e1000_irq_enable(adapter);
+#endif /* CONFIG_E1000_MQ */
+
+#else /* if !CONFIG_E1000_NAPI */
/* Writing IMC and IMS is needed for 82547.
Due to Hub Link bus being occupied, an interrupt
de-assertion message is not able to be sent.
@@ -2632,13 +3159,14 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
}
for(i = 0; i < E1000_MAX_INTR; i++)
- if(unlikely(!adapter->clean_rx(adapter) &
- !e1000_clean_tx_irq(adapter)))
+ if(unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
+ !e1000_clean_tx_irq(adapter, adapter->tx_ring)))
break;
if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
e1000_irq_enable(adapter);
-#endif
+
+#endif /* CONFIG_E1000_NAPI */
return IRQ_HANDLED;
}
@@ -2650,22 +3178,37 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
**/
static int
-e1000_clean(struct net_device *netdev, int *budget)
+e1000_clean(struct net_device *poll_dev, int *budget)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
- int work_to_do = min(*budget, netdev->quota);
- int tx_cleaned;
- int work_done = 0;
+ struct e1000_adapter *adapter;
+ int work_to_do = min(*budget, poll_dev->quota);
+ int tx_cleaned, i = 0, work_done = 0;
- tx_cleaned = e1000_clean_tx_irq(adapter);
- adapter->clean_rx(adapter, &work_done, work_to_do);
+ /* Must NOT use netdev_priv macro here. */
+ adapter = poll_dev->priv;
+
+ /* Keep link state information with original netdev */
+ if (!netif_carrier_ok(adapter->netdev))
+ goto quit_polling;
+
+ while (poll_dev != &adapter->polling_netdev[i]) {
+ i++;
+ if (unlikely(i == adapter->num_queues))
+ BUG();
+ }
+
+ tx_cleaned = e1000_clean_tx_irq(adapter, &adapter->tx_ring[i]);
+ adapter->clean_rx(adapter, &adapter->rx_ring[i],
+ &work_done, work_to_do);
*budget -= work_done;
- netdev->quota -= work_done;
+ poll_dev->quota -= work_done;
- if ((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
/* If no Tx and not enough Rx work done, exit the polling mode */
- netif_rx_complete(netdev);
+ if((!tx_cleaned && (work_done == 0)) ||
+ !netif_running(adapter->netdev)) {
+quit_polling:
+ netif_rx_complete(poll_dev);
e1000_irq_enable(adapter);
return 0;
}
@@ -2680,9 +3223,9 @@ e1000_clean(struct net_device *netdev, int *budget)
**/
static boolean_t
-e1000_clean_tx_irq(struct e1000_adapter *adapter)
+e1000_clean_tx_irq(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring)
{
- struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
struct net_device *netdev = adapter->netdev;
struct e1000_tx_desc *tx_desc, *eop_desc;
struct e1000_buffer *buffer_info;
@@ -2693,12 +3236,12 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = E1000_TX_DESC(*tx_ring, eop);
- while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
+ while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
/* Premature writeback of Tx descriptors clear (free buffers
* and unmap pci_mapping) previous_buffer_info */
- if (likely(adapter->previous_buffer_info.skb != NULL)) {
+ if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
e1000_unmap_and_free_tx_resource(adapter,
- &adapter->previous_buffer_info);
+ &tx_ring->previous_buffer_info);
}
for(cleaned = FALSE; !cleaned; ) {
@@ -2714,7 +3257,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
#ifdef NETIF_F_TSO
} else {
if (cleaned) {
- memcpy(&adapter->previous_buffer_info,
+ memcpy(&tx_ring->previous_buffer_info,
buffer_info,
sizeof(struct e1000_buffer));
memset(buffer_info, 0,
@@ -2732,6 +3275,8 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
if(unlikely(++i == tx_ring->count)) i = 0;
}
+
+ tx_ring->pkt++;
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = E1000_TX_DESC(*tx_ring, eop);
@@ -2739,15 +3284,15 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
tx_ring->next_to_clean = i;
- spin_lock(&adapter->tx_lock);
+ spin_lock(&tx_ring->tx_lock);
if(unlikely(cleaned && netif_queue_stopped(netdev) &&
netif_carrier_ok(netdev)))
netif_wake_queue(netdev);
- spin_unlock(&adapter->tx_lock);
- if(adapter->detect_tx_hung) {
+ spin_unlock(&tx_ring->tx_lock);
+ if (adapter->detect_tx_hung) {
/* Detect a transmit hang in hardware, this serializes the
* check with the clearing of time_stamp and movement of i */
adapter->detect_tx_hung = FALSE;
@@ -2771,8 +3316,8 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
" next_to_watch <%x>\n"
" jiffies <%lx>\n"
" next_to_watch.status <%x>\n",
- E1000_READ_REG(&adapter->hw, TDH),
- E1000_READ_REG(&adapter->hw, TDT),
+ readl(adapter->hw.hw_addr + tx_ring->tdh),
+ readl(adapter->hw.hw_addr + tx_ring->tdt),
tx_ring->next_to_use,
i,
(unsigned long long)tx_ring->buffer_info[i].dma,
@@ -2784,12 +3329,10 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
}
}
#ifdef NETIF_F_TSO
-
- if( unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
- time_after(jiffies, adapter->previous_buffer_info.time_stamp + HZ)))
+ if (unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
+ time_after(jiffies, tx_ring->previous_buffer_info.time_stamp + HZ)))
e1000_unmap_and_free_tx_resource(
- adapter, &adapter->previous_buffer_info);
-
+ adapter, &tx_ring->previous_buffer_info);
#endif
return cleaned;
}
@@ -2852,13 +3395,14 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
static boolean_t
#ifdef CONFIG_E1000_NAPI
-e1000_clean_rx_irq(struct e1000_adapter *adapter, int *work_done,
- int work_to_do)
+e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int *work_done, int work_to_do)
#else
-e1000_clean_rx_irq(struct e1000_adapter *adapter)
+e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring)
#endif
{
- struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
struct e1000_rx_desc *rx_desc;
@@ -2944,6 +3488,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter)
}
#endif /* CONFIG_E1000_NAPI */
netdev->last_rx = jiffies;
+ rx_ring->pkt++;
next_desc:
rx_desc->status = 0;
@@ -2953,7 +3498,7 @@ next_desc:
rx_desc = E1000_RX_DESC(*rx_ring, i);
}
rx_ring->next_to_clean = i;
- adapter->alloc_rx_buf(adapter);
+ adapter->alloc_rx_buf(adapter, rx_ring);
return cleaned;
}
@@ -2965,13 +3510,14 @@ next_desc:
static boolean_t
#ifdef CONFIG_E1000_NAPI
-e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, int *work_done,
- int work_to_do)
+e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int *work_done, int work_to_do)
#else
-e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
+e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring)
#endif
{
- struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
union e1000_rx_desc_packet_split *rx_desc;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
@@ -3027,7 +3573,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
/* Good Receive */
skb_put(skb, length);
- for(j = 0; j < PS_PAGE_BUFFERS; j++) {
+ for(j = 0; j < adapter->rx_ps_pages; j++) {
if(!(length = le16_to_cpu(rx_desc->wb.upper.length[j])))
break;
@@ -3048,11 +3594,13 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
rx_desc->wb.lower.hi_dword.csum_ip.csum, skb);
skb->protocol = eth_type_trans(skb, netdev);
-#ifdef HAVE_RX_ZERO_COPY
if(likely(rx_desc->wb.upper.header_status &
- E1000_RXDPS_HDRSTAT_HDRSP))
+ E1000_RXDPS_HDRSTAT_HDRSP)) {
+ adapter->rx_hdr_split++;
+#ifdef HAVE_RX_ZERO_COPY
skb_shinfo(skb)->zero_copy = TRUE;
#endif
+ }
#ifdef CONFIG_E1000_NAPI
if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
@@ -3071,6 +3619,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
}
#endif /* CONFIG_E1000_NAPI */
netdev->last_rx = jiffies;
+ rx_ring->pkt++;
next_desc:
rx_desc->wb.middle.status_error &= ~0xFF;
@@ -3081,7 +3630,7 @@ next_desc:
staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
}
rx_ring->next_to_clean = i;
- adapter->alloc_rx_buf(adapter);
+ adapter->alloc_rx_buf(adapter, rx_ring);
return cleaned;
}
@@ -3092,9 +3641,9 @@ next_desc:
**/
static void
-e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
+e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring)
{
- struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
struct e1000_rx_desc *rx_desc;
@@ -3178,7 +3727,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
* applicable for weak-ordered memory model archs,
* such as IA-64). */
wmb();
- E1000_WRITE_REG(&adapter->hw, RDT, i);
+ writel(i, adapter->hw.hw_addr + rx_ring->rdt);
}
if(unlikely(++i == rx_ring->count)) i = 0;
@@ -3194,9 +3743,9 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
**/
static void
-e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter)
+e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring)
{
- struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
union e1000_rx_desc_packet_split *rx_desc;
@@ -3215,22 +3764,26 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter)
rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
for(j = 0; j < PS_PAGE_BUFFERS; j++) {
- if(unlikely(!ps_page->ps_page[j])) {
- ps_page->ps_page[j] =
- alloc_page(GFP_ATOMIC);
- if(unlikely(!ps_page->ps_page[j]))
- goto no_buffers;
- ps_page_dma->ps_page_dma[j] =
- pci_map_page(pdev,
- ps_page->ps_page[j],
- 0, PAGE_SIZE,
- PCI_DMA_FROMDEVICE);
- }
- /* Refresh the desc even if buffer_addrs didn't
- * change because each write-back erases this info.
- */
- rx_desc->read.buffer_addr[j+1] =
- cpu_to_le64(ps_page_dma->ps_page_dma[j]);
+ if (j < adapter->rx_ps_pages) {
+ if (likely(!ps_page->ps_page[j])) {
+ ps_page->ps_page[j] =
+ alloc_page(GFP_ATOMIC);
+ if (unlikely(!ps_page->ps_page[j]))
+ goto no_buffers;
+ ps_page_dma->ps_page_dma[j] =
+ pci_map_page(pdev,
+ ps_page->ps_page[j],
+ 0, PAGE_SIZE,
+ PCI_DMA_FROMDEVICE);
+ }
+ /* Refresh the desc even if buffer_addrs didn't
+ * change because each write-back erases
+ * this info.
+ */
+ rx_desc->read.buffer_addr[j+1] =
+ cpu_to_le64(ps_page_dma->ps_page_dma[j]);
+ } else
+ rx_desc->read.buffer_addr[j+1] = ~0;
}
skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN);
@@ -3264,7 +3817,7 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter)
* descriptors are 32 bytes...so we increment tail
* twice as much.
*/
- E1000_WRITE_REG(&adapter->hw, RDT, i<<1);
+ writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt);
}
if(unlikely(++i == rx_ring->count)) i = 0;
@@ -3715,6 +4268,12 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
}
switch(adapter->hw.mac_type) {
+ case e1000_82571:
+ case e1000_82572:
+ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+ E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+ ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
+ break;
case e1000_82573:
swsm = E1000_READ_REG(&adapter->hw, SWSM);
E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -3737,6 +4296,7 @@ e1000_resume(struct pci_dev *pdev)
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
uint32_t manc, ret_val, swsm;
+ uint32_t ctrl_ext;
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
@@ -3762,6 +4322,12 @@ e1000_resume(struct pci_dev *pdev)
}
switch(adapter->hw.mac_type) {
+ case e1000_82571:
+ case e1000_82572:
+ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+ E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+ ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
+ break;
case e1000_82573:
swsm = E1000_READ_REG(&adapter->hw, SWSM);
E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -3786,7 +4352,7 @@ e1000_netpoll(struct net_device *netdev)
struct e1000_adapter *adapter = netdev_priv(netdev);
disable_irq(adapter->pdev->irq);
e1000_intr(adapter->pdev->irq, netdev, NULL);
- e1000_clean_tx_irq(adapter);
+ e1000_clean_tx_irq(adapter, adapter->tx_ring);
enable_irq(adapter->pdev->irq);
}
#endif
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index 676247f9f1cca0..38695d5b46377c 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -306,7 +306,8 @@ e1000_check_options(struct e1000_adapter *adapter)
.def = E1000_DEFAULT_TXD,
.arg = { .r = { .min = E1000_MIN_TXD }}
};
- struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
+ struct e1000_tx_ring *tx_ring = adapter->tx_ring;
+ int i;
e1000_mac_type mac_type = adapter->hw.mac_type;
opt.arg.r.max = mac_type < e1000_82544 ?
E1000_MAX_TXD : E1000_MAX_82544_TXD;
@@ -319,6 +320,8 @@ e1000_check_options(struct e1000_adapter *adapter)
} else {
tx_ring->count = opt.def;
}
+ for (i = 0; i < adapter->num_queues; i++)
+ tx_ring[i].count = tx_ring->count;
}
{ /* Receive Descriptor Count */
struct e1000_option opt = {
@@ -329,7 +332,8 @@ e1000_check_options(struct e1000_adapter *adapter)
.def = E1000_DEFAULT_RXD,
.arg = { .r = { .min = E1000_MIN_RXD }}
};
- struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
+ struct e1000_rx_ring *rx_ring = adapter->rx_ring;
+ int i;
e1000_mac_type mac_type = adapter->hw.mac_type;
opt.arg.r.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
E1000_MAX_82544_RXD;
@@ -342,6 +346,8 @@ e1000_check_options(struct e1000_adapter *adapter)
} else {
rx_ring->count = opt.def;
}
+ for (i = 0; i < adapter->num_queues; i++)
+ rx_ring[i].count = rx_ring->count;
}
{ /* Checksum Offload Enable/Disable */
struct e1000_option opt = {
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 87f522738bfcb7..f119ec4e89ea37 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -1334,7 +1334,7 @@ static void epic_rx_err(struct net_device *dev, struct epic_private *ep)
static int epic_poll(struct net_device *dev, int *budget)
{
struct epic_private *ep = dev->priv;
- int work_done, orig_budget;
+ int work_done = 0, orig_budget;
long ioaddr = dev->base_addr;
orig_budget = (*budget > dev->quota) ? dev->quota : *budget;
@@ -1343,7 +1343,7 @@ rx_action:
epic_tx(dev, ep);
- work_done = epic_rx(dev, *budget);
+ work_done += epic_rx(dev, *budget);
epic_rx_err(dev, ep);
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index d6eefdb71c1748..22aec6ed80f56b 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -95,6 +95,8 @@
* of nv_remove
* 0.42: 06 Aug 2005: Fix lack of link speed initialization
* in the second (and later) nv_open call
+ * 0.43: 10 Aug 2005: Add support for tx checksum.
+ * 0.44: 20 Aug 2005: Add support for scatter gather and segmentation.
*
* Known bugs:
* We suspect that on some hardware no TX done interrupts are generated.
@@ -106,7 +108,7 @@
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
* superfluous timer interrupts from the nic.
*/
-#define FORCEDETH_VERSION "0.41"
+#define FORCEDETH_VERSION "0.44"
#define DRV_NAME "forcedeth"
#include <linux/module.h>
@@ -145,6 +147,7 @@
#define DEV_NEED_LINKTIMER 0x0002 /* poll link settings. Relies on the timer irq */
#define DEV_HAS_LARGEDESC 0x0004 /* device supports jumbo frames and needs packet format 2 */
#define DEV_HAS_HIGH_DMA 0x0008 /* device supports 64bit dma */
+#define DEV_HAS_CHECKSUM 0x0010 /* device supports tx and rx checksum offloads */
enum {
NvRegIrqStatus = 0x000,
@@ -241,6 +244,9 @@ enum {
#define NVREG_TXRXCTL_IDLE 0x0008
#define NVREG_TXRXCTL_RESET 0x0010
#define NVREG_TXRXCTL_RXCHECK 0x0400
+#define NVREG_TXRXCTL_DESC_1 0
+#define NVREG_TXRXCTL_DESC_2 0x02100
+#define NVREG_TXRXCTL_DESC_3 0x02200
NvRegMIIStatus = 0x180,
#define NVREG_MIISTAT_ERROR 0x0001
#define NVREG_MIISTAT_LINKCHANGE 0x0008
@@ -335,6 +341,10 @@ typedef union _ring_type {
/* error and valid are the same for both */
#define NV_TX2_ERROR (1<<30)
#define NV_TX2_VALID (1<<31)
+#define NV_TX2_TSO (1<<28)
+#define NV_TX2_TSO_SHIFT 14
+#define NV_TX2_CHECKSUM_L3 (1<<27)
+#define NV_TX2_CHECKSUM_L4 (1<<26)
#define NV_RX_DESCRIPTORVALID (1<<16)
#define NV_RX_MISSEDFRAME (1<<17)
@@ -417,14 +427,14 @@ typedef union _ring_type {
/*
* desc_ver values:
- * This field has two purposes:
- * - Newer nics uses a different ring layout. The layout is selected by
- * comparing np->desc_ver with DESC_VER_xy.
- * - It contains bits that are forced on when writing to NvRegTxRxControl.
+ * The nic supports three different descriptor types:
+ * - DESC_VER_1: Original
+ * - DESC_VER_2: support for jumbo frames.
+ * - DESC_VER_3: 64-bit format.
*/
-#define DESC_VER_1 0x0
-#define DESC_VER_2 (0x02100|NVREG_TXRXCTL_RXCHECK)
-#define DESC_VER_3 (0x02200|NVREG_TXRXCTL_RXCHECK)
+#define DESC_VER_1 1
+#define DESC_VER_2 2
+#define DESC_VER_3 3
/* PHY defines */
#define PHY_OUI_MARVELL 0x5043
@@ -491,6 +501,7 @@ struct fe_priv {
u32 orig_mac[2];
u32 irqmask;
u32 desc_ver;
+ u32 txrxctl_bits;
void __iomem *base;
@@ -534,7 +545,7 @@ static inline struct fe_priv *get_nvpriv(struct net_device *dev)
static inline u8 __iomem *get_hwbase(struct net_device *dev)
{
- return get_nvpriv(dev)->base;
+ return ((struct fe_priv *)netdev_priv(dev))->base;
}
static inline void pci_push(u8 __iomem *base)
@@ -623,7 +634,7 @@ static int mii_rw(struct net_device *dev, int addr, int miireg, int value)
static int phy_reset(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u32 miicontrol;
unsigned int tries = 0;
@@ -726,7 +737,7 @@ static int phy_init(struct net_device *dev)
static void nv_start_rx(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
dprintk(KERN_DEBUG "%s: nv_start_rx\n", dev->name);
@@ -782,14 +793,14 @@ static void nv_stop_tx(struct net_device *dev)
static void nv_txrx_reset(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
dprintk(KERN_DEBUG "%s: nv_txrx_reset\n", dev->name);
- writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl);
+ writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl);
pci_push(base);
udelay(NV_TXRX_RESET_DELAY);
- writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl);
+ writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl);
pci_push(base);
}
@@ -801,7 +812,7 @@ static void nv_txrx_reset(struct net_device *dev)
*/
static struct net_device_stats *nv_get_stats(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
/* It seems that the nic always generates interrupts and doesn't
* accumulate errors internally. Thus the current values in np->stats
@@ -817,7 +828,7 @@ static struct net_device_stats *nv_get_stats(struct net_device *dev)
*/
static int nv_alloc_rx(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
unsigned int refill_rx = np->refill_rx;
int nr;
@@ -861,7 +872,7 @@ static int nv_alloc_rx(struct net_device *dev)
static void nv_do_rx_refill(unsigned long data)
{
struct net_device *dev = (struct net_device *) data;
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
disable_irq(dev->irq);
if (nv_alloc_rx(dev)) {
@@ -875,7 +886,7 @@ static void nv_do_rx_refill(unsigned long data)
static void nv_init_rx(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
int i;
np->cur_rx = RX_RING;
@@ -889,15 +900,17 @@ static void nv_init_rx(struct net_device *dev)
static void nv_init_tx(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
int i;
np->next_tx = np->nic_tx = 0;
- for (i = 0; i < TX_RING; i++)
+ for (i = 0; i < TX_RING; i++) {
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
np->tx_ring.orig[i].FlagLen = 0;
else
np->tx_ring.ex[i].FlagLen = 0;
+ np->tx_skbuff[i] = NULL;
+ }
}
static int nv_init_ring(struct net_device *dev)
@@ -907,21 +920,44 @@ static int nv_init_ring(struct net_device *dev)
return nv_alloc_rx(dev);
}
+static void nv_release_txskb(struct net_device *dev, unsigned int skbnr)
+{
+ struct fe_priv *np = netdev_priv(dev);
+ struct sk_buff *skb = np->tx_skbuff[skbnr];
+ unsigned int j, entry, fragments;
+
+ dprintk(KERN_INFO "%s: nv_release_txskb for skbnr %d, skb %p\n",
+ dev->name, skbnr, np->tx_skbuff[skbnr]);
+
+ entry = skbnr;
+ if ((fragments = skb_shinfo(skb)->nr_frags) != 0) {
+ for (j = fragments; j >= 1; j--) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[j-1];
+ pci_unmap_page(np->pci_dev, np->tx_dma[entry],
+ frag->size,
+ PCI_DMA_TODEVICE);
+ entry = (entry - 1) % TX_RING;
+ }
+ }
+ pci_unmap_single(np->pci_dev, np->tx_dma[entry],
+ skb->len - skb->data_len,
+ PCI_DMA_TODEVICE);
+ dev_kfree_skb_irq(skb);
+ np->tx_skbuff[skbnr] = NULL;
+}
+
static void nv_drain_tx(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
- int i;
+ struct fe_priv *np = netdev_priv(dev);
+ unsigned int i;
+
for (i = 0; i < TX_RING; i++) {
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
np->tx_ring.orig[i].FlagLen = 0;
else
np->tx_ring.ex[i].FlagLen = 0;
if (np->tx_skbuff[i]) {
- pci_unmap_single(np->pci_dev, np->tx_dma[i],
- np->tx_skbuff[i]->len,
- PCI_DMA_TODEVICE);
- dev_kfree_skb(np->tx_skbuff[i]);
- np->tx_skbuff[i] = NULL;
+ nv_release_txskb(dev, i);
np->stats.tx_dropped++;
}
}
@@ -929,7 +965,7 @@ static void nv_drain_tx(struct net_device *dev)
static void nv_drain_rx(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
int i;
for (i = 0; i < RX_RING; i++) {
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
@@ -959,28 +995,69 @@ static void drain_ring(struct net_device *dev)
*/
static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
- int nr = np->next_tx % TX_RING;
+ struct fe_priv *np = netdev_priv(dev);
+ u32 tx_flags_extra = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET);
+ unsigned int fragments = skb_shinfo(skb)->nr_frags;
+ unsigned int nr = (np->next_tx + fragments) % TX_RING;
+ unsigned int i;
+
+ spin_lock_irq(&np->lock);
+
+ if ((np->next_tx - np->nic_tx + fragments) > TX_LIMIT_STOP) {
+ spin_unlock_irq(&np->lock);
+ netif_stop_queue(dev);
+ return NETDEV_TX_BUSY;
+ }
np->tx_skbuff[nr] = skb;
- np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data,skb->len,
- PCI_DMA_TODEVICE);
+
+ if (fragments) {
+ dprintk(KERN_DEBUG "%s: nv_start_xmit: buffer contains %d fragments\n", dev->name, fragments);
+ /* setup descriptors in reverse order */
+ for (i = fragments; i >= 1; i--) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1];
+ np->tx_dma[nr] = pci_map_page(np->pci_dev, frag->page, frag->page_offset, frag->size,
+ PCI_DMA_TODEVICE);
- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+ np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
+ np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (frag->size-1) | np->tx_flags | tx_flags_extra);
+ } else {
+ np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
+ np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
+ np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (frag->size-1) | np->tx_flags | tx_flags_extra);
+ }
+
+ nr = (nr - 1) % TX_RING;
+
+ if (np->desc_ver == DESC_VER_1)
+ tx_flags_extra &= ~NV_TX_LASTPACKET;
+ else
+ tx_flags_extra &= ~NV_TX2_LASTPACKET;
+ }
+ }
+
+#ifdef NETIF_F_TSO
+ if (skb_shinfo(skb)->tso_size)
+ tx_flags_extra |= NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT);
+ else
+#endif
+ tx_flags_extra |= (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0);
+
+ np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data, skb->len-skb->data_len,
+ PCI_DMA_TODEVICE);
+
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
- else {
+ np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (skb->len-skb->data_len-1) | np->tx_flags | tx_flags_extra);
+ } else {
np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
- }
+ np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (skb->len-skb->data_len-1) | np->tx_flags | tx_flags_extra);
+ }
- spin_lock_irq(&np->lock);
- wmb();
- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
- np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
- else
- np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
- dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission.\n",
- dev->name, np->next_tx);
+ dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission. tx_flags_extra: %x\n",
+ dev->name, np->next_tx, tx_flags_extra);
{
int j;
for (j=0; j<64; j++) {
@@ -991,15 +1068,13 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
dprintk("\n");
}
- np->next_tx++;
+ np->next_tx += 1 + fragments;
dev->trans_start = jiffies;
- if (np->next_tx - np->nic_tx >= TX_LIMIT_STOP)
- netif_stop_queue(dev);
spin_unlock_irq(&np->lock);
- writel(NVREG_TXRXCTL_KICK|np->desc_ver, get_hwbase(dev) + NvRegTxRxControl);
+ writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
pci_push(get_hwbase(dev));
- return 0;
+ return NETDEV_TX_OK;
}
/*
@@ -1009,9 +1084,10 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
static void nv_tx_done(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u32 Flags;
- int i;
+ unsigned int i;
+ struct sk_buff *skb;
while (np->nic_tx != np->next_tx) {
i = np->nic_tx % TX_RING;
@@ -1026,35 +1102,38 @@ static void nv_tx_done(struct net_device *dev)
if (Flags & NV_TX_VALID)
break;
if (np->desc_ver == DESC_VER_1) {
- if (Flags & (NV_TX_RETRYERROR|NV_TX_CARRIERLOST|NV_TX_LATECOLLISION|
- NV_TX_UNDERFLOW|NV_TX_ERROR)) {
- if (Flags & NV_TX_UNDERFLOW)
- np->stats.tx_fifo_errors++;
- if (Flags & NV_TX_CARRIERLOST)
- np->stats.tx_carrier_errors++;
- np->stats.tx_errors++;
- } else {
- np->stats.tx_packets++;
- np->stats.tx_bytes += np->tx_skbuff[i]->len;
+ if (Flags & NV_TX_LASTPACKET) {
+ skb = np->tx_skbuff[i];
+ if (Flags & (NV_TX_RETRYERROR|NV_TX_CARRIERLOST|NV_TX_LATECOLLISION|
+ NV_TX_UNDERFLOW|NV_TX_ERROR)) {
+ if (Flags & NV_TX_UNDERFLOW)
+ np->stats.tx_fifo_errors++;
+ if (Flags & NV_TX_CARRIERLOST)
+ np->stats.tx_carrier_errors++;
+ np->stats.tx_errors++;
+ } else {
+ np->stats.tx_packets++;
+ np->stats.tx_bytes += skb->len;
+ }
+ nv_release_txskb(dev, i);
}
} else {
- if (Flags & (NV_TX2_RETRYERROR|NV_TX2_CARRIERLOST|NV_TX2_LATECOLLISION|
- NV_TX2_UNDERFLOW|NV_TX2_ERROR)) {
- if (Flags & NV_TX2_UNDERFLOW)
- np->stats.tx_fifo_errors++;
- if (Flags & NV_TX2_CARRIERLOST)
- np->stats.tx_carrier_errors++;
- np->stats.tx_errors++;
- } else {
- np->stats.tx_packets++;
- np->stats.tx_bytes += np->tx_skbuff[i]->len;
+ if (Flags & NV_TX2_LASTPACKET) {
+ skb = np->tx_skbuff[i];
+ if (Flags & (NV_TX2_RETRYERROR|NV_TX2_CARRIERLOST|NV_TX2_LATECOLLISION|
+ NV_TX2_UNDERFLOW|NV_TX2_ERROR)) {
+ if (Flags & NV_TX2_UNDERFLOW)
+ np->stats.tx_fifo_errors++;
+ if (Flags & NV_TX2_CARRIERLOST)
+ np->stats.tx_carrier_errors++;
+ np->stats.tx_errors++;
+ } else {
+ np->stats.tx_packets++;
+ np->stats.tx_bytes += skb->len;
+ }
+ nv_release_txskb(dev, i);
}
}
- pci_unmap_single(np->pci_dev, np->tx_dma[i],
- np->tx_skbuff[i]->len,
- PCI_DMA_TODEVICE);
- dev_kfree_skb_irq(np->tx_skbuff[i]);
- np->tx_skbuff[i] = NULL;
np->nic_tx++;
}
if (np->next_tx - np->nic_tx < TX_LIMIT_START)
@@ -1067,7 +1146,7 @@ static void nv_tx_done(struct net_device *dev)
*/
static void nv_tx_timeout(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
printk(KERN_INFO "%s: Got tx_timeout. irq: %08x\n", dev->name,
@@ -1200,7 +1279,7 @@ static int nv_getlen(struct net_device *dev, void *packet, int datalen)
static void nv_rx_process(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u32 Flags;
for (;;) {
@@ -1355,7 +1434,7 @@ static void set_bufsize(struct net_device *dev)
*/
static int nv_change_mtu(struct net_device *dev, int new_mtu)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
int old_mtu;
if (new_mtu < 64 || new_mtu > np->pkt_limit)
@@ -1408,7 +1487,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
base + NvRegRingSizes);
pci_push(base);
- writel(NVREG_TXRXCTL_KICK|np->desc_ver, get_hwbase(dev) + NvRegTxRxControl);
+ writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
pci_push(base);
/* restart rx engine */
@@ -1440,7 +1519,7 @@ static void nv_copy_mac_to_hw(struct net_device *dev)
*/
static int nv_set_mac_address(struct net_device *dev, void *addr)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
struct sockaddr *macaddr = (struct sockaddr*)addr;
if(!is_valid_ether_addr(macaddr->sa_data))
@@ -1475,7 +1554,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
*/
static void nv_set_multicast(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
u32 addr[2];
u32 mask[2];
@@ -1535,7 +1614,7 @@ static void nv_set_multicast(struct net_device *dev)
static int nv_update_linkspeed(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
int adv, lpa;
int newls = np->linkspeed;
@@ -1705,7 +1784,7 @@ static void nv_link_irq(struct net_device *dev)
static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) data;
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
u32 events;
int i;
@@ -1777,7 +1856,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
static void nv_do_nic_poll(unsigned long data)
{
struct net_device *dev = (struct net_device *) data;
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
disable_irq(dev->irq);
@@ -1801,7 +1880,7 @@ static void nv_poll_controller(struct net_device *dev)
static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
strcpy(info->driver, "forcedeth");
strcpy(info->version, FORCEDETH_VERSION);
strcpy(info->bus_info, pci_name(np->pci_dev));
@@ -1809,7 +1888,7 @@ static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
static void nv_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
wolinfo->supported = WAKE_MAGIC;
spin_lock_irq(&np->lock);
@@ -1820,7 +1899,7 @@ static void nv_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
static int nv_set_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
spin_lock_irq(&np->lock);
@@ -2021,7 +2100,7 @@ static int nv_get_regs_len(struct net_device *dev)
static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
u32 *rbuf = buf;
int i;
@@ -2035,7 +2114,7 @@ static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void
static int nv_nway_reset(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
int ret;
spin_lock_irq(&np->lock);
@@ -2065,11 +2144,12 @@ static struct ethtool_ops ops = {
.get_regs_len = nv_get_regs_len,
.get_regs = nv_get_regs,
.nway_reset = nv_nway_reset,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static int nv_open(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
int ret, oom, i;
@@ -2114,9 +2194,9 @@ static int nv_open(struct net_device *dev)
/* 5) continue setup */
writel(np->linkspeed, base + NvRegLinkSpeed);
writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);
- writel(np->desc_ver, base + NvRegTxRxControl);
+ writel(np->txrxctl_bits, base + NvRegTxRxControl);
pci_push(base);
- writel(NVREG_TXRXCTL_BIT1|np->desc_ver, base + NvRegTxRxControl);
+ writel(NVREG_TXRXCTL_BIT1|np->txrxctl_bits, base + NvRegTxRxControl);
reg_delay(dev, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31,
NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX,
KERN_INFO "open: SetupReg5, Bit 31 remained off\n");
@@ -2205,7 +2285,7 @@ out_drain:
static int nv_close(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base;
spin_lock_irq(&np->lock);
@@ -2261,7 +2341,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
if (!dev)
goto out;
- np = get_nvpriv(dev);
+ np = netdev_priv(dev);
np->pci_dev = pci_dev;
spin_lock_init(&np->lock);
SET_MODULE_OWNER(dev);
@@ -2313,19 +2393,32 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
if (pci_set_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
pci_name(pci_dev));
+ } else {
+ dev->features |= NETIF_F_HIGHDMA;
}
+ np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
} else if (id->driver_data & DEV_HAS_LARGEDESC) {
/* packet format 2: supports jumbo frames */
np->desc_ver = DESC_VER_2;
+ np->txrxctl_bits = NVREG_TXRXCTL_DESC_2;
} else {
/* original packet format */
np->desc_ver = DESC_VER_1;
+ np->txrxctl_bits = NVREG_TXRXCTL_DESC_1;
}
np->pkt_limit = NV_PKTLIMIT_1;
if (id->driver_data & DEV_HAS_LARGEDESC)
np->pkt_limit = NV_PKTLIMIT_2;
+ if (id->driver_data & DEV_HAS_CHECKSUM) {
+ np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
+ dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
+#ifdef NETIF_F_TSO
+ dev->features |= NETIF_F_TSO;
+#endif
+ }
+
err = -ENOMEM;
np->base = ioremap(addr, NV_PCI_REGSZ);
if (!np->base)
@@ -2377,8 +2470,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff;
dev->dev_addr[4] = (np->orig_mac[0] >> 8) & 0xff;
dev->dev_addr[5] = (np->orig_mac[0] >> 0) & 0xff;
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
- if (!is_valid_ether_addr(dev->dev_addr)) {
+ if (!is_valid_ether_addr(dev->perm_addr)) {
/*
* Bad mac address. At least one bios sets the mac address
* to 01:23:45:67:89:ab
@@ -2403,9 +2497,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
np->wolenabled = 0;
if (np->desc_ver == DESC_VER_1) {
- np->tx_flags = NV_TX_LASTPACKET|NV_TX_VALID;
+ np->tx_flags = NV_TX_VALID;
} else {
- np->tx_flags = NV_TX2_LASTPACKET|NV_TX2_VALID;
+ np->tx_flags = NV_TX2_VALID;
}
np->irqmask = NVREG_IRQMASK_WANTED;
if (id->driver_data & DEV_NEED_TIMERIRQ)
@@ -2494,7 +2588,7 @@ out:
static void __devexit nv_remove(struct pci_dev *pci_dev)
{
struct net_device *dev = pci_get_drvdata(pci_dev);
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
unregister_netdev(dev);
@@ -2525,35 +2619,35 @@ static struct pci_device_id pci_tbl[] = {
},
{ /* nForce3 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_4),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
},
{ /* nForce3 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_5),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
},
{ /* nForce3 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_6),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
},
{ /* nForce3 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_7),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
},
{ /* CK804 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_8),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
},
{ /* CK804 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_9),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
},
{ /* MCP04 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_10),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
},
{ /* MCP04 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_11),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
},
{ /* MCP51 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12),
@@ -2565,11 +2659,11 @@ static struct pci_device_id pci_tbl[] = {
},
{ /* MCP55 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
},
{ /* MCP55 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
},
{0,},
};
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 6518334b92801a..ae5a2ed3b26403 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -29,12 +29,7 @@
* define the configuration needed by the board are defined in a
* board structure in arch/ppc/platforms (though I do not
* discount the possibility that other architectures could one
- * day be supported. One assumption the driver currently makes
- * is that the PHY is configured in such a way to advertise all
- * capabilities. This is a sensible default, and on certain
- * PHYs, changing this default encounters substantial errata
- * issues. Future versions may remove this requirement, but for
- * now, it is best for the firmware to ensure this is the case.
+ * day be supported.
*
* The Gianfar Ethernet Controller uses a ring of buffer
* descriptors. The beginning is indicated by a register
@@ -47,7 +42,7 @@
* corresponding bit in the IMASK register is also set (if
* interrupt coalescing is active, then the interrupt may not
* happen immediately, but will wait until either a set number
- * of frames or amount of time have passed.). In NAPI, the
+ * of frames or amount of time have passed). In NAPI, the
* interrupt handler will signal there is work to be done, and
* exit. Without NAPI, the packet(s) will be handled
* immediately. Both methods will start at the last known empty
@@ -75,6 +70,7 @@
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/errno.h>
+#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -97,9 +93,11 @@
#include <linux/version.h>
#include <linux/dma-mapping.h>
#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
#include "gianfar.h"
-#include "gianfar_phy.h"
+#include "gianfar_mii.h"
#define TX_TIMEOUT (1*HZ)
#define SKB_ALLOC_TIMEOUT 1000000
@@ -113,9 +111,8 @@
#endif
const char gfar_driver_name[] = "Gianfar Ethernet";
-const char gfar_driver_version[] = "1.1";
+const char gfar_driver_version[] = "1.2";
-int startup_gfar(struct net_device *dev);
static int gfar_enet_open(struct net_device *dev);
static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void gfar_timeout(struct net_device *dev);
@@ -126,17 +123,13 @@ static int gfar_set_mac_address(struct net_device *dev);
static int gfar_change_mtu(struct net_device *dev, int new_mtu);
static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs);
static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void gfar_phy_change(void *data);
-static void gfar_phy_timer(unsigned long data);
static void adjust_link(struct net_device *dev);
static void init_registers(struct net_device *dev);
static int init_phy(struct net_device *dev);
static int gfar_probe(struct device *device);
static int gfar_remove(struct device *device);
-void free_skb_resources(struct gfar_private *priv);
+static void free_skb_resources(struct gfar_private *priv);
static void gfar_set_multi(struct net_device *dev);
static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
#ifdef CONFIG_GFAR_NAPI
@@ -144,7 +137,6 @@ static int gfar_poll(struct net_device *dev, int *budget);
#endif
int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
-static void gfar_phy_startup_timer(unsigned long data);
static void gfar_vlan_rx_register(struct net_device *netdev,
struct vlan_group *grp);
static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
@@ -162,6 +154,9 @@ int gfar_uses_fcb(struct gfar_private *priv)
else
return 0;
}
+
+/* Set up the ethernet device structure, private data,
+ * and anything else we need before we start */
static int gfar_probe(struct device *device)
{
u32 tempval;
@@ -175,7 +170,7 @@ static int gfar_probe(struct device *device)
einfo = (struct gianfar_platform_data *) pdev->dev.platform_data;
- if (einfo == NULL) {
+ if (NULL == einfo) {
printk(KERN_ERR "gfar %d: Missing additional data!\n",
pdev->id);
@@ -185,7 +180,7 @@ static int gfar_probe(struct device *device)
/* Create an ethernet device instance */
dev = alloc_etherdev(sizeof (*priv));
- if (dev == NULL)
+ if (NULL == dev)
return -ENOMEM;
priv = netdev_priv(dev);
@@ -207,20 +202,11 @@ static int gfar_probe(struct device *device)
priv->regs = (struct gfar *)
ioremap(r->start, sizeof (struct gfar));
- if (priv->regs == NULL) {
+ if (NULL == priv->regs) {
err = -ENOMEM;
goto regs_fail;
}
- /* Set the PHY base address */
- priv->phyregs = (struct gfar *)
- ioremap(einfo->phy_reg_addr, sizeof (struct gfar));
-
- if (priv->phyregs == NULL) {
- err = -ENOMEM;
- goto phy_regs_fail;
- }
-
spin_lock_init(&priv->lock);
dev_set_drvdata(device, dev);
@@ -386,12 +372,10 @@ static int gfar_probe(struct device *device)
return 0;
register_fail:
- iounmap((void *) priv->phyregs);
-phy_regs_fail:
iounmap((void *) priv->regs);
regs_fail:
free_netdev(dev);
- return -ENOMEM;
+ return err;
}
static int gfar_remove(struct device *device)
@@ -402,108 +386,41 @@ static int gfar_remove(struct device *device)
dev_set_drvdata(device, NULL);
iounmap((void *) priv->regs);
- iounmap((void *) priv->phyregs);
free_netdev(dev);
return 0;
}
-/* Configure the PHY for dev.
- * returns 0 if success. -1 if failure
+/* Initializes driver's PHY state, and attaches to the PHY.
+ * Returns 0 on success.
*/
static int init_phy(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
- struct phy_info *curphy;
- unsigned int timeout = PHY_INIT_TIMEOUT;
- struct gfar *phyregs = priv->phyregs;
- struct gfar_mii_info *mii_info;
- int err;
+ uint gigabit_support =
+ priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
+ SUPPORTED_1000baseT_Full : 0;
+ struct phy_device *phydev;
priv->oldlink = 0;
priv->oldspeed = 0;
priv->oldduplex = -1;
- mii_info = kmalloc(sizeof(struct gfar_mii_info),
- GFP_KERNEL);
-
- if(NULL == mii_info) {
- if (netif_msg_ifup(priv))
- printk(KERN_ERR "%s: Could not allocate mii_info\n",
- dev->name);
- return -ENOMEM;
- }
-
- mii_info->speed = SPEED_1000;
- mii_info->duplex = DUPLEX_FULL;
- mii_info->pause = 0;
- mii_info->link = 1;
-
- mii_info->advertising = (ADVERTISED_10baseT_Half |
- ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Half |
- ADVERTISED_100baseT_Full |
- ADVERTISED_1000baseT_Full);
- mii_info->autoneg = 1;
+ phydev = phy_connect(dev, priv->einfo->bus_id, &adjust_link, 0);
- spin_lock_init(&mii_info->mdio_lock);
-
- mii_info->mii_id = priv->einfo->phyid;
-
- mii_info->dev = dev;
-
- mii_info->mdio_read = &read_phy_reg;
- mii_info->mdio_write = &write_phy_reg;
-
- priv->mii_info = mii_info;
-
- /* Reset the management interface */
- gfar_write(&phyregs->miimcfg, MIIMCFG_RESET);
-
- /* Setup the MII Mgmt clock speed */
- gfar_write(&phyregs->miimcfg, MIIMCFG_INIT_VALUE);
-
- /* Wait until the bus is free */
- while ((gfar_read(&phyregs->miimind) & MIIMIND_BUSY) &&
- timeout--)
- cpu_relax();
-
- if(timeout <= 0) {
- printk(KERN_ERR "%s: The MII Bus is stuck!\n",
- dev->name);
- err = -1;
- goto bus_fail;
- }
-
- /* get info for this PHY */
- curphy = get_phy_info(priv->mii_info);
-
- if (curphy == NULL) {
- if (netif_msg_ifup(priv))
- printk(KERN_ERR "%s: No PHY found\n", dev->name);
- err = -1;
- goto no_phy;
+ if (IS_ERR(phydev)) {
+ printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+ return PTR_ERR(phydev);
}
- mii_info->phyinfo = curphy;
+ /* Remove any features not supported by the controller */
+ phydev->supported &= (GFAR_SUPPORTED | gigabit_support);
+ phydev->advertising = phydev->supported;
- /* Run the commands which initialize the PHY */
- if(curphy->init) {
- err = curphy->init(priv->mii_info);
-
- if (err)
- goto phy_init_fail;
- }
+ priv->phydev = phydev;
return 0;
-
-phy_init_fail:
-no_phy:
-bus_fail:
- kfree(mii_info);
-
- return err;
}
static void init_registers(struct net_device *dev)
@@ -603,24 +520,13 @@ void stop_gfar(struct net_device *dev)
struct gfar *regs = priv->regs;
unsigned long flags;
+ phy_stop(priv->phydev);
+
/* Lock it down */
spin_lock_irqsave(&priv->lock, flags);
- /* Tell the kernel the link is down */
- priv->mii_info->link = 0;
- adjust_link(dev);
-
gfar_halt(dev);
- if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
- /* Clear any pending interrupts */
- mii_clear_phy_interrupt(priv->mii_info);
-
- /* Disable PHY Interrupts */
- mii_configure_phy_interrupt(priv->mii_info,
- MII_INTERRUPT_DISABLED);
- }
-
spin_unlock_irqrestore(&priv->lock, flags);
/* Free the IRQs */
@@ -629,13 +535,7 @@ void stop_gfar(struct net_device *dev)
free_irq(priv->interruptTransmit, dev);
free_irq(priv->interruptReceive, dev);
} else {
- free_irq(priv->interruptTransmit, dev);
- }
-
- if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
- free_irq(priv->einfo->interruptPHY, dev);
- } else {
- del_timer_sync(&priv->phy_info_timer);
+ free_irq(priv->interruptTransmit, dev);
}
free_skb_resources(priv);
@@ -649,7 +549,7 @@ void stop_gfar(struct net_device *dev)
/* If there are any tx skbs or rx skbs still around, free them.
* Then free tx_skbuff and rx_skbuff */
-void free_skb_resources(struct gfar_private *priv)
+static void free_skb_resources(struct gfar_private *priv)
{
struct rxbd8 *rxbdp;
struct txbd8 *txbdp;
@@ -770,7 +670,7 @@ int startup_gfar(struct net_device *dev)
(struct sk_buff **) kmalloc(sizeof (struct sk_buff *) *
priv->tx_ring_size, GFP_KERNEL);
- if (priv->tx_skbuff == NULL) {
+ if (NULL == priv->tx_skbuff) {
if (netif_msg_ifup(priv))
printk(KERN_ERR "%s: Could not allocate tx_skbuff\n",
dev->name);
@@ -785,7 +685,7 @@ int startup_gfar(struct net_device *dev)
(struct sk_buff **) kmalloc(sizeof (struct sk_buff *) *
priv->rx_ring_size, GFP_KERNEL);
- if (priv->rx_skbuff == NULL) {
+ if (NULL == priv->rx_skbuff) {
if (netif_msg_ifup(priv))
printk(KERN_ERR "%s: Could not allocate rx_skbuff\n",
dev->name);
@@ -879,13 +779,7 @@ int startup_gfar(struct net_device *dev)
}
}
- /* Set up the PHY change work queue */
- INIT_WORK(&priv->tq, gfar_phy_change, dev);
-
- init_timer(&priv->phy_info_timer);
- priv->phy_info_timer.function = &gfar_phy_startup_timer;
- priv->phy_info_timer.data = (unsigned long) priv->mii_info;
- mod_timer(&priv->phy_info_timer, jiffies + HZ);
+ phy_start(priv->phydev);
/* Configure the coalescing support */
if (priv->txcoalescing)
@@ -933,11 +827,6 @@ tx_skb_fail:
priv->tx_bd_base,
gfar_read(&regs->tbase0));
- if (priv->mii_info->phyinfo->close)
- priv->mii_info->phyinfo->close(priv->mii_info);
-
- kfree(priv->mii_info);
-
return err;
}
@@ -1035,7 +924,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
txbdp->status &= TXBD_WRAP;
/* Set up checksumming */
- if ((dev->features & NETIF_F_IP_CSUM)
+ if ((dev->features & NETIF_F_IP_CSUM)
&& (CHECKSUM_HW == skb->ip_summed)) {
fcb = gfar_add_fcb(skb, txbdp);
gfar_tx_checksum(skb, fcb);
@@ -1103,11 +992,9 @@ static int gfar_close(struct net_device *dev)
struct gfar_private *priv = netdev_priv(dev);
stop_gfar(dev);
- /* Shutdown the PHY */
- if (priv->mii_info->phyinfo->close)
- priv->mii_info->phyinfo->close(priv->mii_info);
-
- kfree(priv->mii_info);
+ /* Disconnect from the PHY */
+ phy_disconnect(priv->phydev);
+ priv->phydev = NULL;
netif_stop_queue(dev);
@@ -1343,7 +1230,7 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
while ((!skb) && timeout--)
skb = dev_alloc_skb(priv->rx_buffer_size + RXBUF_ALIGNMENT);
- if (skb == NULL)
+ if (NULL == skb)
return NULL;
/* We need the data buffer to be aligned properly. We will reserve
@@ -1490,7 +1377,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
struct gfar_private *priv = netdev_priv(dev);
struct rxfcb *fcb = NULL;
- if (skb == NULL) {
+ if (NULL == skb) {
if (netif_msg_rx_err(priv))
printk(KERN_WARNING "%s: Missing skb!!.\n", dev->name);
priv->stats.rx_dropped++;
@@ -1718,131 +1605,9 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct net_device *dev = (struct net_device *) dev_id;
- struct gfar_private *priv = netdev_priv(dev);
-
- /* Clear the interrupt */
- mii_clear_phy_interrupt(priv->mii_info);
-
- /* Disable PHY interrupts */
- mii_configure_phy_interrupt(priv->mii_info,
- MII_INTERRUPT_DISABLED);
-
- /* Schedule the phy change */
- schedule_work(&priv->tq);
-
- return IRQ_HANDLED;
-}
-
-/* Scheduled by the phy_interrupt/timer to handle PHY changes */
-static void gfar_phy_change(void *data)
-{
- struct net_device *dev = (struct net_device *) data;
- struct gfar_private *priv = netdev_priv(dev);
- int result = 0;
-
- /* Delay to give the PHY a chance to change the
- * register state */
- msleep(1);
-
- /* Update the link, speed, duplex */
- result = priv->mii_info->phyinfo->read_status(priv->mii_info);
-
- /* Adjust the known status as long as the link
- * isn't still coming up */
- if((0 == result) || (priv->mii_info->link == 0))
- adjust_link(dev);
-
- /* Reenable interrupts, if needed */
- if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR)
- mii_configure_phy_interrupt(priv->mii_info,
- MII_INTERRUPT_ENABLED);
-}
-
-/* Called every so often on systems that don't interrupt
- * the core for PHY changes */
-static void gfar_phy_timer(unsigned long data)
-{
- struct net_device *dev = (struct net_device *) data;
- struct gfar_private *priv = netdev_priv(dev);
-
- schedule_work(&priv->tq);
-
- mod_timer(&priv->phy_info_timer, jiffies +
- GFAR_PHY_CHANGE_TIME * HZ);
-}
-
-/* Keep trying aneg for some time
- * If, after GFAR_AN_TIMEOUT seconds, it has not
- * finished, we switch to forced.
- * Either way, once the process has completed, we either
- * request the interrupt, or switch the timer over to
- * using gfar_phy_timer to check status */
-static void gfar_phy_startup_timer(unsigned long data)
-{
- int result;
- static int secondary = GFAR_AN_TIMEOUT;
- struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data;
- struct gfar_private *priv = netdev_priv(mii_info->dev);
-
- /* Configure the Auto-negotiation */
- result = mii_info->phyinfo->config_aneg(mii_info);
-
- /* If autonegotiation failed to start, and
- * we haven't timed out, reset the timer, and return */
- if (result && secondary--) {
- mod_timer(&priv->phy_info_timer, jiffies + HZ);
- return;
- } else if (result) {
- /* Couldn't start autonegotiation.
- * Try switching to forced */
- mii_info->autoneg = 0;
- result = mii_info->phyinfo->config_aneg(mii_info);
-
- /* Forcing failed! Give up */
- if(result) {
- if (netif_msg_link(priv))
- printk(KERN_ERR "%s: Forcing failed!\n",
- mii_info->dev->name);
- return;
- }
- }
-
- /* Kill the timer so it can be restarted */
- del_timer_sync(&priv->phy_info_timer);
-
- /* Grab the PHY interrupt, if necessary/possible */
- if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
- if (request_irq(priv->einfo->interruptPHY,
- phy_interrupt,
- SA_SHIRQ,
- "phy_interrupt",
- mii_info->dev) < 0) {
- if (netif_msg_intr(priv))
- printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n",
- mii_info->dev->name,
- priv->einfo->interruptPHY);
- } else {
- mii_configure_phy_interrupt(priv->mii_info,
- MII_INTERRUPT_ENABLED);
- return;
- }
- }
-
- /* Start the timer again, this time in order to
- * handle a change in status */
- init_timer(&priv->phy_info_timer);
- priv->phy_info_timer.function = &gfar_phy_timer;
- priv->phy_info_timer.data = (unsigned long) mii_info->dev;
- mod_timer(&priv->phy_info_timer, jiffies +
- GFAR_PHY_CHANGE_TIME * HZ);
-}
-
/* Called every time the controller might need to be made
* aware of new link state. The PHY code conveys this
- * information through variables in the priv structure, and this
+ * information through variables in the phydev structure, and this
* function converts those variables into the appropriate
* register values, and can bring down the device if needed.
*/
@@ -1850,84 +1615,68 @@ static void adjust_link(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
struct gfar *regs = priv->regs;
- u32 tempval;
- struct gfar_mii_info *mii_info = priv->mii_info;
+ unsigned long flags;
+ struct phy_device *phydev = priv->phydev;
+ int new_state = 0;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (phydev->link) {
+ u32 tempval = gfar_read(&regs->maccfg2);
- if (mii_info->link) {
/* Now we make sure that we can be in full duplex mode.
* If not, we operate in half-duplex mode. */
- if (mii_info->duplex != priv->oldduplex) {
- if (!(mii_info->duplex)) {
- tempval = gfar_read(&regs->maccfg2);
+ if (phydev->duplex != priv->oldduplex) {
+ new_state = 1;
+ if (!(phydev->duplex))
tempval &= ~(MACCFG2_FULL_DUPLEX);
- gfar_write(&regs->maccfg2, tempval);
-
- if (netif_msg_link(priv))
- printk(KERN_INFO "%s: Half Duplex\n",
- dev->name);
- } else {
- tempval = gfar_read(&regs->maccfg2);
+ else
tempval |= MACCFG2_FULL_DUPLEX;
- gfar_write(&regs->maccfg2, tempval);
- if (netif_msg_link(priv))
- printk(KERN_INFO "%s: Full Duplex\n",
- dev->name);
- }
-
- priv->oldduplex = mii_info->duplex;
+ priv->oldduplex = phydev->duplex;
}
- if (mii_info->speed != priv->oldspeed) {
- switch (mii_info->speed) {
+ if (phydev->speed != priv->oldspeed) {
+ new_state = 1;
+ switch (phydev->speed) {
case 1000:
- tempval = gfar_read(&regs->maccfg2);
tempval =
((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII);
- gfar_write(&regs->maccfg2, tempval);
break;
case 100:
case 10:
- tempval = gfar_read(&regs->maccfg2);
tempval =
((tempval & ~(MACCFG2_IF)) | MACCFG2_MII);
- gfar_write(&regs->maccfg2, tempval);
break;
default:
if (netif_msg_link(priv))
printk(KERN_WARNING
- "%s: Ack! Speed (%d) is not 10/100/1000!\n",
- dev->name, mii_info->speed);
+ "%s: Ack! Speed (%d) is not 10/100/1000!\n",
+ dev->name, phydev->speed);
break;
}
- if (netif_msg_link(priv))
- printk(KERN_INFO "%s: Speed %dBT\n", dev->name,
- mii_info->speed);
-
- priv->oldspeed = mii_info->speed;
+ priv->oldspeed = phydev->speed;
}
+ gfar_write(&regs->maccfg2, tempval);
+
if (!priv->oldlink) {
- if (netif_msg_link(priv))
- printk(KERN_INFO "%s: Link is up\n", dev->name);
+ new_state = 1;
priv->oldlink = 1;
- netif_carrier_on(dev);
netif_schedule(dev);
}
- } else {
- if (priv->oldlink) {
- if (netif_msg_link(priv))
- printk(KERN_INFO "%s: Link is down\n",
- dev->name);
- priv->oldlink = 0;
- priv->oldspeed = 0;
- priv->oldduplex = -1;
- netif_carrier_off(dev);
- }
+ } else if (priv->oldlink) {
+ new_state = 1;
+ priv->oldlink = 0;
+ priv->oldspeed = 0;
+ priv->oldduplex = -1;
}
-}
+ if (new_state && netif_msg_link(priv))
+ phy_print_status(phydev);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
/* Update the hash table based on the current list of multicast
* addresses we subscribe to. Also, change the promiscuity of
@@ -2122,12 +1871,23 @@ static struct device_driver gfar_driver = {
static int __init gfar_init(void)
{
- return driver_register(&gfar_driver);
+ int err = gfar_mdio_init();
+
+ if (err)
+ return err;
+
+ err = driver_register(&gfar_driver);
+
+ if (err)
+ gfar_mdio_exit();
+
+ return err;
}
static void __exit gfar_exit(void)
{
driver_unregister(&gfar_driver);
+ gfar_mdio_exit();
}
module_init(gfar_init);
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 28af087d9fbba2..c77ca6c0d04a6d 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -17,7 +17,6 @@
*
* Still left to do:
* -Add support for module parameters
- * -Add support for ethtool -s
* -Add patch for ethtool phys id
*/
#ifndef __GIANFAR_H
@@ -37,7 +36,8 @@
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
-#include <linux/fsl_devices.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -48,7 +48,8 @@
#include <linux/workqueue.h>
#include <linux/ethtool.h>
#include <linux/netdevice.h>
-#include "gianfar_phy.h"
+#include <linux/fsl_devices.h>
+#include "gianfar_mii.h"
/* The maximum number of packets to be handled in one call of gfar_poll */
#define GFAR_DEV_WEIGHT 64
@@ -73,7 +74,7 @@
#define PHY_INIT_TIMEOUT 100000
#define GFAR_PHY_CHANGE_TIME 2
-#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.1, "
+#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.2, "
#define DRV_NAME "gfar-enet"
extern const char gfar_driver_name[];
extern const char gfar_driver_version[];
@@ -578,12 +579,7 @@ struct gfar {
u32 hafdup; /* 0x.50c - Half Duplex Register */
u32 maxfrm; /* 0x.510 - Maximum Frame Length Register */
u8 res18[12];
- u32 miimcfg; /* 0x.520 - MII Management Configuration Register */
- u32 miimcom; /* 0x.524 - MII Management Command Register */
- u32 miimadd; /* 0x.528 - MII Management Address Register */
- u32 miimcon; /* 0x.52c - MII Management Control Register */
- u32 miimstat; /* 0x.530 - MII Management Status Register */
- u32 miimind; /* 0x.534 - MII Management Indicator Register */
+ u8 gfar_mii_regs[24]; /* See gianfar_phy.h */
u8 res19[4];
u32 ifstat; /* 0x.53c - Interface Status Register */
u32 macstnaddr1; /* 0x.540 - Station Address Part 1 Register */
@@ -688,9 +684,6 @@ struct gfar_private {
struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */
u32 *hash_regs[16];
int hash_width;
- struct gfar *phyregs;
- struct work_struct tq;
- struct timer_list phy_info_timer;
struct net_device_stats stats; /* linux network statistics */
struct gfar_extra_stats extra_stats;
spinlock_t lock;
@@ -710,7 +703,8 @@ struct gfar_private {
unsigned int interruptError;
struct gianfar_platform_data *einfo;
- struct gfar_mii_info *mii_info;
+ struct phy_device *phydev;
+ struct mii_bus *mii_bus;
int oldspeed;
int oldduplex;
int oldlink;
@@ -732,4 +726,12 @@ extern inline void gfar_write(volatile unsigned *addr, u32 val)
extern struct ethtool_ops *gfar_op_array[];
+extern irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
+extern int startup_gfar(struct net_device *dev);
+extern void stop_gfar(struct net_device *dev);
+extern void gfar_halt(struct net_device *dev);
+extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev,
+ int enable, u32 regnum, u32 read);
+void gfar_setup_stashing(struct net_device *dev);
+
#endif /* __GIANFAR_H */
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index a451de629197b1..68e3578e76133b 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -39,17 +39,18 @@
#include <asm/types.h>
#include <asm/uaccess.h>
#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
#include "gianfar.h"
#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
-extern int startup_gfar(struct net_device *dev);
-extern void stop_gfar(struct net_device *dev);
-extern void gfar_halt(struct net_device *dev);
extern void gfar_start(struct net_device *dev);
extern int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
+#define GFAR_MAX_COAL_USECS 0xffff
+#define GFAR_MAX_COAL_FRAMES 0xff
static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
u64 * buf);
static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf);
@@ -182,38 +183,32 @@ static void gfar_gdrvinfo(struct net_device *dev, struct
drvinfo->eedump_len = 0;
}
+
+static int gfar_ssettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct phy_device *phydev = priv->phydev;
+
+ if (NULL == phydev)
+ return -ENODEV;
+
+ return phy_ethtool_sset(phydev, cmd);
+}
+
+
/* Return the current settings in the ethtool_cmd structure */
static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct gfar_private *priv = netdev_priv(dev);
- uint gigabit_support =
- priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
- SUPPORTED_1000baseT_Full : 0;
- uint gigabit_advert =
- priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
- ADVERTISED_1000baseT_Full: 0;
-
- cmd->supported = (SUPPORTED_10baseT_Half
- | SUPPORTED_100baseT_Half
- | SUPPORTED_100baseT_Full
- | gigabit_support | SUPPORTED_Autoneg);
-
- /* For now, we always advertise everything */
- cmd->advertising = (ADVERTISED_10baseT_Half
- | ADVERTISED_100baseT_Half
- | ADVERTISED_100baseT_Full
- | gigabit_advert | ADVERTISED_Autoneg);
-
- cmd->speed = priv->mii_info->speed;
- cmd->duplex = priv->mii_info->duplex;
- cmd->port = PORT_MII;
- cmd->phy_address = priv->mii_info->mii_id;
- cmd->transceiver = XCVR_EXTERNAL;
- cmd->autoneg = AUTONEG_ENABLE;
+ struct phy_device *phydev = priv->phydev;
+
+ if (NULL == phydev)
+ return -ENODEV;
+
cmd->maxtxpkt = priv->txcount;
cmd->maxrxpkt = priv->rxcount;
- return 0;
+ return phy_ethtool_gset(phydev, cmd);
}
/* Return the length of the register structure */
@@ -241,14 +236,14 @@ static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int use
unsigned int count;
/* The timer is different, depending on the interface speed */
- switch (priv->mii_info->speed) {
- case 1000:
+ switch (priv->phydev->speed) {
+ case SPEED_1000:
count = GFAR_GBIT_TIME;
break;
- case 100:
+ case SPEED_100:
count = GFAR_100_TIME;
break;
- case 10:
+ case SPEED_10:
default:
count = GFAR_10_TIME;
break;
@@ -265,14 +260,14 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic
unsigned int count;
/* The timer is different, depending on the interface speed */
- switch (priv->mii_info->speed) {
- case 1000:
+ switch (priv->phydev->speed) {
+ case SPEED_1000:
count = GFAR_GBIT_TIME;
break;
- case 100:
+ case SPEED_100:
count = GFAR_100_TIME;
break;
- case 10:
+ case SPEED_10:
default:
count = GFAR_10_TIME;
break;
@@ -292,6 +287,9 @@ static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
return -EOPNOTSUPP;
+ if (NULL == priv->phydev)
+ return -ENODEV;
+
cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime);
cvals->rx_max_coalesced_frames = priv->rxcount;
@@ -348,6 +346,22 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
else
priv->rxcoalescing = 1;
+ if (NULL == priv->phydev)
+ return -ENODEV;
+
+ /* Check the bounds of the values */
+ if (cvals->rx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
+ pr_info("Coalescing is limited to %d microseconds\n",
+ GFAR_MAX_COAL_USECS);
+ return -EINVAL;
+ }
+
+ if (cvals->rx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
+ pr_info("Coalescing is limited to %d frames\n",
+ GFAR_MAX_COAL_FRAMES);
+ return -EINVAL;
+ }
+
priv->rxtime = gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs);
priv->rxcount = cvals->rx_max_coalesced_frames;
@@ -358,6 +372,19 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
else
priv->txcoalescing = 1;
+ /* Check the bounds of the values */
+ if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
+ pr_info("Coalescing is limited to %d microseconds\n",
+ GFAR_MAX_COAL_USECS);
+ return -EINVAL;
+ }
+
+ if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
+ pr_info("Coalescing is limited to %d frames\n",
+ GFAR_MAX_COAL_FRAMES);
+ return -EINVAL;
+ }
+
priv->txtime = gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs);
priv->txcount = cvals->tx_max_coalesced_frames;
@@ -536,6 +563,7 @@ static void gfar_set_msglevel(struct net_device *dev, uint32_t data)
struct ethtool_ops gfar_ethtool_ops = {
.get_settings = gfar_gsettings,
+ .set_settings = gfar_ssettings,
.get_drvinfo = gfar_gdrvinfo,
.get_regs_len = gfar_reglen,
.get_regs = gfar_get_regs,
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
new file mode 100644
index 00000000000000..1eca1dbca7f1a1
--- /dev/null
+++ b/drivers/net/gianfar_mii.c
@@ -0,0 +1,219 @@
+/*
+ * drivers/net/gianfar_mii.c
+ *
+ * Gianfar Ethernet Driver -- MIIM bus implementation
+ * Provides Bus interface for MIIM regs
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <asm/ocp.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "gianfar.h"
+#include "gianfar_mii.h"
+
+/* Write value to the PHY at mii_id at register regnum,
+ * on the bus, waiting until the write is done before returning.
+ * All PHY configuration is done through the TSEC1 MIIM regs */
+int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
+{
+ struct gfar_mii *regs = bus->priv;
+
+ /* Set the PHY address and the register address we want to write */
+ gfar_write(&regs->miimadd, (mii_id << 8) | regnum);
+
+ /* Write out the value we want */
+ gfar_write(&regs->miimcon, value);
+
+ /* Wait for the transaction to finish */
+ while (gfar_read(&regs->miimind) & MIIMIND_BUSY)
+ cpu_relax();
+
+ return 0;
+}
+
+/* Read the bus for PHY at addr mii_id, register regnum, and
+ * return the value. Clears miimcom first. All PHY
+ * configuration has to be done through the TSEC1 MIIM regs */
+int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+ struct gfar_mii *regs = bus->priv;
+ u16 value;
+
+ /* Set the PHY address and the register address we want to read */
+ gfar_write(&regs->miimadd, (mii_id << 8) | regnum);
+
+ /* Clear miimcom, and then initiate a read */
+ gfar_write(&regs->miimcom, 0);
+ gfar_write(&regs->miimcom, MII_READ_COMMAND);
+
+ /* Wait for the transaction to finish */
+ while (gfar_read(&regs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
+ cpu_relax();
+
+ /* Grab the value of the register from miimstat */
+ value = gfar_read(&regs->miimstat);
+
+ return value;
+}
+
+
+/* Reset the MIIM registers, and wait for the bus to free */
+int gfar_mdio_reset(struct mii_bus *bus)
+{
+ struct gfar_mii *regs = bus->priv;
+ unsigned int timeout = PHY_INIT_TIMEOUT;
+
+ spin_lock_bh(&bus->mdio_lock);
+
+ /* Reset the management interface */
+ gfar_write(&regs->miimcfg, MIIMCFG_RESET);
+
+ /* Setup the MII Mgmt clock speed */
+ gfar_write(&regs->miimcfg, MIIMCFG_INIT_VALUE);
+
+ /* Wait until the bus is free */
+ while ((gfar_read(&regs->miimind) & MIIMIND_BUSY) &&
+ timeout--)
+ cpu_relax();
+
+ spin_unlock_bh(&bus->mdio_lock);
+
+ if(timeout <= 0) {
+ printk(KERN_ERR "%s: The MII Bus is stuck!\n",
+ bus->name);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+
+int gfar_mdio_probe(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct gianfar_mdio_data *pdata;
+ struct gfar_mii *regs;
+ struct mii_bus *new_bus;
+ int err = 0;
+
+ if (NULL == dev)
+ return -EINVAL;
+
+ new_bus = kmalloc(sizeof(struct mii_bus), GFP_KERNEL);
+
+ if (NULL == new_bus)
+ return -ENOMEM;
+
+ new_bus->name = "Gianfar MII Bus",
+ new_bus->read = &gfar_mdio_read,
+ new_bus->write = &gfar_mdio_write,
+ new_bus->reset = &gfar_mdio_reset,
+ new_bus->id = pdev->id;
+
+ pdata = (struct gianfar_mdio_data *)pdev->dev.platform_data;
+
+ if (NULL == pdata) {
+ printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id);
+ return -ENODEV;
+ }
+
+ /* Set the PHY base address */
+ regs = (struct gfar_mii *) ioremap(pdata->paddr,
+ sizeof (struct gfar_mii));
+
+ if (NULL == regs) {
+ err = -ENOMEM;
+ goto reg_map_fail;
+ }
+
+ new_bus->priv = regs;
+
+ new_bus->irq = pdata->irq;
+
+ new_bus->dev = dev;
+ dev_set_drvdata(dev, new_bus);
+
+ err = mdiobus_register(new_bus);
+
+ if (0 != err) {
+ printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
+ new_bus->name);
+ goto bus_register_fail;
+ }
+
+ return 0;
+
+bus_register_fail:
+ iounmap((void *) regs);
+reg_map_fail:
+ kfree(new_bus);
+
+ return err;
+}
+
+
+int gfar_mdio_remove(struct device *dev)
+{
+ struct mii_bus *bus = dev_get_drvdata(dev);
+
+ mdiobus_unregister(bus);
+
+ dev_set_drvdata(dev, NULL);
+
+ iounmap((void *) (&bus->priv));
+ bus->priv = NULL;
+ kfree(bus);
+
+ return 0;
+}
+
+static struct device_driver gianfar_mdio_driver = {
+ .name = "fsl-gianfar_mdio",
+ .bus = &platform_bus_type,
+ .probe = gfar_mdio_probe,
+ .remove = gfar_mdio_remove,
+};
+
+int __init gfar_mdio_init(void)
+{
+ return driver_register(&gianfar_mdio_driver);
+}
+
+void __exit gfar_mdio_exit(void)
+{
+ driver_unregister(&gianfar_mdio_driver);
+}
diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h
new file mode 100644
index 00000000000000..56e5665d5c9b8e
--- /dev/null
+++ b/drivers/net/gianfar_mii.h
@@ -0,0 +1,45 @@
+/*
+ * drivers/net/gianfar_mii.h
+ *
+ * Gianfar Ethernet Driver -- MII Management Bus Implementation
+ * Driver for the MDIO bus controller in the Gianfar register space
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ */
+#ifndef __GIANFAR_MII_H
+#define __GIANFAR_MII_H
+
+#define MIIMIND_BUSY 0x00000001
+#define MIIMIND_NOTVALID 0x00000004
+
+#define MII_READ_COMMAND 0x00000001
+
+#define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \
+ | SUPPORTED_100baseT_Half \
+ | SUPPORTED_100baseT_Full \
+ | SUPPORTED_Autoneg \
+ | SUPPORTED_MII)
+
+struct gfar_mii {
+ u32 miimcfg; /* 0x.520 - MII Management Config Register */
+ u32 miimcom; /* 0x.524 - MII Management Command Register */
+ u32 miimadd; /* 0x.528 - MII Management Address Register */
+ u32 miimcon; /* 0x.52c - MII Management Control Register */
+ u32 miimstat; /* 0x.530 - MII Management Status Register */
+ u32 miimind; /* 0x.534 - MII Management Indicator Register */
+};
+
+int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum);
+int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
+int __init gfar_mdio_init(void);
+void __exit gfar_mdio_exit(void);
+#endif /* GIANFAR_PHY_H */
diff --git a/drivers/net/gianfar_phy.c b/drivers/net/gianfar_phy.c
deleted file mode 100644
index 7c965f268a824a..00000000000000
--- a/drivers/net/gianfar_phy.c
+++ /dev/null
@@ -1,661 +0,0 @@
-/*
- * drivers/net/gianfar_phy.c
- *
- * Gianfar Ethernet Driver -- PHY handling
- * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
- * Based on 8260_io/fcc_enet.c
- *
- * Author: Andy Fleming
- * Maintainer: Kumar Gala (kumar.gala@freescale.com)
- *
- * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
- *
- * 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.
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/crc32.h>
-#include <linux/mii.h>
-
-#include "gianfar.h"
-#include "gianfar_phy.h"
-
-static void config_genmii_advert(struct gfar_mii_info *mii_info);
-static void genmii_setup_forced(struct gfar_mii_info *mii_info);
-static void genmii_restart_aneg(struct gfar_mii_info *mii_info);
-static int gbit_config_aneg(struct gfar_mii_info *mii_info);
-static int genmii_config_aneg(struct gfar_mii_info *mii_info);
-static int genmii_update_link(struct gfar_mii_info *mii_info);
-static int genmii_read_status(struct gfar_mii_info *mii_info);
-u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum);
-void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val);
-
-/* Write value to the PHY for this device to the register at regnum, */
-/* waiting until the write is done before it returns. All PHY */
-/* configuration has to be done through the TSEC1 MIIM regs */
-void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value)
-{
- struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regbase = priv->phyregs;
-
- /* Set the PHY address and the register address we want to write */
- gfar_write(&regbase->miimadd, (mii_id << 8) | regnum);
-
- /* Write out the value we want */
- gfar_write(&regbase->miimcon, value);
-
- /* Wait for the transaction to finish */
- while (gfar_read(&regbase->miimind) & MIIMIND_BUSY)
- cpu_relax();
-}
-
-/* Reads from register regnum in the PHY for device dev, */
-/* returning the value. Clears miimcom first. All PHY */
-/* configuration has to be done through the TSEC1 MIIM regs */
-int read_phy_reg(struct net_device *dev, int mii_id, int regnum)
-{
- struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regbase = priv->phyregs;
- u16 value;
-
- /* Set the PHY address and the register address we want to read */
- gfar_write(&regbase->miimadd, (mii_id << 8) | regnum);
-
- /* Clear miimcom, and then initiate a read */
- gfar_write(&regbase->miimcom, 0);
- gfar_write(&regbase->miimcom, MII_READ_COMMAND);
-
- /* Wait for the transaction to finish */
- while (gfar_read(&regbase->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
- cpu_relax();
-
- /* Grab the value of the register from miimstat */
- value = gfar_read(&regbase->miimstat);
-
- return value;
-}
-
-void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info)
-{
- if(mii_info->phyinfo->ack_interrupt)
- mii_info->phyinfo->ack_interrupt(mii_info);
-}
-
-
-void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts)
-{
- mii_info->interrupts = interrupts;
- if(mii_info->phyinfo->config_intr)
- mii_info->phyinfo->config_intr(mii_info);
-}
-
-
-/* Writes MII_ADVERTISE with the appropriate values, after
- * sanitizing advertise to make sure only supported features
- * are advertised
- */
-static void config_genmii_advert(struct gfar_mii_info *mii_info)
-{
- u32 advertise;
- u16 adv;
-
- /* Only allow advertising what this PHY supports */
- mii_info->advertising &= mii_info->phyinfo->features;
- advertise = mii_info->advertising;
-
- /* Setup standard advertisement */
- adv = phy_read(mii_info, MII_ADVERTISE);
- adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
- if (advertise & ADVERTISED_10baseT_Half)
- adv |= ADVERTISE_10HALF;
- if (advertise & ADVERTISED_10baseT_Full)
- adv |= ADVERTISE_10FULL;
- if (advertise & ADVERTISED_100baseT_Half)
- adv |= ADVERTISE_100HALF;
- if (advertise & ADVERTISED_100baseT_Full)
- adv |= ADVERTISE_100FULL;
- phy_write(mii_info, MII_ADVERTISE, adv);
-}
-
-static void genmii_setup_forced(struct gfar_mii_info *mii_info)
-{
- u16 ctrl;
- u32 features = mii_info->phyinfo->features;
-
- ctrl = phy_read(mii_info, MII_BMCR);
-
- ctrl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPEED1000|BMCR_ANENABLE);
- ctrl |= BMCR_RESET;
-
- switch(mii_info->speed) {
- case SPEED_1000:
- if(features & (SUPPORTED_1000baseT_Half
- | SUPPORTED_1000baseT_Full)) {
- ctrl |= BMCR_SPEED1000;
- break;
- }
- mii_info->speed = SPEED_100;
- case SPEED_100:
- if (features & (SUPPORTED_100baseT_Half
- | SUPPORTED_100baseT_Full)) {
- ctrl |= BMCR_SPEED100;
- break;
- }
- mii_info->speed = SPEED_10;
- case SPEED_10:
- if (features & (SUPPORTED_10baseT_Half
- | SUPPORTED_10baseT_Full))
- break;
- default: /* Unsupported speed! */
- printk(KERN_ERR "%s: Bad speed!\n",
- mii_info->dev->name);
- break;
- }
-
- phy_write(mii_info, MII_BMCR, ctrl);
-}
-
-
-/* Enable and Restart Autonegotiation */
-static void genmii_restart_aneg(struct gfar_mii_info *mii_info)
-{
- u16 ctl;
-
- ctl = phy_read(mii_info, MII_BMCR);
- ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
- phy_write(mii_info, MII_BMCR, ctl);
-}
-
-
-static int gbit_config_aneg(struct gfar_mii_info *mii_info)
-{
- u16 adv;
- u32 advertise;
-
- if(mii_info->autoneg) {
- /* Configure the ADVERTISE register */
- config_genmii_advert(mii_info);
- advertise = mii_info->advertising;
-
- adv = phy_read(mii_info, MII_1000BASETCONTROL);
- adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
- MII_1000BASETCONTROL_HALFDUPLEXCAP);
- if (advertise & SUPPORTED_1000baseT_Half)
- adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
- if (advertise & SUPPORTED_1000baseT_Full)
- adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
- phy_write(mii_info, MII_1000BASETCONTROL, adv);
-
- /* Start/Restart aneg */
- genmii_restart_aneg(mii_info);
- } else
- genmii_setup_forced(mii_info);
-
- return 0;
-}
-
-static int marvell_config_aneg(struct gfar_mii_info *mii_info)
-{
- /* The Marvell PHY has an errata which requires
- * that certain registers get written in order
- * to restart autonegotiation */
- phy_write(mii_info, MII_BMCR, BMCR_RESET);
-
- phy_write(mii_info, 0x1d, 0x1f);
- phy_write(mii_info, 0x1e, 0x200c);
- phy_write(mii_info, 0x1d, 0x5);
- phy_write(mii_info, 0x1e, 0);
- phy_write(mii_info, 0x1e, 0x100);
-
- gbit_config_aneg(mii_info);
-
- return 0;
-}
-static int genmii_config_aneg(struct gfar_mii_info *mii_info)
-{
- if (mii_info->autoneg) {
- config_genmii_advert(mii_info);
- genmii_restart_aneg(mii_info);
- } else
- genmii_setup_forced(mii_info);
-
- return 0;
-}
-
-
-static int genmii_update_link(struct gfar_mii_info *mii_info)
-{
- u16 status;
-
- /* Do a fake read */
- phy_read(mii_info, MII_BMSR);
-
- /* Read link and autonegotiation status */
- status = phy_read(mii_info, MII_BMSR);
- if ((status & BMSR_LSTATUS) == 0)
- mii_info->link = 0;
- else
- mii_info->link = 1;
-
- /* If we are autonegotiating, and not done,
- * return an error */
- if (mii_info->autoneg && !(status & BMSR_ANEGCOMPLETE))
- return -EAGAIN;
-
- return 0;
-}
-
-static int genmii_read_status(struct gfar_mii_info *mii_info)
-{
- u16 status;
- int err;
-
- /* Update the link, but return if there
- * was an error */
- err = genmii_update_link(mii_info);
- if (err)
- return err;
-
- if (mii_info->autoneg) {
- status = phy_read(mii_info, MII_LPA);
-
- if (status & (LPA_10FULL | LPA_100FULL))
- mii_info->duplex = DUPLEX_FULL;
- else
- mii_info->duplex = DUPLEX_HALF;
- if (status & (LPA_100FULL | LPA_100HALF))
- mii_info->speed = SPEED_100;
- else
- mii_info->speed = SPEED_10;
- mii_info->pause = 0;
- }
- /* On non-aneg, we assume what we put in BMCR is the speed,
- * though magic-aneg shouldn't prevent this case from occurring
- */
-
- return 0;
-}
-static int marvell_read_status(struct gfar_mii_info *mii_info)
-{
- u16 status;
- int err;
-
- /* Update the link, but return if there
- * was an error */
- err = genmii_update_link(mii_info);
- if (err)
- return err;
-
- /* If the link is up, read the speed and duplex */
- /* If we aren't autonegotiating, assume speeds
- * are as set */
- if (mii_info->autoneg && mii_info->link) {
- int speed;
- status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
-
-#if 0
- /* If speed and duplex aren't resolved,
- * return an error. Isn't this handled
- * by checking aneg?
- */
- if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
- return -EAGAIN;
-#endif
-
- /* Get the duplexity */
- if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
- mii_info->duplex = DUPLEX_FULL;
- else
- mii_info->duplex = DUPLEX_HALF;
-
- /* Get the speed */
- speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK;
- switch(speed) {
- case MII_M1011_PHY_SPEC_STATUS_1000:
- mii_info->speed = SPEED_1000;
- break;
- case MII_M1011_PHY_SPEC_STATUS_100:
- mii_info->speed = SPEED_100;
- break;
- default:
- mii_info->speed = SPEED_10;
- break;
- }
- mii_info->pause = 0;
- }
-
- return 0;
-}
-
-
-static int cis820x_read_status(struct gfar_mii_info *mii_info)
-{
- u16 status;
- int err;
-
- /* Update the link, but return if there
- * was an error */
- err = genmii_update_link(mii_info);
- if (err)
- return err;
-
- /* If the link is up, read the speed and duplex */
- /* If we aren't autonegotiating, assume speeds
- * are as set */
- if (mii_info->autoneg && mii_info->link) {
- int speed;
-
- status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT);
- if (status & MII_CIS8201_AUXCONSTAT_DUPLEX)
- mii_info->duplex = DUPLEX_FULL;
- else
- mii_info->duplex = DUPLEX_HALF;
-
- speed = status & MII_CIS8201_AUXCONSTAT_SPEED;
-
- switch (speed) {
- case MII_CIS8201_AUXCONSTAT_GBIT:
- mii_info->speed = SPEED_1000;
- break;
- case MII_CIS8201_AUXCONSTAT_100:
- mii_info->speed = SPEED_100;
- break;
- default:
- mii_info->speed = SPEED_10;
- break;
- }
- }
-
- return 0;
-}
-
-static int marvell_ack_interrupt(struct gfar_mii_info *mii_info)
-{
- /* Clear the interrupts by reading the reg */
- phy_read(mii_info, MII_M1011_IEVENT);
-
- return 0;
-}
-
-static int marvell_config_intr(struct gfar_mii_info *mii_info)
-{
- if(mii_info->interrupts == MII_INTERRUPT_ENABLED)
- phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
- else
- phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
-
- return 0;
-}
-
-static int cis820x_init(struct gfar_mii_info *mii_info)
-{
- phy_write(mii_info, MII_CIS8201_AUX_CONSTAT,
- MII_CIS8201_AUXCONSTAT_INIT);
- phy_write(mii_info, MII_CIS8201_EXT_CON1,
- MII_CIS8201_EXTCON1_INIT);
-
- return 0;
-}
-
-static int cis820x_ack_interrupt(struct gfar_mii_info *mii_info)
-{
- phy_read(mii_info, MII_CIS8201_ISTAT);
-
- return 0;
-}
-
-static int cis820x_config_intr(struct gfar_mii_info *mii_info)
-{
- if(mii_info->interrupts == MII_INTERRUPT_ENABLED)
- phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK);
- else
- phy_write(mii_info, MII_CIS8201_IMASK, 0);
-
- return 0;
-}
-
-#define DM9161_DELAY 10
-
-static int dm9161_read_status(struct gfar_mii_info *mii_info)
-{
- u16 status;
- int err;
-
- /* Update the link, but return if there
- * was an error */
- err = genmii_update_link(mii_info);
- if (err)
- return err;
-
- /* If the link is up, read the speed and duplex */
- /* If we aren't autonegotiating, assume speeds
- * are as set */
- if (mii_info->autoneg && mii_info->link) {
- status = phy_read(mii_info, MII_DM9161_SCSR);
- if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
- mii_info->speed = SPEED_100;
- else
- mii_info->speed = SPEED_10;
-
- if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F))
- mii_info->duplex = DUPLEX_FULL;
- else
- mii_info->duplex = DUPLEX_HALF;
- }
-
- return 0;
-}
-
-
-static int dm9161_config_aneg(struct gfar_mii_info *mii_info)
-{
- struct dm9161_private *priv = mii_info->priv;
-
- if(0 == priv->resetdone)
- return -EAGAIN;
-
- return 0;
-}
-
-static void dm9161_timer(unsigned long data)
-{
- struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data;
- struct dm9161_private *priv = mii_info->priv;
- u16 status = phy_read(mii_info, MII_BMSR);
-
- if (status & BMSR_ANEGCOMPLETE) {
- priv->resetdone = 1;
- } else
- mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
-}
-
-static int dm9161_init(struct gfar_mii_info *mii_info)
-{
- struct dm9161_private *priv;
-
- /* Allocate the private data structure */
- priv = kmalloc(sizeof(struct dm9161_private), GFP_KERNEL);
-
- if (NULL == priv)
- return -ENOMEM;
-
- mii_info->priv = priv;
-
- /* Reset is not done yet */
- priv->resetdone = 0;
-
- /* Isolate the PHY */
- phy_write(mii_info, MII_BMCR, BMCR_ISOLATE);
-
- /* Do not bypass the scrambler/descrambler */
- phy_write(mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
-
- /* Clear 10BTCSR to default */
- phy_write(mii_info, MII_DM9161_10BTCSR, MII_DM9161_10BTCSR_INIT);
-
- /* Reconnect the PHY, and enable Autonegotiation */
- phy_write(mii_info, MII_BMCR, BMCR_ANENABLE);
-
- /* Start a timer for DM9161_DELAY seconds to wait
- * for the PHY to be ready */
- init_timer(&priv->timer);
- priv->timer.function = &dm9161_timer;
- priv->timer.data = (unsigned long) mii_info;
- mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
-
- return 0;
-}
-
-static void dm9161_close(struct gfar_mii_info *mii_info)
-{
- struct dm9161_private *priv = mii_info->priv;
-
- del_timer_sync(&priv->timer);
- kfree(priv);
-}
-
-#if 0
-static int dm9161_ack_interrupt(struct gfar_mii_info *mii_info)
-{
- phy_read(mii_info, MII_DM9161_INTR);
-
- return 0;
-}
-#endif
-
-/* Cicada 820x */
-static struct phy_info phy_info_cis820x = {
- 0x000fc440,
- "Cicada Cis8204",
- 0x000fffc0,
- .features = MII_GBIT_FEATURES,
- .init = &cis820x_init,
- .config_aneg = &gbit_config_aneg,
- .read_status = &cis820x_read_status,
- .ack_interrupt = &cis820x_ack_interrupt,
- .config_intr = &cis820x_config_intr,
-};
-
-static struct phy_info phy_info_dm9161 = {
- .phy_id = 0x0181b880,
- .name = "Davicom DM9161E",
- .phy_id_mask = 0x0ffffff0,
- .init = dm9161_init,
- .config_aneg = dm9161_config_aneg,
- .read_status = dm9161_read_status,
- .close = dm9161_close,
-};
-
-static struct phy_info phy_info_marvell = {
- .phy_id = 0x01410c00,
- .phy_id_mask = 0xffffff00,
- .name = "Marvell 88E1101/88E1111",
- .features = MII_GBIT_FEATURES,
- .config_aneg = &marvell_config_aneg,
- .read_status = &marvell_read_status,
- .ack_interrupt = &marvell_ack_interrupt,
- .config_intr = &marvell_config_intr,
-};
-
-static struct phy_info phy_info_genmii= {
- .phy_id = 0x00000000,
- .phy_id_mask = 0x00000000,
- .name = "Generic MII",
- .features = MII_BASIC_FEATURES,
- .config_aneg = genmii_config_aneg,
- .read_status = genmii_read_status,
-};
-
-static struct phy_info *phy_info[] = {
- &phy_info_cis820x,
- &phy_info_marvell,
- &phy_info_dm9161,
- &phy_info_genmii,
- NULL
-};
-
-u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum)
-{
- u16 retval;
- unsigned long flags;
-
- spin_lock_irqsave(&mii_info->mdio_lock, flags);
- retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
- spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
-
- return retval;
-}
-
-void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&mii_info->mdio_lock, flags);
- mii_info->mdio_write(mii_info->dev,
- mii_info->mii_id,
- regnum, val);
- spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
-}
-
-/* Use the PHY ID registers to determine what type of PHY is attached
- * to device dev. return a struct phy_info structure describing that PHY
- */
-struct phy_info * get_phy_info(struct gfar_mii_info *mii_info)
-{
- u16 phy_reg;
- u32 phy_ID;
- int i;
- struct phy_info *theInfo = NULL;
- struct net_device *dev = mii_info->dev;
-
- /* Grab the bits from PHYIR1, and put them in the upper half */
- phy_reg = phy_read(mii_info, MII_PHYSID1);
- phy_ID = (phy_reg & 0xffff) << 16;
-
- /* Grab the bits from PHYIR2, and put them in the lower half */
- phy_reg = phy_read(mii_info, MII_PHYSID2);
- phy_ID |= (phy_reg & 0xffff);
-
- /* loop through all the known PHY types, and find one that */
- /* matches the ID we read from the PHY. */
- for (i = 0; phy_info[i]; i++)
- if (phy_info[i]->phy_id ==
- (phy_ID & phy_info[i]->phy_id_mask)) {
- theInfo = phy_info[i];
- break;
- }
-
- /* This shouldn't happen, as we have generic PHY support */
- if (theInfo == NULL) {
- printk("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
- return NULL;
- } else {
- printk("%s: PHY is %s (%x)\n", dev->name, theInfo->name,
- phy_ID);
- }
-
- return theInfo;
-}
diff --git a/drivers/net/gianfar_phy.h b/drivers/net/gianfar_phy.h
deleted file mode 100644
index 1e9b3abf1e6d71..00000000000000
--- a/drivers/net/gianfar_phy.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * drivers/net/gianfar_phy.h
- *
- * Gianfar Ethernet Driver -- PHY handling
- * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
- * Based on 8260_io/fcc_enet.c
- *
- * Author: Andy Fleming
- * Maintainer: Kumar Gala (kumar.gala@freescale.com)
- *
- * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
- *
- * 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.
- *
- */
-#ifndef __GIANFAR_PHY_H
-#define __GIANFAR_PHY_H
-
-#define MII_end ((u32)-2)
-#define MII_read ((u32)-1)
-
-#define MIIMIND_BUSY 0x00000001
-#define MIIMIND_NOTVALID 0x00000004
-
-#define GFAR_AN_TIMEOUT 2000
-
-/* 1000BT control (Marvell & BCM54xx at least) */
-#define MII_1000BASETCONTROL 0x09
-#define MII_1000BASETCONTROL_FULLDUPLEXCAP 0x0200
-#define MII_1000BASETCONTROL_HALFDUPLEXCAP 0x0100
-
-/* Cicada Extended Control Register 1 */
-#define MII_CIS8201_EXT_CON1 0x17
-#define MII_CIS8201_EXTCON1_INIT 0x0000
-
-/* Cicada Interrupt Mask Register */
-#define MII_CIS8201_IMASK 0x19
-#define MII_CIS8201_IMASK_IEN 0x8000
-#define MII_CIS8201_IMASK_SPEED 0x4000
-#define MII_CIS8201_IMASK_LINK 0x2000
-#define MII_CIS8201_IMASK_DUPLEX 0x1000
-#define MII_CIS8201_IMASK_MASK 0xf000
-
-/* Cicada Interrupt Status Register */
-#define MII_CIS8201_ISTAT 0x1a
-#define MII_CIS8201_ISTAT_STATUS 0x8000
-#define MII_CIS8201_ISTAT_SPEED 0x4000
-#define MII_CIS8201_ISTAT_LINK 0x2000
-#define MII_CIS8201_ISTAT_DUPLEX 0x1000
-
-/* Cicada Auxiliary Control/Status Register */
-#define MII_CIS8201_AUX_CONSTAT 0x1c
-#define MII_CIS8201_AUXCONSTAT_INIT 0x0004
-#define MII_CIS8201_AUXCONSTAT_DUPLEX 0x0020
-#define MII_CIS8201_AUXCONSTAT_SPEED 0x0018
-#define MII_CIS8201_AUXCONSTAT_GBIT 0x0010
-#define MII_CIS8201_AUXCONSTAT_100 0x0008
-
-/* 88E1011 PHY Status Register */
-#define MII_M1011_PHY_SPEC_STATUS 0x11
-#define MII_M1011_PHY_SPEC_STATUS_1000 0x8000
-#define MII_M1011_PHY_SPEC_STATUS_100 0x4000
-#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK 0xc000
-#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX 0x2000
-#define MII_M1011_PHY_SPEC_STATUS_RESOLVED 0x0800
-#define MII_M1011_PHY_SPEC_STATUS_LINK 0x0400
-
-#define MII_M1011_IEVENT 0x13
-#define MII_M1011_IEVENT_CLEAR 0x0000
-
-#define MII_M1011_IMASK 0x12
-#define MII_M1011_IMASK_INIT 0x6400
-#define MII_M1011_IMASK_CLEAR 0x0000
-
-#define MII_DM9161_SCR 0x10
-#define MII_DM9161_SCR_INIT 0x0610
-
-/* DM9161 Specified Configuration and Status Register */
-#define MII_DM9161_SCSR 0x11
-#define MII_DM9161_SCSR_100F 0x8000
-#define MII_DM9161_SCSR_100H 0x4000
-#define MII_DM9161_SCSR_10F 0x2000
-#define MII_DM9161_SCSR_10H 0x1000
-
-/* DM9161 Interrupt Register */
-#define MII_DM9161_INTR 0x15
-#define MII_DM9161_INTR_PEND 0x8000
-#define MII_DM9161_INTR_DPLX_MASK 0x0800
-#define MII_DM9161_INTR_SPD_MASK 0x0400
-#define MII_DM9161_INTR_LINK_MASK 0x0200
-#define MII_DM9161_INTR_MASK 0x0100
-#define MII_DM9161_INTR_DPLX_CHANGE 0x0010
-#define MII_DM9161_INTR_SPD_CHANGE 0x0008
-#define MII_DM9161_INTR_LINK_CHANGE 0x0004
-#define MII_DM9161_INTR_INIT 0x0000
-#define MII_DM9161_INTR_STOP \
-(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
- | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
-
-/* DM9161 10BT Configuration/Status */
-#define MII_DM9161_10BTCSR 0x12
-#define MII_DM9161_10BTCSR_INIT 0x7800
-
-#define MII_BASIC_FEATURES (SUPPORTED_10baseT_Half | \
- SUPPORTED_10baseT_Full | \
- SUPPORTED_100baseT_Half | \
- SUPPORTED_100baseT_Full | \
- SUPPORTED_Autoneg | \
- SUPPORTED_TP | \
- SUPPORTED_MII)
-
-#define MII_GBIT_FEATURES (MII_BASIC_FEATURES | \
- SUPPORTED_1000baseT_Half | \
- SUPPORTED_1000baseT_Full)
-
-#define MII_READ_COMMAND 0x00000001
-
-#define MII_INTERRUPT_DISABLED 0x0
-#define MII_INTERRUPT_ENABLED 0x1
-/* Taken from mii_if_info and sungem_phy.h */
-struct gfar_mii_info {
- /* Information about the PHY type */
- /* And management functions */
- struct phy_info *phyinfo;
-
- /* forced speed & duplex (no autoneg)
- * partner speed & duplex & pause (autoneg)
- */
- int speed;
- int duplex;
- int pause;
-
- /* The most recently read link state */
- int link;
-
- /* Enabled Interrupts */
- u32 interrupts;
-
- u32 advertising;
- int autoneg;
- int mii_id;
-
- /* private data pointer */
- /* For use by PHYs to maintain extra state */
- void *priv;
-
- /* Provided by host chip */
- struct net_device *dev;
-
- /* A lock to ensure that only one thing can read/write
- * the MDIO bus at a time */
- spinlock_t mdio_lock;
-
- /* Provided by ethernet driver */
- int (*mdio_read) (struct net_device *dev, int mii_id, int reg);
- void (*mdio_write) (struct net_device *dev, int mii_id, int reg, int val);
-};
-
-/* struct phy_info: a structure which defines attributes for a PHY
- *
- * id will contain a number which represents the PHY. During
- * startup, the driver will poll the PHY to find out what its
- * UID--as defined by registers 2 and 3--is. The 32-bit result
- * gotten from the PHY will be ANDed with phy_id_mask to
- * discard any bits which may change based on revision numbers
- * unimportant to functionality
- *
- * There are 6 commands which take a gfar_mii_info structure.
- * Each PHY must declare config_aneg, and read_status.
- */
-struct phy_info {
- u32 phy_id;
- char *name;
- unsigned int phy_id_mask;
- u32 features;
-
- /* Called to initialize the PHY */
- int (*init)(struct gfar_mii_info *mii_info);
-
- /* Called to suspend the PHY for power */
- int (*suspend)(struct gfar_mii_info *mii_info);
-
- /* Reconfigures autonegotiation (or disables it) */
- int (*config_aneg)(struct gfar_mii_info *mii_info);
-
- /* Determines the negotiated speed and duplex */
- int (*read_status)(struct gfar_mii_info *mii_info);
-
- /* Clears any pending interrupts */
- int (*ack_interrupt)(struct gfar_mii_info *mii_info);
-
- /* Enables or disables interrupts */
- int (*config_intr)(struct gfar_mii_info *mii_info);
-
- /* Clears up any memory if needed */
- void (*close)(struct gfar_mii_info *mii_info);
-};
-
-struct phy_info *get_phy_info(struct gfar_mii_info *mii_info);
-int read_phy_reg(struct net_device *dev, int mii_id, int regnum);
-void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value);
-void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info);
-void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts);
-
-struct dm9161_private {
- struct timer_list timer;
- int resetdone;
-};
-
-#endif /* GIANFAR_PHY_H */
diff --git a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig
index de087cd609d98f..896aa02000d730 100644
--- a/drivers/net/hamradio/Kconfig
+++ b/drivers/net/hamradio/Kconfig
@@ -1,6 +1,7 @@
config MKISS
tristate "Serial port KISS driver"
depends on AX25
+ select CRC16
---help---
KISS is a protocol used for the exchange of data between a computer
and a Terminal Node Controller (a small embedded system commonly
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 1756f0ed54ccc7..cb43a9d28774fa 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -144,7 +144,7 @@ static inline struct net_device *bpq_get_ax25_dev(struct net_device *dev)
{
struct bpqdev *bpq;
- list_for_each_entry(bpq, &bpq_devices, bpq_list) {
+ list_for_each_entry_rcu(bpq, &bpq_devices, bpq_list) {
if (bpq->ethdev == dev)
return bpq->axdev;
}
@@ -399,7 +399,7 @@ static void *bpq_seq_start(struct seq_file *seq, loff_t *pos)
if (*pos == 0)
return SEQ_START_TOKEN;
- list_for_each_entry(bpqdev, &bpq_devices, bpq_list) {
+ list_for_each_entry_rcu(bpqdev, &bpq_devices, bpq_list) {
if (i == *pos)
return bpqdev;
}
@@ -418,7 +418,7 @@ static void *bpq_seq_next(struct seq_file *seq, void *v, loff_t *pos)
p = ((struct bpqdev *)v)->bpq_list.next;
return (p == &bpq_devices) ? NULL
- : list_entry(p, struct bpqdev, bpq_list);
+ : rcu_dereference(list_entry(p, struct bpqdev, bpq_list));
}
static void bpq_seq_stop(struct seq_file *seq, void *v)
@@ -561,8 +561,6 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi
if (!dev_is_ethdev(dev))
return NOTIFY_DONE;
- rcu_read_lock();
-
switch (event) {
case NETDEV_UP: /* new ethernet device -> new BPQ interface */
if (bpq_get_ax25_dev(dev) == NULL)
@@ -581,7 +579,6 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi
default:
break;
}
- rcu_read_unlock();
return NOTIFY_DONE;
}
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index d9fe64b46f4bf4..85d6dc005be0f0 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -14,13 +14,14 @@
*
* Copyright (C) Hans Alblas PE1AYX <hans@esrac.ele.tue.nl>
* Copyright (C) 2004, 05 Ralf Baechle DL5RB <ralf@linux-mips.org>
+ * Copyright (C) 2004, 05 Thomas Osterried DL9SAU <thomas@x-berg.in-berlin.de>
*/
-
#include <linux/config.h>
#include <linux/module.h>
#include <asm/system.h>
#include <linux/bitops.h>
#include <asm/uaccess.h>
+#include <linux/crc16.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
@@ -39,11 +40,6 @@
#include <net/ax25.h>
-#ifdef CONFIG_INET
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#endif
-
#define AX_MTU 236
/* SLIP/KISS protocol characters. */
@@ -80,9 +76,13 @@ struct mkiss {
int mode;
int crcmode; /* MW: for FlexNet, SMACK etc. */
-#define CRC_MODE_NONE 0
-#define CRC_MODE_FLEX 1
-#define CRC_MODE_SMACK 2
+ int crcauto; /* CRC auto mode */
+
+#define CRC_MODE_NONE 0
+#define CRC_MODE_FLEX 1
+#define CRC_MODE_SMACK 2
+#define CRC_MODE_FLEX_TEST 3
+#define CRC_MODE_SMACK_TEST 4
atomic_t refcnt;
struct semaphore dead_sem;
@@ -151,6 +151,21 @@ static int check_crc_flex(unsigned char *cp, int size)
return 0;
}
+static int check_crc_16(unsigned char *cp, int size)
+{
+ unsigned short crc = 0x0000;
+
+ if (size < 3)
+ return -1;
+
+ crc = crc16(0, cp, size);
+
+ if (crc != 0x0000)
+ return -1;
+
+ return 0;
+}
+
/*
* Standard encapsulation
*/
@@ -237,19 +252,42 @@ static void ax_bump(struct mkiss *ax)
spin_lock_bh(&ax->buflock);
if (ax->rbuff[0] > 0x0f) {
- if (ax->rbuff[0] & 0x20) {
- ax->crcmode = CRC_MODE_FLEX;
+ if (ax->rbuff[0] & 0x80) {
+ if (check_crc_16(ax->rbuff, ax->rcount) < 0) {
+ ax->stats.rx_errors++;
+ spin_unlock_bh(&ax->buflock);
+
+ return;
+ }
+ if (ax->crcmode != CRC_MODE_SMACK && ax->crcauto) {
+ printk(KERN_INFO
+ "mkiss: %s: Switchting to crc-smack\n",
+ ax->dev->name);
+ ax->crcmode = CRC_MODE_SMACK;
+ }
+ ax->rcount -= 2;
+ *ax->rbuff &= ~0x80;
+ } else if (ax->rbuff[0] & 0x20) {
if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
- ax->stats.rx_errors++;
+ ax->stats.rx_errors++;
+ spin_unlock_bh(&ax->buflock);
return;
}
+ if (ax->crcmode != CRC_MODE_FLEX && ax->crcauto) {
+ printk(KERN_INFO
+ "mkiss: %s: Switchting to crc-flexnet\n",
+ ax->dev->name);
+ ax->crcmode = CRC_MODE_FLEX;
+ }
ax->rcount -= 2;
- /* dl9sau bugfix: the trailling two bytes flexnet crc
- * will not be passed to the kernel. thus we have
- * to correct the kissparm signature, because it
- * indicates a crc but there's none
+
+ /*
+ * dl9sau bugfix: the trailling two bytes flexnet crc
+ * will not be passed to the kernel. thus we have to
+ * correct the kissparm signature, because it indicates
+ * a crc but there's none
*/
- *ax->rbuff &= ~0x20;
+ *ax->rbuff &= ~0x20;
}
}
spin_unlock_bh(&ax->buflock);
@@ -417,20 +455,69 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
p = icp;
spin_lock_bh(&ax->buflock);
- switch (ax->crcmode) {
- unsigned short crc;
+ if ((*p & 0x0f) != 0) {
+ /* Configuration Command (kissparms(1).
+ * Protocol spec says: never append CRC.
+ * This fixes a very old bug in the linux
+ * kiss driver. -- dl9sau */
+ switch (*p & 0xff) {
+ case 0x85:
+ /* command from userspace especially for us,
+ * not for delivery to the tnc */
+ if (len > 1) {
+ int cmd = (p[1] & 0xff);
+ switch(cmd) {
+ case 3:
+ ax->crcmode = CRC_MODE_SMACK;
+ break;
+ case 2:
+ ax->crcmode = CRC_MODE_FLEX;
+ break;
+ case 1:
+ ax->crcmode = CRC_MODE_NONE;
+ break;
+ case 0:
+ default:
+ ax->crcmode = CRC_MODE_SMACK_TEST;
+ cmd = 0;
+ }
+ ax->crcauto = (cmd ? 0 : 1);
+ printk(KERN_INFO "mkiss: %s: crc mode %s %d\n", ax->dev->name, (len) ? "set to" : "is", cmd);
+ }
+ spin_unlock_bh(&ax->buflock);
+ netif_start_queue(dev);
- case CRC_MODE_FLEX:
- *p |= 0x20;
- crc = calc_crc_flex(p, len);
- count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
- break;
+ return;
+ default:
+ count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
+ }
+ } else {
+ unsigned short crc;
+ switch (ax->crcmode) {
+ case CRC_MODE_SMACK_TEST:
+ ax->crcmode = CRC_MODE_FLEX_TEST;
+ printk(KERN_INFO "mkiss: %s: Trying crc-smack\n", ax->dev->name);
+ // fall through
+ case CRC_MODE_SMACK:
+ *p |= 0x80;
+ crc = swab16(crc16(0, p, len));
+ count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
+ break;
+ case CRC_MODE_FLEX_TEST:
+ ax->crcmode = CRC_MODE_NONE;
+ printk(KERN_INFO "mkiss: %s: Trying crc-flexnet\n", ax->dev->name);
+ // fall through
+ case CRC_MODE_FLEX:
+ *p |= 0x20;
+ crc = calc_crc_flex(p, len);
+ count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
+ break;
+
+ default:
+ count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
+ }
+ }
- default:
- count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
- break;
- }
-
set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
actual = ax->tty->driver->write(ax->tty, ax->xbuff, count);
ax->stats.tx_packets++;
@@ -439,8 +526,6 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
ax->dev->trans_start = jiffies;
ax->xleft = count - actual;
ax->xhead = ax->xbuff + actual;
-
- spin_unlock_bh(&ax->buflock);
}
/* Encapsulate an AX.25 packet and kick it into a TTY queue. */
@@ -622,7 +707,7 @@ static void ax_setup(struct net_device *dev)
* best way to fix this is to use a rwlock in the tty struct, but for now we
* use a single global rwlock for all ttys in ppp line discipline.
*/
-static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(disc_data_lock);
static struct mkiss *mkiss_get(struct tty_struct *tty)
{
@@ -643,6 +728,8 @@ static void mkiss_put(struct mkiss *ax)
up(&ax->dead_sem);
}
+static int crc_force = 0; /* Can be overridden with insmod */
+
static int mkiss_open(struct tty_struct *tty)
{
struct net_device *dev;
@@ -682,6 +769,33 @@ static int mkiss_open(struct tty_struct *tty)
if (register_netdev(dev))
goto out_free_buffers;
+ /* after register_netdev() - because else printk smashes the kernel */
+ switch (crc_force) {
+ case 3:
+ ax->crcmode = CRC_MODE_SMACK;
+ printk(KERN_INFO "mkiss: %s: crc mode smack forced.\n",
+ ax->dev->name);
+ break;
+ case 2:
+ ax->crcmode = CRC_MODE_FLEX;
+ printk(KERN_INFO "mkiss: %s: crc mode flexnet forced.\n",
+ ax->dev->name);
+ break;
+ case 1:
+ ax->crcmode = CRC_MODE_NONE;
+ printk(KERN_INFO "mkiss: %s: crc mode disabled.\n",
+ ax->dev->name);
+ break;
+ case 0:
+ /* fall through */
+ default:
+ crc_force = 0;
+ printk(KERN_INFO "mkiss: %s: crc mode is auto.\n",
+ ax->dev->name);
+ ax->crcmode = CRC_MODE_SMACK_TEST;
+ }
+ ax->crcauto = (crc_force ? 0 : 1);
+
netif_start_queue(dev);
/* Done. We have linked the TTY line to a channel. */
@@ -765,7 +879,6 @@ static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
case SIOCSIFHWADDR: {
char addr[AX25_ADDR_LEN];
-printk(KERN_INFO "In SIOCSIFHWADDR");
if (copy_from_user(&addr,
(void __user *) arg, AX25_ADDR_LEN)) {
@@ -864,6 +977,7 @@ out:
}
static struct tty_ldisc ax_ldisc = {
+ .owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "mkiss",
.open = mkiss_open,
@@ -904,6 +1018,8 @@ static void __exit mkiss_exit_driver(void)
MODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>");
MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
+MODULE_PARM(crc_force, "i");
+MODULE_PARM_DESC(crc_force, "crc [0 = auto | 1 = none | 2 = flexnet | 3 = smack]");
MODULE_LICENSE("GPL");
MODULE_ALIAS_LDISC(N_AX25);
diff --git a/drivers/net/hamradio/mkiss.h b/drivers/net/hamradio/mkiss.h
deleted file mode 100644
index 4ab70047859892..00000000000000
--- a/drivers/net/hamradio/mkiss.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
- * Defines for the Multi-KISS driver.
- ****************************************************************************/
-
-#define AX25_MAXDEV 16 /* MAX number of AX25 channels;
- This can be overridden with
- insmod -oax25_maxdev=nnn */
-#define AX_MTU 236
-
-/* SLIP/KISS protocol characters. */
-#define END 0300 /* indicates end of frame */
-#define ESC 0333 /* indicates byte stuffing */
-#define ESC_END 0334 /* ESC ESC_END means END 'data' */
-#define ESC_ESC 0335 /* ESC ESC_ESC means ESC 'data' */
-
-struct ax_disp {
- int magic;
-
- /* Various fields. */
- struct tty_struct *tty; /* ptr to TTY structure */
- struct net_device *dev; /* easy for intr handling */
-
- /* These are pointers to the malloc()ed frame buffers. */
- unsigned char *rbuff; /* receiver buffer */
- int rcount; /* received chars counter */
- unsigned char *xbuff; /* transmitter buffer */
- unsigned char *xhead; /* pointer to next byte to XMIT */
- int xleft; /* bytes left in XMIT queue */
-
- /* SLIP interface statistics. */
- unsigned long rx_packets; /* inbound frames counter */
- unsigned long tx_packets; /* outbound frames counter */
- unsigned long rx_bytes; /* inbound bytes counter */
- unsigned long tx_bytes; /* outbound bytes counter */
- unsigned long rx_errors; /* Parity, etc. errors */
- unsigned long tx_errors; /* Planned stuff */
- unsigned long rx_dropped; /* No memory for skb */
- unsigned long tx_dropped; /* When MTU change */
- unsigned long rx_over_errors; /* Frame bigger then SLIP buf. */
-
- /* Detailed SLIP statistics. */
- int mtu; /* Our mtu (to spot changes!) */
- int buffsize; /* Max buffers sizes */
-
-
- unsigned long flags; /* Flag values/ mode etc */
- /* long req'd: used by set_bit --RR */
-#define AXF_INUSE 0 /* Channel in use */
-#define AXF_ESCAPE 1 /* ESC received */
-#define AXF_ERROR 2 /* Parity, etc. error */
-#define AXF_KEEPTEST 3 /* Keepalive test flag */
-#define AXF_OUTWAIT 4 /* is outpacket was flag */
-
- int mode;
- int crcmode; /* MW: for FlexNet, SMACK etc. */
-#define CRC_MODE_NONE 0
-#define CRC_MODE_FLEX 1
-#define CRC_MODE_SMACK 2
- spinlock_t buflock; /* lock for rbuf and xbuf */
-};
-
-#define AX25_MAGIC 0x5316
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index cf0ac6fda1a174..b71fab6e34f426 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -2517,10 +2517,8 @@ static int hp100_down_vg_link(struct net_device *dev)
do {
if (hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST)
break;
- if (!in_interrupt()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ if (!in_interrupt())
+ schedule_timeout_interruptible(1);
} while (time_after(time, jiffies));
if (time_after_eq(jiffies, time)) /* no signal->no logout */
@@ -2536,10 +2534,8 @@ static int hp100_down_vg_link(struct net_device *dev)
do {
if (!(hp100_inb(VG_LAN_CFG_1) & HP100_LINK_UP_ST))
break;
- if (!in_interrupt()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ if (!in_interrupt())
+ schedule_timeout_interruptible(1);
} while (time_after(time, jiffies));
#ifdef HP100_DEBUG
@@ -2577,10 +2573,8 @@ static int hp100_down_vg_link(struct net_device *dev)
do {
if (!(hp100_inb(MAC_CFG_4) & HP100_MAC_SEL_ST))
break;
- if (!in_interrupt()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ if (!in_interrupt())
+ schedule_timeout_interruptible(1);
} while (time_after(time, jiffies));
hp100_orb(HP100_AUTO_MODE, MAC_CFG_3); /* Autosel back on */
@@ -2591,10 +2585,8 @@ static int hp100_down_vg_link(struct net_device *dev)
do {
if ((hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST) == 0)
break;
- if (!in_interrupt()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ if (!in_interrupt())
+ schedule_timeout_interruptible(1);
} while (time_after(time, jiffies));
if (time_before_eq(time, jiffies)) {
@@ -2606,10 +2598,8 @@ static int hp100_down_vg_link(struct net_device *dev)
time = jiffies + (2 * HZ); /* This seems to take a while.... */
do {
- if (!in_interrupt()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ if (!in_interrupt())
+ schedule_timeout_interruptible(1);
} while (time_after(time, jiffies));
return 0;
@@ -2659,10 +2649,8 @@ static int hp100_login_to_vg_hub(struct net_device *dev, u_short force_relogin)
do {
if (~(hp100_inb(VG_LAN_CFG_1) & HP100_LINK_UP_ST))
break;
- if (!in_interrupt()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ if (!in_interrupt())
+ schedule_timeout_interruptible(1);
} while (time_after(time, jiffies));
/* Start an addressed training and optionally request promiscuous port */
@@ -2697,10 +2685,8 @@ static int hp100_login_to_vg_hub(struct net_device *dev, u_short force_relogin)
do {
if (hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST)
break;
- if (!in_interrupt()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ if (!in_interrupt())
+ schedule_timeout_interruptible(1);
} while (time_before(jiffies, time));
if (time_after_eq(jiffies, time)) {
@@ -2723,10 +2709,8 @@ static int hp100_login_to_vg_hub(struct net_device *dev, u_short force_relogin)
#endif
break;
}
- if (!in_interrupt()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ if (!in_interrupt())
+ schedule_timeout_interruptible(1);
} while (time_after(time, jiffies));
}
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index ca5914091d3afb..d54156f11e61a3 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -400,5 +400,15 @@ config VIA_FIR
To compile it as a module, choose M here: the module will be called
via-ircc.
+config PXA_FICP
+ tristate "Intel PXA2xx Internal FICP"
+ depends on ARCH_PXA && IRDA
+ help
+ Say Y or M here if you want to build support for the PXA2xx
+ built-in IRDA interface which can support both SIR and FIR.
+ This driver relies on platform specific helper routines so
+ available capabilities may vary from one PXA2xx target to
+ another.
+
endmenu
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index 29a8bd812b2125..e7a8b7f7f5ddf7 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SMC_IRCC_FIR) += smsc-ircc2.o
obj-$(CONFIG_ALI_FIR) += ali-ircc.o
obj-$(CONFIG_VLSI_FIR) += vlsi_ir.o
obj-$(CONFIG_VIA_FIR) += via-ircc.o
+obj-$(CONFIG_PXA_FICP) += pxaficp_ir.o
# Old dongle drivers for old SIR drivers
obj-$(CONFIG_ESI_DONGLE_OLD) += esi.o
obj-$(CONFIG_TEKRAM_DONGLE_OLD) += tekram.o
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
new file mode 100644
index 00000000000000..aef80f5e7c9cff
--- /dev/null
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -0,0 +1,871 @@
+/*
+ * linux/drivers/net/irda/pxaficp_ir.c
+ *
+ * Based on sa1100_ir.c by Russell King
+ *
+ * Changes copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Infra-red driver (SIR/FIR) for the PXA2xx embedded microprocessor
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/slab.h>
+#include <linux/rtnetlink.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/pm.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/irda_device.h>
+
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/delay.h>
+#include <asm/hardware.h>
+#include <asm/arch/irda.h>
+#include <asm/arch/pxa-regs.h>
+
+#ifdef CONFIG_MACH_MAINSTONE
+#include <asm/arch/mainstone.h>
+#endif
+
+#define IrSR_RXPL_NEG_IS_ZERO (1<<4)
+#define IrSR_RXPL_POS_IS_ZERO 0x0
+#define IrSR_TXPL_NEG_IS_ZERO (1<<3)
+#define IrSR_TXPL_POS_IS_ZERO 0x0
+#define IrSR_XMODE_PULSE_1_6 (1<<2)
+#define IrSR_XMODE_PULSE_3_16 0x0
+#define IrSR_RCVEIR_IR_MODE (1<<1)
+#define IrSR_RCVEIR_UART_MODE 0x0
+#define IrSR_XMITIR_IR_MODE (1<<0)
+#define IrSR_XMITIR_UART_MODE 0x0
+
+#define IrSR_IR_RECEIVE_ON (\
+ IrSR_RXPL_NEG_IS_ZERO | \
+ IrSR_TXPL_POS_IS_ZERO | \
+ IrSR_XMODE_PULSE_3_16 | \
+ IrSR_RCVEIR_IR_MODE | \
+ IrSR_XMITIR_UART_MODE)
+
+#define IrSR_IR_TRANSMIT_ON (\
+ IrSR_RXPL_NEG_IS_ZERO | \
+ IrSR_TXPL_POS_IS_ZERO | \
+ IrSR_XMODE_PULSE_3_16 | \
+ IrSR_RCVEIR_UART_MODE | \
+ IrSR_XMITIR_IR_MODE)
+
+struct pxa_irda {
+ int speed;
+ int newspeed;
+ unsigned long last_oscr;
+
+ unsigned char *dma_rx_buff;
+ unsigned char *dma_tx_buff;
+ dma_addr_t dma_rx_buff_phy;
+ dma_addr_t dma_tx_buff_phy;
+ unsigned int dma_tx_buff_len;
+ int txdma;
+ int rxdma;
+
+ struct net_device_stats stats;
+ struct irlap_cb *irlap;
+ struct qos_info qos;
+
+ iobuff_t tx_buff;
+ iobuff_t rx_buff;
+
+ struct device *dev;
+ struct pxaficp_platform_data *pdata;
+};
+
+
+#define IS_FIR(si) ((si)->speed >= 4000000)
+#define IRDA_FRAME_SIZE_LIMIT 2047
+
+inline static void pxa_irda_fir_dma_rx_start(struct pxa_irda *si)
+{
+ DCSR(si->rxdma) = DCSR_NODESC;
+ DSADR(si->rxdma) = __PREG(ICDR);
+ DTADR(si->rxdma) = si->dma_rx_buff_phy;
+ DCMD(si->rxdma) = DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_WIDTH1 | DCMD_BURST32 | IRDA_FRAME_SIZE_LIMIT;
+ DCSR(si->rxdma) |= DCSR_RUN;
+}
+
+inline static void pxa_irda_fir_dma_tx_start(struct pxa_irda *si)
+{
+ DCSR(si->txdma) = DCSR_NODESC;
+ DSADR(si->txdma) = si->dma_tx_buff_phy;
+ DTADR(si->txdma) = __PREG(ICDR);
+ DCMD(si->txdma) = DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_ENDIRQEN | DCMD_WIDTH1 | DCMD_BURST32 | si->dma_tx_buff_len;
+ DCSR(si->txdma) |= DCSR_RUN;
+}
+
+/*
+ * Set the IrDA communications speed.
+ */
+static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
+{
+ unsigned long flags;
+ unsigned int divisor;
+
+ switch (speed) {
+ case 9600: case 19200: case 38400:
+ case 57600: case 115200:
+
+ /* refer to PXA250/210 Developer's Manual 10-7 */
+ /* BaudRate = 14.7456 MHz / (16*Divisor) */
+ divisor = 14745600 / (16 * speed);
+
+ local_irq_save(flags);
+
+ if (IS_FIR(si)) {
+ /* stop RX DMA */
+ DCSR(si->rxdma) &= ~DCSR_RUN;
+ /* disable FICP */
+ ICCR0 = 0;
+ pxa_set_cken(CKEN13_FICP, 0);
+
+ /* set board transceiver to SIR mode */
+ si->pdata->transceiver_mode(si->dev, IR_SIRMODE);
+
+ /* configure GPIO46/47 */
+ pxa_gpio_mode(GPIO46_STRXD_MD);
+ pxa_gpio_mode(GPIO47_STTXD_MD);
+
+ /* enable the STUART clock */
+ pxa_set_cken(CKEN5_STUART, 1);
+ }
+
+ /* disable STUART first */
+ STIER = 0;
+
+ /* access DLL & DLH */
+ STLCR |= LCR_DLAB;
+ STDLL = divisor & 0xff;
+ STDLH = divisor >> 8;
+ STLCR &= ~LCR_DLAB;
+
+ si->speed = speed;
+ STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6;
+ STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE;
+
+ local_irq_restore(flags);
+ break;
+
+ case 4000000:
+ local_irq_save(flags);
+
+ /* disable STUART */
+ STIER = 0;
+ STISR = 0;
+ pxa_set_cken(CKEN5_STUART, 0);
+
+ /* disable FICP first */
+ ICCR0 = 0;
+
+ /* set board transceiver to FIR mode */
+ si->pdata->transceiver_mode(si->dev, IR_FIRMODE);
+
+ /* configure GPIO46/47 */
+ pxa_gpio_mode(GPIO46_ICPRXD_MD);
+ pxa_gpio_mode(GPIO47_ICPTXD_MD);
+
+ /* enable the FICP clock */
+ pxa_set_cken(CKEN13_FICP, 1);
+
+ si->speed = speed;
+ pxa_irda_fir_dma_rx_start(si);
+ ICCR0 = ICCR0_ITR | ICCR0_RXE;
+
+ local_irq_restore(flags);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* SIR interrupt service routine. */
+static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct pxa_irda *si = netdev_priv(dev);
+ int iir, lsr, data;
+
+ iir = STIIR;
+
+ switch (iir & 0x0F) {
+ case 0x06: /* Receiver Line Status */
+ lsr = STLSR;
+ while (lsr & LSR_FIFOE) {
+ data = STRBR;
+ if (lsr & (LSR_OE | LSR_PE | LSR_FE | LSR_BI)) {
+ printk(KERN_DEBUG "pxa_ir: sir receiving error\n");
+ si->stats.rx_errors++;
+ if (lsr & LSR_FE)
+ si->stats.rx_frame_errors++;
+ if (lsr & LSR_OE)
+ si->stats.rx_fifo_errors++;
+ } else {
+ si->stats.rx_bytes++;
+ async_unwrap_char(dev, &si->stats, &si->rx_buff, data);
+ }
+ lsr = STLSR;
+ }
+ dev->last_rx = jiffies;
+ si->last_oscr = OSCR;
+ break;
+
+ case 0x04: /* Received Data Available */
+ /* forth through */
+
+ case 0x0C: /* Character Timeout Indication */
+ do {
+ si->stats.rx_bytes++;
+ async_unwrap_char(dev, &si->stats, &si->rx_buff, STRBR);
+ } while (STLSR & LSR_DR);
+ dev->last_rx = jiffies;
+ si->last_oscr = OSCR;
+ break;
+
+ case 0x02: /* Transmit FIFO Data Request */
+ while ((si->tx_buff.len) && (STLSR & LSR_TDRQ)) {
+ STTHR = *si->tx_buff.data++;
+ si->tx_buff.len -= 1;
+ }
+
+ if (si->tx_buff.len == 0) {
+ si->stats.tx_packets++;
+ si->stats.tx_bytes += si->tx_buff.data -
+ si->tx_buff.head;
+
+ /* We need to ensure that the transmitter has finished. */
+ while ((STLSR & LSR_TEMT) == 0)
+ cpu_relax();
+ si->last_oscr = OSCR;
+
+ /*
+ * Ok, we've finished transmitting. Now enable
+ * the receiver. Sometimes we get a receive IRQ
+ * immediately after a transmit...
+ */
+ if (si->newspeed) {
+ pxa_irda_set_speed(si, si->newspeed);
+ si->newspeed = 0;
+ } else {
+ /* enable IR Receiver, disable IR Transmitter */
+ STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6;
+ /* enable STUART and receive interrupts */
+ STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE;
+ }
+ /* I'm hungry! */
+ netif_wake_queue(dev);
+ }
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
+/* FIR Receive DMA interrupt handler */
+static void pxa_irda_fir_dma_rx_irq(int channel, void *data, struct pt_regs *regs)
+{
+ int dcsr = DCSR(channel);
+
+ DCSR(channel) = dcsr & ~DCSR_RUN;
+
+ printk(KERN_DEBUG "pxa_ir: fir rx dma bus error %#x\n", dcsr);
+}
+
+/* FIR Transmit DMA interrupt handler */
+static void pxa_irda_fir_dma_tx_irq(int channel, void *data, struct pt_regs *regs)
+{
+ struct net_device *dev = data;
+ struct pxa_irda *si = netdev_priv(dev);
+ int dcsr;
+
+ dcsr = DCSR(channel);
+ DCSR(channel) = dcsr & ~DCSR_RUN;
+
+ if (dcsr & DCSR_ENDINTR) {
+ si->stats.tx_packets++;
+ si->stats.tx_bytes += si->dma_tx_buff_len;
+ } else {
+ si->stats.tx_errors++;
+ }
+
+ while (ICSR1 & ICSR1_TBY)
+ cpu_relax();
+ si->last_oscr = OSCR;
+
+ /*
+ * HACK: It looks like the TBY bit is dropped too soon.
+ * Without this delay things break.
+ */
+ udelay(120);
+
+ if (si->newspeed) {
+ pxa_irda_set_speed(si, si->newspeed);
+ si->newspeed = 0;
+ } else {
+ ICCR0 = 0;
+ pxa_irda_fir_dma_rx_start(si);
+ ICCR0 = ICCR0_ITR | ICCR0_RXE;
+ }
+ netif_wake_queue(dev);
+}
+
+/* EIF(Error in FIFO/End in Frame) handler for FIR */
+static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev)
+{
+ unsigned int len, stat, data;
+
+ /* Get the current data position. */
+ len = DTADR(si->rxdma) - si->dma_rx_buff_phy;
+
+ do {
+ /* Read Status, and then Data. */
+ stat = ICSR1;
+ rmb();
+ data = ICDR;
+
+ if (stat & (ICSR1_CRE | ICSR1_ROR)) {
+ si->stats.rx_errors++;
+ if (stat & ICSR1_CRE) {
+ printk(KERN_DEBUG "pxa_ir: fir receive CRC error\n");
+ si->stats.rx_crc_errors++;
+ }
+ if (stat & ICSR1_ROR) {
+ printk(KERN_DEBUG "pxa_ir: fir receive overrun\n");
+ si->stats.rx_frame_errors++;
+ }
+ } else {
+ si->dma_rx_buff[len++] = data;
+ }
+ /* If we hit the end of frame, there's no point in continuing. */
+ if (stat & ICSR1_EOF)
+ break;
+ } while (ICSR0 & ICSR0_EIF);
+
+ if (stat & ICSR1_EOF) {
+ /* end of frame. */
+ struct sk_buff *skb = alloc_skb(len+1,GFP_ATOMIC);
+ if (!skb) {
+ printk(KERN_ERR "pxa_ir: fir out of memory for receive skb\n");
+ si->stats.rx_dropped++;
+ return;
+ }
+
+ /* Align IP header to 20 bytes */
+ skb_reserve(skb, 1);
+ memcpy(skb->data, si->dma_rx_buff, len);
+ skb_put(skb, len);
+
+ /* Feed it to IrLAP */
+ skb->dev = dev;
+ skb->mac.raw = skb->data;
+ skb->protocol = htons(ETH_P_IRDA);
+ netif_rx(skb);
+
+ si->stats.rx_packets++;
+ si->stats.rx_bytes += len;
+
+ dev->last_rx = jiffies;
+ }
+}
+
+/* FIR interrupt handler */
+static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct pxa_irda *si = netdev_priv(dev);
+ int icsr0;
+
+ /* stop RX DMA */
+ DCSR(si->rxdma) &= ~DCSR_RUN;
+ si->last_oscr = OSCR;
+ icsr0 = ICSR0;
+
+ if (icsr0 & (ICSR0_FRE | ICSR0_RAB)) {
+ if (icsr0 & ICSR0_FRE) {
+ printk(KERN_DEBUG "pxa_ir: fir receive frame error\n");
+ si->stats.rx_frame_errors++;
+ } else {
+ printk(KERN_DEBUG "pxa_ir: fir receive abort\n");
+ si->stats.rx_errors++;
+ }
+ ICSR0 = icsr0 & (ICSR0_FRE | ICSR0_RAB);
+ }
+
+ if (icsr0 & ICSR0_EIF) {
+ /* An error in FIFO occured, or there is a end of frame */
+ pxa_irda_fir_irq_eif(si, dev);
+ }
+
+ ICCR0 = 0;
+ pxa_irda_fir_dma_rx_start(si);
+ ICCR0 = ICCR0_ITR | ICCR0_RXE;
+
+ return IRQ_HANDLED;
+}
+
+/* hard_xmit interface of irda device */
+static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct pxa_irda *si = netdev_priv(dev);
+ int speed = irda_get_next_speed(skb);
+
+ /*
+ * Does this packet contain a request to change the interface
+ * speed? If so, remember it until we complete the transmission
+ * of this frame.
+ */
+ if (speed != si->speed && speed != -1)
+ si->newspeed = speed;
+
+ /*
+ * If this is an empty frame, we can bypass a lot.
+ */
+ if (skb->len == 0) {
+ if (si->newspeed) {
+ si->newspeed = 0;
+ pxa_irda_set_speed(si, speed);
+ }
+ dev_kfree_skb(skb);
+ return 0;
+ }
+
+ netif_stop_queue(dev);
+
+ if (!IS_FIR(si)) {
+ si->tx_buff.data = si->tx_buff.head;
+ si->tx_buff.len = async_wrap_skb(skb, si->tx_buff.data, si->tx_buff.truesize);
+
+ /* Disable STUART interrupts and switch to transmit mode. */
+ STIER = 0;
+ STISR = IrSR_IR_TRANSMIT_ON | IrSR_XMODE_PULSE_1_6;
+
+ /* enable STUART and transmit interrupts */
+ STIER = IER_UUE | IER_TIE;
+ } else {
+ unsigned long mtt = irda_get_mtt(skb);
+
+ si->dma_tx_buff_len = skb->len;
+ memcpy(si->dma_tx_buff, skb->data, skb->len);
+
+ if (mtt)
+ while ((unsigned)(OSCR - si->last_oscr)/4 < mtt)
+ cpu_relax();
+
+ /* stop RX DMA, disable FICP */
+ DCSR(si->rxdma) &= ~DCSR_RUN;
+ ICCR0 = 0;
+
+ pxa_irda_fir_dma_tx_start(si);
+ ICCR0 = ICCR0_ITR | ICCR0_TXE;
+ }
+
+ dev_kfree_skb(skb);
+ dev->trans_start = jiffies;
+ return 0;
+}
+
+static int pxa_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
+{
+ struct if_irda_req *rq = (struct if_irda_req *)ifreq;
+ struct pxa_irda *si = netdev_priv(dev);
+ int ret;
+
+ switch (cmd) {
+ case SIOCSBANDWIDTH:
+ ret = -EPERM;
+ if (capable(CAP_NET_ADMIN)) {
+ /*
+ * We are unable to set the speed if the
+ * device is not running.
+ */
+ if (netif_running(dev)) {
+ ret = pxa_irda_set_speed(si,
+ rq->ifr_baudrate);
+ } else {
+ printk(KERN_INFO "pxa_ir: SIOCSBANDWIDTH: !netif_running\n");
+ ret = 0;
+ }
+ }
+ break;
+
+ case SIOCSMEDIABUSY:
+ ret = -EPERM;
+ if (capable(CAP_NET_ADMIN)) {
+ irda_device_set_media_busy(dev, TRUE);
+ ret = 0;
+ }
+ break;
+
+ case SIOCGRECEIVING:
+ ret = 0;
+ rq->ifr_receiving = IS_FIR(si) ? 0
+ : si->rx_buff.state != OUTSIDE_FRAME;
+ break;
+
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+static struct net_device_stats *pxa_irda_stats(struct net_device *dev)
+{
+ struct pxa_irda *si = netdev_priv(dev);
+ return &si->stats;
+}
+
+static void pxa_irda_startup(struct pxa_irda *si)
+{
+ /* Disable STUART interrupts */
+ STIER = 0;
+ /* enable STUART interrupt to the processor */
+ STMCR = MCR_OUT2;
+ /* configure SIR frame format: StartBit - Data 7 ... Data 0 - Stop Bit */
+ STLCR = LCR_WLS0 | LCR_WLS1;
+ /* enable FIFO, we use FIFO to improve performance */
+ STFCR = FCR_TRFIFOE | FCR_ITL_32;
+
+ /* disable FICP */
+ ICCR0 = 0;
+ /* configure FICP ICCR2 */
+ ICCR2 = ICCR2_TXP | ICCR2_TRIG_32;
+
+ /* configure DMAC */
+ DRCMR17 = si->rxdma | DRCMR_MAPVLD;
+ DRCMR18 = si->txdma | DRCMR_MAPVLD;
+
+ /* force SIR reinitialization */
+ si->speed = 4000000;
+ pxa_irda_set_speed(si, 9600);
+
+ printk(KERN_DEBUG "pxa_ir: irda startup\n");
+}
+
+static void pxa_irda_shutdown(struct pxa_irda *si)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ /* disable STUART and interrupt */
+ STIER = 0;
+ /* disable STUART SIR mode */
+ STISR = 0;
+ /* disable the STUART clock */
+ pxa_set_cken(CKEN5_STUART, 0);
+
+ /* disable DMA */
+ DCSR(si->txdma) &= ~DCSR_RUN;
+ DCSR(si->rxdma) &= ~DCSR_RUN;
+ /* disable FICP */
+ ICCR0 = 0;
+ /* disable the FICP clock */
+ pxa_set_cken(CKEN13_FICP, 0);
+
+ DRCMR17 = 0;
+ DRCMR18 = 0;
+
+ local_irq_restore(flags);
+
+ /* power off board transceiver */
+ si->pdata->transceiver_mode(si->dev, IR_OFF);
+
+ printk(KERN_DEBUG "pxa_ir: irda shutdown\n");
+}
+
+static int pxa_irda_start(struct net_device *dev)
+{
+ struct pxa_irda *si = netdev_priv(dev);
+ int err;
+
+ si->speed = 9600;
+
+ err = request_irq(IRQ_STUART, pxa_irda_sir_irq, 0, dev->name, dev);
+ if (err)
+ goto err_irq1;
+
+ err = request_irq(IRQ_ICP, pxa_irda_fir_irq, 0, dev->name, dev);
+ if (err)
+ goto err_irq2;
+
+ /*
+ * The interrupt must remain disabled for now.
+ */
+ disable_irq(IRQ_STUART);
+ disable_irq(IRQ_ICP);
+
+ err = -EBUSY;
+ si->rxdma = pxa_request_dma("FICP_RX",DMA_PRIO_LOW, pxa_irda_fir_dma_rx_irq, dev);
+ if (si->rxdma < 0)
+ goto err_rx_dma;
+
+ si->txdma = pxa_request_dma("FICP_TX",DMA_PRIO_LOW, pxa_irda_fir_dma_tx_irq, dev);
+ if (si->txdma < 0)
+ goto err_tx_dma;
+
+ err = -ENOMEM;
+ si->dma_rx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT,
+ &si->dma_rx_buff_phy, GFP_KERNEL );
+ if (!si->dma_rx_buff)
+ goto err_dma_rx_buff;
+
+ si->dma_tx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT,
+ &si->dma_tx_buff_phy, GFP_KERNEL );
+ if (!si->dma_tx_buff)
+ goto err_dma_tx_buff;
+
+ /* Setup the serial port for the initial speed. */
+ pxa_irda_startup(si);
+
+ /*
+ * Open a new IrLAP layer instance.
+ */
+ si->irlap = irlap_open(dev, &si->qos, "pxa");
+ err = -ENOMEM;
+ if (!si->irlap)
+ goto err_irlap;
+
+ /*
+ * Now enable the interrupt and start the queue
+ */
+ enable_irq(IRQ_STUART);
+ enable_irq(IRQ_ICP);
+ netif_start_queue(dev);
+
+ printk(KERN_DEBUG "pxa_ir: irda driver opened\n");
+
+ return 0;
+
+err_irlap:
+ pxa_irda_shutdown(si);
+ dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_tx_buff, si->dma_tx_buff_phy);
+err_dma_tx_buff:
+ dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_rx_buff, si->dma_rx_buff_phy);
+err_dma_rx_buff:
+ pxa_free_dma(si->txdma);
+err_tx_dma:
+ pxa_free_dma(si->rxdma);
+err_rx_dma:
+ free_irq(IRQ_ICP, dev);
+err_irq2:
+ free_irq(IRQ_STUART, dev);
+err_irq1:
+
+ return err;
+}
+
+static int pxa_irda_stop(struct net_device *dev)
+{
+ struct pxa_irda *si = netdev_priv(dev);
+
+ netif_stop_queue(dev);
+
+ pxa_irda_shutdown(si);
+
+ /* Stop IrLAP */
+ if (si->irlap) {
+ irlap_close(si->irlap);
+ si->irlap = NULL;
+ }
+
+ free_irq(IRQ_STUART, dev);
+ free_irq(IRQ_ICP, dev);
+
+ pxa_free_dma(si->rxdma);
+ pxa_free_dma(si->txdma);
+
+ if (si->dma_rx_buff)
+ dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_tx_buff, si->dma_tx_buff_phy);
+ if (si->dma_tx_buff)
+ dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_rx_buff, si->dma_rx_buff_phy);
+
+ printk(KERN_DEBUG "pxa_ir: irda driver closed\n");
+ return 0;
+}
+
+static int pxa_irda_suspend(struct device *_dev, pm_message_t state, u32 level)
+{
+ struct net_device *dev = dev_get_drvdata(_dev);
+ struct pxa_irda *si;
+
+ if (!dev || level != SUSPEND_DISABLE)
+ return 0;
+
+ if (netif_running(dev)) {
+ si = netdev_priv(dev);
+ netif_device_detach(dev);
+ pxa_irda_shutdown(si);
+ }
+
+ return 0;
+}
+
+static int pxa_irda_resume(struct device *_dev, u32 level)
+{
+ struct net_device *dev = dev_get_drvdata(_dev);
+ struct pxa_irda *si;
+
+ if (!dev || level != RESUME_ENABLE)
+ return 0;
+
+ if (netif_running(dev)) {
+ si = netdev_priv(dev);
+ pxa_irda_startup(si);
+ netif_device_attach(dev);
+ netif_wake_queue(dev);
+ }
+
+ return 0;
+}
+
+
+static int pxa_irda_init_iobuf(iobuff_t *io, int size)
+{
+ io->head = kmalloc(size, GFP_KERNEL | GFP_DMA);
+ if (io->head != NULL) {
+ io->truesize = size;
+ io->in_frame = FALSE;
+ io->state = OUTSIDE_FRAME;
+ io->data = io->head;
+ }
+ return io->head ? 0 : -ENOMEM;
+}
+
+static int pxa_irda_probe(struct device *_dev)
+{
+ struct platform_device *pdev = to_platform_device(_dev);
+ struct net_device *dev;
+ struct pxa_irda *si;
+ unsigned int baudrate_mask;
+ int err;
+
+ if (!pdev->dev.platform_data)
+ return -ENODEV;
+
+ err = request_mem_region(__PREG(STUART), 0x24, "IrDA") ? 0 : -EBUSY;
+ if (err)
+ goto err_mem_1;
+
+ err = request_mem_region(__PREG(FICP), 0x1c, "IrDA") ? 0 : -EBUSY;
+ if (err)
+ goto err_mem_2;
+
+ dev = alloc_irdadev(sizeof(struct pxa_irda));
+ if (!dev)
+ goto err_mem_3;
+
+ si = netdev_priv(dev);
+ si->dev = &pdev->dev;
+ si->pdata = pdev->dev.platform_data;
+
+ /*
+ * Initialise the SIR buffers
+ */
+ err = pxa_irda_init_iobuf(&si->rx_buff, 14384);
+ if (err)
+ goto err_mem_4;
+ err = pxa_irda_init_iobuf(&si->tx_buff, 4000);
+ if (err)
+ goto err_mem_5;
+
+ dev->hard_start_xmit = pxa_irda_hard_xmit;
+ dev->open = pxa_irda_start;
+ dev->stop = pxa_irda_stop;
+ dev->do_ioctl = pxa_irda_ioctl;
+ dev->get_stats = pxa_irda_stats;
+
+ irda_init_max_qos_capabilies(&si->qos);
+
+ baudrate_mask = 0;
+ if (si->pdata->transceiver_cap & IR_SIRMODE)
+ baudrate_mask |= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+ if (si->pdata->transceiver_cap & IR_FIRMODE)
+ baudrate_mask |= IR_4000000 << 8;
+
+ si->qos.baud_rate.bits &= baudrate_mask;
+ si->qos.min_turn_time.bits = 7; /* 1ms or more */
+
+ irda_qos_bits_to_value(&si->qos);
+
+ err = register_netdev(dev);
+
+ if (err == 0)
+ dev_set_drvdata(&pdev->dev, dev);
+
+ if (err) {
+ kfree(si->tx_buff.head);
+err_mem_5:
+ kfree(si->rx_buff.head);
+err_mem_4:
+ free_netdev(dev);
+err_mem_3:
+ release_mem_region(__PREG(FICP), 0x1c);
+err_mem_2:
+ release_mem_region(__PREG(STUART), 0x24);
+ }
+err_mem_1:
+ return err;
+}
+
+static int pxa_irda_remove(struct device *_dev)
+{
+ struct net_device *dev = dev_get_drvdata(_dev);
+
+ if (dev) {
+ struct pxa_irda *si = netdev_priv(dev);
+ unregister_netdev(dev);
+ kfree(si->tx_buff.head);
+ kfree(si->rx_buff.head);
+ free_netdev(dev);
+ }
+
+ release_mem_region(__PREG(STUART), 0x24);
+ release_mem_region(__PREG(FICP), 0x1c);
+
+ return 0;
+}
+
+static struct device_driver pxa_ir_driver = {
+ .name = "pxa2xx-ir",
+ .bus = &platform_bus_type,
+ .probe = pxa_irda_probe,
+ .remove = pxa_irda_remove,
+ .suspend = pxa_irda_suspend,
+ .resume = pxa_irda_resume,
+};
+
+static int __init pxa_irda_init(void)
+{
+ return driver_register(&pxa_ir_driver);
+}
+
+static void __exit pxa_irda_exit(void)
+{
+ driver_unregister(&pxa_ir_driver);
+}
+
+module_init(pxa_irda_init);
+module_exit(pxa_irda_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index 8d34ac60d90679..06883309916d49 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -291,12 +291,12 @@ static void sa1100_irda_shutdown(struct sa1100_irda *si)
/*
* Suspend the IrDA interface.
*/
-static int sa1100_irda_suspend(struct device *_dev, pm_message_t state, u32 level)
+static int sa1100_irda_suspend(struct device *_dev, pm_message_t state)
{
struct net_device *dev = dev_get_drvdata(_dev);
struct sa1100_irda *si;
- if (!dev || level != SUSPEND_DISABLE)
+ if (!dev)
return 0;
si = dev->priv;
@@ -316,12 +316,12 @@ static int sa1100_irda_suspend(struct device *_dev, pm_message_t state, u32 leve
/*
* Resume the IrDA interface.
*/
-static int sa1100_irda_resume(struct device *_dev, u32 level)
+static int sa1100_irda_resume(struct device *_dev)
{
struct net_device *dev = dev_get_drvdata(_dev);
struct sa1100_irda *si;
- if (!dev || level != RESUME_ENABLE)
+ if (!dev)
return 0;
si = dev->priv;
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index dd89bda1f13159..bbac720cca63d9 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -213,8 +213,8 @@ static int smsc_ircc_probe_transceiver_smsc_ircc_atc(int fir_base);
/* Power Management */
-static int smsc_ircc_suspend(struct device *dev, pm_message_t state, u32 level);
-static int smsc_ircc_resume(struct device *dev, u32 level);
+static int smsc_ircc_suspend(struct device *dev, pm_message_t state);
+static int smsc_ircc_resume(struct device *dev);
static struct device_driver smsc_ircc_driver = {
.name = SMSC_IRCC2_DRIVER_NAME,
@@ -1646,13 +1646,13 @@ static int smsc_ircc_net_close(struct net_device *dev)
return 0;
}
-static int smsc_ircc_suspend(struct device *dev, pm_message_t state, u32 level)
+static int smsc_ircc_suspend(struct device *dev, pm_message_t state)
{
struct smsc_ircc_cb *self = dev_get_drvdata(dev);
IRDA_MESSAGE("%s, Suspending\n", driver_name);
- if (level == SUSPEND_DISABLE && !self->io.suspended) {
+ if (!self->io.suspended) {
smsc_ircc_net_close(self->netdev);
self->io.suspended = 1;
}
@@ -1660,11 +1660,11 @@ static int smsc_ircc_suspend(struct device *dev, pm_message_t state, u32 level)
return 0;
}
-static int smsc_ircc_resume(struct device *dev, u32 level)
+static int smsc_ircc_resume(struct device *dev)
{
struct smsc_ircc_cb *self = dev_get_drvdata(dev);
- if (level == RESUME_ENABLE && self->io.suspended) {
+ if (self->io.suspended) {
smsc_ircc_net_open(self->netdev);
self->io.suspended = 0;
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index 15f207323d9704..3961a754e920e3 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -678,10 +678,9 @@ static void turnaround_delay(const struct stir_cb *stir, long us)
return;
ticks = us / (1000000 / HZ);
- if (ticks > 0) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1 + ticks);
- } else
+ if (ticks > 0)
+ schedule_timeout_interruptible(1 + ticks);
+ else
udelay(us);
}
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index 9d026ed77ddd42..04e47189d83010 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -645,11 +645,10 @@ ixgb_phys_id(struct net_device *netdev, uint32_t data)
mod_timer(&adapter->blink_timer, jiffies);
- set_current_state(TASK_INTERRUPTIBLE);
- if(data)
- schedule_timeout(data * HZ);
+ if (data)
+ schedule_timeout_interruptible(data * HZ);
else
- schedule_timeout(MAX_SCHEDULE_TIMEOUT);
+ schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT);
del_timer_sync(&adapter->blink_timer);
ixgb_led_off(&adapter->hw);
@@ -723,6 +722,7 @@ struct ethtool_ops ixgb_ethtool_ops = {
.phys_id = ixgb_phys_id,
.get_stats_count = ixgb_get_stats_count,
.get_ethtool_stats = ixgb_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
void ixgb_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 89d6d69be382a3..176680cb153e8b 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -460,8 +460,9 @@ ixgb_probe(struct pci_dev *pdev,
}
ixgb_get_ee_mac_addr(&adapter->hw, netdev->dev_addr);
+ memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
- if(!is_valid_ether_addr(netdev->dev_addr)) {
+ if(!is_valid_ether_addr(netdev->perm_addr)) {
err = -EIO;
goto err_eeprom;
}
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index b4929beb33b235..1d75ca0bb93942 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -298,7 +298,7 @@ enum {OLD_LANCE = 0, PCNET_ISA=1, PCNET_ISAP=2, PCNET_PCI=3, PCNET_VLB=4, PCNET_
static unsigned char lance_need_isa_bounce_buffers = 1;
static int lance_open(struct net_device *dev);
-static void lance_init_ring(struct net_device *dev, int mode);
+static void lance_init_ring(struct net_device *dev, gfp_t mode);
static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev);
static int lance_rx(struct net_device *dev);
static irqreturn_t lance_interrupt(int irq, void *dev_id, struct pt_regs *regs);
@@ -846,7 +846,7 @@ lance_purge_ring(struct net_device *dev)
/* Initialize the LANCE Rx and Tx rings. */
static void
-lance_init_ring(struct net_device *dev, int gfp)
+lance_init_ring(struct net_device *dev, gfp_t gfp)
{
struct lance_private *lp = dev->priv;
int i;
diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
index 41bad07ac1acc9..f7b7238d8352ed 100644
--- a/drivers/net/lasi_82596.c
+++ b/drivers/net/lasi_82596.c
@@ -415,6 +415,10 @@ static int rx_ring_size = RX_RING_SIZE;
static int ticks_limit = 100;
static int max_cmd_backlog = TX_RING_SIZE-1;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void i596_poll_controller(struct net_device *dev);
+#endif
+
static inline void CA(struct net_device *dev)
{
@@ -636,11 +640,11 @@ static int init_i596_mem(struct net_device *dev)
disable_irq(dev->irq); /* disable IRQs from LAN */
DEB(DEB_INIT,
- printk("RESET 82596 port: %p (with IRQ %d disabled)\n",
- (void*)(dev->base_addr + PA_I82596_RESET),
+ printk("RESET 82596 port: %lx (with IRQ %d disabled)\n",
+ (dev->base_addr + PA_I82596_RESET),
dev->irq));
- gsc_writel(0, (void*)(dev->base_addr + PA_I82596_RESET)); /* Hard Reset */
+ gsc_writel(0, (dev->base_addr + PA_I82596_RESET)); /* Hard Reset */
udelay(100); /* Wait 100us - seems to help */
/* change the scp address */
@@ -1209,6 +1213,9 @@ static int __devinit i82596_probe(struct net_device *dev,
dev->set_multicast_list = set_multicast_list;
dev->tx_timeout = i596_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = i596_poll_controller;
+#endif
dev->priv = (void *)(dev->mem_start);
@@ -1242,6 +1249,14 @@ static int __devinit i82596_probe(struct net_device *dev,
return 0;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void i596_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ i596_interrupt(dev->irq, dev, NULL);
+ enable_irq(dev->irq);
+}
+#endif
static irqreturn_t i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -1528,17 +1543,18 @@ lan_init_chip(struct parisc_device *dev)
if (!dev->irq) {
printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
- __FILE__, dev->hpa);
+ __FILE__, dev->hpa.start);
return -ENODEV;
}
- printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", dev->hpa, dev->irq);
+ printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", dev->hpa.start,
+ dev->irq);
netdevice = alloc_etherdev(0);
if (!netdevice)
return -ENOMEM;
- netdevice->base_addr = dev->hpa;
+ netdevice->base_addr = dev->hpa.start;
netdevice->irq = dev->irq;
retval = i82596_probe(netdevice, &dev->dev);
@@ -1566,7 +1582,7 @@ static struct parisc_device_id lan_tbl[] = {
MODULE_DEVICE_TABLE(parisc, lan_tbl);
static struct parisc_driver lan_driver = {
- .name = "Apricot",
+ .name = "lasi_82596",
.id_table = lan_tbl,
.probe = lan_init_chip,
};
diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c
index 27f0d8ac4c40d9..309d254842cf2f 100644
--- a/drivers/net/lne390.c
+++ b/drivers/net/lne390.c
@@ -298,7 +298,7 @@ static int __init lne390_probe1(struct net_device *dev, int ioaddr)
return 0;
unmap:
if (ei_status.reg0)
- iounmap((void *)dev->mem_start);
+ iounmap(ei_status.mem);
cleanup:
free_irq(dev->irq, dev);
return ret;
diff --git a/drivers/net/mii.c b/drivers/net/mii.c
index c33cb3dc942b71..e42aa797f08b88 100644
--- a/drivers/net/mii.c
+++ b/drivers/net/mii.c
@@ -207,6 +207,20 @@ int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
return 0;
}
+int mii_check_gmii_support(struct mii_if_info *mii)
+{
+ int reg;
+
+ reg = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
+ if (reg & BMSR_ESTATEN) {
+ reg = mii->mdio_read(mii->dev, mii->phy_id, MII_ESTATUS);
+ if (reg & (ESTATUS_1000_TFULL | ESTATUS_1000_THALF))
+ return 1;
+ }
+
+ return 0;
+}
+
int mii_link_ok (struct mii_if_info *mii)
{
/* first, a dummy read, needed to latch some MII phys */
@@ -394,5 +408,6 @@ EXPORT_SYMBOL(mii_ethtool_gset);
EXPORT_SYMBOL(mii_ethtool_sset);
EXPORT_SYMBOL(mii_check_link);
EXPORT_SYMBOL(mii_check_media);
+EXPORT_SYMBOL(mii_check_gmii_support);
EXPORT_SYMBOL(generic_mii_ioctl);
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
new file mode 100644
index 00000000000000..f79f7ee72ab894
--- /dev/null
+++ b/drivers/net/mipsnet.c
@@ -0,0 +1,371 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#define DEBUG
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <linux/etherdevice.h>
+#include <linux/netdevice.h>
+#include <asm/io.h>
+#include <asm/mips-boards/simint.h>
+
+#include "mipsnet.h" /* actual device IO mapping */
+
+#define MIPSNET_VERSION "2005-06-20"
+
+#define mipsnet_reg_address(dev, field) (dev->base_addr + field_offset(field))
+
+struct mipsnet_priv {
+ struct net_device_stats stats;
+};
+
+static struct platform_device *mips_plat_dev;
+
+static char mipsnet_string[] = "mipsnet";
+
+/*
+ * Copy data from the MIPSNET rx data port
+ */
+static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata,
+ int len)
+{
+ uint32_t available_len = inl(mipsnet_reg_address(dev, rxDataCount));
+ if (available_len < len)
+ return -EFAULT;
+
+ for (; len > 0; len--, kdata++) {
+ *kdata = inb(mipsnet_reg_address(dev, rxDataBuffer));
+ }
+
+ return inl(mipsnet_reg_address(dev, rxDataCount));
+}
+
+static inline ssize_t mipsnet_put_todevice(struct net_device *dev,
+ struct sk_buff *skb)
+{
+ int count_to_go = skb->len;
+ char *buf_ptr = skb->data;
+ struct mipsnet_priv *mp = netdev_priv(dev);
+
+ pr_debug("%s: %s(): telling MIPSNET txDataCount(%d)\n",
+ dev->name, __FUNCTION__, skb->len);
+
+ outl(skb->len, mipsnet_reg_address(dev, txDataCount));
+
+ pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n",
+ dev->name, __FUNCTION__, skb->len);
+
+ for (; count_to_go; buf_ptr++, count_to_go--) {
+ outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer));
+ }
+
+ mp->stats.tx_packets++;
+ mp->stats.tx_bytes += skb->len;
+
+ return skb->len;
+}
+
+static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ pr_debug("%s:%s(): transmitting %d bytes\n",
+ dev->name, __FUNCTION__, skb->len);
+
+ /* Only one packet at a time. Once TXDONE interrupt is serviced, the
+ * queue will be restarted.
+ */
+ netif_stop_queue(dev);
+ mipsnet_put_todevice(dev, skb);
+
+ return 0;
+}
+
+static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count)
+{
+ struct sk_buff *skb;
+ size_t len = count;
+ struct mipsnet_priv *mp = netdev_priv(dev);
+
+ if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) {
+ mp->stats.rx_dropped++;
+ return -ENOMEM;
+ }
+
+ skb_reserve(skb, 2);
+ if (ioiocpy_frommipsnet(dev, skb_put(skb, len), len))
+ return -EFAULT;
+
+ skb->dev = dev;
+ skb->protocol = eth_type_trans(skb, dev);
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ pr_debug("%s:%s(): pushing RXed data to kernel\n",
+ dev->name, __FUNCTION__);
+ netif_rx(skb);
+
+ mp->stats.rx_packets++;
+ mp->stats.rx_bytes += len;
+
+ return count;
+}
+
+static irqreturn_t
+mipsnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+
+ irqreturn_t retval = IRQ_NONE;
+ uint64_t interruptFlags;
+
+ if (irq == dev->irq) {
+ pr_debug("%s:%s(): irq %d for device\n",
+ dev->name, __FUNCTION__, irq);
+
+ retval = IRQ_HANDLED;
+
+ interruptFlags =
+ inl(mipsnet_reg_address(dev, interruptControl));
+ pr_debug("%s:%s(): intCtl=0x%016llx\n", dev->name,
+ __FUNCTION__, interruptFlags);
+
+ if (interruptFlags & MIPSNET_INTCTL_TXDONE) {
+ pr_debug("%s:%s(): got TXDone\n",
+ dev->name, __FUNCTION__);
+ outl(MIPSNET_INTCTL_TXDONE,
+ mipsnet_reg_address(dev, interruptControl));
+ // only one packet at a time, we are done.
+ netif_wake_queue(dev);
+ } else if (interruptFlags & MIPSNET_INTCTL_RXDONE) {
+ pr_debug("%s:%s(): got RX data\n",
+ dev->name, __FUNCTION__);
+ mipsnet_get_fromdev(dev,
+ inl(mipsnet_reg_address(dev, rxDataCount)));
+ pr_debug("%s:%s(): clearing RX int\n",
+ dev->name, __FUNCTION__);
+ outl(MIPSNET_INTCTL_RXDONE,
+ mipsnet_reg_address(dev, interruptControl));
+
+ } else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) {
+ pr_debug("%s:%s(): got test interrupt\n",
+ dev->name, __FUNCTION__);
+ // TESTBIT is cleared on read.
+ // And takes effect after a write with 0
+ outl(0, mipsnet_reg_address(dev, interruptControl));
+ } else {
+ pr_debug("%s:%s(): no valid fags 0x%016llx\n",
+ dev->name, __FUNCTION__, interruptFlags);
+ // Maybe shared IRQ, just ignore, no clearing.
+ retval = IRQ_NONE;
+ }
+
+ } else {
+ printk(KERN_INFO "%s: %s(): irq %d for unknown device\n",
+ dev->name, __FUNCTION__, irq);
+ retval = IRQ_NONE;
+ }
+ return retval;
+} //mipsnet_interrupt()
+
+static int mipsnet_open(struct net_device *dev)
+{
+ int err;
+ pr_debug("%s: mipsnet_open\n", dev->name);
+
+ err = request_irq(dev->irq, &mipsnet_interrupt,
+ SA_SHIRQ, dev->name, (void *) dev);
+
+ if (err) {
+ pr_debug("%s: %s(): can't get irq %d\n",
+ dev->name, __FUNCTION__, dev->irq);
+ release_region(dev->base_addr, MIPSNET_IO_EXTENT);
+ return err;
+ }
+
+ pr_debug("%s: %s(): got IO region at 0x%04lx and irq %d for dev.\n",
+ dev->name, __FUNCTION__, dev->base_addr, dev->irq);
+
+
+ netif_start_queue(dev);
+
+ // test interrupt handler
+ outl(MIPSNET_INTCTL_TESTBIT,
+ mipsnet_reg_address(dev, interruptControl));
+
+
+ return 0;
+}
+
+static int mipsnet_close(struct net_device *dev)
+{
+ pr_debug("%s: %s()\n", dev->name, __FUNCTION__);
+ netif_stop_queue(dev);
+ return 0;
+}
+
+static struct net_device_stats *mipsnet_get_stats(struct net_device *dev)
+{
+ struct mipsnet_priv *mp = netdev_priv(dev);
+
+ return &mp->stats;
+}
+
+static void mipsnet_set_mclist(struct net_device *dev)
+{
+ // we don't do anything
+ return;
+}
+
+static int __init mipsnet_probe(struct device *dev)
+{
+ struct net_device *netdev;
+ int err;
+
+ netdev = alloc_etherdev(sizeof(struct mipsnet_priv));
+ if (!netdev) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ dev_set_drvdata(dev, netdev);
+
+ netdev->open = mipsnet_open;
+ netdev->stop = mipsnet_close;
+ netdev->hard_start_xmit = mipsnet_xmit;
+ netdev->get_stats = mipsnet_get_stats;
+ netdev->set_multicast_list = mipsnet_set_mclist;
+
+ /*
+ * TODO: probe for these or load them from PARAM
+ */
+ netdev->base_addr = 0x4200;
+ netdev->irq = MIPSCPU_INT_BASE + MIPSCPU_INT_MB0 +
+ inl(mipsnet_reg_address(netdev, interruptInfo));
+
+ // Get the io region now, get irq on open()
+ if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) {
+ pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} "
+ "for dev is not availble.\n", netdev->name,
+ __FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT);
+ err = -EBUSY;
+ goto out_free_netdev;
+ }
+
+ /*
+ * Lacking any better mechanism to allocate a MAC address we use a
+ * random one ...
+ */
+ random_ether_addr(netdev->dev_addr);
+
+ err = register_netdev(netdev);
+ if (err) {
+ printk(KERN_ERR "MIPSNet: failed to register netdev.\n");
+ goto out_free_region;
+ }
+
+ return 0;
+
+out_free_region:
+ release_region(netdev->base_addr, MIPSNET_IO_EXTENT);
+
+out_free_netdev:
+ free_netdev(netdev);
+
+out:
+ return err;
+}
+
+static int __devexit mipsnet_device_remove(struct device *device)
+{
+ struct net_device *dev = dev_get_drvdata(device);
+
+ unregister_netdev(dev);
+ release_region(dev->base_addr, MIPSNET_IO_EXTENT);
+ free_netdev(dev);
+ dev_set_drvdata(device, NULL);
+
+ return 0;
+}
+
+static struct device_driver mipsnet_driver = {
+ .name = mipsnet_string,
+ .bus = &platform_bus_type,
+ .probe = mipsnet_probe,
+ .remove = __devexit_p(mipsnet_device_remove),
+};
+
+static void mipsnet_platform_release(struct device *device)
+{
+ struct platform_device *pldev;
+
+ /* free device */
+ pldev = to_platform_device(device);
+ kfree(pldev);
+}
+
+static int __init mipsnet_init_module(void)
+{
+ struct platform_device *pldev;
+ int err;
+
+ printk(KERN_INFO "MIPSNet Ethernet driver. Version: %s. "
+ "(c)2005 MIPS Technologies, Inc.\n", MIPSNET_VERSION);
+
+ if (driver_register(&mipsnet_driver)) {
+ printk(KERN_ERR "Driver registration failed\n");
+ err = -ENODEV;
+ goto out;
+ }
+
+ if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto out_unregister_driver;
+ }
+
+ memset (pldev, 0, sizeof (*pldev));
+ pldev->name = mipsnet_string;
+ pldev->id = 0;
+ pldev->dev.release = mipsnet_platform_release;
+
+ if (platform_device_register(pldev)) {
+ err = -ENODEV;
+ goto out_free_pldev;
+ }
+
+ if (!pldev->dev.driver) {
+ /*
+ * The driver was not bound to this device, there was
+ * no hardware at this address. Unregister it, as the
+ * release fuction will take care of freeing the
+ * allocated structure
+ */
+ platform_device_unregister (pldev);
+ }
+
+ mips_plat_dev = pldev;
+
+ return 0;
+
+out_free_pldev:
+ kfree(pldev);
+
+out_unregister_driver:
+ driver_unregister(&mipsnet_driver);
+out:
+ return err;
+}
+
+static void __exit mipsnet_exit_module(void)
+{
+ pr_debug("MIPSNet Ethernet driver exiting\n");
+
+ driver_unregister(&mipsnet_driver);
+}
+
+module_init(mipsnet_init_module);
+module_exit(mipsnet_exit_module);
diff --git a/drivers/net/mipsnet.h b/drivers/net/mipsnet.h
new file mode 100644
index 00000000000000..878535953cb13d
--- /dev/null
+++ b/drivers/net/mipsnet.h
@@ -0,0 +1,127 @@
+//
+// <COPYRIGHT CLASS="1B" YEAR="2005">
+// Unpublished work (c) MIPS Technologies, Inc. All rights reserved.
+// Unpublished rights reserved under the copyright laws of the U.S.A. and
+// other countries.
+//
+// PROPRIETARY / SECRET CONFIDENTIAL INFORMATION OF MIPS TECHNOLOGIES, INC.
+// FOR INTERNAL USE ONLY.
+//
+// Under no circumstances (contract or otherwise) may this information be
+// disclosed to, or copied, modified or used by anyone other than employees
+// or contractors of MIPS Technologies having a need to know.
+// </COPYRIGHT>
+//
+//++
+// File: MIPS_Net.h
+//
+// Description:
+// The definition of the emulated MIPSNET device's interface.
+//
+// Notes: This include file needs to work from a Linux device drivers.
+//
+//--
+//
+
+#ifndef __MIPSNET_H
+#define __MIPSNET_H
+
+/*
+ * Id of this Net device, as seen by the core.
+ */
+#define MIPS_NET_DEV_ID ((uint64_t) \
+ ((uint64_t)'M'<< 0)| \
+ ((uint64_t)'I'<< 8)| \
+ ((uint64_t)'P'<<16)| \
+ ((uint64_t)'S'<<24)| \
+ ((uint64_t)'N'<<32)| \
+ ((uint64_t)'E'<<40)| \
+ ((uint64_t)'T'<<48)| \
+ ((uint64_t)'0'<<56))
+
+/*
+ * Net status/control block as seen by sw in the core.
+ * (Why not use bit fields? can't be bothered with cross-platform struct
+ * packing.)
+ */
+typedef struct _net_control_block {
+ /// dev info for probing
+ /// reads as MIPSNET%d where %d is some form of version
+ uint64_t devId; /*0x00 */
+
+ /*
+ * read only busy flag.
+ * Set and cleared by the Net Device to indicate that an rx or a tx
+ * is in progress.
+ */
+ uint32_t busy; /*0x08 */
+
+ /*
+ * Set by the Net Device.
+ * The device will set it once data has been received.
+ * The value is the number of bytes that should be read from
+ * rxDataBuffer. The value will decrease till 0 until all the data
+ * from rxDataBuffer has been read.
+ */
+ uint32_t rxDataCount; /*0x0c */
+#define MIPSNET_MAX_RXTX_DATACOUNT (1<<16)
+
+ /*
+ * Settable from the MIPS core, cleared by the Net Device.
+ * The core should set the number of bytes it wants to send,
+ * then it should write those bytes of data to txDataBuffer.
+ * The device will clear txDataCount has been processed (not necessarily sent).
+ */
+ uint32_t txDataCount; /*0x10 */
+
+ /*
+ * Interrupt control
+ *
+ * Used to clear the interrupted generated by this dev.
+ * Write a 1 to clear the interrupt. (except bit31).
+ *
+ * Bit0 is set if it was a tx-done interrupt.
+ * Bit1 is set when new rx-data is available.
+ * Until this bit is cleared there will be no other RXs.
+ *
+ * Bit31 is used for testing, it clears after a read.
+ * Writing 1 to this bit will cause an interrupt to be generated.
+ * To clear the test interrupt, write 0 to this register.
+ */
+ uint32_t interruptControl; /*0x14 */
+#define MIPSNET_INTCTL_TXDONE ((uint32_t)(1<< 0))
+#define MIPSNET_INTCTL_RXDONE ((uint32_t)(1<< 1))
+#define MIPSNET_INTCTL_TESTBIT ((uint32_t)(1<<31))
+#define MIPSNET_INTCTL_ALLSOURCES (MIPSNET_INTCTL_TXDONE|MIPSNET_INTCTL_RXDONE|MIPSNET_INTCTL_TESTBIT)
+
+ /*
+ * Readonly core-specific interrupt info for the device to signal the core.
+ * The meaning of the contents of this field might change.
+ */
+ /*###\todo: the whole memIntf interrupt scheme is messy: the device should have
+ * no control what so ever of what VPE/register set is being used.
+ * The MemIntf should only expose interrupt lines, and something in the
+ * config should be responsible for the line<->core/vpe bindings.
+ */
+ uint32_t interruptInfo; /*0x18 */
+
+ /*
+ * This is where the received data is read out.
+ * There is more data to read until rxDataReady is 0.
+ * Only 1 byte at this regs offset is used.
+ */
+ uint32_t rxDataBuffer; /*0x1c */
+
+ /*
+ * This is where the data to transmit is written.
+ * Data should be written for the amount specified in the txDataCount register.
+ * Only 1 byte at this regs offset is used.
+ */
+ uint32_t txDataBuffer; /*0x20 */
+} MIPS_T_NetControl;
+
+#define MIPSNET_IO_EXTENT 0x40 /* being generous */
+
+#define field_offset(field) ((int)&((MIPS_T_NetControl*)(0))->field)
+
+#endif /* __MIPSNET_H */
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index f0996ce5c26869..6c86dca62e2a56 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -277,7 +277,7 @@ static void myri_init_rings(struct myri_eth *mp, int from_irq)
struct recvq __iomem *rq = mp->rq;
struct myri_rxd __iomem *rxd = &rq->myri_rxd[0];
struct net_device *dev = mp->dev;
- int gfp_flags = GFP_KERNEL;
+ gfp_t gfp_flags = GFP_KERNEL;
int i;
if (from_irq || in_interrupt())
diff --git a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h
index 9391e55a5e9248..47722f708a4182 100644
--- a/drivers/net/myri_sbus.h
+++ b/drivers/net/myri_sbus.h
@@ -296,7 +296,7 @@ struct myri_eth {
/* We use this to acquire receive skb's that we can DMA directly into. */
#define ALIGNED_RX_SKB_ADDR(addr) \
((((unsigned long)(addr) + (64 - 1)) & ~(64 - 1)) - (unsigned long)(addr))
-static inline struct sk_buff *myri_alloc_skb(unsigned int length, int gfp_flags)
+static inline struct sk_buff *myri_alloc_skb(unsigned int length, gfp_t gfp_flags)
{
struct sk_buff *skb;
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index d209a1556b2ebc..0de8fdd2aa86f3 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -54,6 +54,10 @@ static const char version2[] =
#include <asm/system.h>
#include <asm/io.h>
+#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
+#include <asm/tx4938/rbtx4938.h>
+#endif
+
#include "8390.h"
#define DRV_NAME "ne"
@@ -111,6 +115,9 @@ bad_clone_list[] __initdata = {
{"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
{"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
{"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
+#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
+ {"RBHMA4X00-RTL8019", "RBHMA4X00/RTL8019", {0x00, 0x60, 0x0a}}, /* Toshiba built-in */
+#endif
{"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
{NULL,}
};
@@ -226,6 +233,10 @@ struct net_device * __init ne_probe(int unit)
sprintf(dev->name, "eth%d", unit);
netdev_boot_setup_check(dev);
+#ifdef CONFIG_TOSHIBA_RBTX4938
+ dev->base_addr = 0x07f20280;
+ dev->irq = RBTX4938_RTL_8019_IRQ;
+#endif
err = do_ne_probe(dev);
if (err)
goto out;
@@ -506,6 +517,10 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
ei_status.name = name;
ei_status.tx_start_page = start_page;
ei_status.stop_page = stop_page;
+#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
+ wordlength = 1;
+#endif
+
#ifdef CONFIG_PLAT_OAKS32R
ei_status.word16 = 0;
#else
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index f1c01ac2910239..e531a4eedfeee3 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -372,6 +372,7 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
printk("%2.2X%s", SA_prom[i], i == 5 ? ".\n": ":");
dev->dev_addr[i] = SA_prom[i];
}
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
return 0;
@@ -637,6 +638,7 @@ static struct ethtool_ops ne2k_pci_ethtool_ops = {
.get_drvinfo = ne2k_pci_get_drvinfo,
.get_tx_csum = ethtool_op_get_tx_csum,
.get_sg = ethtool_op_get_sg,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev)
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index e4811b42a6b7fe..a3c3fc9c0d8a8e 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -1632,8 +1632,7 @@ static void ns83820_run_bist(struct net_device *ndev, const char *name, u32 enab
timed_out = 1;
break;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
if (status & fail)
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 113b68099216b4..70fe81a89df958 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -22,8 +22,8 @@
*************************************************************************/
#define DRV_NAME "pcnet32"
-#define DRV_VERSION "1.30j"
-#define DRV_RELDATE "29.04.2005"
+#define DRV_VERSION "1.31a"
+#define DRV_RELDATE "12.Sep.2005"
#define PFX DRV_NAME ": "
static const char *version =
@@ -257,6 +257,9 @@ static int homepna[MAX_UNITS];
* v1.30h 24 Jun 2004 Don Fry correctly select auto, speed, duplex in bcr32.
* v1.30i 28 Jun 2004 Don Fry change to use module_param.
* v1.30j 29 Apr 2005 Don Fry fix skb/map leak with loopback test.
+ * v1.31 02 Sep 2005 Hubert WS Lin <wslin@tw.ibm.c0m> added set_ringparam().
+ * v1.31a 12 Sep 2005 Hubert WS Lin <wslin@tw.ibm.c0m> set min ring size to 4
+ * to allow loopback test to work unchanged.
*/
@@ -266,17 +269,17 @@ static int homepna[MAX_UNITS];
* That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4).
*/
#ifndef PCNET32_LOG_TX_BUFFERS
-#define PCNET32_LOG_TX_BUFFERS 4
-#define PCNET32_LOG_RX_BUFFERS 5
+#define PCNET32_LOG_TX_BUFFERS 4
+#define PCNET32_LOG_RX_BUFFERS 5
+#define PCNET32_LOG_MAX_TX_BUFFERS 9 /* 2^9 == 512 */
+#define PCNET32_LOG_MAX_RX_BUFFERS 9
#endif
#define TX_RING_SIZE (1 << (PCNET32_LOG_TX_BUFFERS))
-#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
-#define TX_RING_LEN_BITS ((PCNET32_LOG_TX_BUFFERS) << 12)
+#define TX_MAX_RING_SIZE (1 << (PCNET32_LOG_MAX_TX_BUFFERS))
#define RX_RING_SIZE (1 << (PCNET32_LOG_RX_BUFFERS))
-#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
-#define RX_RING_LEN_BITS ((PCNET32_LOG_RX_BUFFERS) << 4)
+#define RX_MAX_RING_SIZE (1 << (PCNET32_LOG_MAX_RX_BUFFERS))
#define PKT_BUF_SZ 1544
@@ -334,14 +337,14 @@ struct pcnet32_access {
};
/*
- * The first three fields of pcnet32_private are read by the ethernet device
- * so we allocate the structure should be allocated by pci_alloc_consistent().
+ * The first field of pcnet32_private is read by the ethernet device
+ * so the structure should be allocated using pci_alloc_consistent().
*/
struct pcnet32_private {
- /* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */
- struct pcnet32_rx_head rx_ring[RX_RING_SIZE];
- struct pcnet32_tx_head tx_ring[TX_RING_SIZE];
struct pcnet32_init_block init_block;
+ /* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */
+ struct pcnet32_rx_head *rx_ring;
+ struct pcnet32_tx_head *tx_ring;
dma_addr_t dma_addr; /* DMA address of beginning of this
object, returned by
pci_alloc_consistent */
@@ -349,13 +352,21 @@ struct pcnet32_private {
structure */
const char *name;
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
- struct sk_buff *tx_skbuff[TX_RING_SIZE];
- struct sk_buff *rx_skbuff[RX_RING_SIZE];
- dma_addr_t tx_dma_addr[TX_RING_SIZE];
- dma_addr_t rx_dma_addr[RX_RING_SIZE];
+ struct sk_buff **tx_skbuff;
+ struct sk_buff **rx_skbuff;
+ dma_addr_t *tx_dma_addr;
+ dma_addr_t *rx_dma_addr;
struct pcnet32_access a;
spinlock_t lock; /* Guard lock */
unsigned int cur_rx, cur_tx; /* The next free ring entry */
+ unsigned int rx_ring_size; /* current rx ring size */
+ unsigned int tx_ring_size; /* current tx ring size */
+ unsigned int rx_mod_mask; /* rx ring modular mask */
+ unsigned int tx_mod_mask; /* tx ring modular mask */
+ unsigned short rx_len_bits;
+ unsigned short tx_len_bits;
+ dma_addr_t rx_ring_dma_addr;
+ dma_addr_t tx_ring_dma_addr;
unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
struct net_device_stats stats;
char tx_full;
@@ -397,6 +408,9 @@ static int pcnet32_get_regs_len(struct net_device *dev);
static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *ptr);
static void pcnet32_purge_tx_ring(struct net_device *dev);
+static int pcnet32_alloc_ring(struct net_device *dev);
+static void pcnet32_free_ring(struct net_device *dev);
+
enum pci_flags_bit {
PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
@@ -613,10 +627,62 @@ static void pcnet32_get_ringparam(struct net_device *dev, struct ethtool_ringpar
{
struct pcnet32_private *lp = dev->priv;
- ering->tx_max_pending = TX_RING_SIZE - 1;
- ering->tx_pending = lp->cur_tx - lp->dirty_tx;
- ering->rx_max_pending = RX_RING_SIZE - 1;
- ering->rx_pending = lp->cur_rx & RX_RING_MOD_MASK;
+ ering->tx_max_pending = TX_MAX_RING_SIZE - 1;
+ ering->tx_pending = lp->tx_ring_size - 1;
+ ering->rx_max_pending = RX_MAX_RING_SIZE - 1;
+ ering->rx_pending = lp->rx_ring_size - 1;
+}
+
+static int pcnet32_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
+{
+ struct pcnet32_private *lp = dev->priv;
+ unsigned long flags;
+ int i;
+
+ if (ering->rx_mini_pending || ering->rx_jumbo_pending)
+ return -EINVAL;
+
+ if (netif_running(dev))
+ pcnet32_close(dev);
+
+ spin_lock_irqsave(&lp->lock, flags);
+ pcnet32_free_ring(dev);
+ lp->tx_ring_size = min(ering->tx_pending, (unsigned int) TX_MAX_RING_SIZE);
+ lp->rx_ring_size = min(ering->rx_pending, (unsigned int) RX_MAX_RING_SIZE);
+
+ /* set the minimum ring size to 4, to allow the loopback test to work
+ * unchanged.
+ */
+ for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) {
+ if (lp->tx_ring_size <= (1 << i))
+ break;
+ }
+ lp->tx_ring_size = (1 << i);
+ lp->tx_mod_mask = lp->tx_ring_size - 1;
+ lp->tx_len_bits = (i << 12);
+
+ for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) {
+ if (lp->rx_ring_size <= (1 << i))
+ break;
+ }
+ lp->rx_ring_size = (1 << i);
+ lp->rx_mod_mask = lp->rx_ring_size - 1;
+ lp->rx_len_bits = (i << 4);
+
+ if (pcnet32_alloc_ring(dev)) {
+ pcnet32_free_ring(dev);
+ return -ENOMEM;
+ }
+
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk(KERN_INFO PFX "Ring Param Settings: RX: %d, TX: %d\n", lp->rx_ring_size, lp->tx_ring_size);
+
+ if (netif_running(dev))
+ pcnet32_open(dev);
+
+ return 0;
}
static void pcnet32_get_strings(struct net_device *dev, u32 stringset, u8 *data)
@@ -948,6 +1014,7 @@ static struct ethtool_ops pcnet32_ethtool_ops = {
.nway_reset = pcnet32_nway_reset,
.get_link = pcnet32_get_link,
.get_ringparam = pcnet32_get_ringparam,
+ .set_ringparam = pcnet32_set_ringparam,
.get_tx_csum = ethtool_op_get_tx_csum,
.get_sg = ethtool_op_get_sg,
.get_tso = ethtool_op_get_tso,
@@ -957,6 +1024,7 @@ static struct ethtool_ops pcnet32_ethtool_ops = {
.phys_id = pcnet32_phys_id,
.get_regs_len = pcnet32_get_regs_len,
.get_regs = pcnet32_get_regs,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
/* only probes for non-PCI devices, the rest are handled by
@@ -1185,9 +1253,10 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
memcpy(dev->dev_addr, promaddr, 6);
}
}
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
/* if the ethernet address is not valid, force to 00:00:00:00:00:00 */
- if (!is_valid_ether_addr(dev->dev_addr))
+ if (!is_valid_ether_addr(dev->perm_addr))
memset(dev->dev_addr, 0, sizeof(dev->dev_addr));
if (pcnet32_debug & NETIF_MSG_PROBE) {
@@ -1239,6 +1308,12 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
dev->priv = lp;
lp->name = chipname;
lp->shared_irq = shared;
+ lp->tx_ring_size = TX_RING_SIZE; /* default tx ring size */
+ lp->rx_ring_size = RX_RING_SIZE; /* default rx ring size */
+ lp->tx_mod_mask = lp->tx_ring_size - 1;
+ lp->rx_mod_mask = lp->rx_ring_size - 1;
+ lp->tx_len_bits = (PCNET32_LOG_TX_BUFFERS << 12);
+ lp->rx_len_bits = (PCNET32_LOG_RX_BUFFERS << 4);
lp->mii_if.full_duplex = fdx;
lp->mii_if.phy_id_mask = 0x1f;
lp->mii_if.reg_num_mask = 0x1f;
@@ -1265,21 +1340,23 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
}
lp->a = *a;
+ if (pcnet32_alloc_ring(dev)) {
+ ret = -ENOMEM;
+ goto err_free_ring;
+ }
/* detect special T1/E1 WAN card by checking for MAC address */
if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0
&& dev->dev_addr[2] == 0x75)
lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI;
lp->init_block.mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */
- lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
+ lp->init_block.tlen_rlen = le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits);
for (i = 0; i < 6; i++)
lp->init_block.phys_addr[i] = dev->dev_addr[i];
lp->init_block.filter[0] = 0x00000000;
lp->init_block.filter[1] = 0x00000000;
- lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr +
- offsetof(struct pcnet32_private, rx_ring));
- lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr +
- offsetof(struct pcnet32_private, tx_ring));
+ lp->init_block.rx_ring = (u32)le32_to_cpu(lp->rx_ring_dma_addr);
+ lp->init_block.tx_ring = (u32)le32_to_cpu(lp->tx_ring_dma_addr);
/* switch pcnet32 to 32bit mode */
a->write_bcr(ioaddr, 20, 2);
@@ -1310,7 +1387,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(", failed to detect IRQ line.\n");
ret = -ENODEV;
- goto err_free_consistent;
+ goto err_free_ring;
}
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(", probed IRQ %d.\n", dev->irq);
@@ -1341,7 +1418,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
/* Fill in the generic fields of the device structure. */
if (register_netdev(dev))
- goto err_free_consistent;
+ goto err_free_ring;
if (pdev) {
pci_set_drvdata(pdev, dev);
@@ -1359,6 +1436,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
return 0;
+err_free_ring:
+ pcnet32_free_ring(dev);
err_free_consistent:
pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
err_free_netdev:
@@ -1369,6 +1448,86 @@ err_release_region:
}
+static int pcnet32_alloc_ring(struct net_device *dev)
+{
+ struct pcnet32_private *lp = dev->priv;
+
+ if ((lp->tx_ring = pci_alloc_consistent(lp->pci_dev, sizeof(struct pcnet32_tx_head) * lp->tx_ring_size,
+ &lp->tx_ring_dma_addr)) == NULL) {
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk(KERN_ERR PFX "Consistent memory allocation failed.\n");
+ return -ENOMEM;
+ }
+
+ if ((lp->rx_ring = pci_alloc_consistent(lp->pci_dev, sizeof(struct pcnet32_rx_head) * lp->rx_ring_size,
+ &lp->rx_ring_dma_addr)) == NULL) {
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk(KERN_ERR PFX "Consistent memory allocation failed.\n");
+ return -ENOMEM;
+ }
+
+ if (!(lp->tx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->tx_ring_size, GFP_ATOMIC))) {
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk(KERN_ERR PFX "Memory allocation failed.\n");
+ return -ENOMEM;
+ }
+ memset(lp->tx_dma_addr, 0, sizeof(dma_addr_t) * lp->tx_ring_size);
+
+ if (!(lp->rx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->rx_ring_size, GFP_ATOMIC))) {
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk(KERN_ERR PFX "Memory allocation failed.\n");
+ return -ENOMEM;
+ }
+ memset(lp->rx_dma_addr, 0, sizeof(dma_addr_t) * lp->rx_ring_size);
+
+ if (!(lp->tx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->tx_ring_size, GFP_ATOMIC))) {
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk(KERN_ERR PFX "Memory allocation failed.\n");
+ return -ENOMEM;
+ }
+ memset(lp->tx_skbuff, 0, sizeof(struct sk_buff *) * lp->tx_ring_size);
+
+ if (!(lp->rx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->rx_ring_size, GFP_ATOMIC))) {
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk(KERN_ERR PFX "Memory allocation failed.\n");
+ return -ENOMEM;
+ }
+ memset(lp->rx_skbuff, 0, sizeof(struct sk_buff *) * lp->rx_ring_size);
+
+ return 0;
+}
+
+
+static void pcnet32_free_ring(struct net_device *dev)
+{
+ struct pcnet32_private *lp = dev->priv;
+
+ kfree(lp->tx_skbuff);
+ lp->tx_skbuff = NULL;
+
+ kfree(lp->rx_skbuff);
+ lp->rx_skbuff = NULL;
+
+ kfree(lp->tx_dma_addr);
+ lp->tx_dma_addr = NULL;
+
+ kfree(lp->rx_dma_addr);
+ lp->rx_dma_addr = NULL;
+
+ if (lp->tx_ring) {
+ pci_free_consistent(lp->pci_dev, sizeof(struct pcnet32_tx_head) * lp->tx_ring_size,
+ lp->tx_ring, lp->tx_ring_dma_addr);
+ lp->tx_ring = NULL;
+ }
+
+ if (lp->rx_ring) {
+ pci_free_consistent(lp->pci_dev, sizeof(struct pcnet32_rx_head) * lp->rx_ring_size,
+ lp->rx_ring, lp->rx_ring_dma_addr);
+ lp->rx_ring = NULL;
+ }
+}
+
+
static int
pcnet32_open(struct net_device *dev)
{
@@ -1400,8 +1559,8 @@ pcnet32_open(struct net_device *dev)
if (netif_msg_ifup(lp))
printk(KERN_DEBUG "%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n",
dev->name, dev->irq,
- (u32) (lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)),
- (u32) (lp->dma_addr + offsetof(struct pcnet32_private, rx_ring)),
+ (u32) (lp->tx_ring_dma_addr),
+ (u32) (lp->rx_ring_dma_addr),
(u32) (lp->dma_addr + offsetof(struct pcnet32_private, init_block)));
/* set/reset autoselect bit */
@@ -1521,7 +1680,7 @@ pcnet32_open(struct net_device *dev)
err_free_ring:
/* free any allocated skbuffs */
- for (i = 0; i < RX_RING_SIZE; i++) {
+ for (i = 0; i < lp->rx_ring_size; i++) {
lp->rx_ring[i].status = 0;
if (lp->rx_skbuff[i]) {
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2,
@@ -1531,6 +1690,9 @@ err_free_ring:
lp->rx_skbuff[i] = NULL;
lp->rx_dma_addr[i] = 0;
}
+
+ pcnet32_free_ring(dev);
+
/*
* Switch back to 16bit mode to avoid problems with dumb
* DOS packet driver after a warm reboot
@@ -1562,7 +1724,7 @@ pcnet32_purge_tx_ring(struct net_device *dev)
struct pcnet32_private *lp = dev->priv;
int i;
- for (i = 0; i < TX_RING_SIZE; i++) {
+ for (i = 0; i < lp->tx_ring_size; i++) {
lp->tx_ring[i].status = 0; /* CPU owns buffer */
wmb(); /* Make sure adapter sees owner change */
if (lp->tx_skbuff[i]) {
@@ -1587,7 +1749,7 @@ pcnet32_init_ring(struct net_device *dev)
lp->cur_rx = lp->cur_tx = 0;
lp->dirty_rx = lp->dirty_tx = 0;
- for (i = 0; i < RX_RING_SIZE; i++) {
+ for (i = 0; i < lp->rx_ring_size; i++) {
struct sk_buff *rx_skbuff = lp->rx_skbuff[i];
if (rx_skbuff == NULL) {
if (!(rx_skbuff = lp->rx_skbuff[i] = dev_alloc_skb (PKT_BUF_SZ))) {
@@ -1611,20 +1773,18 @@ pcnet32_init_ring(struct net_device *dev)
}
/* The Tx buffer address is filled in as needed, but we do need to clear
* the upper ownership bit. */
- for (i = 0; i < TX_RING_SIZE; i++) {
+ for (i = 0; i < lp->tx_ring_size; i++) {
lp->tx_ring[i].status = 0; /* CPU owns buffer */
wmb(); /* Make sure adapter sees owner change */
lp->tx_ring[i].base = 0;
lp->tx_dma_addr[i] = 0;
}
- lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
+ lp->init_block.tlen_rlen = le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits);
for (i = 0; i < 6; i++)
lp->init_block.phys_addr[i] = dev->dev_addr[i];
- lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr +
- offsetof(struct pcnet32_private, rx_ring));
- lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr +
- offsetof(struct pcnet32_private, tx_ring));
+ lp->init_block.rx_ring = (u32)le32_to_cpu(lp->rx_ring_dma_addr);
+ lp->init_block.tx_ring = (u32)le32_to_cpu(lp->tx_ring_dma_addr);
wmb(); /* Make sure all changes are visible */
return 0;
}
@@ -1682,13 +1842,13 @@ pcnet32_tx_timeout (struct net_device *dev)
printk(KERN_DEBUG " Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "",
lp->cur_rx);
- for (i = 0 ; i < RX_RING_SIZE; i++)
+ for (i = 0 ; i < lp->rx_ring_size; i++)
printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
le32_to_cpu(lp->rx_ring[i].base),
(-le16_to_cpu(lp->rx_ring[i].buf_length)) & 0xffff,
le32_to_cpu(lp->rx_ring[i].msg_length),
le16_to_cpu(lp->rx_ring[i].status));
- for (i = 0 ; i < TX_RING_SIZE; i++)
+ for (i = 0 ; i < lp->tx_ring_size; i++)
printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
le32_to_cpu(lp->tx_ring[i].base),
(-le16_to_cpu(lp->tx_ring[i].length)) & 0xffff,
@@ -1729,7 +1889,7 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Fill in a Tx ring entry */
/* Mask to ring buffer boundary. */
- entry = lp->cur_tx & TX_RING_MOD_MASK;
+ entry = lp->cur_tx & lp->tx_mod_mask;
/* Caution: the write order is important here, set the status
* with the "ownership" bits last. */
@@ -1753,7 +1913,7 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
- if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base != 0) {
+ if (lp->tx_ring[(entry+1) & lp->tx_mod_mask].base != 0) {
lp->tx_full = 1;
netif_stop_queue(dev);
}
@@ -1806,7 +1966,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
int delta;
while (dirty_tx != lp->cur_tx) {
- int entry = dirty_tx & TX_RING_MOD_MASK;
+ int entry = dirty_tx & lp->tx_mod_mask;
int status = (short)le16_to_cpu(lp->tx_ring[entry].status);
if (status < 0)
@@ -1864,18 +2024,18 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
dirty_tx++;
}
- delta = (lp->cur_tx - dirty_tx) & (TX_RING_MOD_MASK + TX_RING_SIZE);
- if (delta > TX_RING_SIZE) {
+ delta = (lp->cur_tx - dirty_tx) & (lp->tx_mod_mask + lp->tx_ring_size);
+ if (delta > lp->tx_ring_size) {
if (netif_msg_drv(lp))
printk(KERN_ERR "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
dev->name, dirty_tx, lp->cur_tx, lp->tx_full);
- dirty_tx += TX_RING_SIZE;
- delta -= TX_RING_SIZE;
+ dirty_tx += lp->tx_ring_size;
+ delta -= lp->tx_ring_size;
}
if (lp->tx_full &&
netif_queue_stopped(dev) &&
- delta < TX_RING_SIZE - 2) {
+ delta < lp->tx_ring_size - 2) {
/* The ring is no longer full, clear tbusy. */
lp->tx_full = 0;
netif_wake_queue (dev);
@@ -1932,8 +2092,8 @@ static int
pcnet32_rx(struct net_device *dev)
{
struct pcnet32_private *lp = dev->priv;
- int entry = lp->cur_rx & RX_RING_MOD_MASK;
- int boguscnt = RX_RING_SIZE / 2;
+ int entry = lp->cur_rx & lp->rx_mod_mask;
+ int boguscnt = lp->rx_ring_size / 2;
/* If we own the next entry, it's a new packet. Send it up. */
while ((short)le16_to_cpu(lp->rx_ring[entry].status) >= 0) {
@@ -1998,12 +2158,12 @@ pcnet32_rx(struct net_device *dev)
if (netif_msg_drv(lp))
printk(KERN_ERR "%s: Memory squeeze, deferring packet.\n",
dev->name);
- for (i = 0; i < RX_RING_SIZE; i++)
+ for (i = 0; i < lp->rx_ring_size; i++)
if ((short)le16_to_cpu(lp->rx_ring[(entry+i)
- & RX_RING_MOD_MASK].status) < 0)
+ & lp->rx_mod_mask].status) < 0)
break;
- if (i > RX_RING_SIZE -2) {
+ if (i > lp->rx_ring_size -2) {
lp->stats.rx_dropped++;
lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
wmb(); /* Make sure adapter sees owner change */
@@ -2041,7 +2201,7 @@ pcnet32_rx(struct net_device *dev)
lp->rx_ring[entry].buf_length = le16_to_cpu(2-PKT_BUF_SZ);
wmb(); /* Make sure owner changes after all others are visible */
lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
- entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
+ entry = (++lp->cur_rx) & lp->rx_mod_mask;
if (--boguscnt <= 0) break; /* don't stay in loop forever */
}
@@ -2084,7 +2244,7 @@ pcnet32_close(struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags);
/* free all allocated skbuffs */
- for (i = 0; i < RX_RING_SIZE; i++) {
+ for (i = 0; i < lp->rx_ring_size; i++) {
lp->rx_ring[i].status = 0;
wmb(); /* Make sure adapter sees owner change */
if (lp->rx_skbuff[i]) {
@@ -2096,7 +2256,7 @@ pcnet32_close(struct net_device *dev)
lp->rx_dma_addr[i] = 0;
}
- for (i = 0; i < TX_RING_SIZE; i++) {
+ for (i = 0; i < lp->tx_ring_size; i++) {
lp->tx_ring[i].status = 0; /* CPU owns buffer */
wmb(); /* Make sure adapter sees owner change */
if (lp->tx_skbuff[i]) {
@@ -2265,6 +2425,7 @@ static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
struct pcnet32_private *lp = dev->priv;
unregister_netdev(dev);
+ pcnet32_free_ring(dev);
release_region(dev->base_addr, PCNET32_TOTAL_SIZE);
pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
free_netdev(dev);
@@ -2340,6 +2501,7 @@ static void __exit pcnet32_cleanup_module(void)
struct pcnet32_private *lp = pcnet32_dev->priv;
next_dev = lp->next;
unregister_netdev(pcnet32_dev);
+ pcnet32_free_ring(pcnet32_dev);
release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE);
pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
free_netdev(pcnet32_dev);
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 14f4de1a818028..c782a632980571 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -12,14 +12,6 @@ config PHYLIB
devices. This option provides infrastructure for
managing PHY devices.
-config PHYCONTROL
- bool " Support for automatically handling PHY state changes"
- depends on PHYLIB
- help
- Adds code to perform all the work for keeping PHY link
- state (speed/duplex/etc) up-to-date. Also handles
- interrupts.
-
comment "MII PHY device drivers"
depends on PHYLIB
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 90630672703d1c..ad93b0da87f020 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -133,13 +133,9 @@ static int mdio_bus_suspend(struct device * dev, pm_message_t state)
int ret = 0;
struct device_driver *drv = dev->driver;
- if (drv && drv->suspend) {
- ret = drv->suspend(dev, state, SUSPEND_DISABLE);
- if (ret == 0)
- ret = drv->suspend(dev, state, SUSPEND_SAVE_STATE);
- if (ret == 0)
- ret = drv->suspend(dev, state, SUSPEND_POWER_DOWN);
- }
+ if (drv && drv->suspend)
+ ret = drv->suspend(dev, state);
+
return ret;
}
@@ -148,13 +144,9 @@ static int mdio_bus_resume(struct device * dev)
int ret = 0;
struct device_driver *drv = dev->driver;
- if (drv && drv->resume) {
- ret = drv->resume(dev, RESUME_POWER_ON);
- if (ret == 0)
- ret = drv->resume(dev, RESUME_RESTORE_STATE);
- if (ret == 0)
- ret = drv->resume(dev, RESUME_ENABLE);
- }
+ if (drv && drv->resume)
+ ret = drv->resume(dev);
+
return ret;
}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index d9e11f93bf3a34..9209da9dde0da9 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -242,10 +242,6 @@ EXPORT_SYMBOL(phy_sanitize_settings);
* choose the next best ones from the ones selected, so we don't
* care if ethtool tries to give us bad values
*
- * A note about the PHYCONTROL Layer. If you turn off
- * CONFIG_PHYCONTROL, you will need to read the PHY status
- * registers after this function completes, and update your
- * controller manually.
*/
int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
{
@@ -380,7 +376,6 @@ int phy_start_aneg(struct phy_device *phydev)
err = phydev->drv->config_aneg(phydev);
-#ifdef CONFIG_PHYCONTROL
if (err < 0)
goto out_unlock;
@@ -395,14 +390,12 @@ int phy_start_aneg(struct phy_device *phydev)
}
out_unlock:
-#endif
spin_unlock(&phydev->lock);
return err;
}
EXPORT_SYMBOL(phy_start_aneg);
-#ifdef CONFIG_PHYCONTROL
static void phy_change(void *data);
static void phy_timer(unsigned long data);
@@ -868,4 +861,3 @@ static void phy_timer(unsigned long data)
mod_timer(&phydev->phy_timer, jiffies + PHY_STATE_TIME * HZ);
}
-#endif /* CONFIG_PHYCONTROL */
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 33f7bdb5857c8d..6da1aa0706a144 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -101,7 +101,6 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
return dev;
}
-#ifdef CONFIG_PHYCONTROL
/* phy_prepare_link:
*
* description: Tells the PHY infrastructure to handle the
@@ -160,8 +159,6 @@ void phy_disconnect(struct phy_device *phydev)
}
EXPORT_SYMBOL(phy_disconnect);
-#endif /* CONFIG_PHYCONTROL */
-
/* phy_attach:
*
* description: Called by drivers to attach to a particular PHY
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 0df7e92b0bf8d5..d3c9958b00d06d 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -863,7 +863,7 @@ static int __init ppp_init(void)
err = PTR_ERR(ppp_class);
goto out_chrdev;
}
- class_device_create(ppp_class, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
+ class_device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
err = devfs_mk_cdev(MKDEV(PPP_MAJOR, 0),
S_IFCHR|S_IRUSR|S_IWUSR, "ppp");
if (err)
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index afb3f186b8843b..159b56a56ef491 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1027,6 +1027,7 @@ static struct ethtool_ops rtl8169_ethtool_ops = {
.get_strings = rtl8169_get_strings,
.get_stats_count = rtl8169_get_stats_count,
.get_ethtool_stats = rtl8169_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum,
@@ -1511,6 +1512,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Get MAC address. FIXME: read EEPROM */
for (i = 0; i < MAC_ADDR_LEN; i++)
dev->dev_addr[i] = RTL_R8(MAC0 + i);
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
dev->open = rtl8169_open;
dev->hard_start_xmit = rtl8169_start_xmit;
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
new file mode 100644
index 00000000000000..12cde060458050
--- /dev/null
+++ b/drivers/net/rionet.c
@@ -0,0 +1,574 @@
+/*
+ * rionet - Ethernet driver over RapidIO messaging services
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/rio.h>
+#include <linux/rio_drv.h>
+#include <linux/rio_ids.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/crc32.h>
+#include <linux/ethtool.h>
+
+#define DRV_NAME "rionet"
+#define DRV_VERSION "0.2"
+#define DRV_AUTHOR "Matt Porter <mporter@kernel.crashing.org>"
+#define DRV_DESC "Ethernet over RapidIO"
+
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_LICENSE("GPL");
+
+#define RIONET_DEFAULT_MSGLEVEL \
+ (NETIF_MSG_DRV | \
+ NETIF_MSG_LINK | \
+ NETIF_MSG_RX_ERR | \
+ NETIF_MSG_TX_ERR)
+
+#define RIONET_DOORBELL_JOIN 0x1000
+#define RIONET_DOORBELL_LEAVE 0x1001
+
+#define RIONET_MAILBOX 0
+
+#define RIONET_TX_RING_SIZE CONFIG_RIONET_TX_SIZE
+#define RIONET_RX_RING_SIZE CONFIG_RIONET_RX_SIZE
+
+static LIST_HEAD(rionet_peers);
+
+struct rionet_private {
+ struct rio_mport *mport;
+ struct sk_buff *rx_skb[RIONET_RX_RING_SIZE];
+ struct sk_buff *tx_skb[RIONET_TX_RING_SIZE];
+ struct net_device_stats stats;
+ int rx_slot;
+ int tx_slot;
+ int tx_cnt;
+ int ack_slot;
+ spinlock_t lock;
+ spinlock_t tx_lock;
+ u32 msg_enable;
+};
+
+struct rionet_peer {
+ struct list_head node;
+ struct rio_dev *rdev;
+ struct resource *res;
+};
+
+static int rionet_check = 0;
+static int rionet_capable = 1;
+
+/*
+ * This is a fast lookup table for for translating TX
+ * Ethernet packets into a destination RIO device. It
+ * could be made into a hash table to save memory depending
+ * on system trade-offs.
+ */
+static struct rio_dev *rionet_active[RIO_MAX_ROUTE_ENTRIES];
+
+#define is_rionet_capable(pef, src_ops, dst_ops) \
+ ((pef & RIO_PEF_INB_MBOX) && \
+ (pef & RIO_PEF_INB_DOORBELL) && \
+ (src_ops & RIO_SRC_OPS_DOORBELL) && \
+ (dst_ops & RIO_DST_OPS_DOORBELL))
+#define dev_rionet_capable(dev) \
+ is_rionet_capable(dev->pef, dev->src_ops, dev->dst_ops)
+
+#define RIONET_MAC_MATCH(x) (*(u32 *)x == 0x00010001)
+#define RIONET_GET_DESTID(x) (*(u16 *)(x + 4))
+
+static struct net_device_stats *rionet_stats(struct net_device *ndev)
+{
+ struct rionet_private *rnet = ndev->priv;
+ return &rnet->stats;
+}
+
+static int rionet_rx_clean(struct net_device *ndev)
+{
+ int i;
+ int error = 0;
+ struct rionet_private *rnet = ndev->priv;
+ void *data;
+
+ i = rnet->rx_slot;
+
+ do {
+ if (!rnet->rx_skb[i])
+ continue;
+
+ if (!(data = rio_get_inb_message(rnet->mport, RIONET_MAILBOX)))
+ break;
+
+ rnet->rx_skb[i]->data = data;
+ skb_put(rnet->rx_skb[i], RIO_MAX_MSG_SIZE);
+ rnet->rx_skb[i]->dev = ndev;
+ rnet->rx_skb[i]->protocol =
+ eth_type_trans(rnet->rx_skb[i], ndev);
+ error = netif_rx(rnet->rx_skb[i]);
+
+ if (error == NET_RX_DROP) {
+ rnet->stats.rx_dropped++;
+ } else if (error == NET_RX_BAD) {
+ if (netif_msg_rx_err(rnet))
+ printk(KERN_WARNING "%s: bad rx packet\n",
+ DRV_NAME);
+ rnet->stats.rx_errors++;
+ } else {
+ rnet->stats.rx_packets++;
+ rnet->stats.rx_bytes += RIO_MAX_MSG_SIZE;
+ }
+
+ } while ((i = (i + 1) % RIONET_RX_RING_SIZE) != rnet->rx_slot);
+
+ return i;
+}
+
+static void rionet_rx_fill(struct net_device *ndev, int end)
+{
+ int i;
+ struct rionet_private *rnet = ndev->priv;
+
+ i = rnet->rx_slot;
+ do {
+ rnet->rx_skb[i] = dev_alloc_skb(RIO_MAX_MSG_SIZE);
+
+ if (!rnet->rx_skb[i])
+ break;
+
+ rio_add_inb_buffer(rnet->mport, RIONET_MAILBOX,
+ rnet->rx_skb[i]->data);
+ } while ((i = (i + 1) % RIONET_RX_RING_SIZE) != end);
+
+ rnet->rx_slot = i;
+}
+
+static int rionet_queue_tx_msg(struct sk_buff *skb, struct net_device *ndev,
+ struct rio_dev *rdev)
+{
+ struct rionet_private *rnet = ndev->priv;
+
+ rio_add_outb_message(rnet->mport, rdev, 0, skb->data, skb->len);
+ rnet->tx_skb[rnet->tx_slot] = skb;
+
+ rnet->stats.tx_packets++;
+ rnet->stats.tx_bytes += skb->len;
+
+ if (++rnet->tx_cnt == RIONET_TX_RING_SIZE)
+ netif_stop_queue(ndev);
+
+ ++rnet->tx_slot;
+ rnet->tx_slot &= (RIONET_TX_RING_SIZE - 1);
+
+ if (netif_msg_tx_queued(rnet))
+ printk(KERN_INFO "%s: queued skb %8.8x len %8.8x\n", DRV_NAME,
+ (u32) skb, skb->len);
+
+ return 0;
+}
+
+static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+ int i;
+ struct rionet_private *rnet = ndev->priv;
+ struct ethhdr *eth = (struct ethhdr *)skb->data;
+ u16 destid;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ if (!spin_trylock(&rnet->tx_lock)) {
+ local_irq_restore(flags);
+ return NETDEV_TX_LOCKED;
+ }
+
+ if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) {
+ netif_stop_queue(ndev);
+ spin_unlock_irqrestore(&rnet->tx_lock, flags);
+ printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n",
+ ndev->name);
+ return NETDEV_TX_BUSY;
+ }
+
+ if (eth->h_dest[0] & 0x01) {
+ for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++)
+ if (rionet_active[i])
+ rionet_queue_tx_msg(skb, ndev,
+ rionet_active[i]);
+ } else if (RIONET_MAC_MATCH(eth->h_dest)) {
+ destid = RIONET_GET_DESTID(eth->h_dest);
+ if (rionet_active[destid])
+ rionet_queue_tx_msg(skb, ndev, rionet_active[destid]);
+ }
+
+ spin_unlock_irqrestore(&rnet->tx_lock, flags);
+
+ return 0;
+}
+
+static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u16 tid,
+ u16 info)
+{
+ struct net_device *ndev = dev_id;
+ struct rionet_private *rnet = ndev->priv;
+ struct rionet_peer *peer;
+
+ if (netif_msg_intr(rnet))
+ printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x",
+ DRV_NAME, sid, tid, info);
+ if (info == RIONET_DOORBELL_JOIN) {
+ if (!rionet_active[sid]) {
+ list_for_each_entry(peer, &rionet_peers, node) {
+ if (peer->rdev->destid == sid)
+ rionet_active[sid] = peer->rdev;
+ }
+ rio_mport_send_doorbell(mport, sid,
+ RIONET_DOORBELL_JOIN);
+ }
+ } else if (info == RIONET_DOORBELL_LEAVE) {
+ rionet_active[sid] = NULL;
+ } else {
+ if (netif_msg_intr(rnet))
+ printk(KERN_WARNING "%s: unhandled doorbell\n",
+ DRV_NAME);
+ }
+}
+
+static void rionet_inb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
+{
+ int n;
+ struct net_device *ndev = dev_id;
+ struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
+
+ if (netif_msg_intr(rnet))
+ printk(KERN_INFO "%s: inbound message event, mbox %d slot %d\n",
+ DRV_NAME, mbox, slot);
+
+ spin_lock(&rnet->lock);
+ if ((n = rionet_rx_clean(ndev)) != rnet->rx_slot)
+ rionet_rx_fill(ndev, n);
+ spin_unlock(&rnet->lock);
+}
+
+static void rionet_outb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
+{
+ struct net_device *ndev = dev_id;
+ struct rionet_private *rnet = ndev->priv;
+
+ spin_lock(&rnet->lock);
+
+ if (netif_msg_intr(rnet))
+ printk(KERN_INFO
+ "%s: outbound message event, mbox %d slot %d\n",
+ DRV_NAME, mbox, slot);
+
+ while (rnet->tx_cnt && (rnet->ack_slot != slot)) {
+ /* dma unmap single */
+ dev_kfree_skb_irq(rnet->tx_skb[rnet->ack_slot]);
+ rnet->tx_skb[rnet->ack_slot] = NULL;
+ ++rnet->ack_slot;
+ rnet->ack_slot &= (RIONET_TX_RING_SIZE - 1);
+ rnet->tx_cnt--;
+ }
+
+ if (rnet->tx_cnt < RIONET_TX_RING_SIZE)
+ netif_wake_queue(ndev);
+
+ spin_unlock(&rnet->lock);
+}
+
+static int rionet_open(struct net_device *ndev)
+{
+ int i, rc = 0;
+ struct rionet_peer *peer, *tmp;
+ u32 pwdcsr;
+ struct rionet_private *rnet = ndev->priv;
+
+ if (netif_msg_ifup(rnet))
+ printk(KERN_INFO "%s: open\n", DRV_NAME);
+
+ if ((rc = rio_request_inb_dbell(rnet->mport,
+ (void *)ndev,
+ RIONET_DOORBELL_JOIN,
+ RIONET_DOORBELL_LEAVE,
+ rionet_dbell_event)) < 0)
+ goto out;
+
+ if ((rc = rio_request_inb_mbox(rnet->mport,
+ (void *)ndev,
+ RIONET_MAILBOX,
+ RIONET_RX_RING_SIZE,
+ rionet_inb_msg_event)) < 0)
+ goto out;
+
+ if ((rc = rio_request_outb_mbox(rnet->mport,
+ (void *)ndev,
+ RIONET_MAILBOX,
+ RIONET_TX_RING_SIZE,
+ rionet_outb_msg_event)) < 0)
+ goto out;
+
+ /* Initialize inbound message ring */
+ for (i = 0; i < RIONET_RX_RING_SIZE; i++)
+ rnet->rx_skb[i] = NULL;
+ rnet->rx_slot = 0;
+ rionet_rx_fill(ndev, 0);
+
+ rnet->tx_slot = 0;
+ rnet->tx_cnt = 0;
+ rnet->ack_slot = 0;
+
+ netif_carrier_on(ndev);
+ netif_start_queue(ndev);
+
+ list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+ if (!(peer->res = rio_request_outb_dbell(peer->rdev,
+ RIONET_DOORBELL_JOIN,
+ RIONET_DOORBELL_LEAVE)))
+ {
+ printk(KERN_ERR "%s: error requesting doorbells\n",
+ DRV_NAME);
+ continue;
+ }
+
+ /*
+ * If device has initialized inbound doorbells,
+ * send a join message
+ */
+ rio_read_config_32(peer->rdev, RIO_WRITE_PORT_CSR, &pwdcsr);
+ if (pwdcsr & RIO_DOORBELL_AVAIL)
+ rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN);
+ }
+
+ out:
+ return rc;
+}
+
+static int rionet_close(struct net_device *ndev)
+{
+ struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
+ struct rionet_peer *peer, *tmp;
+ int i;
+
+ if (netif_msg_ifup(rnet))
+ printk(KERN_INFO "%s: close\n", DRV_NAME);
+
+ netif_stop_queue(ndev);
+ netif_carrier_off(ndev);
+
+ for (i = 0; i < RIONET_RX_RING_SIZE; i++)
+ if (rnet->rx_skb[i])
+ kfree_skb(rnet->rx_skb[i]);
+
+ list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+ if (rionet_active[peer->rdev->destid]) {
+ rio_send_doorbell(peer->rdev, RIONET_DOORBELL_LEAVE);
+ rionet_active[peer->rdev->destid] = NULL;
+ }
+ rio_release_outb_dbell(peer->rdev, peer->res);
+ }
+
+ rio_release_inb_dbell(rnet->mport, RIONET_DOORBELL_JOIN,
+ RIONET_DOORBELL_LEAVE);
+ rio_release_inb_mbox(rnet->mport, RIONET_MAILBOX);
+ rio_release_outb_mbox(rnet->mport, RIONET_MAILBOX);
+
+ return 0;
+}
+
+static void rionet_remove(struct rio_dev *rdev)
+{
+ struct net_device *ndev = NULL;
+ struct rionet_peer *peer, *tmp;
+
+ unregister_netdev(ndev);
+ kfree(ndev);
+
+ list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+ list_del(&peer->node);
+ kfree(peer);
+ }
+}
+
+static void rionet_get_drvinfo(struct net_device *ndev,
+ struct ethtool_drvinfo *info)
+{
+ struct rionet_private *rnet = ndev->priv;
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->fw_version, "n/a");
+ strcpy(info->bus_info, rnet->mport->name);
+}
+
+static u32 rionet_get_msglevel(struct net_device *ndev)
+{
+ struct rionet_private *rnet = ndev->priv;
+
+ return rnet->msg_enable;
+}
+
+static void rionet_set_msglevel(struct net_device *ndev, u32 value)
+{
+ struct rionet_private *rnet = ndev->priv;
+
+ rnet->msg_enable = value;
+}
+
+static struct ethtool_ops rionet_ethtool_ops = {
+ .get_drvinfo = rionet_get_drvinfo,
+ .get_msglevel = rionet_get_msglevel,
+ .set_msglevel = rionet_set_msglevel,
+ .get_link = ethtool_op_get_link,
+};
+
+static int rionet_setup_netdev(struct rio_mport *mport)
+{
+ int rc = 0;
+ struct net_device *ndev = NULL;
+ struct rionet_private *rnet;
+ u16 device_id;
+
+ /* Allocate our net_device structure */
+ ndev = alloc_etherdev(sizeof(struct rionet_private));
+ if (ndev == NULL) {
+ printk(KERN_INFO "%s: could not allocate ethernet device.\n",
+ DRV_NAME);
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ /* Set up private area */
+ rnet = (struct rionet_private *)ndev->priv;
+ rnet->mport = mport;
+
+ /* Set the default MAC address */
+ device_id = rio_local_get_device_id(mport);
+ ndev->dev_addr[0] = 0x00;
+ ndev->dev_addr[1] = 0x01;
+ ndev->dev_addr[2] = 0x00;
+ ndev->dev_addr[3] = 0x01;
+ ndev->dev_addr[4] = device_id >> 8;
+ ndev->dev_addr[5] = device_id & 0xff;
+
+ /* Fill in the driver function table */
+ ndev->open = &rionet_open;
+ ndev->hard_start_xmit = &rionet_start_xmit;
+ ndev->stop = &rionet_close;
+ ndev->get_stats = &rionet_stats;
+ ndev->mtu = RIO_MAX_MSG_SIZE - 14;
+ ndev->features = NETIF_F_LLTX;
+ SET_ETHTOOL_OPS(ndev, &rionet_ethtool_ops);
+
+ SET_MODULE_OWNER(ndev);
+
+ spin_lock_init(&rnet->lock);
+ spin_lock_init(&rnet->tx_lock);
+
+ rnet->msg_enable = RIONET_DEFAULT_MSGLEVEL;
+
+ rc = register_netdev(ndev);
+ if (rc != 0)
+ goto out;
+
+ printk("%s: %s %s Version %s, MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+ ndev->name,
+ DRV_NAME,
+ DRV_DESC,
+ DRV_VERSION,
+ ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
+ ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
+
+ out:
+ return rc;
+}
+
+/*
+ * XXX Make multi-net safe
+ */
+static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
+{
+ int rc = -ENODEV;
+ u32 lpef, lsrc_ops, ldst_ops;
+ struct rionet_peer *peer;
+
+ /* If local device is not rionet capable, give up quickly */
+ if (!rionet_capable)
+ goto out;
+
+ /*
+ * First time through, make sure local device is rionet
+ * capable, setup netdev, and set flags so this is skipped
+ * on later probes
+ */
+ if (!rionet_check) {
+ rio_local_read_config_32(rdev->net->hport, RIO_PEF_CAR, &lpef);
+ rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR,
+ &lsrc_ops);
+ rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR,
+ &ldst_ops);
+ if (!is_rionet_capable(lpef, lsrc_ops, ldst_ops)) {
+ printk(KERN_ERR
+ "%s: local device is not network capable\n",
+ DRV_NAME);
+ rionet_check = 1;
+ rionet_capable = 0;
+ goto out;
+ }
+
+ rc = rionet_setup_netdev(rdev->net->hport);
+ rionet_check = 1;
+ }
+
+ /*
+ * If the remote device has mailbox/doorbell capabilities,
+ * add it to the peer list.
+ */
+ if (dev_rionet_capable(rdev)) {
+ if (!(peer = kmalloc(sizeof(struct rionet_peer), GFP_KERNEL))) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ peer->rdev = rdev;
+ list_add_tail(&peer->node, &rionet_peers);
+ }
+
+ out:
+ return rc;
+}
+
+static struct rio_device_id rionet_id_table[] = {
+ {RIO_DEVICE(RIO_ANY_ID, RIO_ANY_ID)}
+};
+
+static struct rio_driver rionet_driver = {
+ .name = "rionet",
+ .id_table = rionet_id_table,
+ .probe = rionet_probe,
+ .remove = rionet_remove,
+};
+
+static int __init rionet_init(void)
+{
+ return rio_register_driver(&rionet_driver);
+}
+
+static void __exit rionet_exit(void)
+{
+ rio_unregister_driver(&rionet_driver);
+}
+
+module_init(rionet_init);
+module_exit(rionet_exit);
diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h
index 7cefe5507b9e12..00179bc3437fcc 100644
--- a/drivers/net/s2io-regs.h
+++ b/drivers/net/s2io-regs.h
@@ -814,6 +814,17 @@ typedef struct _XENA_dev_config {
u64 rxgxs_ber_0; /* CHANGED */
u64 rxgxs_ber_1; /* CHANGED */
+ u64 spi_control;
+#define SPI_CONTROL_KEY(key) vBIT(key,0,4)
+#define SPI_CONTROL_BYTECNT(cnt) vBIT(cnt,29,3)
+#define SPI_CONTROL_CMD(cmd) vBIT(cmd,32,8)
+#define SPI_CONTROL_ADDR(addr) vBIT(addr,40,24)
+#define SPI_CONTROL_SEL1 BIT(4)
+#define SPI_CONTROL_REQ BIT(7)
+#define SPI_CONTROL_NACK BIT(5)
+#define SPI_CONTROL_DONE BIT(6)
+ u64 spi_data;
+#define SPI_DATA_WRITE(data,len) vBIT(data,0,len)
} XENA_dev_config_t;
#define XENA_REG_SPACE sizeof(XENA_dev_config_t)
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index dd451e099a4c46..d303d162974f9c 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -65,9 +65,11 @@
#include "s2io.h"
#include "s2io-regs.h"
+#define DRV_VERSION "Version 2.0.9.1"
+
/* S2io Driver name & version. */
static char s2io_driver_name[] = "Neterion";
-static char s2io_driver_version[] = "Version 2.0.8.1";
+static char s2io_driver_version[] = DRV_VERSION;
static inline int RXD_IS_UP2DT(RxD_t *rxdp)
{
@@ -307,6 +309,8 @@ static unsigned int indicate_max_pkts;
#endif
/* Frequency of Rx desc syncs expressed as power of 2 */
static unsigned int rxsync_frequency = 3;
+/* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */
+static unsigned int intr_type = 0;
/*
* S2IO device table.
@@ -1396,8 +1400,13 @@ static int init_nic(struct s2io_nic *nic)
writeq(val64, &bar0->rti_data1_mem);
val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
- RTI_DATA2_MEM_RX_UFC_B(0x2) |
- RTI_DATA2_MEM_RX_UFC_C(0x40) | RTI_DATA2_MEM_RX_UFC_D(0x80);
+ RTI_DATA2_MEM_RX_UFC_B(0x2) ;
+ if (nic->intr_type == MSI_X)
+ val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x20) | \
+ RTI_DATA2_MEM_RX_UFC_D(0x40));
+ else
+ val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x40) | \
+ RTI_DATA2_MEM_RX_UFC_D(0x80));
writeq(val64, &bar0->rti_data2_mem);
for (i = 0; i < config->rx_ring_num; i++) {
@@ -1507,17 +1516,15 @@ static int init_nic(struct s2io_nic *nic)
#define LINK_UP_DOWN_INTERRUPT 1
#define MAC_RMAC_ERR_TIMER 2
-#if defined(CONFIG_MSI_MODE) || defined(CONFIG_MSIX_MODE)
-#define s2io_link_fault_indication(x) MAC_RMAC_ERR_TIMER
-#else
int s2io_link_fault_indication(nic_t *nic)
{
+ if (nic->intr_type != INTA)
+ return MAC_RMAC_ERR_TIMER;
if (nic->device_type == XFRAME_II_DEVICE)
return LINK_UP_DOWN_INTERRUPT;
else
return MAC_RMAC_ERR_TIMER;
}
-#endif
/**
* en_dis_able_nic_intrs - Enable or Disable the interrupts
@@ -1941,11 +1948,14 @@ static int start_nic(struct s2io_nic *nic)
}
/* Enable select interrupts */
- interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
- interruptible |= TX_PIC_INTR | RX_PIC_INTR;
- interruptible |= TX_MAC_INTR | RX_MAC_INTR;
-
- en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
+ if (nic->intr_type != INTA)
+ en_dis_able_nic_intrs(nic, ENA_ALL_INTRS, DISABLE_INTRS);
+ else {
+ interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
+ interruptible |= TX_PIC_INTR | RX_PIC_INTR;
+ interruptible |= TX_MAC_INTR | RX_MAC_INTR;
+ en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
+ }
/*
* With some switches, link might be already up at this point.
@@ -2633,11 +2643,11 @@ static void tx_intr_handler(fifo_info_t *fifo_data)
err = txdlp->Control_1 & TXD_T_CODE;
if ((err >> 48) == 0xA) {
DBG_PRINT(TX_DBG, "TxD returned due \
- to loss of link\n");
+to loss of link\n");
}
else {
DBG_PRINT(ERR_DBG, "***TxD error \
- %llx\n", err);
+%llx\n", err);
}
}
@@ -2854,6 +2864,9 @@ void s2io_reset(nic_t * sp)
/* Set swapper to enable I/O register access */
s2io_set_swapper(sp);
+ /* Restore the MSIX table entries from local variables */
+ restore_xmsi_data(sp);
+
/* Clear certain PCI/PCI-X fields after reset */
if (sp->device_type == XFRAME_II_DEVICE) {
/* Clear parity err detect bit */
@@ -2983,8 +2996,9 @@ int s2io_set_swapper(nic_t * sp)
SWAPPER_CTRL_RXD_W_FE |
SWAPPER_CTRL_RXF_W_FE |
SWAPPER_CTRL_XMSI_FE |
- SWAPPER_CTRL_XMSI_SE |
SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
+ if (sp->intr_type == INTA)
+ val64 |= SWAPPER_CTRL_XMSI_SE;
writeq(val64, &bar0->swapper_ctrl);
#else
/*
@@ -3005,8 +3019,9 @@ int s2io_set_swapper(nic_t * sp)
SWAPPER_CTRL_RXD_W_SE |
SWAPPER_CTRL_RXF_W_FE |
SWAPPER_CTRL_XMSI_FE |
- SWAPPER_CTRL_XMSI_SE |
SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
+ if (sp->intr_type == INTA)
+ val64 |= SWAPPER_CTRL_XMSI_SE;
writeq(val64, &bar0->swapper_ctrl);
#endif
val64 = readq(&bar0->swapper_ctrl);
@@ -3028,6 +3043,201 @@ int s2io_set_swapper(nic_t * sp)
return SUCCESS;
}
+int wait_for_msix_trans(nic_t *nic, int i)
+{
+ XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+ u64 val64;
+ int ret = 0, cnt = 0;
+
+ do {
+ val64 = readq(&bar0->xmsi_access);
+ if (!(val64 & BIT(15)))
+ break;
+ mdelay(1);
+ cnt++;
+ } while(cnt < 5);
+ if (cnt == 5) {
+ DBG_PRINT(ERR_DBG, "XMSI # %d Access failed\n", i);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+void restore_xmsi_data(nic_t *nic)
+{
+ XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+ u64 val64;
+ int i;
+
+ for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+ writeq(nic->msix_info[i].addr, &bar0->xmsi_address);
+ writeq(nic->msix_info[i].data, &bar0->xmsi_data);
+ val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6));
+ writeq(val64, &bar0->xmsi_access);
+ if (wait_for_msix_trans(nic, i)) {
+ DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
+ continue;
+ }
+ }
+}
+
+void store_xmsi_data(nic_t *nic)
+{
+ XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+ u64 val64, addr, data;
+ int i;
+
+ /* Store and display */
+ for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+ val64 = (BIT(15) | vBIT(i, 26, 6));
+ writeq(val64, &bar0->xmsi_access);
+ if (wait_for_msix_trans(nic, i)) {
+ DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
+ continue;
+ }
+ addr = readq(&bar0->xmsi_address);
+ data = readq(&bar0->xmsi_data);
+ if (addr && data) {
+ nic->msix_info[i].addr = addr;
+ nic->msix_info[i].data = data;
+ }
+ }
+}
+
+int s2io_enable_msi(nic_t *nic)
+{
+ XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+ u16 msi_ctrl, msg_val;
+ struct config_param *config = &nic->config;
+ struct net_device *dev = nic->dev;
+ u64 val64, tx_mat, rx_mat;
+ int i, err;
+
+ val64 = readq(&bar0->pic_control);
+ val64 &= ~BIT(1);
+ writeq(val64, &bar0->pic_control);
+
+ err = pci_enable_msi(nic->pdev);
+ if (err) {
+ DBG_PRINT(ERR_DBG, "%s: enabling MSI failed\n",
+ nic->dev->name);
+ return err;
+ }
+
+ /*
+ * Enable MSI and use MSI-1 in stead of the standard MSI-0
+ * for interrupt handling.
+ */
+ pci_read_config_word(nic->pdev, 0x4c, &msg_val);
+ msg_val ^= 0x1;
+ pci_write_config_word(nic->pdev, 0x4c, msg_val);
+ pci_read_config_word(nic->pdev, 0x4c, &msg_val);
+
+ pci_read_config_word(nic->pdev, 0x42, &msi_ctrl);
+ msi_ctrl |= 0x10;
+ pci_write_config_word(nic->pdev, 0x42, msi_ctrl);
+
+ /* program MSI-1 into all usable Tx_Mat and Rx_Mat fields */
+ tx_mat = readq(&bar0->tx_mat0_n[0]);
+ for (i=0; i<config->tx_fifo_num; i++) {
+ tx_mat |= TX_MAT_SET(i, 1);
+ }
+ writeq(tx_mat, &bar0->tx_mat0_n[0]);
+
+ rx_mat = readq(&bar0->rx_mat);
+ for (i=0; i<config->rx_ring_num; i++) {
+ rx_mat |= RX_MAT_SET(i, 1);
+ }
+ writeq(rx_mat, &bar0->rx_mat);
+
+ dev->irq = nic->pdev->irq;
+ return 0;
+}
+
+int s2io_enable_msi_x(nic_t *nic)
+{
+ XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+ u64 tx_mat, rx_mat;
+ u16 msi_control; /* Temp variable */
+ int ret, i, j, msix_indx = 1;
+
+ nic->entries = kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct msix_entry),
+ GFP_KERNEL);
+ if (nic->entries == NULL) {
+ DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+ memset(nic->entries, 0, MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
+
+ nic->s2io_entries =
+ kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry),
+ GFP_KERNEL);
+ if (nic->s2io_entries == NULL) {
+ DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", __FUNCTION__);
+ kfree(nic->entries);
+ return -ENOMEM;
+ }
+ memset(nic->s2io_entries, 0,
+ MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
+
+ for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+ nic->entries[i].entry = i;
+ nic->s2io_entries[i].entry = i;
+ nic->s2io_entries[i].arg = NULL;
+ nic->s2io_entries[i].in_use = 0;
+ }
+
+ tx_mat = readq(&bar0->tx_mat0_n[0]);
+ for (i=0; i<nic->config.tx_fifo_num; i++, msix_indx++) {
+ tx_mat |= TX_MAT_SET(i, msix_indx);
+ nic->s2io_entries[msix_indx].arg = &nic->mac_control.fifos[i];
+ nic->s2io_entries[msix_indx].type = MSIX_FIFO_TYPE;
+ nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
+ }
+ writeq(tx_mat, &bar0->tx_mat0_n[0]);
+
+ if (!nic->config.bimodal) {
+ rx_mat = readq(&bar0->rx_mat);
+ for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) {
+ rx_mat |= RX_MAT_SET(j, msix_indx);
+ nic->s2io_entries[msix_indx].arg = &nic->mac_control.rings[j];
+ nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
+ nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
+ }
+ writeq(rx_mat, &bar0->rx_mat);
+ } else {
+ tx_mat = readq(&bar0->tx_mat0_n[7]);
+ for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) {
+ tx_mat |= TX_MAT_SET(i, msix_indx);
+ nic->s2io_entries[msix_indx].arg = &nic->mac_control.rings[j];
+ nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
+ nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
+ }
+ writeq(tx_mat, &bar0->tx_mat0_n[7]);
+ }
+
+ ret = pci_enable_msix(nic->pdev, nic->entries, MAX_REQUESTED_MSI_X);
+ if (ret) {
+ DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name);
+ kfree(nic->entries);
+ kfree(nic->s2io_entries);
+ nic->entries = NULL;
+ nic->s2io_entries = NULL;
+ return -ENOMEM;
+ }
+
+ /*
+ * To enable MSI-X, MSI also needs to be enabled, due to a bug
+ * in the herc NIC. (Temp change, needs to be removed later)
+ */
+ pci_read_config_word(nic->pdev, 0x42, &msi_control);
+ msi_control |= 0x1; /* Enable MSI */
+ pci_write_config_word(nic->pdev, 0x42, msi_control);
+
+ return 0;
+}
+
/* ********************************************************* *
* Functions defined below concern the OS part of the driver *
* ********************************************************* */
@@ -3048,6 +3258,8 @@ int s2io_open(struct net_device *dev)
{
nic_t *sp = dev->priv;
int err = 0;
+ int i;
+ u16 msi_control; /* Temp variable */
/*
* Make sure you have link off by default every time
@@ -3064,13 +3276,55 @@ int s2io_open(struct net_device *dev)
goto hw_init_failed;
}
+ /* Store the values of the MSIX table in the nic_t structure */
+ store_xmsi_data(sp);
+
/* After proper initialization of H/W, register ISR */
- err = request_irq((int) sp->pdev->irq, s2io_isr, SA_SHIRQ,
- sp->name, dev);
- if (err) {
- DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
- dev->name);
- goto isr_registration_failed;
+ if (sp->intr_type == MSI) {
+ err = request_irq((int) sp->pdev->irq, s2io_msi_handle,
+ SA_SHIRQ, sp->name, dev);
+ if (err) {
+ DBG_PRINT(ERR_DBG, "%s: MSI registration \
+failed\n", dev->name);
+ goto isr_registration_failed;
+ }
+ }
+ if (sp->intr_type == MSI_X) {
+ for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
+ if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) {
+ sprintf(sp->desc1, "%s:MSI-X-%d-TX",
+ dev->name, i);
+ err = request_irq(sp->entries[i].vector,
+ s2io_msix_fifo_handle, 0, sp->desc1,
+ sp->s2io_entries[i].arg);
+ DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc1,
+ sp->msix_info[i].addr);
+ } else {
+ sprintf(sp->desc2, "%s:MSI-X-%d-RX",
+ dev->name, i);
+ err = request_irq(sp->entries[i].vector,
+ s2io_msix_ring_handle, 0, sp->desc2,
+ sp->s2io_entries[i].arg);
+ DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc2,
+ sp->msix_info[i].addr);
+ }
+ if (err) {
+ DBG_PRINT(ERR_DBG, "%s: MSI-X-%d registration \
+failed\n", dev->name, i);
+ DBG_PRINT(ERR_DBG, "Returned: %d\n", err);
+ goto isr_registration_failed;
+ }
+ sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
+ }
+ }
+ if (sp->intr_type == INTA) {
+ err = request_irq((int) sp->pdev->irq, s2io_isr, SA_SHIRQ,
+ sp->name, dev);
+ if (err) {
+ DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
+ dev->name);
+ goto isr_registration_failed;
+ }
}
if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) {
@@ -3083,11 +3337,37 @@ int s2io_open(struct net_device *dev)
return 0;
setting_mac_address_failed:
- free_irq(sp->pdev->irq, dev);
+ if (sp->intr_type != MSI_X)
+ free_irq(sp->pdev->irq, dev);
isr_registration_failed:
del_timer_sync(&sp->alarm_timer);
+ if (sp->intr_type == MSI_X) {
+ if (sp->device_type == XFRAME_II_DEVICE) {
+ for (i=1; (sp->s2io_entries[i].in_use ==
+ MSIX_REGISTERED_SUCCESS); i++) {
+ int vector = sp->entries[i].vector;
+ void *arg = sp->s2io_entries[i].arg;
+
+ free_irq(vector, arg);
+ }
+ pci_disable_msix(sp->pdev);
+
+ /* Temp */
+ pci_read_config_word(sp->pdev, 0x42, &msi_control);
+ msi_control &= 0xFFFE; /* Disable MSI */
+ pci_write_config_word(sp->pdev, 0x42, msi_control);
+ }
+ }
+ else if (sp->intr_type == MSI)
+ pci_disable_msi(sp->pdev);
s2io_reset(sp);
hw_init_failed:
+ if (sp->intr_type == MSI_X) {
+ if (sp->entries)
+ kfree(sp->entries);
+ if (sp->s2io_entries)
+ kfree(sp->s2io_entries);
+ }
return err;
}
@@ -3107,12 +3387,35 @@ hw_init_failed:
int s2io_close(struct net_device *dev)
{
nic_t *sp = dev->priv;
+ int i;
+ u16 msi_control;
+
flush_scheduled_work();
netif_stop_queue(dev);
/* Reset card, kill tasklet and free Tx and Rx buffers. */
s2io_card_down(sp);
- free_irq(sp->pdev->irq, dev);
+ if (sp->intr_type == MSI_X) {
+ if (sp->device_type == XFRAME_II_DEVICE) {
+ for (i=1; (sp->s2io_entries[i].in_use ==
+ MSIX_REGISTERED_SUCCESS); i++) {
+ int vector = sp->entries[i].vector;
+ void *arg = sp->s2io_entries[i].arg;
+
+ free_irq(vector, arg);
+ }
+ pci_read_config_word(sp->pdev, 0x42, &msi_control);
+ msi_control &= 0xFFFE; /* Disable MSI */
+ pci_write_config_word(sp->pdev, 0x42, msi_control);
+
+ pci_disable_msix(sp->pdev);
+ }
+ }
+ else {
+ free_irq(sp->pdev->irq, dev);
+ if (sp->intr_type == MSI)
+ pci_disable_msi(sp->pdev);
+ }
sp->device_close_flag = TRUE; /* Device is shut down. */
return 0;
}
@@ -3278,6 +3581,104 @@ s2io_alarm_handle(unsigned long data)
mod_timer(&sp->alarm_timer, jiffies + HZ / 2);
}
+static irqreturn_t
+s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *) dev_id;
+ nic_t *sp = dev->priv;
+ int i;
+ int ret;
+ mac_info_t *mac_control;
+ struct config_param *config;
+
+ atomic_inc(&sp->isr_cnt);
+ mac_control = &sp->mac_control;
+ config = &sp->config;
+ DBG_PRINT(INTR_DBG, "%s: MSI handler\n", __FUNCTION__);
+
+ /* If Intr is because of Rx Traffic */
+ for (i = 0; i < config->rx_ring_num; i++)
+ rx_intr_handler(&mac_control->rings[i]);
+
+ /* If Intr is because of Tx Traffic */
+ for (i = 0; i < config->tx_fifo_num; i++)
+ tx_intr_handler(&mac_control->fifos[i]);
+
+ /*
+ * If the Rx buffer count is below the panic threshold then
+ * reallocate the buffers from the interrupt handler itself,
+ * else schedule a tasklet to reallocate the buffers.
+ */
+ for (i = 0; i < config->rx_ring_num; i++) {
+ int rxb_size = atomic_read(&sp->rx_bufs_left[i]);
+ int level = rx_buffer_level(sp, rxb_size, i);
+
+ if ((level == PANIC) && (!TASKLET_IN_USE)) {
+ DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", dev->name);
+ DBG_PRINT(INTR_DBG, "PANIC levels\n");
+ if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) {
+ DBG_PRINT(ERR_DBG, "%s:Out of memory",
+ dev->name);
+ DBG_PRINT(ERR_DBG, " in ISR!!\n");
+ clear_bit(0, (&sp->tasklet_status));
+ atomic_dec(&sp->isr_cnt);
+ return IRQ_HANDLED;
+ }
+ clear_bit(0, (&sp->tasklet_status));
+ } else if (level == LOW) {
+ tasklet_schedule(&sp->task);
+ }
+ }
+
+ atomic_dec(&sp->isr_cnt);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+ ring_info_t *ring = (ring_info_t *)dev_id;
+ nic_t *sp = ring->nic;
+ int rxb_size, level, rng_n;
+
+ atomic_inc(&sp->isr_cnt);
+ rx_intr_handler(ring);
+
+ rng_n = ring->ring_no;
+ rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]);
+ level = rx_buffer_level(sp, rxb_size, rng_n);
+
+ if ((level == PANIC) && (!TASKLET_IN_USE)) {
+ int ret;
+ DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__);
+ DBG_PRINT(INTR_DBG, "PANIC levels\n");
+ if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) {
+ DBG_PRINT(ERR_DBG, "Out of memory in %s",
+ __FUNCTION__);
+ clear_bit(0, (&sp->tasklet_status));
+ return IRQ_HANDLED;
+ }
+ clear_bit(0, (&sp->tasklet_status));
+ } else if (level == LOW) {
+ tasklet_schedule(&sp->task);
+ }
+ atomic_dec(&sp->isr_cnt);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+ fifo_info_t *fifo = (fifo_info_t *)dev_id;
+ nic_t *sp = fifo->nic;
+
+ atomic_inc(&sp->isr_cnt);
+ tx_intr_handler(fifo);
+ atomic_dec(&sp->isr_cnt);
+ return IRQ_HANDLED;
+}
+
static void s2io_txpic_intr_handle(nic_t *sp)
{
XENA_dev_config_t __iomem *bar0 = sp->bar0;
@@ -3778,11 +4179,10 @@ static void s2io_ethtool_gdrvinfo(struct net_device *dev,
{
nic_t *sp = dev->priv;
- strncpy(info->driver, s2io_driver_name, sizeof(s2io_driver_name));
- strncpy(info->version, s2io_driver_version,
- sizeof(s2io_driver_version));
- strncpy(info->fw_version, "", 32);
- strncpy(info->bus_info, pci_name(sp->pdev), 32);
+ strncpy(info->driver, s2io_driver_name, sizeof(info->driver));
+ strncpy(info->version, s2io_driver_version, sizeof(info->version));
+ strncpy(info->fw_version, "", sizeof(info->fw_version));
+ strncpy(info->bus_info, pci_name(sp->pdev), sizeof(info->bus_info));
info->regdump_len = XENA_REG_SPACE;
info->eedump_len = XENA_EEPROM_SPACE;
info->testinfo_len = S2IO_TEST_LEN;
@@ -3978,29 +4378,53 @@ static int s2io_ethtool_setpause_data(struct net_device *dev,
*/
#define S2IO_DEV_ID 5
-static int read_eeprom(nic_t * sp, int off, u32 * data)
+static int read_eeprom(nic_t * sp, int off, u64 * data)
{
int ret = -1;
u32 exit_cnt = 0;
u64 val64;
XENA_dev_config_t __iomem *bar0 = sp->bar0;
- val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
- I2C_CONTROL_BYTE_CNT(0x3) | I2C_CONTROL_READ |
- I2C_CONTROL_CNTL_START;
- SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
+ if (sp->device_type == XFRAME_I_DEVICE) {
+ val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
+ I2C_CONTROL_BYTE_CNT(0x3) | I2C_CONTROL_READ |
+ I2C_CONTROL_CNTL_START;
+ SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
- while (exit_cnt < 5) {
- val64 = readq(&bar0->i2c_control);
- if (I2C_CONTROL_CNTL_END(val64)) {
- *data = I2C_CONTROL_GET_DATA(val64);
- ret = 0;
- break;
+ while (exit_cnt < 5) {
+ val64 = readq(&bar0->i2c_control);
+ if (I2C_CONTROL_CNTL_END(val64)) {
+ *data = I2C_CONTROL_GET_DATA(val64);
+ ret = 0;
+ break;
+ }
+ msleep(50);
+ exit_cnt++;
}
- msleep(50);
- exit_cnt++;
}
+ if (sp->device_type == XFRAME_II_DEVICE) {
+ val64 = SPI_CONTROL_KEY(0x9) | SPI_CONTROL_SEL1 |
+ SPI_CONTROL_BYTECNT(0x3) |
+ SPI_CONTROL_CMD(0x3) | SPI_CONTROL_ADDR(off);
+ SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+ val64 |= SPI_CONTROL_REQ;
+ SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+ while (exit_cnt < 5) {
+ val64 = readq(&bar0->spi_control);
+ if (val64 & SPI_CONTROL_NACK) {
+ ret = 1;
+ break;
+ } else if (val64 & SPI_CONTROL_DONE) {
+ *data = readq(&bar0->spi_data);
+ *data &= 0xffffff;
+ ret = 0;
+ break;
+ }
+ msleep(50);
+ exit_cnt++;
+ }
+ }
return ret;
}
@@ -4019,28 +4443,53 @@ static int read_eeprom(nic_t * sp, int off, u32 * data)
* 0 on success, -1 on failure.
*/
-static int write_eeprom(nic_t * sp, int off, u32 data, int cnt)
+static int write_eeprom(nic_t * sp, int off, u64 data, int cnt)
{
int exit_cnt = 0, ret = -1;
u64 val64;
XENA_dev_config_t __iomem *bar0 = sp->bar0;
- val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
- I2C_CONTROL_BYTE_CNT(cnt) | I2C_CONTROL_SET_DATA(data) |
- I2C_CONTROL_CNTL_START;
- SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
+ if (sp->device_type == XFRAME_I_DEVICE) {
+ val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
+ I2C_CONTROL_BYTE_CNT(cnt) | I2C_CONTROL_SET_DATA((u32)data) |
+ I2C_CONTROL_CNTL_START;
+ SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
+
+ while (exit_cnt < 5) {
+ val64 = readq(&bar0->i2c_control);
+ if (I2C_CONTROL_CNTL_END(val64)) {
+ if (!(val64 & I2C_CONTROL_NACK))
+ ret = 0;
+ break;
+ }
+ msleep(50);
+ exit_cnt++;
+ }
+ }
- while (exit_cnt < 5) {
- val64 = readq(&bar0->i2c_control);
- if (I2C_CONTROL_CNTL_END(val64)) {
- if (!(val64 & I2C_CONTROL_NACK))
+ if (sp->device_type == XFRAME_II_DEVICE) {
+ int write_cnt = (cnt == 8) ? 0 : cnt;
+ writeq(SPI_DATA_WRITE(data,(cnt<<3)), &bar0->spi_data);
+
+ val64 = SPI_CONTROL_KEY(0x9) | SPI_CONTROL_SEL1 |
+ SPI_CONTROL_BYTECNT(write_cnt) |
+ SPI_CONTROL_CMD(0x2) | SPI_CONTROL_ADDR(off);
+ SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+ val64 |= SPI_CONTROL_REQ;
+ SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+ while (exit_cnt < 5) {
+ val64 = readq(&bar0->spi_control);
+ if (val64 & SPI_CONTROL_NACK) {
+ ret = 1;
+ break;
+ } else if (val64 & SPI_CONTROL_DONE) {
ret = 0;
- break;
+ break;
+ }
+ msleep(50);
+ exit_cnt++;
}
- msleep(50);
- exit_cnt++;
}
-
return ret;
}
@@ -4060,7 +4509,8 @@ static int write_eeprom(nic_t * sp, int off, u32 data, int cnt)
static int s2io_ethtool_geeprom(struct net_device *dev,
struct ethtool_eeprom *eeprom, u8 * data_buf)
{
- u32 data, i, valid;
+ u32 i, valid;
+ u64 data;
nic_t *sp = dev->priv;
eeprom->magic = sp->pdev->vendor | (sp->pdev->device << 16);
@@ -4098,7 +4548,7 @@ static int s2io_ethtool_seeprom(struct net_device *dev,
u8 * data_buf)
{
int len = eeprom->len, cnt = 0;
- u32 valid = 0, data;
+ u64 valid = 0, data;
nic_t *sp = dev->priv;
if (eeprom->magic != (sp->pdev->vendor | (sp->pdev->device << 16))) {
@@ -4146,7 +4596,7 @@ static int s2io_ethtool_seeprom(struct net_device *dev,
static int s2io_register_test(nic_t * sp, uint64_t * data)
{
XENA_dev_config_t __iomem *bar0 = sp->bar0;
- u64 val64 = 0;
+ u64 val64 = 0, exp_val;
int fail = 0;
val64 = readq(&bar0->pif_rd_swapper_fb);
@@ -4162,7 +4612,11 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
}
val64 = readq(&bar0->rx_queue_cfg);
- if (val64 != 0x0808080808080808ULL) {
+ if (sp->device_type == XFRAME_II_DEVICE)
+ exp_val = 0x0404040404040404ULL;
+ else
+ exp_val = 0x0808080808080808ULL;
+ if (val64 != exp_val) {
fail = 1;
DBG_PRINT(INFO_DBG, "Read Test level 3 fails\n");
}
@@ -4190,7 +4644,7 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
}
*data = fail;
- return 0;
+ return fail;
}
/**
@@ -4209,58 +4663,83 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
static int s2io_eeprom_test(nic_t * sp, uint64_t * data)
{
int fail = 0;
- u32 ret_data;
+ u64 ret_data, org_4F0, org_7F0;
+ u8 saved_4F0 = 0, saved_7F0 = 0;
+ struct net_device *dev = sp->dev;
/* Test Write Error at offset 0 */
- if (!write_eeprom(sp, 0, 0, 3))
- fail = 1;
+ /* Note that SPI interface allows write access to all areas
+ * of EEPROM. Hence doing all negative testing only for Xframe I.
+ */
+ if (sp->device_type == XFRAME_I_DEVICE)
+ if (!write_eeprom(sp, 0, 0, 3))
+ fail = 1;
+
+ /* Save current values at offsets 0x4F0 and 0x7F0 */
+ if (!read_eeprom(sp, 0x4F0, &org_4F0))
+ saved_4F0 = 1;
+ if (!read_eeprom(sp, 0x7F0, &org_7F0))
+ saved_7F0 = 1;
/* Test Write at offset 4f0 */
- if (write_eeprom(sp, 0x4F0, 0x01234567, 3))
+ if (write_eeprom(sp, 0x4F0, 0x012345, 3))
fail = 1;
if (read_eeprom(sp, 0x4F0, &ret_data))
fail = 1;
- if (ret_data != 0x01234567)
+ if (ret_data != 0x012345) {
+ DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x4F0. Data written %llx Data read %llx\n", dev->name, (u64)0x12345, ret_data);
fail = 1;
+ }
/* Reset the EEPROM data go FFFF */
- write_eeprom(sp, 0x4F0, 0xFFFFFFFF, 3);
+ write_eeprom(sp, 0x4F0, 0xFFFFFF, 3);
/* Test Write Request Error at offset 0x7c */
- if (!write_eeprom(sp, 0x07C, 0, 3))
- fail = 1;
+ if (sp->device_type == XFRAME_I_DEVICE)
+ if (!write_eeprom(sp, 0x07C, 0, 3))
+ fail = 1;
- /* Test Write Request at offset 0x7fc */
- if (write_eeprom(sp, 0x7FC, 0x01234567, 3))
+ /* Test Write Request at offset 0x7f0 */
+ if (write_eeprom(sp, 0x7F0, 0x012345, 3))
fail = 1;
- if (read_eeprom(sp, 0x7FC, &ret_data))
+ if (read_eeprom(sp, 0x7F0, &ret_data))
fail = 1;
- if (ret_data != 0x01234567)
+ if (ret_data != 0x012345) {
+ DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x7F0. Data written %llx Data read %llx\n", dev->name, (u64)0x12345, ret_data);
fail = 1;
+ }
/* Reset the EEPROM data go FFFF */
- write_eeprom(sp, 0x7FC, 0xFFFFFFFF, 3);
+ write_eeprom(sp, 0x7F0, 0xFFFFFF, 3);
- /* Test Write Error at offset 0x80 */
- if (!write_eeprom(sp, 0x080, 0, 3))
- fail = 1;
+ if (sp->device_type == XFRAME_I_DEVICE) {
+ /* Test Write Error at offset 0x80 */
+ if (!write_eeprom(sp, 0x080, 0, 3))
+ fail = 1;
- /* Test Write Error at offset 0xfc */
- if (!write_eeprom(sp, 0x0FC, 0, 3))
- fail = 1;
+ /* Test Write Error at offset 0xfc */
+ if (!write_eeprom(sp, 0x0FC, 0, 3))
+ fail = 1;
- /* Test Write Error at offset 0x100 */
- if (!write_eeprom(sp, 0x100, 0, 3))
- fail = 1;
+ /* Test Write Error at offset 0x100 */
+ if (!write_eeprom(sp, 0x100, 0, 3))
+ fail = 1;
- /* Test Write Error at offset 4ec */
- if (!write_eeprom(sp, 0x4EC, 0, 3))
- fail = 1;
+ /* Test Write Error at offset 4ec */
+ if (!write_eeprom(sp, 0x4EC, 0, 3))
+ fail = 1;
+ }
+
+ /* Restore values at offsets 0x4F0 and 0x7F0 */
+ if (saved_4F0)
+ write_eeprom(sp, 0x4F0, org_4F0, 3);
+ if (saved_7F0)
+ write_eeprom(sp, 0x7F0, org_7F0, 3);
*data = fail;
- return 0;
+ return fail;
}
/**
@@ -4342,7 +4821,7 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
{
XENA_dev_config_t __iomem *bar0 = sp->bar0;
u64 val64;
- int cnt, iteration = 0, test_pass = 0;
+ int cnt, iteration = 0, test_fail = 0;
val64 = readq(&bar0->adapter_control);
val64 &= ~ADAPTER_ECC_EN;
@@ -4350,7 +4829,7 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
val64 = readq(&bar0->mc_rldram_test_ctrl);
val64 |= MC_RLDRAM_TEST_MODE;
- writeq(val64, &bar0->mc_rldram_test_ctrl);
+ SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
val64 = readq(&bar0->mc_rldram_mrs);
val64 |= MC_RLDRAM_QUEUE_SIZE_ENABLE;
@@ -4378,17 +4857,12 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
}
writeq(val64, &bar0->mc_rldram_test_d2);
- val64 = (u64) (0x0000003fffff0000ULL);
+ val64 = (u64) (0x0000003ffffe0100ULL);
writeq(val64, &bar0->mc_rldram_test_add);
-
- val64 = MC_RLDRAM_TEST_MODE;
- writeq(val64, &bar0->mc_rldram_test_ctrl);
-
- val64 |=
- MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_WRITE |
- MC_RLDRAM_TEST_GO;
- writeq(val64, &bar0->mc_rldram_test_ctrl);
+ val64 = MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_WRITE |
+ MC_RLDRAM_TEST_GO;
+ SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
for (cnt = 0; cnt < 5; cnt++) {
val64 = readq(&bar0->mc_rldram_test_ctrl);
@@ -4400,11 +4874,8 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
if (cnt == 5)
break;
- val64 = MC_RLDRAM_TEST_MODE;
- writeq(val64, &bar0->mc_rldram_test_ctrl);
-
- val64 |= MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_GO;
- writeq(val64, &bar0->mc_rldram_test_ctrl);
+ val64 = MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_GO;
+ SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
for (cnt = 0; cnt < 5; cnt++) {
val64 = readq(&bar0->mc_rldram_test_ctrl);
@@ -4417,18 +4888,18 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
break;
val64 = readq(&bar0->mc_rldram_test_ctrl);
- if (val64 & MC_RLDRAM_TEST_PASS)
- test_pass = 1;
+ if (!(val64 & MC_RLDRAM_TEST_PASS))
+ test_fail = 1;
iteration++;
}
- if (!test_pass)
- *data = 1;
- else
- *data = 0;
+ *data = test_fail;
- return 0;
+ /* Bring the adapter out of test mode */
+ SPECIAL_REG_WRITE(0, &bar0->mc_rldram_test_ctrl, LF);
+
+ return test_fail;
}
/**
@@ -4932,7 +5403,7 @@ static void s2io_card_down(nic_t * sp)
static int s2io_card_up(nic_t * sp)
{
- int i, ret;
+ int i, ret = 0;
mac_info_t *mac_control;
struct config_param *config;
struct net_device *dev = (struct net_device *) sp->dev;
@@ -4944,6 +5415,15 @@ static int s2io_card_up(nic_t * sp)
return -ENODEV;
}
+ if (sp->intr_type == MSI)
+ ret = s2io_enable_msi(sp);
+ else if (sp->intr_type == MSI_X)
+ ret = s2io_enable_msi_x(sp);
+ if (ret) {
+ DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name);
+ sp->intr_type = INTA;
+ }
+
/*
* Initializing the Rx buffers. For now we are considering only 1
* Rx ring and initializing buffers into 30 Rx blocks
@@ -5228,6 +5708,8 @@ static void s2io_init_pci(nic_t * sp)
MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>");
MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
module_param(tx_fifo_num, int, 0);
module_param(rx_ring_num, int, 0);
module_param_array(tx_fifo_len, uint, NULL, 0);
@@ -5245,6 +5727,7 @@ module_param(bimodal, bool, 0);
module_param(indicate_max_pkts, int, 0);
#endif
module_param(rxsync_frequency, int, 0);
+module_param(intr_type, int, 0);
/**
* s2io_init_nic - Initialization of the adapter .
@@ -5274,9 +5757,16 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
mac_info_t *mac_control;
struct config_param *config;
int mode;
+ u8 dev_intr_type = intr_type;
#ifdef CONFIG_S2IO_NAPI
- DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n");
+ if (dev_intr_type != INTA) {
+ DBG_PRINT(ERR_DBG, "NAPI cannot be enabled when MSI/MSI-X \
+is enabled. Defaulting to INTA\n");
+ dev_intr_type = INTA;
+ }
+ else
+ DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n");
#endif
if ((ret = pci_enable_device(pdev))) {
@@ -5303,10 +5793,35 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
return -ENOMEM;
}
- if (pci_request_regions(pdev, s2io_driver_name)) {
- DBG_PRINT(ERR_DBG, "Request Regions failed\n"),
- pci_disable_device(pdev);
- return -ENODEV;
+ if ((dev_intr_type == MSI_X) &&
+ ((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
+ (pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
+ DBG_PRINT(ERR_DBG, "Xframe I does not support MSI_X. \
+Defaulting to INTA\n");
+ dev_intr_type = INTA;
+ }
+ if (dev_intr_type != MSI_X) {
+ if (pci_request_regions(pdev, s2io_driver_name)) {
+ DBG_PRINT(ERR_DBG, "Request Regions failed\n"),
+ pci_disable_device(pdev);
+ return -ENODEV;
+ }
+ }
+ else {
+ if (!(request_mem_region(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0), s2io_driver_name))) {
+ DBG_PRINT(ERR_DBG, "bar0 Request Regions failed\n");
+ pci_disable_device(pdev);
+ return -ENODEV;
+ }
+ if (!(request_mem_region(pci_resource_start(pdev, 2),
+ pci_resource_len(pdev, 2), s2io_driver_name))) {
+ DBG_PRINT(ERR_DBG, "bar1 Request Regions failed\n");
+ release_mem_region(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ pci_disable_device(pdev);
+ return -ENODEV;
+ }
}
dev = alloc_etherdev(sizeof(nic_t));
@@ -5329,6 +5844,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
sp->pdev = pdev;
sp->high_dma_flag = dma_flag;
sp->device_enabled_once = FALSE;
+ sp->intr_type = dev_intr_type;
if ((pdev->device == PCI_DEVICE_ID_HERC_WIN) ||
(pdev->device == PCI_DEVICE_ID_HERC_UNI))
@@ -5336,6 +5852,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
else
sp->device_type = XFRAME_I_DEVICE;
+
/* Initialize some PCI/PCI-X fields of the NIC. */
s2io_init_pci(sp);
@@ -5571,12 +6088,23 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
if (sp->device_type & XFRAME_II_DEVICE) {
DBG_PRINT(ERR_DBG, "%s: Neterion Xframe II 10GbE adapter ",
dev->name);
- DBG_PRINT(ERR_DBG, "(rev %d), %s",
+ DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
get_xena_rev_id(sp->pdev),
s2io_driver_version);
#ifdef CONFIG_2BUFF_MODE
DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
#endif
+ switch(sp->intr_type) {
+ case INTA:
+ DBG_PRINT(ERR_DBG, ", Intr type INTA");
+ break;
+ case MSI:
+ DBG_PRINT(ERR_DBG, ", Intr type MSI");
+ break;
+ case MSI_X:
+ DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
+ break;
+ }
DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
@@ -5595,12 +6123,23 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
} else {
DBG_PRINT(ERR_DBG, "%s: Neterion Xframe I 10GbE adapter ",
dev->name);
- DBG_PRINT(ERR_DBG, "(rev %d), %s",
+ DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
get_xena_rev_id(sp->pdev),
s2io_driver_version);
#ifdef CONFIG_2BUFF_MODE
DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
#endif
+ switch(sp->intr_type) {
+ case INTA:
+ DBG_PRINT(ERR_DBG, ", Intr type INTA");
+ break;
+ case MSI:
+ DBG_PRINT(ERR_DBG, ", Intr type MSI");
+ break;
+ case MSI_X:
+ DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
+ break;
+ }
DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
sp->def_mac_addr[0].mac_addr[0],
@@ -5644,7 +6183,14 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
mem_alloc_failed:
free_shared_mem(sp);
pci_disable_device(pdev);
- pci_release_regions(pdev);
+ if (dev_intr_type != MSI_X)
+ pci_release_regions(pdev);
+ else {
+ release_mem_region(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ release_mem_region(pci_resource_start(pdev, 2),
+ pci_resource_len(pdev, 2));
+ }
pci_set_drvdata(pdev, NULL);
free_netdev(dev);
@@ -5678,7 +6224,14 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)
iounmap(sp->bar0);
iounmap(sp->bar1);
pci_disable_device(pdev);
- pci_release_regions(pdev);
+ if (sp->intr_type != MSI_X)
+ pci_release_regions(pdev);
+ else {
+ release_mem_region(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ release_mem_region(pci_resource_start(pdev, 2),
+ pci_resource_len(pdev, 2));
+ }
pci_set_drvdata(pdev, NULL);
free_netdev(dev);
}
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 89151cb5218132..1cc24b56760e1f 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -652,6 +652,30 @@ typedef struct {
#define SMALL_BLK_CNT 30
#define LARGE_BLK_CNT 100
+/*
+ * Structure to keep track of the MSI-X vectors and the corresponding
+ * argument registered against each vector
+ */
+#define MAX_REQUESTED_MSI_X 17
+struct s2io_msix_entry
+{
+ u16 vector;
+ u16 entry;
+ void *arg;
+
+ u8 type;
+#define MSIX_FIFO_TYPE 1
+#define MSIX_RING_TYPE 2
+
+ u8 in_use;
+#define MSIX_REGISTERED_SUCCESS 0xAA
+};
+
+struct msix_info_st {
+ u64 addr;
+ u64 data;
+};
+
/* Structure representing one instance of the NIC */
struct s2io_nic {
#ifdef CONFIG_S2IO_NAPI
@@ -719,13 +743,8 @@ struct s2io_nic {
* a schedule task that will set the correct Link state once the
* NIC's PHY has stabilized after a state change.
*/
-#ifdef INIT_TQUEUE
- struct tq_struct rst_timer_task;
- struct tq_struct set_link_task;
-#else
struct work_struct rst_timer_task;
struct work_struct set_link_task;
-#endif
/* Flag that can be used to turn on or turn off the Rx checksum
* offload feature.
@@ -748,10 +767,23 @@ struct s2io_nic {
atomic_t card_state;
volatile unsigned long link_state;
struct vlan_group *vlgrp;
+#define MSIX_FLG 0xA5
+ struct msix_entry *entries;
+ struct s2io_msix_entry *s2io_entries;
+ char desc1[35];
+ char desc2[35];
+
+ struct msix_info_st msix_info[0x3f];
+
#define XFRAME_I_DEVICE 1
#define XFRAME_II_DEVICE 2
u8 device_type;
+#define INTA 0
+#define MSI 1
+#define MSI_X 2
+ u8 intr_type;
+
spinlock_t rx_lock;
atomic_t isr_cnt;
};
@@ -886,6 +918,13 @@ static int s2io_poll(struct net_device *dev, int *budget);
static void s2io_init_pci(nic_t * sp);
int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
static void s2io_alarm_handle(unsigned long data);
+static int s2io_enable_msi(nic_t *nic);
+static irqreturn_t s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t
+s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t
+s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs);
+int s2io_enable_msi_x(nic_t *nic);
static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs);
static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag);
static struct ethtool_ops netdev_ethtool_ops;
@@ -894,4 +933,5 @@ int s2io_set_swapper(nic_t * sp);
static void s2io_card_down(nic_t *nic);
static int s2io_card_up(nic_t *nic);
int get_xena_rev_id(struct pci_dev *pdev);
+void restore_xmsi_data(nic_t *nic);
#endif /* _S2IO_H */
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 7abd55a4fb21fe..aa4ca182175909 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -10,7 +10,7 @@
* 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.
@@ -118,8 +118,6 @@ MODULE_PARM_DESC(int_timeout, "Timeout value");
********************************************************************* */
-typedef unsigned long sbmac_port_t;
-
typedef enum { sbmac_speed_auto, sbmac_speed_10,
sbmac_speed_100, sbmac_speed_1000 } sbmac_speed_t;
@@ -129,7 +127,7 @@ typedef enum { sbmac_duplex_auto, sbmac_duplex_half,
typedef enum { sbmac_fc_auto, sbmac_fc_disabled, sbmac_fc_frame,
sbmac_fc_collision, sbmac_fc_carrier } sbmac_fc_t;
-typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on,
+typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on,
sbmac_state_broken } sbmac_state_t;
@@ -144,17 +142,13 @@ typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on,
#define NUMCACHEBLKS(x) (((x)+SMP_CACHE_BYTES-1)/SMP_CACHE_BYTES)
-#define SBMAC_READCSR(t) __raw_readq((unsigned long)t)
-#define SBMAC_WRITECSR(t,v) __raw_writeq(v, (unsigned long)t)
-
-
#define SBMAC_MAX_TXDESCR 32
#define SBMAC_MAX_RXDESCR 32
#define ETHER_ALIGN 2
#define ETHER_ADDR_LEN 6
-#define ENET_PACKET_SIZE 1518
-/*#define ENET_PACKET_SIZE 9216 */
+#define ENET_PACKET_SIZE 1518
+/*#define ENET_PACKET_SIZE 9216 */
/**********************************************************************
* DMA Descriptor structure
@@ -172,12 +166,12 @@ typedef unsigned long paddr_t;
********************************************************************* */
typedef struct sbmacdma_s {
-
- /*
+
+ /*
* This stuff is used to identify the channel and the registers
* associated with it.
*/
-
+
struct sbmac_softc *sbdma_eth; /* back pointer to associated MAC */
int sbdma_channel; /* channel number */
int sbdma_txdir; /* direction (1=transmit) */
@@ -187,21 +181,21 @@ typedef struct sbmacdma_s {
int sbdma_int_timeout; /* # usec rx/tx interrupt */
#endif
- sbmac_port_t sbdma_config0; /* DMA config register 0 */
- sbmac_port_t sbdma_config1; /* DMA config register 1 */
- sbmac_port_t sbdma_dscrbase; /* Descriptor base address */
- sbmac_port_t sbdma_dscrcnt; /* Descriptor count register */
- sbmac_port_t sbdma_curdscr; /* current descriptor address */
-
+ volatile void __iomem *sbdma_config0; /* DMA config register 0 */
+ volatile void __iomem *sbdma_config1; /* DMA config register 1 */
+ volatile void __iomem *sbdma_dscrbase; /* Descriptor base address */
+ volatile void __iomem *sbdma_dscrcnt; /* Descriptor count register */
+ volatile void __iomem *sbdma_curdscr; /* current descriptor address */
+
/*
* This stuff is for maintenance of the ring
*/
-
+
sbdmadscr_t *sbdma_dscrtable; /* base of descriptor table */
sbdmadscr_t *sbdma_dscrtable_end; /* end of descriptor table */
-
+
struct sk_buff **sbdma_ctxtable; /* context table, one per descr */
-
+
paddr_t sbdma_dscrtable_phys; /* and also the phys addr */
sbdmadscr_t *sbdma_addptr; /* next dscr for sw to add */
sbdmadscr_t *sbdma_remptr; /* next dscr for sw to remove */
@@ -213,15 +207,15 @@ typedef struct sbmacdma_s {
********************************************************************* */
struct sbmac_softc {
-
+
/*
* Linux-specific things
*/
-
+
struct net_device *sbm_dev; /* pointer to linux device */
spinlock_t sbm_lock; /* spin lock */
struct timer_list sbm_timer; /* for monitoring MII */
- struct net_device_stats sbm_stats;
+ struct net_device_stats sbm_stats;
int sbm_devflags; /* current device flags */
int sbm_phy_oldbmsr;
@@ -229,31 +223,31 @@ struct sbmac_softc {
int sbm_phy_oldk1stsr;
int sbm_phy_oldlinkstat;
int sbm_buffersize;
-
+
unsigned char sbm_phys[2];
-
+
/*
* Controller-specific things
*/
-
- unsigned long sbm_base; /* MAC's base address */
+
+ volatile void __iomem *sbm_base; /* MAC's base address */
sbmac_state_t sbm_state; /* current state */
-
- sbmac_port_t sbm_macenable; /* MAC Enable Register */
- sbmac_port_t sbm_maccfg; /* MAC Configuration Register */
- sbmac_port_t sbm_fifocfg; /* FIFO configuration register */
- sbmac_port_t sbm_framecfg; /* Frame configuration register */
- sbmac_port_t sbm_rxfilter; /* receive filter register */
- sbmac_port_t sbm_isr; /* Interrupt status register */
- sbmac_port_t sbm_imr; /* Interrupt mask register */
- sbmac_port_t sbm_mdio; /* MDIO register */
-
+
+ volatile void __iomem *sbm_macenable; /* MAC Enable Register */
+ volatile void __iomem *sbm_maccfg; /* MAC Configuration Register */
+ volatile void __iomem *sbm_fifocfg; /* FIFO configuration register */
+ volatile void __iomem *sbm_framecfg; /* Frame configuration register */
+ volatile void __iomem *sbm_rxfilter; /* receive filter register */
+ volatile void __iomem *sbm_isr; /* Interrupt status register */
+ volatile void __iomem *sbm_imr; /* Interrupt mask register */
+ volatile void __iomem *sbm_mdio; /* MDIO register */
+
sbmac_speed_t sbm_speed; /* current speed */
sbmac_duplex_t sbm_duplex; /* current duplex */
sbmac_fc_t sbm_fc; /* current flow control setting */
-
+
unsigned char sbm_hwaddr[ETHER_ADDR_LEN];
-
+
sbmacdma_t sbm_txdma; /* for now, only use channel 0 */
sbmacdma_t sbm_rxdma;
int rx_hw_checksum;
@@ -302,6 +296,7 @@ static void sbmac_set_rx_mode(struct net_device *dev);
static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static int sbmac_close(struct net_device *dev);
static int sbmac_mii_poll(struct sbmac_softc *s,int noisy);
+static int sbmac_mii_probe(struct net_device *dev);
static void sbmac_mii_sync(struct sbmac_softc *s);
static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitcnt);
@@ -439,6 +434,9 @@ static uint64_t sbmac_orig_hwaddr[MAX_UNITS];
#define MII_BMCR 0x00 /* Basic mode control register (rw) */
#define MII_BMSR 0x01 /* Basic mode status register (ro) */
+#define MII_PHYIDR1 0x02
+#define MII_PHYIDR2 0x03
+
#define MII_K1STSR 0x0A /* 1K Status Register (ro) */
#define MII_ANLPAR 0x05 /* Autonegotiation lnk partner abilities (rw) */
@@ -450,13 +448,13 @@ static uint64_t sbmac_orig_hwaddr[MAX_UNITS];
/**********************************************************************
* SBMAC_MII_SYNC(s)
- *
+ *
* Synchronize with the MII - send a pattern of bits to the MII
* that will guarantee that it is ready to accept a command.
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -467,25 +465,25 @@ static void sbmac_mii_sync(struct sbmac_softc *s)
uint64_t bits;
int mac_mdio_genc;
- mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
-
+ mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
+
bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT;
-
- SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
-
+
+ __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
+
for (cnt = 0; cnt < 32; cnt++) {
- SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC | mac_mdio_genc);
- SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
+ __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
}
}
/**********************************************************************
* SBMAC_MII_SENDDATA(s,data,bitcnt)
- *
+ *
* Send some bits to the MII. The bits to be sent are right-
* justified in the 'data' parameter.
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
* data - data to send
* bitcnt - number of bits to send
@@ -498,20 +496,20 @@ static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitc
unsigned int curmask;
int mac_mdio_genc;
- mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
-
+ mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
+
bits = M_MAC_MDIO_DIR_OUTPUT;
- SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
-
+ __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
+
curmask = 1 << (bitcnt - 1);
-
+
for (i = 0; i < bitcnt; i++) {
if (data & curmask)
bits |= M_MAC_MDIO_OUT;
else bits &= ~M_MAC_MDIO_OUT;
- SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
- SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC | mac_mdio_genc);
- SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
+ __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
curmask >>= 1;
}
}
@@ -520,14 +518,14 @@ static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitc
/**********************************************************************
* SBMAC_MII_READ(s,phyaddr,regidx)
- *
+ *
* Read a PHY register.
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
* phyaddr - PHY's address
* regidx = index of register to read
- *
+ *
* Return value:
* value read, or 0 if an error occurred.
********************************************************************* */
@@ -543,9 +541,9 @@ static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx)
* Synchronize ourselves so that the PHY knows the next
* thing coming down is a command
*/
-
+
sbmac_mii_sync(s);
-
+
/*
* Send the data to the PHY. The sequence is
* a "start" command (2 bits)
@@ -553,59 +551,55 @@ static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx)
* the PHY addr (5 bits)
* the register index (5 bits)
*/
-
+
sbmac_mii_senddata(s,MII_COMMAND_START, 2);
sbmac_mii_senddata(s,MII_COMMAND_READ, 2);
sbmac_mii_senddata(s,phyaddr, 5);
sbmac_mii_senddata(s,regidx, 5);
-
- mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
-
- /*
+
+ mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
+
+ /*
* Switch the port around without a clock transition.
*/
- SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
-
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
+
/*
* Send out a clock pulse to signal we want the status
*/
-
- SBMAC_WRITECSR(s->sbm_mdio,
- M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc);
- SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
-
- /*
+
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
+
+ /*
* If an error occurred, the PHY will signal '1' back
*/
- error = SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN;
-
- /*
+ error = __raw_readq(s->sbm_mdio) & M_MAC_MDIO_IN;
+
+ /*
* Issue an 'idle' clock pulse, but keep the direction
* the same.
*/
- SBMAC_WRITECSR(s->sbm_mdio,
- M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc);
- SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
-
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
+
regval = 0;
-
+
for (idx = 0; idx < 16; idx++) {
regval <<= 1;
-
+
if (error == 0) {
- if (SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN)
+ if (__raw_readq(s->sbm_mdio) & M_MAC_MDIO_IN)
regval |= 1;
}
-
- SBMAC_WRITECSR(s->sbm_mdio,
- M_MAC_MDIO_DIR_INPUT|M_MAC_MDC | mac_mdio_genc);
- SBMAC_WRITECSR(s->sbm_mdio,
- M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
+
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT|M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
}
-
+
/* Switch back to output */
- SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc);
-
+ __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, s->sbm_mdio);
+
if (error == 0)
return regval;
return 0;
@@ -614,15 +608,15 @@ static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx)
/**********************************************************************
* SBMAC_MII_WRITE(s,phyaddr,regidx,regval)
- *
+ *
* Write a value to a PHY register.
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
* phyaddr - PHY to use
* regidx - register within the PHY
* regval - data to write to register
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -633,7 +627,7 @@ static void sbmac_mii_write(struct sbmac_softc *s,int phyaddr,int regidx,
int mac_mdio_genc;
sbmac_mii_sync(s);
-
+
sbmac_mii_senddata(s,MII_COMMAND_START,2);
sbmac_mii_senddata(s,MII_COMMAND_WRITE,2);
sbmac_mii_senddata(s,phyaddr, 5);
@@ -641,27 +635,27 @@ static void sbmac_mii_write(struct sbmac_softc *s,int phyaddr,int regidx,
sbmac_mii_senddata(s,MII_COMMAND_ACK,2);
sbmac_mii_senddata(s,regval,16);
- mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
+ mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
- SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc);
+ __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, s->sbm_mdio);
}
/**********************************************************************
* SBDMA_INITCTX(d,s,chan,txrx,maxdescr)
- *
+ *
* Initialize a DMA channel context. Since there are potentially
* eight DMA channels per MAC, it's nice to do this in a standard
- * way.
- *
- * Input parameters:
+ * way.
+ *
+ * Input parameters:
* d - sbmacdma_t structure (DMA channel context)
* s - sbmac_softc structure (pointer to a MAC)
* chan - channel number (0..1 right now)
* txrx - Identifies DMA_TX or DMA_RX for channel direction
* maxdescr - number of descriptors
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -672,101 +666,87 @@ static void sbdma_initctx(sbmacdma_t *d,
int txrx,
int maxdescr)
{
- /*
- * Save away interesting stuff in the structure
+ /*
+ * Save away interesting stuff in the structure
*/
-
+
d->sbdma_eth = s;
d->sbdma_channel = chan;
d->sbdma_txdir = txrx;
-
+
#if 0
/* RMON clearing */
s->sbe_idx =(s->sbm_base - A_MAC_BASE_0)/MAC_SPACING;
#endif
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BYTES)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_COLLISIONS)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_LATE_COL)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_EX_COL)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_FCS_ERROR)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_ABORT)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BAD)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_GOOD)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_RUNT)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_OVERSIZE)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BYTES)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_MCAST)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BCAST)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BAD)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_GOOD)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_RUNT)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_OVERSIZE)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_FCS_ERROR)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_LENGTH_ERROR)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_CODE_ERROR)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_ALIGN_ERROR)), 0);
-
- /*
- * initialize register pointers
- */
-
- d->sbdma_config0 =
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BYTES)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_COLLISIONS)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_LATE_COL)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_EX_COL)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_FCS_ERROR)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_ABORT)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BAD)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_GOOD)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_RUNT)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_OVERSIZE)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BYTES)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_MCAST)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BCAST)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BAD)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_GOOD)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_RUNT)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_OVERSIZE)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_FCS_ERROR)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_LENGTH_ERROR)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_CODE_ERROR)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_ALIGN_ERROR)));
+
+ /*
+ * initialize register pointers
+ */
+
+ d->sbdma_config0 =
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0);
- d->sbdma_config1 =
+ d->sbdma_config1 =
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG1);
- d->sbdma_dscrbase =
+ d->sbdma_dscrbase =
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE);
- d->sbdma_dscrcnt =
+ d->sbdma_dscrcnt =
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT);
- d->sbdma_curdscr =
+ d->sbdma_curdscr =
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR);
-
+
/*
* Allocate memory for the ring
*/
-
+
d->sbdma_maxdescr = maxdescr;
-
- d->sbdma_dscrtable = (sbdmadscr_t *)
- kmalloc(d->sbdma_maxdescr*sizeof(sbdmadscr_t), GFP_KERNEL);
-
+
+ d->sbdma_dscrtable = (sbdmadscr_t *)
+ kmalloc((d->sbdma_maxdescr+1)*sizeof(sbdmadscr_t), GFP_KERNEL);
+
+ /*
+ * The descriptor table must be aligned to at least 16 bytes or the
+ * MAC will corrupt it.
+ */
+ d->sbdma_dscrtable = (sbdmadscr_t *)
+ ALIGN((unsigned long)d->sbdma_dscrtable, sizeof(sbdmadscr_t));
+
memset(d->sbdma_dscrtable,0,d->sbdma_maxdescr*sizeof(sbdmadscr_t));
-
+
d->sbdma_dscrtable_end = d->sbdma_dscrtable + d->sbdma_maxdescr;
-
+
d->sbdma_dscrtable_phys = virt_to_phys(d->sbdma_dscrtable);
-
+
/*
* And context table
*/
-
- d->sbdma_ctxtable = (struct sk_buff **)
+
+ d->sbdma_ctxtable = (struct sk_buff **)
kmalloc(d->sbdma_maxdescr*sizeof(struct sk_buff *), GFP_KERNEL);
-
+
memset(d->sbdma_ctxtable,0,d->sbdma_maxdescr*sizeof(struct sk_buff *));
-
+
#ifdef CONFIG_SBMAC_COALESCE
/*
* Setup Rx/Tx DMA coalescing defaults
@@ -777,7 +757,7 @@ static void sbdma_initctx(sbmacdma_t *d,
} else {
d->sbdma_int_pktcnt = 1;
}
-
+
if ( int_timeout ) {
d->sbdma_int_timeout = int_timeout;
} else {
@@ -789,13 +769,13 @@ static void sbdma_initctx(sbmacdma_t *d,
/**********************************************************************
* SBDMA_CHANNEL_START(d)
- *
+ *
* Initialize the hardware registers for a DMA channel.
- *
- * Input parameters:
+ *
+ * Input parameters:
* d - DMA channel to init (context must be previously init'd
* rxtx - DMA_RX or DMA_TX depending on what type of channel
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -805,24 +785,21 @@ static void sbdma_channel_start(sbmacdma_t *d, int rxtx )
/*
* Turn on the DMA channel
*/
-
+
#ifdef CONFIG_SBMAC_COALESCE
- SBMAC_WRITECSR(d->sbdma_config1,
- V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) |
- 0);
- SBMAC_WRITECSR(d->sbdma_config0,
- M_DMA_EOP_INT_EN |
+ __raw_writeq(V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) |
+ 0, d->sbdma_config1);
+ __raw_writeq(M_DMA_EOP_INT_EN |
V_DMA_RINGSZ(d->sbdma_maxdescr) |
V_DMA_INT_PKTCNT(d->sbdma_int_pktcnt) |
- 0);
+ 0, d->sbdma_config0);
#else
- SBMAC_WRITECSR(d->sbdma_config1,0);
- SBMAC_WRITECSR(d->sbdma_config0,
- V_DMA_RINGSZ(d->sbdma_maxdescr) |
- 0);
+ __raw_writeq(0, d->sbdma_config1);
+ __raw_writeq(V_DMA_RINGSZ(d->sbdma_maxdescr) |
+ 0, d->sbdma_config0);
#endif
- SBMAC_WRITECSR(d->sbdma_dscrbase,d->sbdma_dscrtable_phys);
+ __raw_writeq(d->sbdma_dscrtable_phys, d->sbdma_dscrbase);
/*
* Initialize ring pointers
@@ -834,12 +811,12 @@ static void sbdma_channel_start(sbmacdma_t *d, int rxtx )
/**********************************************************************
* SBDMA_CHANNEL_STOP(d)
- *
+ *
* Initialize the hardware registers for a DMA channel.
- *
- * Input parameters:
+ *
+ * Input parameters:
* d - DMA channel to init (context must be previously init'd
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -849,44 +826,44 @@ static void sbdma_channel_stop(sbmacdma_t *d)
/*
* Turn off the DMA channel
*/
-
- SBMAC_WRITECSR(d->sbdma_config1,0);
-
- SBMAC_WRITECSR(d->sbdma_dscrbase,0);
-
- SBMAC_WRITECSR(d->sbdma_config0,0);
-
+
+ __raw_writeq(0, d->sbdma_config1);
+
+ __raw_writeq(0, d->sbdma_dscrbase);
+
+ __raw_writeq(0, d->sbdma_config0);
+
/*
* Zero ring pointers
*/
-
- d->sbdma_addptr = 0;
- d->sbdma_remptr = 0;
+
+ d->sbdma_addptr = NULL;
+ d->sbdma_remptr = NULL;
}
static void sbdma_align_skb(struct sk_buff *skb,int power2,int offset)
{
unsigned long addr;
unsigned long newaddr;
-
+
addr = (unsigned long) skb->data;
-
+
newaddr = (addr + power2 - 1) & ~(power2 - 1);
-
+
skb_reserve(skb,newaddr-addr+offset);
}
/**********************************************************************
* SBDMA_ADD_RCVBUFFER(d,sb)
- *
+ *
* Add a buffer to the specified DMA channel. For receive channels,
* this queues a buffer for inbound packets.
- *
- * Input parameters:
+ *
+ * Input parameters:
* d - DMA channel descriptor
* sb - sk_buff to add, or NULL if we should allocate one
- *
+ *
* Return value:
* 0 if buffer could not be added (ring is full)
* 1 if buffer added successfully
@@ -899,24 +876,24 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
sbdmadscr_t *nextdsc;
struct sk_buff *sb_new = NULL;
int pktsize = ENET_PACKET_SIZE;
-
+
/* get pointer to our current place in the ring */
-
+
dsc = d->sbdma_addptr;
nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr);
-
+
/*
* figure out if the ring is full - if the next descriptor
* is the same as the one that we're going to remove from
* the ring, the ring is full
*/
-
+
if (nextdsc == d->sbdma_remptr) {
return -ENOSPC;
}
- /*
- * Allocate a sk_buff if we don't already have one.
+ /*
+ * Allocate a sk_buff if we don't already have one.
* If we do have an sk_buff, reset it so that it's empty.
*
* Note: sk_buffs don't seem to be guaranteed to have any sort
@@ -925,7 +902,7 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
*
* 1. the data does not start in the middle of a cache line.
* 2. The data does not end in the middle of a cache line
- * 3. The buffer can be aligned such that the IP addresses are
+ * 3. The buffer can be aligned such that the IP addresses are
* naturally aligned.
*
* Remember, the SOCs MAC writes whole cache lines at a time,
@@ -933,7 +910,7 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
* data portion starts in the middle of a cache line, the SOC
* DMA will trash the beginning (and ending) portions.
*/
-
+
if (sb == NULL) {
sb_new = dev_alloc_skb(ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN);
if (sb_new == NULL) {
@@ -949,23 +926,22 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
}
else {
sb_new = sb;
- /*
+ /*
* nothing special to reinit buffer, it's already aligned
* and sb->data already points to a good place.
*/
}
-
+
/*
- * fill in the descriptor
+ * fill in the descriptor
*/
-
+
#ifdef CONFIG_SBMAC_COALESCE
/*
* Do not interrupt per DMA transfer.
*/
dsc->dscr_a = virt_to_phys(sb_new->data) |
- V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
- 0;
+ V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) | 0;
#else
dsc->dscr_a = virt_to_phys(sb_new->data) |
V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
@@ -974,38 +950,38 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
/* receiving: no options */
dsc->dscr_b = 0;
-
+
/*
- * fill in the context
+ * fill in the context
*/
-
+
d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb_new;
-
- /*
- * point at next packet
+
+ /*
+ * point at next packet
*/
-
+
d->sbdma_addptr = nextdsc;
-
- /*
+
+ /*
* Give the buffer to the DMA engine.
*/
-
- SBMAC_WRITECSR(d->sbdma_dscrcnt,1);
-
+
+ __raw_writeq(1, d->sbdma_dscrcnt);
+
return 0; /* we did it */
}
/**********************************************************************
* SBDMA_ADD_TXBUFFER(d,sb)
- *
+ *
* Add a transmit buffer to the specified DMA channel, causing a
* transmit to start.
- *
- * Input parameters:
+ *
+ * Input parameters:
* d - DMA channel descriptor
* sb - sk_buff to add
- *
+ *
* Return value:
* 0 transmit queued successfully
* otherwise error code
@@ -1019,70 +995,70 @@ static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *sb)
uint64_t phys;
uint64_t ncb;
int length;
-
+
/* get pointer to our current place in the ring */
-
+
dsc = d->sbdma_addptr;
nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr);
-
+
/*
* figure out if the ring is full - if the next descriptor
* is the same as the one that we're going to remove from
* the ring, the ring is full
*/
-
+
if (nextdsc == d->sbdma_remptr) {
return -ENOSPC;
}
-
+
/*
* Under Linux, it's not necessary to copy/coalesce buffers
* like it is on NetBSD. We think they're all contiguous,
* but that may not be true for GBE.
*/
-
+
length = sb->len;
-
+
/*
* fill in the descriptor. Note that the number of cache
* blocks in the descriptor is the number of blocks
* *spanned*, so we need to add in the offset (if any)
* while doing the calculation.
*/
-
+
phys = virt_to_phys(sb->data);
ncb = NUMCACHEBLKS(length+(phys & (SMP_CACHE_BYTES - 1)));
- dsc->dscr_a = phys |
+ dsc->dscr_a = phys |
V_DMA_DSCRA_A_SIZE(ncb) |
#ifndef CONFIG_SBMAC_COALESCE
M_DMA_DSCRA_INTERRUPT |
#endif
M_DMA_ETHTX_SOP;
-
+
/* transmitting: set outbound options and length */
dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) |
V_DMA_DSCRB_PKT_SIZE(length);
-
+
/*
- * fill in the context
+ * fill in the context
*/
-
+
d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb;
-
- /*
- * point at next packet
+
+ /*
+ * point at next packet
*/
-
+
d->sbdma_addptr = nextdsc;
-
- /*
+
+ /*
* Give the buffer to the DMA engine.
*/
-
- SBMAC_WRITECSR(d->sbdma_dscrcnt,1);
-
+
+ __raw_writeq(1, d->sbdma_dscrcnt);
+
return 0; /* we did it */
}
@@ -1091,12 +1067,12 @@ static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *sb)
/**********************************************************************
* SBDMA_EMPTYRING(d)
- *
+ *
* Free all allocated sk_buffs on the specified DMA channel;
- *
- * Input parameters:
+ *
+ * Input parameters:
* d - DMA channel
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1105,7 +1081,7 @@ static void sbdma_emptyring(sbmacdma_t *d)
{
int idx;
struct sk_buff *sb;
-
+
for (idx = 0; idx < d->sbdma_maxdescr; idx++) {
sb = d->sbdma_ctxtable[idx];
if (sb) {
@@ -1118,13 +1094,13 @@ static void sbdma_emptyring(sbmacdma_t *d)
/**********************************************************************
* SBDMA_FILLRING(d)
- *
+ *
* Fill the specified DMA channel (must be receive channel)
* with sk_buffs
- *
- * Input parameters:
+ *
+ * Input parameters:
* d - DMA channel
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1132,7 +1108,7 @@ static void sbdma_emptyring(sbmacdma_t *d)
static void sbdma_fillring(sbmacdma_t *d)
{
int idx;
-
+
for (idx = 0; idx < SBMAC_MAX_RXDESCR-1; idx++) {
if (sbdma_add_rcvbuffer(d,NULL) != 0)
break;
@@ -1142,16 +1118,16 @@ static void sbdma_fillring(sbmacdma_t *d)
/**********************************************************************
* SBDMA_RX_PROCESS(sc,d)
- *
- * Process "completed" receive buffers on the specified DMA channel.
+ *
+ * Process "completed" receive buffers on the specified DMA channel.
* Note that this isn't really ideal for priority channels, since
- * it processes all of the packets on a given channel before
- * returning.
+ * it processes all of the packets on a given channel before
+ * returning.
*
- * Input parameters:
+ * Input parameters:
* sc - softc structure
* d - DMA channel context
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1163,56 +1139,56 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
sbdmadscr_t *dsc;
struct sk_buff *sb;
int len;
-
+
for (;;) {
- /*
+ /*
* figure out where we are (as an index) and where
* the hardware is (also as an index)
*
- * This could be done faster if (for example) the
+ * This could be done faster if (for example) the
* descriptor table was page-aligned and contiguous in
* both virtual and physical memory -- you could then
* just compare the low-order bits of the virtual address
* (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
*/
-
+
curidx = d->sbdma_remptr - d->sbdma_dscrtable;
- hwidx = (int) (((SBMAC_READCSR(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
+ hwidx = (int) (((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t));
-
+
/*
* If they're the same, that means we've processed all
* of the descriptors up to (but not including) the one that
* the hardware is working on right now.
*/
-
+
if (curidx == hwidx)
break;
-
+
/*
* Otherwise, get the packet's sk_buff ptr back
*/
-
+
dsc = &(d->sbdma_dscrtable[curidx]);
sb = d->sbdma_ctxtable[curidx];
d->sbdma_ctxtable[curidx] = NULL;
-
+
len = (int)G_DMA_DSCRB_PKT_SIZE(dsc->dscr_b) - 4;
-
+
/*
* Check packet status. If good, process it.
* If not, silently drop it and put it back on the
* receive ring.
*/
-
+
if (!(dsc->dscr_a & M_DMA_ETHRX_BAD)) {
-
+
/*
* Add a new buffer to replace the old one. If we fail
* to allocate a buffer, we're going to drop this
* packet and put it right back on the receive ring.
*/
-
+
if (sbdma_add_rcvbuffer(d,NULL) == -ENOBUFS) {
sc->sbm_stats.rx_dropped++;
sbdma_add_rcvbuffer(d,sb); /* re-add old buffer */
@@ -1221,7 +1197,7 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
* Set length into the packet
*/
skb_put(sb,len);
-
+
/*
* Buffer has been replaced on the
* receive ring. Pass the buffer to
@@ -1240,7 +1216,7 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
sb->ip_summed = CHECKSUM_NONE;
}
}
-
+
netif_rx(sb);
}
} else {
@@ -1251,14 +1227,14 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
sc->sbm_stats.rx_errors++;
sbdma_add_rcvbuffer(d,sb);
}
-
-
- /*
+
+
+ /*
* .. and advance to the next buffer.
*/
-
+
d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
-
+
}
}
@@ -1266,17 +1242,17 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
/**********************************************************************
* SBDMA_TX_PROCESS(sc,d)
- *
- * Process "completed" transmit buffers on the specified DMA channel.
+ *
+ * Process "completed" transmit buffers on the specified DMA channel.
* This is normally called within the interrupt service routine.
* Note that this isn't really ideal for priority channels, since
- * it processes all of the packets on a given channel before
- * returning.
+ * it processes all of the packets on a given channel before
+ * returning.
*
- * Input parameters:
+ * Input parameters:
* sc - softc structure
* d - DMA channel context
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1290,21 +1266,21 @@ static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d)
unsigned long flags;
spin_lock_irqsave(&(sc->sbm_lock), flags);
-
+
for (;;) {
- /*
+ /*
* figure out where we are (as an index) and where
* the hardware is (also as an index)
*
- * This could be done faster if (for example) the
+ * This could be done faster if (for example) the
* descriptor table was page-aligned and contiguous in
* both virtual and physical memory -- you could then
* just compare the low-order bits of the virtual address
* (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
*/
-
+
curidx = d->sbdma_remptr - d->sbdma_dscrtable;
- hwidx = (int) (((SBMAC_READCSR(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
+ hwidx = (int) (((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t));
/*
@@ -1312,75 +1288,75 @@ static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d)
* of the descriptors up to (but not including) the one that
* the hardware is working on right now.
*/
-
+
if (curidx == hwidx)
break;
-
+
/*
* Otherwise, get the packet's sk_buff ptr back
*/
-
+
dsc = &(d->sbdma_dscrtable[curidx]);
sb = d->sbdma_ctxtable[curidx];
d->sbdma_ctxtable[curidx] = NULL;
-
+
/*
* Stats
*/
-
+
sc->sbm_stats.tx_bytes += sb->len;
sc->sbm_stats.tx_packets++;
-
+
/*
* for transmits, we just free buffers.
*/
-
+
dev_kfree_skb_irq(sb);
-
- /*
+
+ /*
* .. and advance to the next buffer.
*/
d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
-
+
}
-
+
/*
* Decide if we should wake up the protocol or not.
* Other drivers seem to do this when we reach a low
* watermark on the transmit queue.
*/
-
+
netif_wake_queue(d->sbdma_eth->sbm_dev);
-
+
spin_unlock_irqrestore(&(sc->sbm_lock), flags);
-
+
}
/**********************************************************************
* SBMAC_INITCTX(s)
- *
+ *
* Initialize an Ethernet context structure - this is called
* once per MAC on the 1250. Memory is allocated here, so don't
* call it again from inside the ioctl routines that bring the
* interface up/down
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac context structure
- *
+ *
* Return value:
* 0
********************************************************************* */
static int sbmac_initctx(struct sbmac_softc *s)
{
-
- /*
- * figure out the addresses of some ports
+
+ /*
+ * figure out the addresses of some ports
*/
-
+
s->sbm_macenable = s->sbm_base + R_MAC_ENABLE;
s->sbm_maccfg = s->sbm_base + R_MAC_CFG;
s->sbm_fifocfg = s->sbm_base + R_MAC_THRSH_CFG;
@@ -1397,29 +1373,29 @@ static int sbmac_initctx(struct sbmac_softc *s)
s->sbm_phy_oldanlpar = 0;
s->sbm_phy_oldk1stsr = 0;
s->sbm_phy_oldlinkstat = 0;
-
+
/*
* Initialize the DMA channels. Right now, only one per MAC is used
* Note: Only do this _once_, as it allocates memory from the kernel!
*/
-
+
sbdma_initctx(&(s->sbm_txdma),s,0,DMA_TX,SBMAC_MAX_TXDESCR);
sbdma_initctx(&(s->sbm_rxdma),s,0,DMA_RX,SBMAC_MAX_RXDESCR);
-
+
/*
* initial state is OFF
*/
-
+
s->sbm_state = sbmac_state_off;
-
+
/*
* Initial speed is (XXX TEMP) 10MBit/s HDX no FC
*/
-
+
s->sbm_speed = sbmac_speed_10;
s->sbm_duplex = sbmac_duplex_half;
s->sbm_fc = sbmac_fc_disabled;
-
+
return 0;
}
@@ -1430,7 +1406,7 @@ static void sbdma_uninitctx(struct sbmacdma_s *d)
kfree(d->sbdma_dscrtable);
d->sbdma_dscrtable = NULL;
}
-
+
if (d->sbdma_ctxtable) {
kfree(d->sbdma_ctxtable);
d->sbdma_ctxtable = NULL;
@@ -1447,12 +1423,12 @@ static void sbmac_uninitctx(struct sbmac_softc *sc)
/**********************************************************************
* SBMAC_CHANNEL_START(s)
- *
+ *
* Start packet processing on this MAC.
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1460,49 +1436,49 @@ static void sbmac_uninitctx(struct sbmac_softc *sc)
static void sbmac_channel_start(struct sbmac_softc *s)
{
uint64_t reg;
- sbmac_port_t port;
+ volatile void __iomem *port;
uint64_t cfg,fifo,framecfg;
int idx, th_value;
-
+
/*
* Don't do this if running
*/
if (s->sbm_state == sbmac_state_on)
return;
-
+
/*
* Bring the controller out of reset, but leave it off.
*/
-
- SBMAC_WRITECSR(s->sbm_macenable,0);
-
+
+ __raw_writeq(0, s->sbm_macenable);
+
/*
* Ignore all received packets
*/
-
- SBMAC_WRITECSR(s->sbm_rxfilter,0);
-
- /*
+
+ __raw_writeq(0, s->sbm_rxfilter);
+
+ /*
* Calculate values for various control registers.
*/
-
+
cfg = M_MAC_RETRY_EN |
- M_MAC_TX_HOLD_SOP_EN |
+ M_MAC_TX_HOLD_SOP_EN |
V_MAC_TX_PAUSE_CNT_16K |
M_MAC_AP_STAT_EN |
M_MAC_FAST_SYNC |
M_MAC_SS_EN |
0;
-
- /*
+
+ /*
* Be sure that RD_THRSH+WR_THRSH <= 32 for pass1 pars
* and make sure that RD_THRSH + WR_THRSH <=128 for pass2 and above
* Use a larger RD_THRSH for gigabit
*/
- if (periph_rev >= 2)
+ if (periph_rev >= 2)
th_value = 64;
- else
+ else
th_value = 28;
fifo = V_MAC_TX_WR_THRSH(4) | /* Must be '4' or '8' */
@@ -1520,51 +1496,51 @@ static void sbmac_channel_start(struct sbmac_softc *s)
V_MAC_BACKOFF_SEL(1);
/*
- * Clear out the hash address map
+ * Clear out the hash address map
*/
-
+
port = s->sbm_base + R_MAC_HASH_BASE;
for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
- SBMAC_WRITECSR(port,0);
+ __raw_writeq(0, port);
port += sizeof(uint64_t);
}
-
+
/*
* Clear out the exact-match table
*/
-
+
port = s->sbm_base + R_MAC_ADDR_BASE;
for (idx = 0; idx < MAC_ADDR_COUNT; idx++) {
- SBMAC_WRITECSR(port,0);
+ __raw_writeq(0, port);
port += sizeof(uint64_t);
}
-
+
/*
* Clear out the DMA Channel mapping table registers
*/
-
+
port = s->sbm_base + R_MAC_CHUP0_BASE;
for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
- SBMAC_WRITECSR(port,0);
+ __raw_writeq(0, port);
port += sizeof(uint64_t);
}
port = s->sbm_base + R_MAC_CHLO0_BASE;
for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
- SBMAC_WRITECSR(port,0);
+ __raw_writeq(0, port);
port += sizeof(uint64_t);
}
-
+
/*
* Program the hardware address. It goes into the hardware-address
* register as well as the first filter register.
*/
-
+
reg = sbmac_addr2reg(s->sbm_hwaddr);
-
+
port = s->sbm_base + R_MAC_ADDR_BASE;
- SBMAC_WRITECSR(port,reg);
+ __raw_writeq(reg, port);
port = s->sbm_base + R_MAC_ETHERNET_ADDR;
#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
@@ -1573,108 +1549,105 @@ static void sbmac_channel_start(struct sbmac_softc *s)
* destination address in the R_MAC_ETHERNET_ADDR register.
* Set the value to zero.
*/
- SBMAC_WRITECSR(port,0);
+ __raw_writeq(0, port);
#else
- SBMAC_WRITECSR(port,reg);
+ __raw_writeq(reg, port);
#endif
-
+
/*
* Set the receive filter for no packets, and write values
* to the various config registers
*/
-
- SBMAC_WRITECSR(s->sbm_rxfilter,0);
- SBMAC_WRITECSR(s->sbm_imr,0);
- SBMAC_WRITECSR(s->sbm_framecfg,framecfg);
- SBMAC_WRITECSR(s->sbm_fifocfg,fifo);
- SBMAC_WRITECSR(s->sbm_maccfg,cfg);
-
+
+ __raw_writeq(0, s->sbm_rxfilter);
+ __raw_writeq(0, s->sbm_imr);
+ __raw_writeq(framecfg, s->sbm_framecfg);
+ __raw_writeq(fifo, s->sbm_fifocfg);
+ __raw_writeq(cfg, s->sbm_maccfg);
+
/*
* Initialize DMA channels (rings should be ok now)
*/
-
+
sbdma_channel_start(&(s->sbm_rxdma), DMA_RX);
sbdma_channel_start(&(s->sbm_txdma), DMA_TX);
-
+
/*
* Configure the speed, duplex, and flow control
*/
sbmac_set_speed(s,s->sbm_speed);
sbmac_set_duplex(s,s->sbm_duplex,s->sbm_fc);
-
+
/*
* Fill the receive ring
*/
-
+
sbdma_fillring(&(s->sbm_rxdma));
-
- /*
+
+ /*
* Turn on the rest of the bits in the enable register
- */
-
- SBMAC_WRITECSR(s->sbm_macenable,
- M_MAC_RXDMA_EN0 |
+ */
+
+ __raw_writeq(M_MAC_RXDMA_EN0 |
M_MAC_TXDMA_EN0 |
M_MAC_RX_ENABLE |
- M_MAC_TX_ENABLE);
-
-
+ M_MAC_TX_ENABLE, s->sbm_macenable);
+
+
#ifdef CONFIG_SBMAC_COALESCE
/*
* Accept any TX interrupt and EOP count/timer RX interrupts on ch 0
*/
- SBMAC_WRITECSR(s->sbm_imr,
- ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
- ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0));
+ __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
+ ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0), s->sbm_imr);
#else
/*
* Accept any kind of interrupt on TX and RX DMA channel 0
*/
- SBMAC_WRITECSR(s->sbm_imr,
- (M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
- (M_MAC_INT_CHANNEL << S_MAC_RX_CH0));
+ __raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
+ (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), s->sbm_imr);
#endif
-
- /*
- * Enable receiving unicasts and broadcasts
+
+ /*
+ * Enable receiving unicasts and broadcasts
*/
-
- SBMAC_WRITECSR(s->sbm_rxfilter,M_MAC_UCAST_EN | M_MAC_BCAST_EN);
-
+
+ __raw_writeq(M_MAC_UCAST_EN | M_MAC_BCAST_EN, s->sbm_rxfilter);
+
/*
- * we're running now.
+ * we're running now.
*/
-
+
s->sbm_state = sbmac_state_on;
-
- /*
- * Program multicast addresses
+
+ /*
+ * Program multicast addresses
*/
-
+
sbmac_setmulti(s);
-
- /*
- * If channel was in promiscuous mode before, turn that on
+
+ /*
+ * If channel was in promiscuous mode before, turn that on
*/
-
+
if (s->sbm_devflags & IFF_PROMISC) {
sbmac_promiscuous_mode(s,1);
}
-
+
}
/**********************************************************************
* SBMAC_CHANNEL_STOP(s)
- *
+ *
* Stop packet processing on this MAC.
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1682,49 +1655,49 @@ static void sbmac_channel_start(struct sbmac_softc *s)
static void sbmac_channel_stop(struct sbmac_softc *s)
{
/* don't do this if already stopped */
-
+
if (s->sbm_state == sbmac_state_off)
return;
-
+
/* don't accept any packets, disable all interrupts */
-
- SBMAC_WRITECSR(s->sbm_rxfilter,0);
- SBMAC_WRITECSR(s->sbm_imr,0);
-
+
+ __raw_writeq(0, s->sbm_rxfilter);
+ __raw_writeq(0, s->sbm_imr);
+
/* Turn off ticker */
-
+
/* XXX */
-
+
/* turn off receiver and transmitter */
-
- SBMAC_WRITECSR(s->sbm_macenable,0);
-
+
+ __raw_writeq(0, s->sbm_macenable);
+
/* We're stopped now. */
-
+
s->sbm_state = sbmac_state_off;
-
+
/*
* Stop DMA channels (rings should be ok now)
*/
-
+
sbdma_channel_stop(&(s->sbm_rxdma));
sbdma_channel_stop(&(s->sbm_txdma));
-
+
/* Empty the receive and transmit rings */
-
+
sbdma_emptyring(&(s->sbm_rxdma));
sbdma_emptyring(&(s->sbm_txdma));
-
+
}
/**********************************************************************
* SBMAC_SET_CHANNEL_STATE(state)
- *
+ *
* Set the channel's state ON or OFF
- *
- * Input parameters:
+ *
+ * Input parameters:
* state - new state
- *
+ *
* Return value:
* old state
********************************************************************* */
@@ -1732,43 +1705,43 @@ static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *sc,
sbmac_state_t state)
{
sbmac_state_t oldstate = sc->sbm_state;
-
+
/*
* If same as previous state, return
*/
-
+
if (state == oldstate) {
return oldstate;
}
-
+
/*
- * If new state is ON, turn channel on
+ * If new state is ON, turn channel on
*/
-
+
if (state == sbmac_state_on) {
sbmac_channel_start(sc);
}
else {
sbmac_channel_stop(sc);
}
-
+
/*
* Return previous state
*/
-
+
return oldstate;
}
/**********************************************************************
* SBMAC_PROMISCUOUS_MODE(sc,onoff)
- *
+ *
* Turn on or off promiscuous mode
- *
- * Input parameters:
+ *
+ * Input parameters:
* sc - softc
* onoff - 1 to turn on, 0 to turn off
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1776,30 +1749,30 @@ static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *sc,
static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff)
{
uint64_t reg;
-
+
if (sc->sbm_state != sbmac_state_on)
return;
-
+
if (onoff) {
- reg = SBMAC_READCSR(sc->sbm_rxfilter);
+ reg = __raw_readq(sc->sbm_rxfilter);
reg |= M_MAC_ALLPKT_EN;
- SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
- }
+ __raw_writeq(reg, sc->sbm_rxfilter);
+ }
else {
- reg = SBMAC_READCSR(sc->sbm_rxfilter);
+ reg = __raw_readq(sc->sbm_rxfilter);
reg &= ~M_MAC_ALLPKT_EN;
- SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+ __raw_writeq(reg, sc->sbm_rxfilter);
}
}
/**********************************************************************
* SBMAC_SETIPHDR_OFFSET(sc,onoff)
- *
+ *
* Set the iphdr offset as 15 assuming ethernet encapsulation
- *
- * Input parameters:
+ *
+ * Input parameters:
* sc - softc
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1807,12 +1780,12 @@ static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff)
static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
{
uint64_t reg;
-
+
/* Hard code the off set to 15 for now */
- reg = SBMAC_READCSR(sc->sbm_rxfilter);
+ reg = __raw_readq(sc->sbm_rxfilter);
reg &= ~M_MAC_IPHDR_OFFSET | V_MAC_IPHDR_OFFSET(15);
- SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
-
+ __raw_writeq(reg, sc->sbm_rxfilter);
+
/* read system identification to determine revision */
if (periph_rev >= 2) {
sc->rx_hw_checksum = ENABLE;
@@ -1824,13 +1797,13 @@ static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
/**********************************************************************
* SBMAC_ADDR2REG(ptr)
- *
+ *
* Convert six bytes into the 64-bit register value that
* we typically write into the SBMAC's address/mcast registers
- *
- * Input parameters:
+ *
+ * Input parameters:
* ptr - pointer to 6 bytes
- *
+ *
* Return value:
* register value
********************************************************************* */
@@ -1838,35 +1811,35 @@ static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
static uint64_t sbmac_addr2reg(unsigned char *ptr)
{
uint64_t reg = 0;
-
+
ptr += 6;
-
- reg |= (uint64_t) *(--ptr);
+
+ reg |= (uint64_t) *(--ptr);
reg <<= 8;
- reg |= (uint64_t) *(--ptr);
+ reg |= (uint64_t) *(--ptr);
reg <<= 8;
- reg |= (uint64_t) *(--ptr);
+ reg |= (uint64_t) *(--ptr);
reg <<= 8;
- reg |= (uint64_t) *(--ptr);
+ reg |= (uint64_t) *(--ptr);
reg <<= 8;
- reg |= (uint64_t) *(--ptr);
+ reg |= (uint64_t) *(--ptr);
reg <<= 8;
- reg |= (uint64_t) *(--ptr);
-
+ reg |= (uint64_t) *(--ptr);
+
return reg;
}
/**********************************************************************
* SBMAC_SET_SPEED(s,speed)
- *
+ *
* Configure LAN speed for the specified MAC.
* Warning: must be called when MAC is off!
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
* speed - speed to set MAC to (see sbmac_speed_t enum)
- *
+ *
* Return value:
* 1 if successful
* 0 indicates invalid parameters
@@ -1880,31 +1853,31 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
/*
* Save new current values
*/
-
+
s->sbm_speed = speed;
-
+
if (s->sbm_state == sbmac_state_on)
return 0; /* save for next restart */
/*
- * Read current register values
+ * Read current register values
*/
-
- cfg = SBMAC_READCSR(s->sbm_maccfg);
- framecfg = SBMAC_READCSR(s->sbm_framecfg);
-
+
+ cfg = __raw_readq(s->sbm_maccfg);
+ framecfg = __raw_readq(s->sbm_framecfg);
+
/*
* Mask out the stuff we want to change
*/
-
+
cfg &= ~(M_MAC_BURST_EN | M_MAC_SPEED_SEL);
framecfg &= ~(M_MAC_IFG_RX | M_MAC_IFG_TX | M_MAC_IFG_THRSH |
M_MAC_SLOT_SIZE);
-
+
/*
* Now add in the new bits
*/
-
+
switch (speed) {
case sbmac_speed_10:
framecfg |= V_MAC_IFG_RX_10 |
@@ -1913,7 +1886,7 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
V_MAC_SLOT_SIZE_10;
cfg |= V_MAC_SPEED_SEL_10MBPS;
break;
-
+
case sbmac_speed_100:
framecfg |= V_MAC_IFG_RX_100 |
V_MAC_IFG_TX_100 |
@@ -1921,7 +1894,7 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
V_MAC_SLOT_SIZE_100;
cfg |= V_MAC_SPEED_SEL_100MBPS ;
break;
-
+
case sbmac_speed_1000:
framecfg |= V_MAC_IFG_RX_1000 |
V_MAC_IFG_TX_1000 |
@@ -1929,34 +1902,34 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
V_MAC_SLOT_SIZE_1000;
cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN;
break;
-
+
case sbmac_speed_auto: /* XXX not implemented */
/* fall through */
default:
return 0;
}
-
+
/*
- * Send the bits back to the hardware
+ * Send the bits back to the hardware
*/
-
- SBMAC_WRITECSR(s->sbm_framecfg,framecfg);
- SBMAC_WRITECSR(s->sbm_maccfg,cfg);
-
+
+ __raw_writeq(framecfg, s->sbm_framecfg);
+ __raw_writeq(cfg, s->sbm_maccfg);
+
return 1;
}
/**********************************************************************
* SBMAC_SET_DUPLEX(s,duplex,fc)
- *
+ *
* Set Ethernet duplex and flow control options for this MAC
* Warning: must be called when MAC is off!
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
* duplex - duplex setting (see sbmac_duplex_t)
* fc - flow control setting (see sbmac_fc_t)
- *
+ *
* Return value:
* 1 if ok
* 0 if an invalid parameter combination was specified
@@ -1965,67 +1938,67 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc_t fc)
{
uint64_t cfg;
-
+
/*
* Save new current values
*/
-
+
s->sbm_duplex = duplex;
s->sbm_fc = fc;
-
+
if (s->sbm_state == sbmac_state_on)
return 0; /* save for next restart */
-
+
/*
- * Read current register values
+ * Read current register values
*/
-
- cfg = SBMAC_READCSR(s->sbm_maccfg);
-
+
+ cfg = __raw_readq(s->sbm_maccfg);
+
/*
* Mask off the stuff we're about to change
*/
-
+
cfg &= ~(M_MAC_FC_SEL | M_MAC_FC_CMD | M_MAC_HDX_EN);
-
-
+
+
switch (duplex) {
case sbmac_duplex_half:
switch (fc) {
case sbmac_fc_disabled:
cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_DISABLED;
break;
-
+
case sbmac_fc_collision:
cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENABLED;
break;
-
+
case sbmac_fc_carrier:
cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR;
break;
-
+
case sbmac_fc_auto: /* XXX not implemented */
- /* fall through */
+ /* fall through */
case sbmac_fc_frame: /* not valid in half duplex */
default: /* invalid selection */
return 0;
}
break;
-
+
case sbmac_duplex_full:
switch (fc) {
case sbmac_fc_disabled:
cfg |= V_MAC_FC_CMD_DISABLED;
break;
-
+
case sbmac_fc_frame:
cfg |= V_MAC_FC_CMD_ENABLED;
break;
-
+
case sbmac_fc_collision: /* not valid in full duplex */
case sbmac_fc_carrier: /* not valid in full duplex */
case sbmac_fc_auto: /* XXX not implemented */
- /* fall through */
+ /* fall through */
default:
return 0;
}
@@ -2034,13 +2007,13 @@ static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc
/* XXX not implemented */
break;
}
-
+
/*
- * Send the bits back to the hardware
+ * Send the bits back to the hardware
*/
-
- SBMAC_WRITECSR(s->sbm_maccfg,cfg);
-
+
+ __raw_writeq(cfg, s->sbm_maccfg);
+
return 1;
}
@@ -2049,12 +2022,12 @@ static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc
/**********************************************************************
* SBMAC_INTR()
- *
+ *
* Interrupt handler for MAC interrupts
- *
- * Input parameters:
+ *
+ * Input parameters:
* MAC structure
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -2066,27 +2039,27 @@ static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
int handled = 0;
for (;;) {
-
+
/*
* Read the ISR (this clears the bits in the real
* register, except for counter addr)
*/
-
- isr = SBMAC_READCSR(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR;
-
+
+ isr = __raw_readq(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR;
+
if (isr == 0)
break;
handled = 1;
-
+
/*
* Transmits on channel 0
*/
-
+
if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) {
sbdma_tx_process(sc,&(sc->sbm_txdma));
}
-
+
/*
* Receives on channel 0
*/
@@ -2106,8 +2079,8 @@ static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
* EOP_SEEN here takes care of this case.
* (EOP_SEEN is part of M_MAC_INT_CHANNEL << S_MAC_RX_CH0)
*/
-
-
+
+
if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
sbdma_rx_process(sc,&(sc->sbm_rxdma));
}
@@ -2118,29 +2091,29 @@ static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
/**********************************************************************
* SBMAC_START_TX(skb,dev)
- *
- * Start output on the specified interface. Basically, we
+ *
+ * Start output on the specified interface. Basically, we
* queue as many buffers as we can until the ring fills up, or
* we run off the end of the queue, whichever comes first.
- *
- * Input parameters:
- *
- *
+ *
+ * Input parameters:
+ *
+ *
* Return value:
* nothing
********************************************************************* */
static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
{
struct sbmac_softc *sc = netdev_priv(dev);
-
+
/* lock eth irq */
spin_lock_irq (&sc->sbm_lock);
-
+
/*
- * Put the buffer on the transmit ring. If we
+ * Put the buffer on the transmit ring. If we
* don't have room, stop the queue.
*/
-
+
if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) {
/* XXX save skb that we could not send */
netif_stop_queue(dev);
@@ -2148,24 +2121,24 @@ static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
return 1;
}
-
+
dev->trans_start = jiffies;
-
+
spin_unlock_irq (&sc->sbm_lock);
-
+
return 0;
}
/**********************************************************************
* SBMAC_SETMULTI(sc)
- *
+ *
* Reprogram the multicast table into the hardware, given
* the list of multicasts associated with the interface
* structure.
- *
- * Input parameters:
+ *
+ * Input parameters:
* sc - softc
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -2173,75 +2146,75 @@ static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
static void sbmac_setmulti(struct sbmac_softc *sc)
{
uint64_t reg;
- sbmac_port_t port;
+ volatile void __iomem *port;
int idx;
struct dev_mc_list *mclist;
struct net_device *dev = sc->sbm_dev;
-
- /*
+
+ /*
* Clear out entire multicast table. We do this by nuking
* the entire hash table and all the direct matches except
- * the first one, which is used for our station address
+ * the first one, which is used for our station address
*/
-
+
for (idx = 1; idx < MAC_ADDR_COUNT; idx++) {
port = sc->sbm_base + R_MAC_ADDR_BASE+(idx*sizeof(uint64_t));
- SBMAC_WRITECSR(port,0);
+ __raw_writeq(0, port);
}
-
+
for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
port = sc->sbm_base + R_MAC_HASH_BASE+(idx*sizeof(uint64_t));
- SBMAC_WRITECSR(port,0);
+ __raw_writeq(0, port);
}
-
+
/*
* Clear the filter to say we don't want any multicasts.
*/
-
- reg = SBMAC_READCSR(sc->sbm_rxfilter);
+
+ reg = __raw_readq(sc->sbm_rxfilter);
reg &= ~(M_MAC_MCAST_INV | M_MAC_MCAST_EN);
- SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
-
+ __raw_writeq(reg, sc->sbm_rxfilter);
+
if (dev->flags & IFF_ALLMULTI) {
- /*
- * Enable ALL multicasts. Do this by inverting the
- * multicast enable bit.
+ /*
+ * Enable ALL multicasts. Do this by inverting the
+ * multicast enable bit.
*/
- reg = SBMAC_READCSR(sc->sbm_rxfilter);
+ reg = __raw_readq(sc->sbm_rxfilter);
reg |= (M_MAC_MCAST_INV | M_MAC_MCAST_EN);
- SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+ __raw_writeq(reg, sc->sbm_rxfilter);
return;
}
-
- /*
+
+ /*
* Progam new multicast entries. For now, only use the
* perfect filter. In the future we'll need to use the
* hash filter if the perfect filter overflows
*/
-
+
/* XXX only using perfect filter for now, need to use hash
* XXX if the table overflows */
-
+
idx = 1; /* skip station address */
mclist = dev->mc_list;
while (mclist && (idx < MAC_ADDR_COUNT)) {
reg = sbmac_addr2reg(mclist->dmi_addr);
port = sc->sbm_base + R_MAC_ADDR_BASE+(idx * sizeof(uint64_t));
- SBMAC_WRITECSR(port,reg);
+ __raw_writeq(reg, port);
idx++;
mclist = mclist->next;
}
-
- /*
+
+ /*
* Enable the "accept multicast bits" if we programmed at least one
- * multicast.
+ * multicast.
*/
-
+
if (idx > 1) {
- reg = SBMAC_READCSR(sc->sbm_rxfilter);
+ reg = __raw_readq(sc->sbm_rxfilter);
reg |= M_MAC_MCAST_EN;
- SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+ __raw_writeq(reg, sc->sbm_rxfilter);
}
}
@@ -2250,12 +2223,12 @@ static void sbmac_setmulti(struct sbmac_softc *sc)
#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR)
/**********************************************************************
* SBMAC_PARSE_XDIGIT(str)
- *
+ *
* Parse a hex digit, returning its value
- *
- * Input parameters:
+ *
+ * Input parameters:
* str - character
- *
+ *
* Return value:
* hex value, or -1 if invalid
********************************************************************* */
@@ -2263,7 +2236,7 @@ static void sbmac_setmulti(struct sbmac_softc *sc)
static int sbmac_parse_xdigit(char str)
{
int digit;
-
+
if ((str >= '0') && (str <= '9'))
digit = str - '0';
else if ((str >= 'a') && (str <= 'f'))
@@ -2272,20 +2245,20 @@ static int sbmac_parse_xdigit(char str)
digit = str - 'A' + 10;
else
return -1;
-
+
return digit;
}
/**********************************************************************
* SBMAC_PARSE_HWADDR(str,hwaddr)
- *
+ *
* Convert a string in the form xx:xx:xx:xx:xx:xx into a 6-byte
* Ethernet address.
- *
- * Input parameters:
+ *
+ * Input parameters:
* str - string
* hwaddr - pointer to hardware address
- *
+ *
* Return value:
* 0 if ok, else -1
********************************************************************* */
@@ -2294,7 +2267,7 @@ static int sbmac_parse_hwaddr(char *str, unsigned char *hwaddr)
{
int digit1,digit2;
int idx = 6;
-
+
while (*str && (idx > 0)) {
digit1 = sbmac_parse_xdigit(*str);
if (digit1 < 0)
@@ -2302,7 +2275,7 @@ static int sbmac_parse_hwaddr(char *str, unsigned char *hwaddr)
str++;
if (!*str)
return -1;
-
+
if ((*str == ':') || (*str == '-')) {
digit2 = digit1;
digit1 = 0;
@@ -2313,10 +2286,10 @@ static int sbmac_parse_hwaddr(char *str, unsigned char *hwaddr)
return -1;
str++;
}
-
+
*hwaddr++ = (digit1 << 4) | digit2;
idx--;
-
+
if (*str == '-')
str++;
if (*str == ':')
@@ -2337,12 +2310,12 @@ static int sb1250_change_mtu(struct net_device *_dev, int new_mtu)
/**********************************************************************
* SBMAC_INIT(dev)
- *
+ *
* Attach routine - init hardware and hook ourselves into linux
- *
- * Input parameters:
+ *
+ * Input parameters:
* dev - net_device structure
- *
+ *
* Return value:
* status
********************************************************************* */
@@ -2354,53 +2327,53 @@ static int sbmac_init(struct net_device *dev, int idx)
uint64_t ea_reg;
int i;
int err;
-
+
sc = netdev_priv(dev);
-
+
/* Determine controller base address */
-
+
sc->sbm_base = IOADDR(dev->base_addr);
sc->sbm_dev = dev;
sc->sbe_idx = idx;
-
+
eaddr = sc->sbm_hwaddr;
-
- /*
+
+ /*
* Read the ethernet address. The firwmare left this programmed
* for us in the ethernet address register for each mac.
*/
-
- ea_reg = SBMAC_READCSR(sc->sbm_base + R_MAC_ETHERNET_ADDR);
- SBMAC_WRITECSR(sc->sbm_base + R_MAC_ETHERNET_ADDR, 0);
+
+ ea_reg = __raw_readq(sc->sbm_base + R_MAC_ETHERNET_ADDR);
+ __raw_writeq(0, sc->sbm_base + R_MAC_ETHERNET_ADDR);
for (i = 0; i < 6; i++) {
eaddr[i] = (uint8_t) (ea_reg & 0xFF);
ea_reg >>= 8;
}
-
+
for (i = 0; i < 6; i++) {
dev->dev_addr[i] = eaddr[i];
}
-
-
+
+
/*
- * Init packet size
+ * Init packet size
*/
-
+
sc->sbm_buffersize = ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN;
- /*
+ /*
* Initialize context (get pointers to registers and stuff), then
* allocate the memory for the descriptor tables.
*/
-
+
sbmac_initctx(sc);
-
+
/*
* Set up Linux device callins
*/
-
+
spin_lock_init(&(sc->sbm_lock));
-
+
dev->open = sbmac_open;
dev->hard_start_xmit = sbmac_start_tx;
dev->stop = sbmac_close;
@@ -2419,7 +2392,7 @@ static int sbmac_init(struct net_device *dev, int idx)
if (err)
goto out_uninit;
- if (periph_rev >= 2) {
+ if (sc->rx_hw_checksum == ENABLE) {
printk(KERN_INFO "%s: enabling TCP rcv checksum\n",
sc->sbm_dev->name);
}
@@ -2430,10 +2403,10 @@ static int sbmac_init(struct net_device *dev, int idx)
* was being displayed)
*/
printk(KERN_INFO
- "%s: SiByte Ethernet at 0x%08lX, address: %02X:%02X:%02X:%02X:%02X:%02X\n",
+ "%s: SiByte Ethernet at 0x%08lX, address: %02X:%02X:%02X:%02X:%02X:%02X\n",
dev->name, dev->base_addr,
eaddr[0],eaddr[1],eaddr[2],eaddr[3],eaddr[4],eaddr[5]);
-
+
return 0;
@@ -2447,54 +2420,86 @@ out_uninit:
static int sbmac_open(struct net_device *dev)
{
struct sbmac_softc *sc = netdev_priv(dev);
-
+
if (debug > 1) {
printk(KERN_DEBUG "%s: sbmac_open() irq %d.\n", dev->name, dev->irq);
}
-
- /*
+
+ /*
* map/route interrupt (clear status first, in case something
* weird is pending; we haven't initialized the mac registers
* yet)
*/
- SBMAC_READCSR(sc->sbm_isr);
+ __raw_readq(sc->sbm_isr);
if (request_irq(dev->irq, &sbmac_intr, SA_SHIRQ, dev->name, dev))
return -EBUSY;
/*
- * Configure default speed
+ * Probe phy address
+ */
+
+ if(sbmac_mii_probe(dev) == -1) {
+ printk("%s: failed to probe PHY.\n", dev->name);
+ return -EINVAL;
+ }
+
+ /*
+ * Configure default speed
*/
sbmac_mii_poll(sc,noisy_mii);
-
+
/*
* Turn on the channel
*/
sbmac_set_channel_state(sc,sbmac_state_on);
-
+
/*
* XXX Station address is in dev->dev_addr
*/
-
+
if (dev->if_port == 0)
- dev->if_port = 0;
-
+ dev->if_port = 0;
+
netif_start_queue(dev);
-
+
sbmac_set_rx_mode(dev);
-
+
/* Set the timer to check for link beat. */
init_timer(&sc->sbm_timer);
sc->sbm_timer.expires = jiffies + 2 * HZ/100;
sc->sbm_timer.data = (unsigned long)dev;
sc->sbm_timer.function = &sbmac_timer;
add_timer(&sc->sbm_timer);
-
+
return 0;
}
+static int sbmac_mii_probe(struct net_device *dev)
+{
+ int i;
+ struct sbmac_softc *s = netdev_priv(dev);
+ u16 bmsr, id1, id2;
+ u32 vendor, device;
+
+ for (i=1; i<31; i++) {
+ bmsr = sbmac_mii_read(s, i, MII_BMSR);
+ if (bmsr != 0) {
+ s->sbm_phys[0] = i;
+ id1 = sbmac_mii_read(s, i, MII_PHYIDR1);
+ id2 = sbmac_mii_read(s, i, MII_PHYIDR2);
+ vendor = ((u32)id1 << 6) | ((id2 >> 10) & 0x3f);
+ device = (id2 >> 4) & 0x3f;
+
+ printk(KERN_INFO "%s: found phy %d, vendor %06x part %02x\n",
+ dev->name, i, vendor, device);
+ return i;
+ }
+ }
+ return -1;
+}
static int sbmac_mii_poll(struct sbmac_softc *s,int noisy)
@@ -2609,20 +2614,20 @@ static void sbmac_timer(unsigned long data)
int mii_status;
spin_lock_irq (&sc->sbm_lock);
-
+
/* make IFF_RUNNING follow the MII status bit "Link established" */
mii_status = sbmac_mii_read(sc, sc->sbm_phys[0], MII_BMSR);
-
+
if ( (mii_status & BMSR_LINKSTAT) != (sc->sbm_phy_oldlinkstat) ) {
sc->sbm_phy_oldlinkstat = mii_status & BMSR_LINKSTAT;
if (mii_status & BMSR_LINKSTAT) {
netif_carrier_on(dev);
}
else {
- netif_carrier_off(dev);
+ netif_carrier_off(dev);
}
}
-
+
/*
* Poll the PHY to see what speed we should be running at
*/
@@ -2640,9 +2645,9 @@ static void sbmac_timer(unsigned long data)
sbmac_channel_start(sc);
}
}
-
+
spin_unlock_irq (&sc->sbm_lock);
-
+
sc->sbm_timer.expires = jiffies + next_tick;
add_timer(&sc->sbm_timer);
}
@@ -2651,13 +2656,13 @@ static void sbmac_timer(unsigned long data)
static void sbmac_tx_timeout (struct net_device *dev)
{
struct sbmac_softc *sc = netdev_priv(dev);
-
+
spin_lock_irq (&sc->sbm_lock);
-
-
+
+
dev->trans_start = jiffies;
sc->sbm_stats.tx_errors++;
-
+
spin_unlock_irq (&sc->sbm_lock);
printk (KERN_WARNING "%s: Transmit timed out\n",dev->name);
@@ -2670,13 +2675,13 @@ static struct net_device_stats *sbmac_get_stats(struct net_device *dev)
{
struct sbmac_softc *sc = netdev_priv(dev);
unsigned long flags;
-
+
spin_lock_irqsave(&sc->sbm_lock, flags);
-
+
/* XXX update other stats here */
-
+
spin_unlock_irqrestore(&sc->sbm_lock, flags);
-
+
return &sc->sbm_stats;
}
@@ -2693,8 +2698,8 @@ static void sbmac_set_rx_mode(struct net_device *dev)
/*
* Promiscuous changed.
*/
-
- if (dev->flags & IFF_PROMISC) {
+
+ if (dev->flags & IFF_PROMISC) {
/* Unconditionally log net taps. */
msg_flag = 1;
sbmac_promiscuous_mode(sc,1);
@@ -2705,18 +2710,18 @@ static void sbmac_set_rx_mode(struct net_device *dev)
}
}
spin_unlock_irqrestore(&sc->sbm_lock, flags);
-
+
if (msg_flag) {
printk(KERN_NOTICE "%s: Promiscuous mode %sabled.\n",
dev->name,(msg_flag==1)?"en":"dis");
}
-
+
/*
* Program the multicasts. Do this every time.
*/
-
+
sbmac_setmulti(sc);
-
+
}
static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -2725,10 +2730,10 @@ static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
u16 *data = (u16 *)&rq->ifr_ifru;
unsigned long flags;
int retval;
-
+
spin_lock_irqsave(&sc->sbm_lock, flags);
retval = 0;
-
+
switch(cmd) {
case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
data[0] = sc->sbm_phys[0] & 0x1f;
@@ -2750,7 +2755,7 @@ static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
default:
retval = -EOPNOTSUPP;
}
-
+
spin_unlock_irqrestore(&sc->sbm_lock, flags);
return retval;
}
@@ -2781,7 +2786,7 @@ static int sbmac_close(struct net_device *dev)
sbdma_emptyring(&(sc->sbm_txdma));
sbdma_emptyring(&(sc->sbm_rxdma));
-
+
return 0;
}
@@ -2793,13 +2798,13 @@ sbmac_setup_hwaddr(int chan,char *addr)
{
uint8_t eaddr[6];
uint64_t val;
- sbmac_port_t port;
+ unsigned long port;
port = A_MAC_CHANNEL_BASE(chan);
sbmac_parse_hwaddr(addr,eaddr);
val = sbmac_addr2reg(eaddr);
- SBMAC_WRITECSR(IOADDR(port+R_MAC_ETHERNET_ADDR),val);
- val = SBMAC_READCSR(IOADDR(port+R_MAC_ETHERNET_ADDR));
+ __raw_writeq(val, IOADDR(port+R_MAC_ETHERNET_ADDR));
+ val = __raw_readq(IOADDR(port+R_MAC_ETHERNET_ADDR));
}
#endif
@@ -2810,9 +2815,9 @@ sbmac_init_module(void)
{
int idx;
struct net_device *dev;
- sbmac_port_t port;
+ unsigned long port;
int chip_max_units;
-
+
/*
* For bringup when not using the firmware, we can pre-fill
* the MAC addresses using the environment variables
@@ -2858,13 +2863,13 @@ sbmac_init_module(void)
port = A_MAC_CHANNEL_BASE(idx);
- /*
+ /*
* The R_MAC_ETHERNET_ADDR register will be set to some nonzero
* value for us by the firmware if we're going to use this MAC.
* If we find a zero, skip this MAC.
*/
- sbmac_orig_hwaddr[idx] = SBMAC_READCSR(IOADDR(port+R_MAC_ETHERNET_ADDR));
+ sbmac_orig_hwaddr[idx] = __raw_readq(IOADDR(port+R_MAC_ETHERNET_ADDR));
if (sbmac_orig_hwaddr[idx] == 0) {
printk(KERN_DEBUG "sbmac: not configuring MAC at "
"%lx\n", port);
@@ -2876,7 +2881,7 @@ sbmac_init_module(void)
*/
dev = alloc_etherdev(sizeof(struct sbmac_softc));
- if (!dev)
+ if (!dev)
return -ENOMEM; /* return ENOMEM */
printk(KERN_DEBUG "sbmac: configuring MAC at %lx\n", port);
@@ -2886,8 +2891,7 @@ sbmac_init_module(void)
dev->mem_end = 0;
if (sbmac_init(dev, idx)) {
port = A_MAC_CHANNEL_BASE(idx);
- SBMAC_WRITECSR(IOADDR(port+R_MAC_ETHERNET_ADDR),
- sbmac_orig_hwaddr[idx]);
+ __raw_writeq(sbmac_orig_hwaddr[idx], IOADDR(port+R_MAC_ETHERNET_ADDR));
free_netdev(dev);
continue;
}
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index 9bc3b1c0dd6a27..a4614df38a903a 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -32,8 +32,6 @@
#include "sgiseeq.h"
-static char *version = "sgiseeq.c: David S. Miller (dm@engr.sgi.com)\n";
-
static char *sgiseeqstr = "SGI Seeq8003";
/*
@@ -113,9 +111,9 @@ static struct net_device *root_sgiseeq_dev;
static inline void hpc3_eth_reset(struct hpc3_ethregs *hregs)
{
- hregs->rx_reset = HPC3_ERXRST_CRESET | HPC3_ERXRST_CLRIRQ;
+ hregs->reset = HPC3_ERST_CRESET | HPC3_ERST_CLRIRQ;
udelay(20);
- hregs->rx_reset = 0;
+ hregs->reset = 0;
}
static inline void reset_hpc3_and_seeq(struct hpc3_ethregs *hregs,
@@ -252,7 +250,6 @@ void sgiseeq_dump_rings(void)
#define TSTAT_INIT_SEEQ (SEEQ_TCMD_IPT|SEEQ_TCMD_I16|SEEQ_TCMD_IC|SEEQ_TCMD_IUF)
#define TSTAT_INIT_EDLC ((TSTAT_INIT_SEEQ) | SEEQ_TCMD_RB2)
-#define RDMACFG_INIT (HPC3_ERXDCFG_FRXDC | HPC3_ERXDCFG_FEOP | HPC3_ERXDCFG_FIRQ)
static int init_seeq(struct net_device *dev, struct sgiseeq_private *sp,
struct sgiseeq_regs *sregs)
@@ -274,8 +271,6 @@ static int init_seeq(struct net_device *dev, struct sgiseeq_private *sp,
sregs->tstat = TSTAT_INIT_SEEQ;
}
- hregs->rx_dconfig |= RDMACFG_INIT;
-
hregs->rx_ndptr = CPHYSADDR(sp->rx_desc);
hregs->tx_ndptr = CPHYSADDR(sp->tx_desc);
@@ -446,7 +441,7 @@ static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs
spin_lock(&sp->tx_lock);
/* Ack the IRQ and set software state. */
- hregs->rx_reset = HPC3_ERXRST_CLRIRQ;
+ hregs->reset = HPC3_ERST_CLRIRQ;
/* Always check for received packets. */
sgiseeq_rx(dev, sp, hregs, sregs);
@@ -493,11 +488,13 @@ static int sgiseeq_close(struct net_device *dev)
{
struct sgiseeq_private *sp = netdev_priv(dev);
struct sgiseeq_regs *sregs = sp->sregs;
+ unsigned int irq = dev->irq;
netif_stop_queue(dev);
/* Shutdown the Seeq. */
reset_hpc3_and_seeq(sp->hregs, sregs);
+ free_irq(irq, dev);
return 0;
}
@@ -644,7 +641,7 @@ static inline void setup_rx_ring(struct sgiseeq_rx_desc *buf, int nbufs)
#define ALIGNED(x) ((((unsigned long)(x)) + 0xf) & ~(0xf))
-static int sgiseeq_init(struct hpc3_regs* regs, int irq)
+static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq)
{
struct sgiseeq_init_block *sr;
struct sgiseeq_private *sp;
@@ -680,8 +677,8 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
gpriv = sp;
gdev = dev;
#endif
- sp->sregs = (struct sgiseeq_regs *) &hpc3c0->eth_ext[0];
- sp->hregs = &hpc3c0->ethregs;
+ sp->sregs = (struct sgiseeq_regs *) &hpcregs->eth_ext[0];
+ sp->hregs = &hpcregs->ethregs;
sp->name = sgiseeqstr;
sp->mode = SEEQ_RCMD_RBCAST;
@@ -698,6 +695,11 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
setup_rx_ring(sp->rx_desc, SEEQ_RX_BUFFERS);
setup_tx_ring(sp->tx_desc, SEEQ_TX_BUFFERS);
+ /* Setup PIO and DMA transfer timing */
+ sp->hregs->pconfig = 0x161;
+ sp->hregs->dconfig = HPC3_EDCFG_FIRQ | HPC3_EDCFG_FEOP |
+ HPC3_EDCFG_FRXDC | HPC3_EDCFG_PTO | 0x026;
+
/* Reset the chip. */
hpc3_eth_reset(sp->hregs);
@@ -724,7 +726,7 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
goto err_out_free_page;
}
- printk(KERN_INFO "%s: SGI Seeq8003 ", dev->name);
+ printk(KERN_INFO "%s: %s ", dev->name, sgiseeqstr);
for (i = 0; i < 6; i++)
printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
@@ -734,7 +736,7 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
return 0;
err_out_free_page:
- free_page((unsigned long) sp);
+ free_page((unsigned long) sp->srings);
err_out_free_dev:
kfree(dev);
@@ -744,8 +746,6 @@ err_out:
static int __init sgiseeq_probe(void)
{
- printk(version);
-
/* On board adapter on 1st HPC is always present */
return sgiseeq_init(hpc3c0, SGI_ENET_IRQ);
}
@@ -754,15 +754,12 @@ static void __exit sgiseeq_exit(void)
{
struct net_device *next, *dev;
struct sgiseeq_private *sp;
- int irq;
for (dev = root_sgiseeq_dev; dev; dev = next) {
sp = (struct sgiseeq_private *) netdev_priv(dev);
next = sp->next_module;
- irq = dev->irq;
unregister_netdev(dev);
- free_irq(irq, dev);
- free_page((unsigned long) sp);
+ free_page((unsigned long) sp->srings);
free_netdev(dev);
}
}
@@ -770,4 +767,6 @@ static void __exit sgiseeq_exit(void)
module_init(sgiseeq_probe);
module_exit(sgiseeq_exit);
+MODULE_DESCRIPTION("SGI Seeq 8003 driver");
+MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips@linux-mips.org>");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index c2e6484ef138f6..572f121b1f4eda 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -730,6 +730,7 @@ static struct ethtool_ops skge_ethtool_ops = {
.phys_id = skge_phys_id,
.get_stats_count = skge_get_stats_count,
.get_ethtool_stats = skge_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
/*
@@ -3096,6 +3097,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
/* read the mac address */
memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN);
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
/* device is off until link detection */
netif_carrier_off(dev);
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 1438fdd2082648..0ddaa611cc6165 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -2291,11 +2291,11 @@ static int smc_drv_remove(struct device *dev)
return 0;
}
-static int smc_drv_suspend(struct device *dev, pm_message_t state, u32 level)
+static int smc_drv_suspend(struct device *dev, pm_message_t state)
{
struct net_device *ndev = dev_get_drvdata(dev);
- if (ndev && level == SUSPEND_DISABLE) {
+ if (ndev) {
if (netif_running(ndev)) {
netif_device_detach(ndev);
smc_shutdown(ndev);
@@ -2305,12 +2305,12 @@ static int smc_drv_suspend(struct device *dev, pm_message_t state, u32 level)
return 0;
}
-static int smc_drv_resume(struct device *dev, u32 level)
+static int smc_drv_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev = dev_get_drvdata(dev);
- if (ndev && level == RESUME_ENABLE) {
+ if (ndev) {
struct smc_local *lp = netdev_priv(ndev);
smc_enable_device(pdev);
if (netif_running(ndev)) {
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index f88f5e32b71451..cfaf47c63c58dd 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -214,7 +214,8 @@ static void bigmac_init_rings(struct bigmac *bp, int from_irq)
{
struct bmac_init_block *bb = bp->bmac_block;
struct net_device *dev = bp->dev;
- int i, gfp_flags = GFP_KERNEL;
+ int i;
+ gfp_t gfp_flags = GFP_KERNEL;
if (from_irq || in_interrupt())
gfp_flags = GFP_ATOMIC;
diff --git a/drivers/net/sunbmac.h b/drivers/net/sunbmac.h
index 5674003fc38aa7..b0dbc518714369 100644
--- a/drivers/net/sunbmac.h
+++ b/drivers/net/sunbmac.h
@@ -339,7 +339,7 @@ struct bigmac {
#define ALIGNED_RX_SKB_ADDR(addr) \
((((unsigned long)(addr) + (64 - 1)) & ~(64 - 1)) - (unsigned long)(addr))
-static inline struct sk_buff *big_mac_alloc_skb(unsigned int length, int gfp_flags)
+static inline struct sk_buff *big_mac_alloc_skb(unsigned int length, gfp_t gfp_flags)
{
struct sk_buff *skb;
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index d500a5771dbc5c..5de0554fd7c67e 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -518,6 +518,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
#else
int bar = 1;
#endif
+ int phy, phy_idx = 0;
/* when built into the kernel, we only print version if device is found */
@@ -549,6 +550,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
for (i = 0; i < 3; i++)
((u16 *)dev->dev_addr)[i] =
le16_to_cpu(eeprom_read(ioaddr, i + EEPROM_SA_OFFSET));
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
dev->base_addr = (unsigned long)ioaddr;
dev->irq = irq;
@@ -605,33 +607,31 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
printk("%2.2x:", dev->dev_addr[i]);
printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
- if (1) {
- int phy, phy_idx = 0;
- np->phys[0] = 1; /* Default setting */
- np->mii_preamble_required++;
- for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) {
- int mii_status = mdio_read(dev, phy, MII_BMSR);
- if (mii_status != 0xffff && mii_status != 0x0000) {
- np->phys[phy_idx++] = phy;
- np->mii_if.advertising = mdio_read(dev, phy, MII_ADVERTISE);
- if ((mii_status & 0x0040) == 0)
- np->mii_preamble_required++;
- printk(KERN_INFO "%s: MII PHY found at address %d, status "
- "0x%4.4x advertising %4.4x.\n",
- dev->name, phy, mii_status, np->mii_if.advertising);
- }
- }
- np->mii_preamble_required--;
-
- if (phy_idx == 0) {
- printk(KERN_INFO "%s: No MII transceiver found, aborting. ASIC status %x\n",
- dev->name, ioread32(ioaddr + ASICCtrl));
- goto err_out_unregister;
+ np->phys[0] = 1; /* Default setting */
+ np->mii_preamble_required++;
+ for (phy = 1; phy <= 32 && phy_idx < MII_CNT; phy++) {
+ int mii_status = mdio_read(dev, phy, MII_BMSR);
+ int phyx = phy & 0x1f;
+ if (mii_status != 0xffff && mii_status != 0x0000) {
+ np->phys[phy_idx++] = phyx;
+ np->mii_if.advertising = mdio_read(dev, phyx, MII_ADVERTISE);
+ if ((mii_status & 0x0040) == 0)
+ np->mii_preamble_required++;
+ printk(KERN_INFO "%s: MII PHY found at address %d, status "
+ "0x%4.4x advertising %4.4x.\n",
+ dev->name, phyx, mii_status, np->mii_if.advertising);
}
+ }
+ np->mii_preamble_required--;
- np->mii_if.phy_id = np->phys[0];
+ if (phy_idx == 0) {
+ printk(KERN_INFO "%s: No MII transceiver found, aborting. ASIC status %x\n",
+ dev->name, ioread32(ioaddr + ASICCtrl));
+ goto err_out_unregister;
}
+ np->mii_if.phy_id = np->phys[0];
+
/* Parse override configuration */
np->an_enable = 1;
if (card_idx < MAX_UNITS) {
@@ -692,7 +692,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
/* Reset the chip to erase previous misconfiguration. */
if (netif_msg_hw(np))
printk("ASIC Control is %x.\n", ioread32(ioaddr + ASICCtrl));
- iowrite16(0x007f, ioaddr + ASICCtrl + 2);
+ iowrite16(0x00ff, ioaddr + ASICCtrl + 2);
if (netif_msg_hw(np))
printk("ASIC Control is now %x.\n", ioread32(ioaddr + ASICCtrl));
@@ -1619,6 +1619,7 @@ static struct ethtool_ops ethtool_ops = {
.get_link = get_link,
.get_msglevel = get_msglevel,
.set_msglevel = set_msglevel,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index 32057e65808bda..9f491563944e91 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -318,7 +318,7 @@ static void ibmtr_cleanup_card(struct net_device *dev)
if (dev->base_addr) {
outb(0,dev->base_addr+ADAPTRESET);
- schedule_timeout(TR_RST_TIME); /* wait 50ms */
+ schedule_timeout_uninterruptible(TR_RST_TIME); /* wait 50ms */
outb(0,dev->base_addr+ADAPTRESETREL);
}
@@ -854,8 +854,7 @@ static int tok_init_card(struct net_device *dev)
writeb(~INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN);
outb(0, PIOaddr + ADAPTRESET);
- current->state=TASK_UNINTERRUPTIBLE;
- schedule_timeout(TR_RST_TIME); /* wait 50ms */
+ schedule_timeout_uninterruptible(TR_RST_TIME); /* wait 50ms */
outb(0, PIOaddr + ADAPTRESETREL);
#ifdef ENABLE_PAGING
@@ -903,8 +902,8 @@ static int tok_open(struct net_device *dev)
DPRINTK("Adapter is up and running\n");
return 0;
}
- current->state=TASK_INTERRUPTIBLE;
- i=schedule_timeout(TR_RETRY_INTERVAL); /* wait 30 seconds */
+ i=schedule_timeout_interruptible(TR_RETRY_INTERVAL);
+ /* wait 30 seconds */
if(i!=0) break; /*prob. a signal, like the i>24*HZ case above */
}
outb(0, dev->base_addr + ADAPTRESET);/* kill pending interrupts*/
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
index 9e7923192a49f0..05477d24fd49c5 100644
--- a/drivers/net/tokenring/olympic.c
+++ b/drivers/net/tokenring/olympic.c
@@ -1101,7 +1101,7 @@ static int olympic_close(struct net_device *dev)
while(olympic_priv->srb_queued) {
- t = schedule_timeout(60*HZ);
+ t = schedule_timeout_interruptible(60*HZ);
if(signal_pending(current)) {
printk(KERN_WARNING "%s: SRB timed out.\n",dev->name);
diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
index 2e39bf1f74620f..c1925590a0e110 100644
--- a/drivers/net/tokenring/tms380tr.c
+++ b/drivers/net/tokenring/tms380tr.c
@@ -1243,8 +1243,7 @@ void tms380tr_wait(unsigned long time)
tmp = jiffies + time/(1000000/HZ);
do {
- current->state = TASK_INTERRUPTIBLE;
- tmp = schedule_timeout(tmp);
+ tmp = schedule_timeout_interruptible(tmp);
} while(time_after(tmp, jiffies));
#else
udelay(time);
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index a22d00198e4d6b..6b8eee8f7bfd1d 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -1787,10 +1787,15 @@ static void __init de21041_get_srom_info (struct de_private *de)
/* DEC now has a specification but early board makers
just put the address in the first EEPROM locations. */
/* This does memcmp(eedata, eedata+16, 8) */
+
+#ifndef CONFIG_MIPS_COBALT
+
for (i = 0; i < 8; i ++)
if (ee_data[i] != ee_data[16+i])
sa_offset = 20;
+#endif
+
/* store MAC address */
for (i = 0; i < 6; i ++)
de->dev->dev_addr[i] = ee_data[i + sa_offset];
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index ecfa6f8805ce0e..4c76cb794bfbb4 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -419,10 +419,9 @@ typhoon_reset(void __iomem *ioaddr, int wait_type)
TYPHOON_STATUS_WAITING_FOR_HOST)
goto out;
- if(wait_type == WaitSleep) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- } else
+ if(wait_type == WaitSleep)
+ schedule_timeout_uninterruptible(1);
+ else
udelay(TYPHOON_UDELAY);
}
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index fc7738ffbfffeb..24187158928336 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -490,6 +490,8 @@ struct rhine_private {
u8 tx_thresh, rx_thresh;
struct mii_if_info mii_if;
+ struct work_struct tx_timeout_task;
+ struct work_struct check_media_task;
void __iomem *base;
};
@@ -497,6 +499,8 @@ static int mdio_read(struct net_device *dev, int phy_id, int location);
static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
static int rhine_open(struct net_device *dev);
static void rhine_tx_timeout(struct net_device *dev);
+static void rhine_tx_timeout_task(struct net_device *dev);
+static void rhine_check_media_task(struct net_device *dev);
static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
static void rhine_tx(struct net_device *dev);
@@ -814,8 +818,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
for (i = 0; i < 6; i++)
dev->dev_addr[i] = ioread8(ioaddr + StationAddr + i);
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
- if (!is_valid_ether_addr(dev->dev_addr)) {
+ if (!is_valid_ether_addr(dev->perm_addr)) {
rc = -EIO;
printk(KERN_ERR "Invalid MAC address\n");
goto err_out_unmap;
@@ -850,6 +855,12 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
if (rp->quirks & rqRhineI)
dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
+ INIT_WORK(&rp->tx_timeout_task,
+ (void (*)(void *))rhine_tx_timeout_task, dev);
+
+ INIT_WORK(&rp->check_media_task,
+ (void (*)(void *))rhine_check_media_task, dev);
+
/* dev->name not defined before register_netdev()! */
rc = register_netdev(dev);
if (rc)
@@ -1076,6 +1087,11 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media)
ioaddr + ChipCmd1);
}
+static void rhine_check_media_task(struct net_device *dev)
+{
+ rhine_check_media(dev, 0);
+}
+
static void init_registers(struct net_device *dev)
{
struct rhine_private *rp = netdev_priv(dev);
@@ -1129,8 +1145,8 @@ static void rhine_disable_linkmon(void __iomem *ioaddr, u32 quirks)
if (quirks & rqRhineI) {
iowrite8(0x01, ioaddr + MIIRegAddr); // MII_BMSR
- /* Can be called from ISR. Evil. */
- mdelay(1);
+ /* Do not call from ISR! */
+ msleep(1);
/* 0x80 must be set immediately before turning it off */
iowrite8(0x80, ioaddr + MIICmd);
@@ -1220,6 +1236,16 @@ static int rhine_open(struct net_device *dev)
static void rhine_tx_timeout(struct net_device *dev)
{
struct rhine_private *rp = netdev_priv(dev);
+
+ /*
+ * Move bulk of work outside of interrupt context
+ */
+ schedule_work(&rp->tx_timeout_task);
+}
+
+static void rhine_tx_timeout_task(struct net_device *dev)
+{
+ struct rhine_private *rp = netdev_priv(dev);
void __iomem *ioaddr = rp->base;
printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status "
@@ -1625,7 +1651,7 @@ static void rhine_error(struct net_device *dev, int intr_status)
spin_lock(&rp->lock);
if (intr_status & IntrLinkChange)
- rhine_check_media(dev, 0);
+ schedule_work(&rp->check_media_task);
if (intr_status & IntrStatsMax) {
rp->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
rp->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
@@ -1829,6 +1855,7 @@ static struct ethtool_ops netdev_ethtool_ops = {
.set_wol = rhine_set_wol,
.get_sg = ethtool_op_get_sg,
.get_tx_csum = ethtool_op_get_tx_csum,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1872,6 +1899,9 @@ static int rhine_close(struct net_device *dev)
spin_unlock_irq(&rp->lock);
free_irq(rp->pdev->irq, dev);
+
+ flush_scheduled_work();
+
free_rbufs(dev);
free_tbufs(dev);
free_ring(dev);
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 7ff814fd65d082..e392ee8b37a148 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -400,7 +400,7 @@ static int __init cosa_init(void)
goto out_chrdev;
}
for (i=0; i<nr_cards; i++) {
- class_device_create(cosa_class, MKDEV(cosa_major, i),
+ class_device_create(cosa_class, NULL, MKDEV(cosa_major, i),
NULL, "cosa%d", i);
err = devfs_mk_cdev(MKDEV(cosa_major, i),
S_IFCHR|S_IRUSR|S_IWUSR,
@@ -1617,8 +1617,7 @@ static int get_wait_data(struct cosa_data *cosa)
return r;
}
/* sleep if not ready to read */
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
}
printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n",
cosa_getstatus(cosa));
@@ -1644,8 +1643,7 @@ static int put_wait_data(struct cosa_data *cosa, int data)
}
#if 0
/* sleep if not ready to read */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
#endif
}
printk(KERN_INFO "cosa%d: timeout in put_wait_data (status 0x%x)\n",
diff --git a/drivers/net/wan/cycx_drv.c b/drivers/net/wan/cycx_drv.c
index 9e56fc346ba4f7..e6d005726aadea 100644
--- a/drivers/net/wan/cycx_drv.c
+++ b/drivers/net/wan/cycx_drv.c
@@ -109,7 +109,7 @@ static long cycx_2x_irq_options[] = { 7, 3, 5, 9, 10, 11, 12, 15 };
* < 0 error.
* Context: process */
-int __init cycx_drv_init(void)
+static int __init cycx_drv_init(void)
{
printk(KERN_INFO "%s v%u.%u %s\n", fullname, MOD_VERSION, MOD_RELEASE,
copyright);
@@ -119,7 +119,7 @@ int __init cycx_drv_init(void)
/* Module 'remove' entry point.
* o release all remaining system resources */
-void cycx_drv_cleanup(void)
+static void cycx_drv_cleanup(void)
{
}
@@ -184,8 +184,7 @@ int cycx_down(struct cycx_hw *hw)
}
/* Enable interrupt generation. */
-EXPORT_SYMBOL(cycx_inten);
-void cycx_inten(struct cycx_hw *hw)
+static void cycx_inten(struct cycx_hw *hw)
{
writeb(0, hw->dpmbase);
}
diff --git a/drivers/net/wan/cycx_main.c b/drivers/net/wan/cycx_main.c
index 7b48064364dc78..430b1f630fb4a7 100644
--- a/drivers/net/wan/cycx_main.c
+++ b/drivers/net/wan/cycx_main.c
@@ -103,7 +103,7 @@ static struct cycx_device *cycx_card_array; /* adapter data space */
* < 0 error.
* Context: process
*/
-int __init cycx_init(void)
+static int __init cycx_init(void)
{
int cnt, err = -ENOMEM;
diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
index 02d57c0b4243ac..a631d1c2fa148a 100644
--- a/drivers/net/wan/cycx_x25.c
+++ b/drivers/net/wan/cycx_x25.c
@@ -78,6 +78,7 @@
#define CYCLOMX_X25_DEBUG 1
+#include <linux/ctype.h> /* isdigit() */
#include <linux/errno.h> /* return codes */
#include <linux/if_arp.h> /* ARPHRD_HWX25 */
#include <linux/kernel.h> /* printk(), and other useful stuff */
@@ -418,7 +419,7 @@ static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
/* Set channel timeouts (default if not specified) */
chan->idle_tmout = conf->idle_timeout ? conf->idle_timeout : 90;
- } else if (is_digit(conf->addr[0])) { /* PVC */
+ } else if (isdigit(conf->addr[0])) { /* PVC */
s16 lcn = dec_to_uint(conf->addr, 0);
if (lcn >= card->u.x.lo_pvc && lcn <= card->u.x.hi_pvc)
@@ -1531,7 +1532,7 @@ static unsigned dec_to_uint(u8 *str, int len)
if (!len)
len = strlen(str);
- for (; len && is_digit(*str); ++str, --len)
+ for (; len && isdigit(*str); ++str, --len)
val = (val * 10) + (*str - (unsigned) '0');
return val;
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index 520a77a798e254..2f61a47b471694 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -446,8 +446,8 @@ static inline unsigned int dscc4_tx_quiescent(struct dscc4_dev_priv *dpriv,
return readl(dpriv->base_addr + CH0FTDA + dpriv->dev_id*4) == dpriv->ltda;
}
-int state_check(u32 state, struct dscc4_dev_priv *dpriv, struct net_device *dev,
- const char *msg)
+static int state_check(u32 state, struct dscc4_dev_priv *dpriv,
+ struct net_device *dev, const char *msg)
{
int ret = 0;
@@ -466,8 +466,9 @@ int state_check(u32 state, struct dscc4_dev_priv *dpriv, struct net_device *dev,
return ret;
}
-void dscc4_tx_print(struct net_device *dev, struct dscc4_dev_priv *dpriv,
- char *msg)
+static void dscc4_tx_print(struct net_device *dev,
+ struct dscc4_dev_priv *dpriv,
+ char *msg)
{
printk(KERN_DEBUG "%s: tx_current=%02d tx_dirty=%02d (%s)\n",
dev->name, dpriv->tx_current, dpriv->tx_dirty, msg);
@@ -507,7 +508,8 @@ static void dscc4_release_ring(struct dscc4_dev_priv *dpriv)
}
}
-inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv, struct net_device *dev)
+static inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv,
+ struct net_device *dev)
{
unsigned int dirty = dpriv->rx_dirty%RX_RING_SIZE;
struct RxFD *rx_fd = dpriv->rx_fd + dirty;
@@ -542,8 +544,7 @@ static int dscc4_wait_ack_cec(struct dscc4_dev_priv *dpriv,
msg, i);
goto done;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(10);
+ schedule_timeout_uninterruptible(10);
rmb();
} while (++i > 0);
printk(KERN_ERR "%s: %s timeout\n", dev->name, msg);
@@ -588,8 +589,7 @@ static inline int dscc4_xpr_ack(struct dscc4_dev_priv *dpriv)
(dpriv->iqtx[cur] & Xpr))
break;
smp_rmb();
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(10);
+ schedule_timeout_uninterruptible(10);
} while (++i > 0);
return (i >= 0 ) ? i : -EAGAIN;
@@ -1035,8 +1035,7 @@ static void dscc4_pci_reset(struct pci_dev *pdev, void __iomem *ioaddr)
/* Flush posted writes */
readl(ioaddr + GSTAR);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(10);
+ schedule_timeout_uninterruptible(10);
for (i = 0; i < 16; i++)
pci_write_config_dword(pdev, i << 2, dscc4_pci_config_store[i]);
@@ -1894,7 +1893,7 @@ try:
* It failed and locked solid. Thus the introduction of a dummy skb.
* Problem is acknowledged in errata sheet DS5. Joy :o/
*/
-struct sk_buff *dscc4_init_dummy_skb(struct dscc4_dev_priv *dpriv)
+static struct sk_buff *dscc4_init_dummy_skb(struct dscc4_dev_priv *dpriv)
{
struct sk_buff *skb;
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index 2c83cca34b8698..7981a2c7906e05 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -74,11 +74,11 @@ MODULE_LICENSE("GPL");
/*
* Modules parameters and associated varaibles
*/
-int fst_txq_low = FST_LOW_WATER_MARK;
-int fst_txq_high = FST_HIGH_WATER_MARK;
-int fst_max_reads = 7;
-int fst_excluded_cards = 0;
-int fst_excluded_list[FST_MAX_CARDS];
+static int fst_txq_low = FST_LOW_WATER_MARK;
+static int fst_txq_high = FST_HIGH_WATER_MARK;
+static int fst_max_reads = 7;
+static int fst_excluded_cards = 0;
+static int fst_excluded_list[FST_MAX_CARDS];
module_param(fst_txq_low, int, 0);
module_param(fst_txq_high, int, 0);
@@ -572,13 +572,13 @@ static void do_bottom_half_rx(struct fst_card_info *card);
static void fst_process_tx_work_q(unsigned long work_q);
static void fst_process_int_work_q(unsigned long work_q);
-DECLARE_TASKLET(fst_tx_task, fst_process_tx_work_q, 0);
-DECLARE_TASKLET(fst_int_task, fst_process_int_work_q, 0);
+static DECLARE_TASKLET(fst_tx_task, fst_process_tx_work_q, 0);
+static DECLARE_TASKLET(fst_int_task, fst_process_int_work_q, 0);
-struct fst_card_info *fst_card_array[FST_MAX_CARDS];
-spinlock_t fst_work_q_lock;
-u64 fst_work_txq;
-u64 fst_work_intq;
+static struct fst_card_info *fst_card_array[FST_MAX_CARDS];
+static spinlock_t fst_work_q_lock;
+static u64 fst_work_txq;
+static u64 fst_work_intq;
static void
fst_q_work_item(u64 * queue, int card_index)
@@ -980,8 +980,7 @@ fst_issue_cmd(struct fst_port_info *port, unsigned short cmd)
/* Wait for any previous command to complete */
while (mbval > NAK) {
spin_unlock_irqrestore(&card->card_lock, flags);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
spin_lock_irqsave(&card->card_lock, flags);
if (++safety > 2000) {
@@ -1498,7 +1497,7 @@ do_bottom_half_rx(struct fst_card_info *card)
* The interrupt service routine
* Dev_id is our fst_card_info pointer
*/
-irqreturn_t
+static irqreturn_t
fst_intr(int irq, void *dev_id, struct pt_regs *regs)
{
struct fst_card_info *card;
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index a5d6891c9d4c39..e1601d35dceddf 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -330,7 +330,7 @@ static int pvc_close(struct net_device *dev)
-int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
pvc_device *pvc = dev_to_pvc(dev);
fr_proto_pvc_info info;
diff --git a/drivers/net/wan/lmc/lmc_debug.c b/drivers/net/wan/lmc/lmc_debug.c
index 9dccd9546a17b8..3b94352b0d0317 100644
--- a/drivers/net/wan/lmc/lmc_debug.c
+++ b/drivers/net/wan/lmc/lmc_debug.c
@@ -8,10 +8,10 @@
/*
* Prints out len, max to 80 octets using printk, 20 per line
*/
-void lmcConsoleLog(char *type, unsigned char *ucData, int iLen)
-{
#ifdef DEBUG
#ifdef LMC_PACKET_LOG
+void lmcConsoleLog(char *type, unsigned char *ucData, int iLen)
+{
int iNewLine = 1;
char str[80], *pstr;
@@ -43,26 +43,24 @@ void lmcConsoleLog(char *type, unsigned char *ucData, int iLen)
}
sprintf(pstr, "\n");
printk(str);
+}
#endif
#endif
-}
#ifdef DEBUG
u_int32_t lmcEventLogIndex = 0;
u_int32_t lmcEventLogBuf[LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS];
-#endif
void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3)
{
-#ifdef DEBUG
lmcEventLogBuf[lmcEventLogIndex++] = EventNum;
lmcEventLogBuf[lmcEventLogIndex++] = arg2;
lmcEventLogBuf[lmcEventLogIndex++] = arg3;
lmcEventLogBuf[lmcEventLogIndex++] = jiffies;
lmcEventLogIndex &= (LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS) - 1;
-#endif
}
+#endif /* DEBUG */
void lmc_trace(struct net_device *dev, char *msg){
#ifdef LMC_TRACE
diff --git a/drivers/net/wan/lmc/lmc_media.c b/drivers/net/wan/lmc/lmc_media.c
index f55ce76b00edd4..af8b55fdd9d980 100644
--- a/drivers/net/wan/lmc/lmc_media.c
+++ b/drivers/net/wan/lmc/lmc_media.c
@@ -48,14 +48,6 @@
*/
/*
- * For lack of a better place, put the SSI cable stuff here.
- */
-char *lmc_t1_cables[] = {
- "V.10/RS423", "EIA530A", "reserved", "X.21", "V.35",
- "EIA449/EIA530/V.36", "V.28/EIA232", "none", NULL
-};
-
-/*
* protocol independent method.
*/
static void lmc_set_protocol (lmc_softc_t * const, lmc_ctl_t *);
diff --git a/drivers/net/wan/pc300.h b/drivers/net/wan/pc300.h
index 73401b0f01517c..2024b26b99e6e2 100644
--- a/drivers/net/wan/pc300.h
+++ b/drivers/net/wan/pc300.h
@@ -472,24 +472,8 @@ enum pc300_loopback_cmds {
#ifdef __KERNEL__
/* Function Prototypes */
-int dma_buf_write(pc300_t *, int, ucchar *, int);
-int dma_buf_read(pc300_t *, int, struct sk_buff *);
void tx_dma_start(pc300_t *, int);
-void rx_dma_start(pc300_t *, int);
-void tx_dma_stop(pc300_t *, int);
-void rx_dma_stop(pc300_t *, int);
-int cpc_queue_xmit(struct sk_buff *, struct net_device *);
-void cpc_net_rx(struct net_device *);
-void cpc_sca_status(pc300_t *, int);
-int cpc_change_mtu(struct net_device *, int);
-int cpc_ioctl(struct net_device *, struct ifreq *, int);
-int ch_config(pc300dev_t *);
-int rx_config(pc300dev_t *);
-int tx_config(pc300dev_t *);
-void cpc_opench(pc300dev_t *);
-void cpc_closech(pc300dev_t *);
int cpc_open(struct net_device *dev);
-int cpc_close(struct net_device *dev);
int cpc_set_media(hdlc_device *, int);
#endif /* __KERNEL__ */
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index 3e7753b1071759..a3e65d1bc19bbc 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -291,6 +291,7 @@ static uclong detect_ram(pc300_t *);
static void plx_init(pc300_t *);
static void cpc_trace(struct net_device *, struct sk_buff *, char);
static int cpc_attach(struct net_device *, unsigned short, unsigned short);
+static int cpc_close(struct net_device *dev);
#ifdef CONFIG_PC300_MLPPP
void cpc_tty_init(pc300dev_t * dev);
@@ -437,7 +438,7 @@ static void rx_dma_buf_check(pc300_t * card, int ch)
printk("\n");
}
-int dma_get_rx_frame_size(pc300_t * card, int ch)
+static int dma_get_rx_frame_size(pc300_t * card, int ch)
{
volatile pcsca_bd_t __iomem *ptdescr;
ucshort first_bd = card->chan[ch].rx_first_bd;
@@ -462,7 +463,7 @@ int dma_get_rx_frame_size(pc300_t * card, int ch)
* dma_buf_write: writes a frame to the Tx DMA buffers
* NOTE: this function writes one frame at a time.
*/
-int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
+static int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
{
int i, nchar;
volatile pcsca_bd_t __iomem *ptdescr;
@@ -503,7 +504,7 @@ int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
* dma_buf_read: reads a frame from the Rx DMA buffers
* NOTE: this function reads one frame at a time.
*/
-int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
+static int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
{
int nchar;
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
@@ -560,7 +561,7 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
return (rcvd);
}
-void tx_dma_stop(pc300_t * card, int ch)
+static void tx_dma_stop(pc300_t * card, int ch)
{
void __iomem *scabase = card->hw.scabase;
ucchar drr_ena_bit = 1 << (5 + 2 * ch);
@@ -571,7 +572,7 @@ void tx_dma_stop(pc300_t * card, int ch)
cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);
}
-void rx_dma_stop(pc300_t * card, int ch)
+static void rx_dma_stop(pc300_t * card, int ch)
{
void __iomem *scabase = card->hw.scabase;
ucchar drr_ena_bit = 1 << (4 + 2 * ch);
@@ -582,7 +583,7 @@ void rx_dma_stop(pc300_t * card, int ch)
cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);
}
-void rx_dma_start(pc300_t * card, int ch)
+static void rx_dma_start(pc300_t * card, int ch)
{
void __iomem *scabase = card->hw.scabase;
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
@@ -607,7 +608,7 @@ void rx_dma_start(pc300_t * card, int ch)
/*************************/
/*** FALC Routines ***/
/*************************/
-void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
+static void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
{
void __iomem *falcbase = card->hw.falcbase;
unsigned long i = 0;
@@ -622,7 +623,7 @@ void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
cpc_writeb(falcbase + F_REG(CMDR, ch), cmd);
}
-void falc_intr_enable(pc300_t * card, int ch)
+static void falc_intr_enable(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -672,7 +673,7 @@ void falc_intr_enable(pc300_t * card, int ch)
}
}
-void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
+static void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
{
void __iomem *falcbase = card->hw.falcbase;
ucchar tshf = card->chan[ch].falc.offset;
@@ -688,7 +689,7 @@ void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
(0x80 >> (timeslot & 0x07)));
}
-void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
+static void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
{
void __iomem *falcbase = card->hw.falcbase;
ucchar tshf = card->chan[ch].falc.offset;
@@ -704,7 +705,7 @@ void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
~(0x80 >> (timeslot & 0x07)));
}
-void falc_close_all_timeslots(pc300_t * card, int ch)
+static void falc_close_all_timeslots(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -726,7 +727,7 @@ void falc_close_all_timeslots(pc300_t * card, int ch)
}
}
-void falc_open_all_timeslots(pc300_t * card, int ch)
+static void falc_open_all_timeslots(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -758,7 +759,7 @@ void falc_open_all_timeslots(pc300_t * card, int ch)
}
}
-void falc_init_timeslot(pc300_t * card, int ch)
+static void falc_init_timeslot(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -776,7 +777,7 @@ void falc_init_timeslot(pc300_t * card, int ch)
}
}
-void falc_enable_comm(pc300_t * card, int ch)
+static void falc_enable_comm(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
falc_t *pfalc = (falc_t *) & chan->falc;
@@ -792,7 +793,7 @@ void falc_enable_comm(pc300_t * card, int ch)
~((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch)));
}
-void falc_disable_comm(pc300_t * card, int ch)
+static void falc_disable_comm(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
falc_t *pfalc = (falc_t *) & chan->falc;
@@ -806,7 +807,7 @@ void falc_disable_comm(pc300_t * card, int ch)
((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch)));
}
-void falc_init_t1(pc300_t * card, int ch)
+static void falc_init_t1(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -975,7 +976,7 @@ void falc_init_t1(pc300_t * card, int ch)
falc_close_all_timeslots(card, ch);
}
-void falc_init_e1(pc300_t * card, int ch)
+static void falc_init_e1(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1155,7 +1156,7 @@ void falc_init_e1(pc300_t * card, int ch)
falc_close_all_timeslots(card, ch);
}
-void falc_init_hdlc(pc300_t * card, int ch)
+static void falc_init_hdlc(pc300_t * card, int ch)
{
void __iomem *falcbase = card->hw.falcbase;
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
@@ -1181,7 +1182,7 @@ void falc_init_hdlc(pc300_t * card, int ch)
falc_intr_enable(card, ch);
}
-void te_config(pc300_t * card, int ch)
+static void te_config(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1241,7 +1242,7 @@ void te_config(pc300_t * card, int ch)
CPC_UNLOCK(card, flags);
}
-void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
+static void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1397,7 +1398,7 @@ void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
}
}
-void falc_update_stats(pc300_t * card, int ch)
+static void falc_update_stats(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1450,7 +1451,7 @@ void falc_update_stats(pc300_t * card, int ch)
* the synchronizer and then sent to the system interface.
*----------------------------------------------------------------------------
*/
-void falc_remote_loop(pc300_t * card, int ch, int loop_on)
+static void falc_remote_loop(pc300_t * card, int ch, int loop_on)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1495,7 +1496,7 @@ void falc_remote_loop(pc300_t * card, int ch, int loop_on)
* coding must be identical.
*----------------------------------------------------------------------------
*/
-void falc_local_loop(pc300_t * card, int ch, int loop_on)
+static void falc_local_loop(pc300_t * card, int ch, int loop_on)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
falc_t *pfalc = (falc_t *) & chan->falc;
@@ -1522,7 +1523,7 @@ void falc_local_loop(pc300_t * card, int ch, int loop_on)
* looped. They are originated by the FALC-LH transmitter.
*----------------------------------------------------------------------------
*/
-void falc_payload_loop(pc300_t * card, int ch, int loop_on)
+static void falc_payload_loop(pc300_t * card, int ch, int loop_on)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1576,7 +1577,7 @@ void falc_payload_loop(pc300_t * card, int ch, int loop_on)
* Description: Turns XLU bit off in the proper register
*----------------------------------------------------------------------------
*/
-void turn_off_xlu(pc300_t * card, int ch)
+static void turn_off_xlu(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1597,7 +1598,7 @@ void turn_off_xlu(pc300_t * card, int ch)
* Description: Turns XLD bit off in the proper register
*----------------------------------------------------------------------------
*/
-void turn_off_xld(pc300_t * card, int ch)
+static void turn_off_xld(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1619,7 +1620,7 @@ void turn_off_xld(pc300_t * card, int ch)
* to generate a LOOP activation code over a T1/E1 line.
*----------------------------------------------------------------------------
*/
-void falc_generate_loop_up_code(pc300_t * card, int ch)
+static void falc_generate_loop_up_code(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1652,7 +1653,7 @@ void falc_generate_loop_up_code(pc300_t * card, int ch)
* to generate a LOOP deactivation code over a T1/E1 line.
*----------------------------------------------------------------------------
*/
-void falc_generate_loop_down_code(pc300_t * card, int ch)
+static void falc_generate_loop_down_code(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1682,7 +1683,7 @@ void falc_generate_loop_down_code(pc300_t * card, int ch)
* it on the reception side.
*----------------------------------------------------------------------------
*/
-void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
+static void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1729,7 +1730,7 @@ void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
* Description: This routine returns the bit error counter value
*----------------------------------------------------------------------------
*/
-ucshort falc_pattern_test_error(pc300_t * card, int ch)
+static ucshort falc_pattern_test_error(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
falc_t *pfalc = (falc_t *) & chan->falc;
@@ -1769,7 +1770,7 @@ cpc_trace(struct net_device *dev, struct sk_buff *skb_main, char rx_tx)
netif_rx(skb);
}
-void cpc_tx_timeout(struct net_device *dev)
+static void cpc_tx_timeout(struct net_device *dev)
{
pc300dev_t *d = (pc300dev_t *) dev->priv;
pc300ch_t *chan = (pc300ch_t *) d->chan;
@@ -1797,7 +1798,7 @@ void cpc_tx_timeout(struct net_device *dev)
netif_wake_queue(dev);
}
-int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
+static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
{
pc300dev_t *d = (pc300dev_t *) dev->priv;
pc300ch_t *chan = (pc300ch_t *) d->chan;
@@ -1880,7 +1881,7 @@ int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
}
-void cpc_net_rx(struct net_device *dev)
+static void cpc_net_rx(struct net_device *dev)
{
pc300dev_t *d = (pc300dev_t *) dev->priv;
pc300ch_t *chan = (pc300ch_t *) d->chan;
@@ -2403,7 +2404,7 @@ static irqreturn_t cpc_intr(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-void cpc_sca_status(pc300_t * card, int ch)
+static void cpc_sca_status(pc300_t * card, int ch)
{
ucchar ilar;
void __iomem *scabase = card->hw.scabase;
@@ -2495,7 +2496,7 @@ void cpc_sca_status(pc300_t * card, int ch)
}
}
-void cpc_falc_status(pc300_t * card, int ch)
+static void cpc_falc_status(pc300_t * card, int ch)
{
pc300ch_t *chan = &card->chan[ch];
falc_t *pfalc = (falc_t *) & chan->falc;
@@ -2523,7 +2524,7 @@ void cpc_falc_status(pc300_t * card, int ch)
CPC_UNLOCK(card, flags);
}
-int cpc_change_mtu(struct net_device *dev, int new_mtu)
+static int cpc_change_mtu(struct net_device *dev, int new_mtu)
{
if ((new_mtu < 128) || (new_mtu > PC300_DEF_MTU))
return -EINVAL;
@@ -2531,7 +2532,7 @@ int cpc_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
-int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
pc300dev_t *d = (pc300dev_t *) dev->priv;
@@ -2856,7 +2857,7 @@ static int clock_rate_calc(uclong rate, uclong clock, int *br_io)
}
}
-int ch_config(pc300dev_t * d)
+static int ch_config(pc300dev_t * d)
{
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -3004,7 +3005,7 @@ int ch_config(pc300dev_t * d)
return 0;
}
-int rx_config(pc300dev_t * d)
+static int rx_config(pc300dev_t * d)
{
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300_t *card = (pc300_t *) chan->card;
@@ -3035,7 +3036,7 @@ int rx_config(pc300dev_t * d)
return 0;
}
-int tx_config(pc300dev_t * d)
+static int tx_config(pc300dev_t * d)
{
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300_t *card = (pc300_t *) chan->card;
@@ -3098,7 +3099,7 @@ static int cpc_attach(struct net_device *dev, unsigned short encoding,
return 0;
}
-void cpc_opench(pc300dev_t * d)
+static void cpc_opench(pc300dev_t * d)
{
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300_t *card = (pc300_t *) chan->card;
@@ -3116,7 +3117,7 @@ void cpc_opench(pc300dev_t * d)
cpc_readb(scabase + M_REG(CTL, ch)) & ~(CTL_RTS | CTL_DTR));
}
-void cpc_closech(pc300dev_t * d)
+static void cpc_closech(pc300dev_t * d)
{
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300_t *card = (pc300_t *) chan->card;
@@ -3173,7 +3174,7 @@ int cpc_open(struct net_device *dev)
return 0;
}
-int cpc_close(struct net_device *dev)
+static int cpc_close(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
pc300dev_t *d = (pc300dev_t *) dev->priv;
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 8454bf6caaa701..52f26b9c69d245 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -112,10 +112,10 @@ typedef struct _st_cpc_tty_area {
static struct tty_driver serial_drv;
/* local variables */
-st_cpc_tty_area cpc_tty_area[CPC_TTY_NPORTS];
+static st_cpc_tty_area cpc_tty_area[CPC_TTY_NPORTS];
-int cpc_tty_cnt=0; /* number of intrfaces configured with MLPPP */
-int cpc_tty_unreg_flag = 0;
+static int cpc_tty_cnt = 0; /* number of intrfaces configured with MLPPP */
+static int cpc_tty_unreg_flag = 0;
/* TTY functions prototype */
static int cpc_tty_open(struct tty_struct *tty, struct file *flip);
@@ -132,9 +132,9 @@ static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx);
static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char);
static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char);
-int pc300_tiocmset(struct tty_struct *, struct file *,
- unsigned int, unsigned int);
-int pc300_tiocmget(struct tty_struct *, struct file *);
+static int pc300_tiocmset(struct tty_struct *, struct file *,
+ unsigned int, unsigned int);
+static int pc300_tiocmget(struct tty_struct *, struct file *);
/* functions called by PC300 driver */
void cpc_tty_init(pc300dev_t *dev);
@@ -538,8 +538,8 @@ static int cpc_tty_chars_in_buffer(struct tty_struct *tty)
return(0);
}
-int pc300_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear)
+static int pc300_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
st_cpc_tty_area *cpc_tty;
@@ -565,7 +565,7 @@ int pc300_tiocmset(struct tty_struct *tty, struct file *file,
return 0;
}
-int pc300_tiocmget(struct tty_struct *tty, struct file *file)
+static int pc300_tiocmget(struct tty_struct *tty, struct file *file)
{
unsigned int result;
unsigned char status;
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index 3ac9a45b20fae7..036adc4f8ba7e8 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -182,7 +182,7 @@ static char sdla_byte(struct net_device *dev, int addr)
return(byte);
}
-void sdla_stop(struct net_device *dev)
+static void sdla_stop(struct net_device *dev)
{
struct frad_local *flp;
@@ -209,7 +209,7 @@ void sdla_stop(struct net_device *dev)
}
}
-void sdla_start(struct net_device *dev)
+static void sdla_start(struct net_device *dev)
{
struct frad_local *flp;
@@ -247,7 +247,7 @@ void sdla_start(struct net_device *dev)
*
***************************************************/
-int sdla_z80_poll(struct net_device *dev, int z80_addr, int jiffs, char resp1, char resp2)
+static int sdla_z80_poll(struct net_device *dev, int z80_addr, int jiffs, char resp1, char resp2)
{
unsigned long start, done, now;
char resp, *temp;
@@ -505,7 +505,7 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags,
static int sdla_reconfig(struct net_device *dev);
-int sdla_activate(struct net_device *slave, struct net_device *master)
+static int sdla_activate(struct net_device *slave, struct net_device *master)
{
struct frad_local *flp;
int i;
@@ -527,7 +527,7 @@ int sdla_activate(struct net_device *slave, struct net_device *master)
return(0);
}
-int sdla_deactivate(struct net_device *slave, struct net_device *master)
+static int sdla_deactivate(struct net_device *slave, struct net_device *master)
{
struct frad_local *flp;
int i;
@@ -549,7 +549,7 @@ int sdla_deactivate(struct net_device *slave, struct net_device *master)
return(0);
}
-int sdla_assoc(struct net_device *slave, struct net_device *master)
+static int sdla_assoc(struct net_device *slave, struct net_device *master)
{
struct frad_local *flp;
int i;
@@ -585,7 +585,7 @@ int sdla_assoc(struct net_device *slave, struct net_device *master)
return(0);
}
-int sdla_deassoc(struct net_device *slave, struct net_device *master)
+static int sdla_deassoc(struct net_device *slave, struct net_device *master)
{
struct frad_local *flp;
int i;
@@ -613,7 +613,7 @@ int sdla_deassoc(struct net_device *slave, struct net_device *master)
return(0);
}
-int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
+static int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
{
struct frad_local *flp;
struct dlci_local *dlp;
@@ -1324,7 +1324,7 @@ NOTE: This is rather a useless action right now, as the
return(0);
}
-int sdla_change_mtu(struct net_device *dev, int new_mtu)
+static int sdla_change_mtu(struct net_device *dev, int new_mtu)
{
struct frad_local *flp;
@@ -1337,7 +1337,7 @@ int sdla_change_mtu(struct net_device *dev, int new_mtu)
return(-EOPNOTSUPP);
}
-int sdla_set_config(struct net_device *dev, struct ifmap *map)
+static int sdla_set_config(struct net_device *dev, struct ifmap *map)
{
struct frad_local *flp;
int i;
diff --git a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c
index 0497dbdb8631fe..7f1ce9d4333e8f 100644
--- a/drivers/net/wan/sdla_fr.c
+++ b/drivers/net/wan/sdla_fr.c
@@ -822,7 +822,7 @@ static int new_if(struct wan_device* wandev, struct net_device* dev,
chan->card = card;
/* verify media address */
- if (is_digit(conf->addr[0])) {
+ if (isdigit(conf->addr[0])) {
dlci = dec_to_uint(conf->addr, 0);
@@ -3456,7 +3456,7 @@ static unsigned int dec_to_uint (unsigned char* str, int len)
if (!len)
len = strlen(str);
- for (val = 0; len && is_digit(*str); ++str, --len)
+ for (val = 0; len && isdigit(*str); ++str, --len)
val = (val * 10) + (*str - (unsigned)'0');
return val;
diff --git a/drivers/net/wan/sdla_x25.c b/drivers/net/wan/sdla_x25.c
index 8a95d61a2f8ff0..63f846d6f3a6dd 100644
--- a/drivers/net/wan/sdla_x25.c
+++ b/drivers/net/wan/sdla_x25.c
@@ -957,7 +957,7 @@ static int new_if(struct wan_device* wandev, struct net_device* dev,
chan->hold_timeout = (conf->hold_timeout) ?
conf->hold_timeout : 10;
- }else if (is_digit(conf->addr[0])){ /* PVC */
+ }else if (isdigit(conf->addr[0])){ /* PVC */
int lcn = dec_to_uint(conf->addr, 0);
if ((lcn >= card->u.x.lo_pvc) && (lcn <= card->u.x.hi_pvc)){
@@ -3875,7 +3875,7 @@ static unsigned int dec_to_uint (unsigned char* str, int len)
if (!len)
len = strlen(str);
- for (val = 0; len && is_digit(*str); ++str, --len)
+ for (val = 0; len && isdigit(*str); ++str, --len)
val = (val * 10) + (*str - (unsigned)'0');
return val;
@@ -3896,9 +3896,9 @@ static unsigned int hex_to_uint (unsigned char* str, int len)
for (val = 0; len; ++str, --len)
{
ch = *str;
- if (is_digit(ch))
+ if (isdigit(ch))
val = (val << 4) + (ch - (unsigned)'0');
- else if (is_hex_digit(ch))
+ else if (isxdigit(ch))
val = (val << 4) + ((ch & 0xDF) - (unsigned)'A' + 10);
else break;
}
diff --git a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c
index c8bc6da57a418b..7c2cf2e76300c4 100644
--- a/drivers/net/wan/sdladrv.c
+++ b/drivers/net/wan/sdladrv.c
@@ -642,9 +642,7 @@ int sdla_mapmem (sdlahw_t* hw, unsigned long addr)
* Enable interrupt generation.
*/
-EXPORT_SYMBOL(sdla_inten);
-
-int sdla_inten (sdlahw_t* hw)
+static int sdla_inten (sdlahw_t* hw)
{
unsigned port = hw->port;
int tmp, i;
@@ -698,8 +696,7 @@ int sdla_inten (sdlahw_t* hw)
* Disable interrupt generation.
*/
-EXPORT_SYMBOL(sdla_intde);
-
+#if 0
int sdla_intde (sdlahw_t* hw)
{
unsigned port = hw->port;
@@ -748,14 +745,13 @@ int sdla_intde (sdlahw_t* hw)
}
return 0;
}
+#endif /* 0 */
/*============================================================================
* Acknowledge SDLA hardware interrupt.
*/
-EXPORT_SYMBOL(sdla_intack);
-
-int sdla_intack (sdlahw_t* hw)
+static int sdla_intack (sdlahw_t* hw)
{
unsigned port = hw->port;
int tmp;
@@ -827,8 +823,7 @@ void read_S514_int_stat (sdlahw_t* hw, u32* int_status)
* Generate an interrupt to adapter's CPU.
*/
-EXPORT_SYMBOL(sdla_intr);
-
+#if 0
int sdla_intr (sdlahw_t* hw)
{
unsigned port = hw->port;
@@ -863,6 +858,7 @@ int sdla_intr (sdlahw_t* hw)
}
return 0;
}
+#endif /* 0 */
/*============================================================================
* Execute Adapter Command.
diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c
index a6d3b55013a510..2d1bba06a08512 100644
--- a/drivers/net/wan/syncppp.c
+++ b/drivers/net/wan/syncppp.c
@@ -221,7 +221,7 @@ static void sppp_clear_timeout(struct sppp *p)
* here.
*/
-void sppp_input (struct net_device *dev, struct sk_buff *skb)
+static void sppp_input (struct net_device *dev, struct sk_buff *skb)
{
struct ppp_header *h;
struct sppp *sp = (struct sppp *)sppp_of(dev);
@@ -355,8 +355,6 @@ done:
return;
}
-EXPORT_SYMBOL(sppp_input);
-
/*
* Handle transmit packets.
*/
@@ -990,7 +988,7 @@ EXPORT_SYMBOL(sppp_reopen);
* the mtu is out of range.
*/
-int sppp_change_mtu(struct net_device *dev, int new_mtu)
+static int sppp_change_mtu(struct net_device *dev, int new_mtu)
{
if(new_mtu<128||new_mtu>PPP_MTU||(dev->flags&IFF_UP))
return -EINVAL;
@@ -998,8 +996,6 @@ int sppp_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
-EXPORT_SYMBOL(sppp_change_mtu);
-
/**
* sppp_do_ioctl - Ioctl handler for ppp/hdlc
* @dev: Device subject to ioctl
@@ -1456,7 +1452,7 @@ static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_t
return 0;
}
-struct packet_type sppp_packet_type = {
+static struct packet_type sppp_packet_type = {
.type = __constant_htons(ETH_P_WAN_PPP),
.func = sppp_rcv,
};
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 06998c2240d9f1..cb429e783749ab 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -1046,7 +1046,6 @@ static WifiCtlHdr wifictlhdr8023 = {
}
};
-#ifdef WIRELESS_EXT
// Frequency list (map channels to frequencies)
static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
2447, 2452, 2457, 2462, 2467, 2472, 2484 };
@@ -1067,7 +1066,6 @@ typedef struct wep_key_t {
/* List of Wireless Handlers (new API) */
static const struct iw_handler_def airo_handler_def;
-#endif /* WIRELESS_EXT */
static const char version[] = "airo.c 0.6 (Ben Reed & Javier Achirica)";
@@ -1110,10 +1108,8 @@ static irqreturn_t airo_interrupt( int irq, void* dev_id, struct pt_regs
static int airo_thread(void *data);
static void timer_func( struct net_device *dev );
static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-#ifdef WIRELESS_EXT
static struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
static void airo_read_wireless_stats (struct airo_info *local);
-#endif /* WIRELESS_EXT */
#ifdef CISCO_EXT
static int readrids(struct net_device *dev, aironet_ioctl *comp);
static int writerids(struct net_device *dev, aironet_ioctl *comp);
@@ -1187,12 +1183,10 @@ struct airo_info {
int fid;
} xmit, xmit11;
struct net_device *wifidev;
-#ifdef WIRELESS_EXT
struct iw_statistics wstats; // wireless stats
unsigned long scan_timestamp; /* Time started to scan */
struct iw_spy_data spy_data;
struct iw_public_data wireless_data;
-#endif /* WIRELESS_EXT */
#ifdef MICSUPPORT
/* MIC stuff */
struct crypto_tfm *tfm;
@@ -2527,7 +2521,8 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
unsigned long mem_start, mem_len, aux_start, aux_len;
int rc = -1;
int i;
- unsigned char *busaddroff,*vpackoff;
+ dma_addr_t busaddroff;
+ unsigned char *vpackoff;
unsigned char __iomem *pciaddroff;
mem_start = pci_resource_start(pci, 1);
@@ -2570,7 +2565,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
/*
* Setup descriptor RX, TX, CONFIG
*/
- busaddroff = (unsigned char *)ai->shared_dma;
+ busaddroff = ai->shared_dma;
pciaddroff = ai->pciaux + AUX_OFFSET;
vpackoff = ai->shared;
@@ -2579,7 +2574,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
ai->rxfids[i].pending = 0;
ai->rxfids[i].card_ram_off = pciaddroff;
ai->rxfids[i].virtual_host_addr = vpackoff;
- ai->rxfids[i].rx_desc.host_addr = (dma_addr_t) busaddroff;
+ ai->rxfids[i].rx_desc.host_addr = busaddroff;
ai->rxfids[i].rx_desc.valid = 1;
ai->rxfids[i].rx_desc.len = PKTSIZE;
ai->rxfids[i].rx_desc.rdy = 0;
@@ -2594,7 +2589,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
ai->txfids[i].card_ram_off = pciaddroff;
ai->txfids[i].virtual_host_addr = vpackoff;
ai->txfids[i].tx_desc.valid = 1;
- ai->txfids[i].tx_desc.host_addr = (dma_addr_t) busaddroff;
+ ai->txfids[i].tx_desc.host_addr = busaddroff;
memcpy(ai->txfids[i].virtual_host_addr,
&wifictlhdr8023, sizeof(wifictlhdr8023));
@@ -2607,8 +2602,8 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
/* Rid descriptor setup */
ai->config_desc.card_ram_off = pciaddroff;
ai->config_desc.virtual_host_addr = vpackoff;
- ai->config_desc.rid_desc.host_addr = (dma_addr_t) busaddroff;
- ai->ridbus = (dma_addr_t)busaddroff;
+ ai->config_desc.rid_desc.host_addr = busaddroff;
+ ai->ridbus = busaddroff;
ai->config_desc.rid_desc.rid = 0;
ai->config_desc.rid_desc.len = RIDSIZE;
ai->config_desc.rid_desc.valid = 1;
@@ -2647,9 +2642,7 @@ static void wifi_setup(struct net_device *dev)
dev->get_stats = &airo_get_stats;
dev->set_mac_address = &airo_set_mac_address;
dev->do_ioctl = &airo_ioctl;
-#ifdef WIRELESS_EXT
dev->wireless_handlers = &airo_handler_def;
-#endif /* WIRELESS_EXT */
dev->change_mtu = &airo_change_mtu;
dev->open = &airo_open;
dev->stop = &airo_close;
@@ -2675,9 +2668,7 @@ static struct net_device *init_wifidev(struct airo_info *ai,
dev->priv = ethdev->priv;
dev->irq = ethdev->irq;
dev->base_addr = ethdev->base_addr;
-#ifdef WIRELESS_EXT
dev->wireless_data = ethdev->wireless_data;
-#endif /* WIRELESS_EXT */
memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len);
err = register_netdev(dev);
if (err<0) {
@@ -2755,11 +2746,9 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
dev->set_multicast_list = &airo_set_multicast_list;
dev->set_mac_address = &airo_set_mac_address;
dev->do_ioctl = &airo_ioctl;
-#ifdef WIRELESS_EXT
dev->wireless_handlers = &airo_handler_def;
ai->wireless_data.spy_data = &ai->spy_data;
dev->wireless_data = &ai->wireless_data;
-#endif /* WIRELESS_EXT */
dev->change_mtu = &airo_change_mtu;
dev->open = &airo_open;
dev->stop = &airo_close;
@@ -5515,12 +5504,13 @@ static int airo_pci_resume(struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
struct airo_info *ai = dev->priv;
Resp rsp;
+ pci_power_t prev_state = pdev->current_state;
- pci_set_power_state(pdev, 0);
+ pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
- pci_enable_wake(pdev, pci_choose_state(pdev, ai->power), 0);
+ pci_enable_wake(pdev, PCI_D0, 0);
- if (ai->power.event > 1) {
+ if (prev_state != PCI_D1) {
reset_card(dev, 0);
mpi_init_descriptors(ai);
setup_card(ai, dev->dev_addr, 0);
@@ -5598,7 +5588,6 @@ static void __exit airo_cleanup_module( void )
remove_proc_entry("aironet", proc_root_driver);
}
-#ifdef WIRELESS_EXT
/*
* Initial Wireless Extension code for Aironet driver by :
* Jean Tourrilhes <jt@hpl.hp.com> - HPL - 17 November 00
@@ -7107,8 +7096,6 @@ static const struct iw_handler_def airo_handler_def =
.get_wireless_stats = airo_get_wireless_stats,
};
-#endif /* WIRELESS_EXT */
-
/*
* This defines the configuration part of the Wireless Extensions
* Note : irq and spinlock protection will occur in the subroutines
@@ -7187,7 +7174,6 @@ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return rc;
}
-#ifdef WIRELESS_EXT
/*
* Get the Wireless stats out of the driver
* Note : irq and spinlock protection will occur in the subroutines
@@ -7260,7 +7246,6 @@ static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
return &local->wstats;
}
-#endif /* WIRELESS_EXT */
#ifdef CISCO_EXT
/*
diff --git a/drivers/net/wireless/airport.c b/drivers/net/wireless/airport.c
index 9d496703c4650d..7b321f7cf358d0 100644
--- a/drivers/net/wireless/airport.c
+++ b/drivers/net/wireless/airport.c
@@ -15,28 +15,11 @@
#define PFX DRIVER_NAME ": "
#include <linux/config.h>
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/current.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
+#include <linux/delay.h>
#include <asm/pmac_feature.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
#include "orinoco.h"
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 587869d86eeea1..d57011028b7279 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -618,12 +618,12 @@ static int atmel_lock_mac(struct atmel_private *priv);
static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data);
static void atmel_command_irq(struct atmel_private *priv);
static int atmel_validate_channel(struct atmel_private *priv, int channel);
-static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header,
+static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
u16 frame_len, u8 rssi);
static void atmel_management_timer(u_long a);
static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size);
static int atmel_send_command_wait(struct atmel_private *priv, int command, void *cmd, int cmd_size);
-static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header,
+static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
u8 *body, int body_len);
static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index);
@@ -827,7 +827,7 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
static int start_tx (struct sk_buff *skb, struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
- struct ieee80211_hdr header;
+ struct ieee80211_hdr_4addr header;
unsigned long flags;
u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
u8 SNAP_RFC1024[6] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
@@ -902,7 +902,7 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
}
static void atmel_transmit_management_frame(struct atmel_private *priv,
- struct ieee80211_hdr *header,
+ struct ieee80211_hdr_4addr *header,
u8 *body, int body_len)
{
u16 buff;
@@ -917,7 +917,7 @@ static void atmel_transmit_management_frame(struct atmel_private *priv,
tx_update_descriptor(priv, header->addr1[0] & 0x01, len, buff, TX_PACKET_TYPE_MGMT);
}
-static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr *header,
+static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
u16 msdu_size, u16 rx_packet_loc, u32 crc)
{
/* fast path: unfragmented packet copy directly into skbuf */
@@ -990,7 +990,7 @@ static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
return (crc ^ 0xffffffff) == netcrc;
}
-static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr *header,
+static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no, u8 frag_no, int more_frags)
{
u8 mac4[6];
@@ -1082,7 +1082,7 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr *heade
static void rx_done_irq(struct atmel_private *priv)
{
int i;
- struct ieee80211_hdr header;
+ struct ieee80211_hdr_4addr header;
for (i = 0;
atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&
@@ -2650,7 +2650,7 @@ static void handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 c
static void send_authentication_request(struct atmel_private *priv, u8 *challenge, int challenge_len)
{
- struct ieee80211_hdr header;
+ struct ieee80211_hdr_4addr header;
struct auth_body auth;
header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
@@ -2688,7 +2688,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
{
u8 *ssid_el_p;
int bodysize;
- struct ieee80211_hdr header;
+ struct ieee80211_hdr_4addr header;
struct ass_req_format {
u16 capability;
u16 listen_interval;
@@ -2738,7 +2738,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize);
}
-static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee80211_hdr *header)
+static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee80211_hdr_4addr *header)
{
if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0;
@@ -2788,7 +2788,7 @@ static int retrieve_bss(struct atmel_private *priv)
}
-static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr *header,
+static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
u16 capability, u16 beacon_period, u8 channel, u8 rssi,
u8 ssid_len, u8 *ssid, int is_beacon)
{
@@ -3072,7 +3072,7 @@ static void atmel_smooth_qual(struct atmel_private *priv)
}
/* deals with incoming managment frames. */
-static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header,
+static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
u16 frame_len, u8 rssi)
{
u16 subtype;
diff --git a/drivers/net/wireless/hermes.c b/drivers/net/wireless/hermes.c
index 21c3d0d227e62e..eba0d9d2b7c530 100644
--- a/drivers/net/wireless/hermes.c
+++ b/drivers/net/wireless/hermes.c
@@ -39,17 +39,10 @@
*/
#include <linux/config.h>
-
#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/threads.h>
-#include <linux/smp.h>
-#include <asm/io.h>
-#include <linux/delay.h>
-#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/net.h>
-#include <asm/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
#include "hermes.h"
diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h
index 8c9e874c9118c4..ad28e32943608a 100644
--- a/drivers/net/wireless/hermes.h
+++ b/drivers/net/wireless/hermes.h
@@ -30,9 +30,8 @@
* access to the hermes_t structure, and to the hardware
*/
-#include <linux/delay.h>
#include <linux/if_ether.h>
-#include <asm/byteorder.h>
+#include <asm/io.h>
/*
* Limits and constants
@@ -192,13 +191,13 @@
#define HERMES_RXSTAT_WMP (0x6000) /* Wavelan-II Management Protocol frame */
struct hermes_tx_descriptor {
- u16 status;
- u16 reserved1;
- u16 reserved2;
- u32 sw_support;
+ __le16 status;
+ __le16 reserved1;
+ __le16 reserved2;
+ __le32 sw_support;
u8 retry_count;
u8 tx_rate;
- u16 tx_control;
+ __le16 tx_control;
} __attribute__ ((packed));
#define HERMES_TXSTAT_RETRYERR (0x0001)
@@ -222,60 +221,60 @@ struct hermes_tx_descriptor {
#define HERMES_INQ_SEC_STAT_AGERE (0xF202)
struct hermes_tallies_frame {
- u16 TxUnicastFrames;
- u16 TxMulticastFrames;
- u16 TxFragments;
- u16 TxUnicastOctets;
- u16 TxMulticastOctets;
- u16 TxDeferredTransmissions;
- u16 TxSingleRetryFrames;
- u16 TxMultipleRetryFrames;
- u16 TxRetryLimitExceeded;
- u16 TxDiscards;
- u16 RxUnicastFrames;
- u16 RxMulticastFrames;
- u16 RxFragments;
- u16 RxUnicastOctets;
- u16 RxMulticastOctets;
- u16 RxFCSErrors;
- u16 RxDiscards_NoBuffer;
- u16 TxDiscardsWrongSA;
- u16 RxWEPUndecryptable;
- u16 RxMsgInMsgFragments;
- u16 RxMsgInBadMsgFragments;
+ __le16 TxUnicastFrames;
+ __le16 TxMulticastFrames;
+ __le16 TxFragments;
+ __le16 TxUnicastOctets;
+ __le16 TxMulticastOctets;
+ __le16 TxDeferredTransmissions;
+ __le16 TxSingleRetryFrames;
+ __le16 TxMultipleRetryFrames;
+ __le16 TxRetryLimitExceeded;
+ __le16 TxDiscards;
+ __le16 RxUnicastFrames;
+ __le16 RxMulticastFrames;
+ __le16 RxFragments;
+ __le16 RxUnicastOctets;
+ __le16 RxMulticastOctets;
+ __le16 RxFCSErrors;
+ __le16 RxDiscards_NoBuffer;
+ __le16 TxDiscardsWrongSA;
+ __le16 RxWEPUndecryptable;
+ __le16 RxMsgInMsgFragments;
+ __le16 RxMsgInBadMsgFragments;
/* Those last are probably not available in very old firmwares */
- u16 RxDiscards_WEPICVError;
- u16 RxDiscards_WEPExcluded;
+ __le16 RxDiscards_WEPICVError;
+ __le16 RxDiscards_WEPExcluded;
} __attribute__ ((packed));
/* Grabbed from wlan-ng - Thanks Mark... - Jean II
* This is the result of a scan inquiry command */
/* Structure describing info about an Access Point */
struct prism2_scan_apinfo {
- u16 channel; /* Channel where the AP sits */
- u16 noise; /* Noise level */
- u16 level; /* Signal level */
+ __le16 channel; /* Channel where the AP sits */
+ __le16 noise; /* Noise level */
+ __le16 level; /* Signal level */
u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
- u16 beacon_interv; /* Beacon interval */
- u16 capabilities; /* Capabilities */
- u16 essid_len; /* ESSID length */
+ __le16 beacon_interv; /* Beacon interval */
+ __le16 capabilities; /* Capabilities */
+ __le16 essid_len; /* ESSID length */
u8 essid[32]; /* ESSID of the network */
u8 rates[10]; /* Bit rate supported */
- u16 proberesp_rate; /* Data rate of the response frame */
- u16 atim; /* ATIM window time, Kus (hostscan only) */
+ __le16 proberesp_rate; /* Data rate of the response frame */
+ __le16 atim; /* ATIM window time, Kus (hostscan only) */
} __attribute__ ((packed));
/* Same stuff for the Lucent/Agere card.
* Thanks to h1kari <h1kari AT dachb0den.com> - Jean II */
struct agere_scan_apinfo {
- u16 channel; /* Channel where the AP sits */
- u16 noise; /* Noise level */
- u16 level; /* Signal level */
+ __le16 channel; /* Channel where the AP sits */
+ __le16 noise; /* Noise level */
+ __le16 level; /* Signal level */
u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
- u16 beacon_interv; /* Beacon interval */
- u16 capabilities; /* Capabilities */
+ __le16 beacon_interv; /* Beacon interval */
+ __le16 capabilities; /* Capabilities */
/* bits: 0-ess, 1-ibss, 4-privacy [wep] */
- u16 essid_len; /* ESSID length */
+ __le16 essid_len; /* ESSID length */
u8 essid[32]; /* ESSID of the network */
} __attribute__ ((packed));
@@ -283,16 +282,16 @@ struct agere_scan_apinfo {
struct symbol_scan_apinfo {
u8 channel; /* Channel where the AP sits */
u8 unknown1; /* 8 in 2.9x and 3.9x f/w, 0 otherwise */
- u16 noise; /* Noise level */
- u16 level; /* Signal level */
+ __le16 noise; /* Noise level */
+ __le16 level; /* Signal level */
u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
- u16 beacon_interv; /* Beacon interval */
- u16 capabilities; /* Capabilities */
+ __le16 beacon_interv; /* Beacon interval */
+ __le16 capabilities; /* Capabilities */
/* bits: 0-ess, 1-ibss, 4-privacy [wep] */
- u16 essid_len; /* ESSID length */
+ __le16 essid_len; /* ESSID length */
u8 essid[32]; /* ESSID of the network */
- u16 rates[5]; /* Bit rate supported */
- u16 basic_rates; /* Basic rates bitmask */
+ __le16 rates[5]; /* Bit rate supported */
+ __le16 basic_rates; /* Basic rates bitmask */
u8 unknown2[6]; /* Always FF:FF:FF:FF:00:00 */
u8 unknown3[8]; /* Always 0, appeared in f/w 3.91-68 */
} __attribute__ ((packed));
@@ -312,7 +311,7 @@ union hermes_scan_info {
#define HERMES_LINKSTATUS_ASSOC_FAILED (0x0006)
struct hermes_linkstatus {
- u16 linkstatus; /* Link status */
+ __le16 linkstatus; /* Link status */
} __attribute__ ((packed));
struct hermes_response {
@@ -321,8 +320,8 @@ struct hermes_response {
/* "ID" structure - used for ESSID and station nickname */
struct hermes_idstring {
- u16 len;
- u16 val[16];
+ __le16 len;
+ __le16 val[16];
} __attribute__ ((packed));
struct hermes_multicast {
@@ -447,7 +446,7 @@ static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count
static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
{
- u16 rec;
+ __le16 rec;
int err;
err = HERMES_READ_RECORD(hw, bap, rid, &rec);
@@ -457,7 +456,7 @@ static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
static inline int hermes_write_wordrec(hermes_t *hw, int bap, u16 rid, u16 word)
{
- u16 rec = cpu_to_le16(word);
+ __le16 rec = cpu_to_le16(word);
return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
}
diff --git a/drivers/net/wireless/hostap/hostap.c b/drivers/net/wireless/hostap/hostap.c
index e7f5821b49429c..6a96cd9f2685c7 100644
--- a/drivers/net/wireless/hostap/hostap.c
+++ b/drivers/net/wireless/hostap/hostap.c
@@ -716,9 +716,6 @@ static int prism2_close(struct net_device *dev)
hostap_deauth_all_stas(dev, local->ap, 1);
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
- if (local->func->dev_close && local->func->dev_close(local))
- return 0;
-
if (dev == local->dev) {
local->func->hw_shutdown(dev, HOSTAP_HW_ENABLE_CMDCOMPL);
}
@@ -766,9 +763,6 @@ static int prism2_open(struct net_device *dev)
local->hw_downloading)
return -ENODEV;
- if (local->func->dev_open && local->func->dev_open(local))
- return 1;
-
if (!try_module_get(local->hw_module))
return -ENODEV;
local->num_dev_open++;
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
index b0501243b175f9..ffac5089945435 100644
--- a/drivers/net/wireless/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
@@ -6,10 +6,10 @@
void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
{
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
u16 fc;
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
printk(KERN_DEBUG "%s: RX signal=%d noise=%d rate=%d len=%d "
"jiffies=%ld\n",
@@ -51,7 +51,7 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
int hdrlen, phdrlen, head_need, tail_need;
u16 fc;
int prism_header, ret;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
iface = netdev_priv(dev);
local = iface->local;
@@ -70,7 +70,7 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
phdrlen = 0;
}
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
if (type == PRISM2_RX_MGMT && (fc & IEEE80211_FCTL_VERS)) {
@@ -215,7 +215,7 @@ prism2_frag_cache_find(local_info_t *local, unsigned int seq,
/* Called only as a tasklet (software IRQ) */
static struct sk_buff *
-prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr)
+prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
{
struct sk_buff *skb = NULL;
u16 sc;
@@ -229,7 +229,7 @@ prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr)
if (frag == 0) {
/* Reserve enough space to fit maximum frame length */
skb = dev_alloc_skb(local->dev->mtu +
- sizeof(struct ieee80211_hdr) +
+ sizeof(struct ieee80211_hdr_4addr) +
8 /* LLC */ +
2 /* alignment */ +
8 /* WEP */ + ETH_ALEN /* WDS */);
@@ -267,7 +267,7 @@ prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr)
/* Called only as a tasklet (software IRQ) */
static int prism2_frag_cache_invalidate(local_info_t *local,
- struct ieee80211_hdr *hdr)
+ struct ieee80211_hdr_4addr *hdr)
{
u16 sc;
unsigned int seq;
@@ -441,7 +441,7 @@ hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb,
u16 stype)
{
if (local->iw_mode == IW_MODE_MASTER) {
- hostap_update_sta_ps(local, (struct ieee80211_hdr *)
+ hostap_update_sta_ps(local, (struct ieee80211_hdr_4addr *)
skb->data);
}
@@ -520,7 +520,7 @@ static inline struct net_device *prism2_rx_get_wds(local_info_t *local,
static inline int
-hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr *hdr,
+hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
u16 fc, struct net_device **wds)
{
/* FIX: is this really supposed to accept WDS frames only in Master
@@ -579,13 +579,13 @@ static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb)
{
struct net_device *dev = local->dev;
u16 fc, ethertype;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
u8 *pos;
if (skb->len < 24)
return 0;
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
/* check that the frame is unicast frame to us */
@@ -619,13 +619,13 @@ static inline int
hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
struct ieee80211_crypt_data *crypt)
{
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
int res, hdrlen;
if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
return 0;
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
if (local->tkip_countermeasures &&
@@ -658,13 +658,13 @@ static inline int
hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
int keyidx, struct ieee80211_crypt_data *crypt)
{
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
int res, hdrlen;
if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
return 0;
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
atomic_inc(&crypt->refcnt);
@@ -689,7 +689,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
{
struct hostap_interface *iface;
local_info_t *local;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
size_t hdrlen;
u16 fc, type, stype, sc;
struct net_device *wds = NULL;
@@ -716,7 +716,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
dev = local->ddev;
iface = netdev_priv(dev);
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
stats = hostap_get_stats(dev);
if (skb->len < 10)
@@ -737,7 +737,8 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
struct iw_quality wstats;
wstats.level = rx_stats->signal;
wstats.noise = rx_stats->noise;
- wstats.updated = 6; /* No qual value */
+ wstats.updated = IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED
+ | IW_QUAL_QUAL_INVALID | IW_QUAL_DBM;
/* Update spy records */
wireless_spy_update(dev, hdr->addr2, &wstats);
}
@@ -889,7 +890,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
(keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0)
goto rx_dropped;
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
/* skb: hdr + (possibly fragmented) plaintext payload */
@@ -941,7 +942,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
/* this was the last fragment and the frame will be
* delivered, so remove skb from fragment cache */
skb = frag_skb;
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
prism2_frag_cache_invalidate(local, hdr);
}
@@ -952,7 +953,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
hostap_rx_frame_decrypt_msdu(local, skb, keyidx, crypt))
goto rx_dropped;
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !local->open_wep) {
if (local->ieee_802_1x &&
hostap_is_eapol_frame(local, skb)) {
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
index 6358015f65260d..9d24f8a38ac525 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -1,9 +1,9 @@
void hostap_dump_tx_80211(const char *name, struct sk_buff *skb)
{
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
u16 fc;
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
printk(KERN_DEBUG "%s: TX len=%d jiffies=%ld\n",
name, skb->len, jiffies);
@@ -41,7 +41,7 @@ int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct hostap_interface *iface;
local_info_t *local;
int need_headroom, need_tailroom = 0;
- struct ieee80211_hdr hdr;
+ struct ieee80211_hdr_4addr hdr;
u16 fc, ethertype = 0;
enum {
WDS_NO = 0, WDS_OWN_FRAME, WDS_COMPLIANT_FRAME
@@ -244,7 +244,7 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct hostap_interface *iface;
local_info_t *local;
struct hostap_skb_tx_data *meta;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
u16 fc;
iface = netdev_priv(dev);
@@ -266,7 +266,7 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
meta->iface = iface;
if (skb->len >= IEEE80211_DATA_HDR3_LEN + sizeof(rfc1042_header) + 2) {
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
WLAN_FC_GET_STYPE(fc) == IEEE80211_STYPE_DATA) {
@@ -289,7 +289,7 @@ struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
{
struct hostap_interface *iface;
local_info_t *local;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
u16 fc;
int hdr_len, res;
@@ -303,7 +303,7 @@ struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
if (local->tkip_countermeasures &&
crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
"TX packet to " MACSTR "\n",
@@ -317,15 +317,15 @@ struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
if (skb == NULL)
return NULL;
- if ((skb_headroom(skb) < crypt->ops->extra_prefix_len ||
- skb_tailroom(skb) < crypt->ops->extra_postfix_len) &&
- pskb_expand_head(skb, crypt->ops->extra_prefix_len,
- crypt->ops->extra_postfix_len, GFP_ATOMIC)) {
+ if ((skb_headroom(skb) < crypt->ops->extra_mpdu_prefix_len ||
+ skb_tailroom(skb) < crypt->ops->extra_mpdu_postfix_len) &&
+ pskb_expand_head(skb, crypt->ops->extra_mpdu_prefix_len,
+ crypt->ops->extra_mpdu_postfix_len, GFP_ATOMIC)) {
kfree_skb(skb);
return NULL;
}
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
hdr_len = hostap_80211_get_hdrlen(fc);
@@ -360,7 +360,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
ap_tx_ret tx_ret;
struct hostap_skb_tx_data *meta;
int no_encrypt = 0;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
iface = netdev_priv(dev);
local = iface->local;
@@ -403,7 +403,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
tx_ret = hostap_handle_sta_tx(local, &tx);
skb = tx.skb;
meta = (struct hostap_skb_tx_data *) skb->cb;
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
switch (tx_ret) {
case AP_TX_CONTINUE:
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 930cef8367f2a2..9da94ab7f05f87 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -591,14 +591,14 @@ static void hostap_ap_tx_cb(struct sk_buff *skb, int ok, void *data)
{
struct ap_data *ap = data;
u16 fc;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
if (!ap->local->hostapd || !ap->local->apdev) {
dev_kfree_skb(skb);
return;
}
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
/* Pass the TX callback frame to the hostapd; use 802.11 header version
@@ -623,7 +623,7 @@ static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data)
{
struct ap_data *ap = data;
struct net_device *dev = ap->local->dev;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
u16 fc, *pos, auth_alg, auth_transaction, status;
struct sta_info *sta = NULL;
char *txt = NULL;
@@ -633,7 +633,7 @@ static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data)
return;
}
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||
WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_AUTH ||
@@ -692,7 +692,7 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
{
struct ap_data *ap = data;
struct net_device *dev = ap->local->dev;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
u16 fc, *pos, status;
struct sta_info *sta = NULL;
char *txt = NULL;
@@ -702,7 +702,7 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
return;
}
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||
(WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_ASSOC_RESP &&
@@ -757,12 +757,12 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
static void hostap_ap_tx_cb_poll(struct sk_buff *skb, int ok, void *data)
{
struct ap_data *ap = data;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
struct sta_info *sta;
if (skb->len < 24)
goto fail;
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
if (ok) {
spin_lock(&ap->sta_table_lock);
sta = ap_get_sta(ap, hdr->addr1);
@@ -918,7 +918,7 @@ static void prism2_send_mgmt(struct net_device *dev,
{
struct hostap_interface *iface;
local_info_t *local;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
u16 fc;
struct sk_buff *skb;
struct hostap_skb_tx_data *meta;
@@ -944,7 +944,7 @@ static void prism2_send_mgmt(struct net_device *dev,
fc = type_subtype;
hdrlen = hostap_80211_get_hdrlen(fc);
- hdr = (struct ieee80211_hdr *) skb_put(skb, hdrlen);
+ hdr = (struct ieee80211_hdr_4addr *) skb_put(skb, hdrlen);
if (body)
memcpy(skb_put(skb, body_len), body, body_len);
@@ -1256,14 +1256,14 @@ static char * ap_auth_make_challenge(struct ap_data *ap)
}
skb = dev_alloc_skb(WLAN_AUTH_CHALLENGE_LEN +
- ap->crypt->extra_prefix_len +
- ap->crypt->extra_postfix_len);
+ ap->crypt->extra_mpdu_prefix_len +
+ ap->crypt->extra_mpdu_postfix_len);
if (skb == NULL) {
kfree(tmpbuf);
return NULL;
}
- skb_reserve(skb, ap->crypt->extra_prefix_len);
+ skb_reserve(skb, ap->crypt->extra_mpdu_prefix_len);
memset(skb_put(skb, WLAN_AUTH_CHALLENGE_LEN), 0,
WLAN_AUTH_CHALLENGE_LEN);
if (ap->crypt->encrypt_mpdu(skb, 0, ap->crypt_priv)) {
@@ -1272,7 +1272,7 @@ static char * ap_auth_make_challenge(struct ap_data *ap)
return NULL;
}
- memcpy(tmpbuf, skb->data + ap->crypt->extra_prefix_len,
+ memcpy(tmpbuf, skb->data + ap->crypt->extra_mpdu_prefix_len,
WLAN_AUTH_CHALLENGE_LEN);
dev_kfree_skb(skb);
@@ -1285,7 +1285,7 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
{
struct net_device *dev = local->dev;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
size_t hdrlen;
struct ap_data *ap = local->ap;
char body[8 + WLAN_AUTH_CHALLENGE_LEN], *challenge = NULL;
@@ -1498,7 +1498,7 @@ static void handle_assoc(local_info_t *local, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats, int reassoc)
{
struct net_device *dev = local->dev;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
char body[12], *p, *lpos;
int len, left;
u16 *pos;
@@ -1705,7 +1705,7 @@ static void handle_deauth(local_info_t *local, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
{
struct net_device *dev = local->dev;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
char *body = (char *) (skb->data + IEEE80211_MGMT_HDR_LEN);
int len;
u16 reason_code, *pos;
@@ -1746,7 +1746,7 @@ static void handle_disassoc(local_info_t *local, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
{
struct net_device *dev = local->dev;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
int len;
u16 reason_code, *pos;
@@ -1784,7 +1784,7 @@ static void handle_disassoc(local_info_t *local, struct sk_buff *skb,
/* Called only as a scheduled task for pending AP frames. */
static void ap_handle_data_nullfunc(local_info_t *local,
- struct ieee80211_hdr *hdr)
+ struct ieee80211_hdr_4addr *hdr)
{
struct net_device *dev = local->dev;
@@ -1801,7 +1801,7 @@ static void ap_handle_data_nullfunc(local_info_t *local,
/* Called only as a scheduled task for pending AP frames. */
static void ap_handle_dropped_data(local_info_t *local,
- struct ieee80211_hdr *hdr)
+ struct ieee80211_hdr_4addr *hdr)
{
struct net_device *dev = local->dev;
struct sta_info *sta;
@@ -1860,7 +1860,7 @@ static void pspoll_send_buffered(local_info_t *local, struct sta_info *sta,
/* Called only as a scheduled task for pending AP frames. */
static void handle_pspoll(local_info_t *local,
- struct ieee80211_hdr *hdr,
+ struct ieee80211_hdr_4addr *hdr,
struct hostap_80211_rx_status *rx_stats)
{
struct net_device *dev = local->dev;
@@ -1979,7 +1979,7 @@ static void handle_wds_oper_queue(void *data)
static void handle_beacon(local_info_t *local, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
int len, left;
u16 *pos, beacon_int, capability;
@@ -2137,11 +2137,11 @@ static void handle_ap_item(local_info_t *local, struct sk_buff *skb,
struct net_device *dev = local->dev;
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
u16 fc, type, stype;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
/* FIX: should give skb->len to handler functions and check that the
* buffer is long enough */
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
type = WLAN_FC_GET_TYPE(fc);
stype = WLAN_FC_GET_STYPE(fc);
@@ -2258,7 +2258,7 @@ void hostap_rx(struct net_device *dev, struct sk_buff *skb,
struct hostap_interface *iface;
local_info_t *local;
u16 fc;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
iface = netdev_priv(dev);
local = iface->local;
@@ -2268,7 +2268,7 @@ void hostap_rx(struct net_device *dev, struct sk_buff *skb,
local->stats.rx_packets++;
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
if (local->ap->ap_policy == AP_OTHER_AP_SKIP_ALL &&
@@ -2289,7 +2289,7 @@ void hostap_rx(struct net_device *dev, struct sk_buff *skb,
static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
{
struct sk_buff *skb;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
struct hostap_80211_rx_status rx_stats;
if (skb_queue_empty(&sta->tx_buf))
@@ -2302,7 +2302,7 @@ static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
return;
}
- hdr = (struct ieee80211_hdr *) skb_put(skb, 16);
+ hdr = (struct ieee80211_hdr_4addr *) skb_put(skb, 16);
/* Generate a fake pspoll frame to start packet delivery */
hdr->frame_ctl = __constant_cpu_to_le16(
@@ -2349,7 +2349,7 @@ static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
qual[count].noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
qual[count].updated = sta->last_rx_updated;
- sta->last_rx_updated = 0;
+ sta->last_rx_updated = IW_QUAL_DBM;
count++;
if (count >= buf_size)
@@ -2467,7 +2467,7 @@ static int prism2_ap_translate_scan(struct net_device *dev, char *buffer)
}
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
- sta->last_rx_updated = 0;
+ sta->last_rx_updated = IW_QUAL_DBM;
/* To be continued, we should make good use of IWEVCUSTOM */
}
@@ -2685,7 +2685,7 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
struct sta_info *sta = NULL;
struct sk_buff *skb = tx->skb;
int set_tim, ret;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
struct hostap_skb_tx_data *meta;
meta = (struct hostap_skb_tx_data *) skb->cb;
@@ -2694,7 +2694,7 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
meta->iface->type == HOSTAP_INTERFACE_STA)
goto out;
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
if (hdr->addr1[0] & 0x01) {
/* broadcast/multicast frame - no AP related processing */
@@ -2821,10 +2821,10 @@ void hostap_handle_sta_release(void *ptr)
void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb)
{
struct sta_info *sta;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
struct hostap_skb_tx_data *meta;
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
meta = (struct hostap_skb_tx_data *) skb->cb;
spin_lock(&local->ap->sta_table_lock);
@@ -2892,7 +2892,7 @@ static void hostap_update_sta_ps2(local_info_t *local, struct sta_info *sta,
/* Called only as a tasklet (software IRQ). Called for each RX frame to update
* STA power saving state. pwrmgt is a flag from 802.11 frame_ctl field. */
-int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr)
+int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
{
struct sta_info *sta;
u16 fc;
@@ -2925,12 +2925,12 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
int ret;
struct sta_info *sta;
u16 fc, type, stype;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_4addr *hdr;
if (local->ap == NULL)
return AP_RX_CONTINUE;
- hdr = (struct ieee80211_hdr *) skb->data;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
type = WLAN_FC_GET_TYPE(fc);
@@ -3058,7 +3058,7 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
/* Called only as a tasklet (software IRQ) */
int hostap_handle_sta_crypto(local_info_t *local,
- struct ieee80211_hdr *hdr,
+ struct ieee80211_hdr_4addr *hdr,
struct ieee80211_crypt_data **crypt,
void **sta_ptr)
{
@@ -3160,7 +3160,7 @@ int hostap_add_sta(struct ap_data *ap, u8 *sta_addr)
/* Called only as a tasklet (software IRQ) */
int hostap_update_rx_stats(struct ap_data *ap,
- struct ieee80211_hdr *hdr,
+ struct ieee80211_hdr_4addr *hdr,
struct hostap_80211_rx_status *rx_stats)
{
struct sta_info *sta;
@@ -3174,7 +3174,7 @@ int hostap_update_rx_stats(struct ap_data *ap,
sta->last_rx_silence = rx_stats->noise;
sta->last_rx_signal = rx_stats->signal;
sta->last_rx_rate = rx_stats->rate;
- sta->last_rx_updated = 7;
+ sta->last_rx_updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
if (rx_stats->rate == 10)
sta->rx_count[0]++;
else if (rx_stats->rate == 20)
diff --git a/drivers/net/wireless/hostap/hostap_ap.h b/drivers/net/wireless/hostap/hostap_ap.h
index 816a52bcea8f7a..6d00df69c2e3e9 100644
--- a/drivers/net/wireless/hostap/hostap_ap.h
+++ b/drivers/net/wireless/hostap/hostap_ap.h
@@ -233,7 +233,7 @@ struct hostap_tx_data {
ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx);
void hostap_handle_sta_release(void *ptr);
void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb);
-int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr);
+int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr_4addr *hdr);
typedef enum {
AP_RX_CONTINUE, AP_RX_DROP, AP_RX_EXIT, AP_RX_CONTINUE_NOT_AUTHORIZED
} ap_rx_ret;
@@ -241,13 +241,13 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats,
int wds);
-int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr *hdr,
+int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
struct ieee80211_crypt_data **crypt,
void **sta_ptr);
int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr);
int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr);
int hostap_add_sta(struct ap_data *ap, u8 *sta_addr);
-int hostap_update_rx_stats(struct ap_data *ap, struct ieee80211_hdr *hdr,
+int hostap_update_rx_stats(struct ap_data *ap, struct ieee80211_hdr_4addr *hdr,
struct hostap_80211_rx_status *rx_stats);
void hostap_update_rates(local_info_t *local);
void hostap_add_wds_links(local_info_t *local);
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index faa83badf0a1b5..2643976a66775f 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -492,42 +492,10 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
}
-static int prism2_pccard_dev_open(local_info_t *local)
-{
- struct hostap_cs_priv *hw_priv = local->hw_priv;
- hw_priv->link->open++;
- return 0;
-}
-
-
-static int prism2_pccard_dev_close(local_info_t *local)
-{
- struct hostap_cs_priv *hw_priv;
-
- if (local == NULL || local->hw_priv == NULL)
- return 1;
- hw_priv = local->hw_priv;
- if (hw_priv->link == NULL)
- return 1;
-
- if (!hw_priv->link->open) {
- printk(KERN_WARNING "%s: prism2_pccard_dev_close(): "
- "link not open?!\n", local->dev->name);
- return 1;
- }
-
- hw_priv->link->open--;
-
- return 0;
-}
-
-
static struct prism2_helper_functions prism2_pccard_funcs =
{
.card_present = prism2_pccard_card_present,
.cor_sreset = prism2_pccard_cor_sreset,
- .dev_open = prism2_pccard_dev_open,
- .dev_close = prism2_pccard_dev_close,
.genesis_reset = prism2_pccard_genesis_reset,
.hw_type = HOSTAP_HW_PCCARD,
};
@@ -597,13 +565,14 @@ static void prism2_detach(dev_link_t *link)
*linkp = link->next;
/* release net devices */
if (link->priv) {
+ struct hostap_cs_priv *hw_priv;
struct net_device *dev;
struct hostap_interface *iface;
dev = link->priv;
iface = netdev_priv(dev);
- kfree(iface->local->hw_priv);
- iface->local->hw_priv = NULL;
+ hw_priv = iface->local->hw_priv;
prism2_free_local_data(dev);
+ kfree(hw_priv);
}
kfree(link);
}
@@ -883,6 +852,13 @@ static int prism2_event(event_t event, int priority,
{
dev_link_t *link = args->client_data;
struct net_device *dev = (struct net_device *) link->priv;
+ int dev_open = 0;
+
+ if (link->state & DEV_CONFIG) {
+ struct hostap_interface *iface = netdev_priv(dev);
+ if (iface && iface->local)
+ dev_open = iface->local->num_dev_open > 0;
+ }
switch (event) {
case CS_EVENT_CARD_INSERTION:
@@ -911,7 +887,7 @@ static int prism2_event(event_t event, int priority,
case CS_EVENT_RESET_PHYSICAL:
PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_RESET_PHYSICAL\n", dev_info);
if (link->state & DEV_CONFIG) {
- if (link->open) {
+ if (dev_open) {
netif_stop_queue(dev);
netif_device_detach(dev);
}
@@ -931,8 +907,8 @@ static int prism2_event(event_t event, int priority,
pcmcia_request_configuration(link->handle,
&link->conf);
prism2_hw_shutdown(dev, 1);
- prism2_hw_config(dev, link->open ? 0 : 1);
- if (link->open) {
+ prism2_hw_config(dev, dev_open ? 0 : 1);
+ if (dev_open) {
netif_device_attach(dev);
netif_start_queue(dev);
}
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index e533a663deda5e..59fc15572395cc 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -3322,6 +3322,18 @@ static void prism2_free_local_data(struct net_device *dev)
iface = netdev_priv(dev);
local = iface->local;
+ /* Unregister all netdevs before freeing local data. */
+ list_for_each_safe(ptr, n, &local->hostap_interfaces) {
+ iface = list_entry(ptr, struct hostap_interface, list);
+ if (iface->type == HOSTAP_INTERFACE_MASTER) {
+ /* special handling for this interface below */
+ continue;
+ }
+ hostap_remove_interface(iface->dev, 0, 1);
+ }
+
+ unregister_netdev(local->dev);
+
flush_scheduled_work();
if (timer_pending(&local->crypt_deinit_timer))
@@ -3382,15 +3394,6 @@ static void prism2_free_local_data(struct net_device *dev)
prism2_download_free_data(local->dl_sec);
#endif /* PRISM2_DOWNLOAD_SUPPORT */
- list_for_each_safe(ptr, n, &local->hostap_interfaces) {
- iface = list_entry(ptr, struct hostap_interface, list);
- if (iface->type == HOSTAP_INTERFACE_MASTER) {
- /* special handling for this interface below */
- continue;
- }
- hostap_remove_interface(iface->dev, 0, 1);
- }
-
prism2_clear_set_tim_queue(local);
list_for_each_safe(ptr, n, &local->bss_list) {
@@ -3403,7 +3406,6 @@ static void prism2_free_local_data(struct net_device *dev)
kfree(local->last_scan_results);
kfree(local->generic_elem);
- unregister_netdev(local->dev);
free_netdev(local->dev);
}
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index e720369a351559..53f5246c40aa3b 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -50,7 +50,8 @@ static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev)
#endif /* in_atomic */
if (update && prism2_update_comms_qual(dev) == 0)
- wstats->qual.updated = 7;
+ wstats->qual.updated = IW_QUAL_ALL_UPDATED |
+ IW_QUAL_DBM;
wstats->qual.qual = local->comms_qual;
wstats->qual.level = local->avg_signal;
@@ -59,7 +60,7 @@ static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev)
wstats->qual.qual = 0;
wstats->qual.level = 0;
wstats->qual.noise = 0;
- wstats->qual.updated = 0;
+ wstats->qual.updated = IW_QUAL_ALL_INVALID;
}
return wstats;
@@ -1827,13 +1828,6 @@ static char * __prism2_translate_scan(local_info_t *local,
iwe.cmd = SIOCGIWAP;
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
memcpy(iwe.u.ap_addr.sa_data, bssid, ETH_ALEN);
- /* FIX:
- * I do not know how this is possible, but iwe_stream_add_event
- * seems to re-order memcpy execution so that len is set only
- * after copying.. Pre-setting len here "fixes" this, but real
- * problems should be solved (after which these iwe.len
- * settings could be removed from this function). */
- iwe.len = IW_EV_ADDR_LEN;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
IW_EV_ADDR_LEN);
@@ -1843,7 +1837,6 @@ static char * __prism2_translate_scan(local_info_t *local,
iwe.cmd = SIOCGIWESSID;
iwe.u.data.length = ssid_len;
iwe.u.data.flags = 1;
- iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, ssid);
memset(&iwe, 0, sizeof(iwe));
@@ -1859,7 +1852,6 @@ static char * __prism2_translate_scan(local_info_t *local,
iwe.u.mode = IW_MODE_MASTER;
else
iwe.u.mode = IW_MODE_ADHOC;
- iwe.len = IW_EV_UINT_LEN;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
IW_EV_UINT_LEN);
}
@@ -1877,7 +1869,6 @@ static char * __prism2_translate_scan(local_info_t *local,
if (chan > 0) {
iwe.u.freq.m = freq_list[le16_to_cpu(chan - 1)] * 100000;
iwe.u.freq.e = 1;
- iwe.len = IW_EV_FREQ_LEN;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
IW_EV_FREQ_LEN);
}
@@ -1894,7 +1885,10 @@ static char * __prism2_translate_scan(local_info_t *local,
iwe.u.qual.noise =
HFA384X_LEVEL_TO_dBm(le16_to_cpu(scan->anl));
}
- iwe.len = IW_EV_QUAL_LEN;
+ iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_NOISE_UPDATED
+ | IW_QUAL_QUAL_INVALID
+ | IW_QUAL_DBM;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
IW_EV_QUAL_LEN);
}
@@ -1906,7 +1900,6 @@ static char * __prism2_translate_scan(local_info_t *local,
else
iwe.u.data.flags = IW_ENCODE_DISABLED;
iwe.u.data.length = 0;
- iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");
/* TODO: add SuppRates into BSS table */
@@ -1930,7 +1923,7 @@ static char * __prism2_translate_scan(local_info_t *local,
}
/* TODO: add BeaconInt,resp_rate,atim into BSS table */
- buf = kmalloc(MAX_WPA_IE_LEN * 2 + 30, GFP_KERNEL);
+ buf = kmalloc(MAX_WPA_IE_LEN * 2 + 30, GFP_ATOMIC);
if (buf && scan) {
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = IWEVCUSTOM;
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index 025f8cdb556637..da0c80fb941cab 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -59,11 +59,13 @@ static struct pci_device_id prism2_pci_id_table[] __devinitdata = {
static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
{
struct hostap_interface *iface;
+ struct hostap_pci_priv *hw_priv;
local_info_t *local;
unsigned long flags;
iface = netdev_priv(dev);
local = iface->local;
+ hw_priv = local->hw_priv;
spin_lock_irqsave(&local->lock, flags);
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v);
@@ -74,12 +76,14 @@ static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
{
struct hostap_interface *iface;
+ struct hostap_pci_priv *hw_priv;
local_info_t *local;
unsigned long flags;
u8 v;
iface = netdev_priv(dev);
local = iface->local;
+ hw_priv = local->hw_priv;
spin_lock_irqsave(&local->lock, flags);
v = readb(hw_priv->mem_start + a);
@@ -91,11 +95,13 @@ static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
{
struct hostap_interface *iface;
+ struct hostap_pci_priv *hw_priv;
local_info_t *local;
unsigned long flags;
iface = netdev_priv(dev);
local = iface->local;
+ hw_priv = local->hw_priv;
spin_lock_irqsave(&local->lock, flags);
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v);
@@ -106,12 +112,14 @@ static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
{
struct hostap_interface *iface;
+ struct hostap_pci_priv *hw_priv;
local_info_t *local;
unsigned long flags;
u16 v;
iface = netdev_priv(dev);
local = iface->local;
+ hw_priv = local->hw_priv;
spin_lock_irqsave(&local->lock, flags);
v = readw(hw_priv->mem_start + a);
@@ -277,8 +285,6 @@ static struct prism2_helper_functions prism2_pci_funcs =
{
.card_present = NULL,
.cor_sreset = prism2_pci_cor_sreset,
- .dev_open = NULL,
- .dev_close = NULL,
.genesis_reset = prism2_pci_genesis_reset,
.hw_type = HOSTAP_HW_PCI,
};
@@ -352,8 +358,6 @@ static int prism2_pci_probe(struct pci_dev *pdev,
return hostap_hw_ready(dev);
fail:
- kfree(hw_priv);
-
if (irq_registered && dev)
free_irq(dev->irq, dev);
@@ -364,10 +368,8 @@ static int prism2_pci_probe(struct pci_dev *pdev,
err_out_disable:
pci_disable_device(pdev);
- kfree(hw_priv);
- if (local)
- local->hw_priv = NULL;
prism2_free_local_data(dev);
+ kfree(hw_priv);
return -ENODEV;
}
@@ -392,9 +394,8 @@ static void prism2_pci_remove(struct pci_dev *pdev)
free_irq(dev->irq, dev);
mem_start = hw_priv->mem_start;
- kfree(hw_priv);
- iface->local->hw_priv = NULL;
prism2_free_local_data(dev);
+ kfree(hw_priv);
iounmap(mem_start);
@@ -441,7 +442,7 @@ static int prism2_pci_resume(struct pci_dev *pdev)
MODULE_DEVICE_TABLE(pci, prism2_pci_id_table);
static struct pci_driver prism2_pci_drv_id = {
- .name = "prism2_pci",
+ .name = "hostap_pci",
.id_table = prism2_pci_id_table,
.probe = prism2_pci_probe,
.remove = prism2_pci_remove,
diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
index 474ef83d813e87..78d67b408b2f94 100644
--- a/drivers/net/wireless/hostap/hostap_plx.c
+++ b/drivers/net/wireless/hostap/hostap_plx.c
@@ -328,8 +328,6 @@ static struct prism2_helper_functions prism2_plx_funcs =
{
.card_present = NULL,
.cor_sreset = prism2_plx_cor_sreset,
- .dev_open = NULL,
- .dev_close = NULL,
.genesis_reset = prism2_plx_genesis_reset,
.hw_type = HOSTAP_HW_PLX,
};
@@ -570,10 +568,8 @@ static int prism2_plx_probe(struct pci_dev *pdev,
return hostap_hw_ready(dev);
fail:
- kfree(hw_priv);
- if (local)
- local->hw_priv = NULL;
prism2_free_local_data(dev);
+ kfree(hw_priv);
if (irq_registered && dev)
free_irq(dev->irq, dev);
@@ -606,9 +602,8 @@ static void prism2_plx_remove(struct pci_dev *pdev)
if (dev->irq)
free_irq(dev->irq, dev);
- kfree(iface->local->hw_priv);
- iface->local->hw_priv = NULL;
prism2_free_local_data(dev);
+ kfree(hw_priv);
pci_disable_device(pdev);
}
@@ -616,7 +611,7 @@ static void prism2_plx_remove(struct pci_dev *pdev)
MODULE_DEVICE_TABLE(pci, prism2_plx_id_table);
static struct pci_driver prism2_plx_drv_id = {
- .name = "prism2_plx",
+ .name = "hostap_plx",
.id_table = prism2_plx_id_table,
.probe = prism2_plx_probe,
.remove = prism2_plx_remove,
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index cc061e1560d39c..cfd8015594921a 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -552,8 +552,6 @@ struct prism2_helper_functions {
* (hostap_{cs,plx,pci}.c */
int (*card_present)(local_info_t *local);
void (*cor_sreset)(local_info_t *local);
- int (*dev_open)(local_info_t *local);
- int (*dev_close)(local_info_t *local);
void (*genesis_reset)(local_info_t *local, int hcr);
/* the following functions are from hostap_hw.c, but they may have some
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 2414e6493aa563..ad7f8cd76db904 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -800,8 +800,7 @@ static int ipw2100_hw_send_command(struct ipw2100_priv *priv,
* doesn't seem to have as many firmware restart cycles...
*
* As a test, we're sticking in a 1/100s delay here */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 100);
+ schedule_timeout_uninterruptible(msecs_to_jiffies(10));
return 0;
@@ -1256,8 +1255,7 @@ static int ipw2100_start_adapter(struct ipw2100_priv *priv)
IPW_DEBUG_FW("Waiting for f/w initialization to complete...\n");
i = 5000;
do {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(40 * HZ / 1000);
+ schedule_timeout_uninterruptible(msecs_to_jiffies(40));
/* Todo... wait for sync command ... */
read_register(priv->net_dev, IPW_REG_INTA, &inta);
@@ -1411,8 +1409,7 @@ static int ipw2100_hw_phy_off(struct ipw2100_priv *priv)
(val2 & IPW2100_COMMAND_PHY_OFF))
return 0;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HW_PHY_OFF_LOOP_DELAY);
+ schedule_timeout_uninterruptible(HW_PHY_OFF_LOOP_DELAY);
}
return -EIO;
@@ -1466,7 +1463,7 @@ fail_up:
static int ipw2100_hw_stop_adapter(struct ipw2100_priv *priv)
{
-#define HW_POWER_DOWN_DELAY (HZ / 10)
+#define HW_POWER_DOWN_DELAY (msecs_to_jiffies(100))
struct host_command cmd = {
.host_command = HOST_PRE_POWER_DOWN,
@@ -1520,10 +1517,8 @@ static int ipw2100_hw_stop_adapter(struct ipw2100_priv *priv)
printk(KERN_WARNING DRV_NAME ": "
"%s: Power down command failed: Error %d\n",
priv->net_dev->name, err);
- else {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HW_POWER_DOWN_DELAY);
- }
+ else
+ schedule_timeout_uninterruptible(HW_POWER_DOWN_DELAY);
}
priv->status &= ~STATUS_ENABLED;
@@ -2953,7 +2948,7 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
int next = txq->next;
int i = 0;
struct ipw2100_data_header *ipw_hdr;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr_3addr *hdr;
while (!list_empty(&priv->tx_pend_list)) {
/* if there isn't enough space in TBD queue, then
@@ -2989,7 +2984,7 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
packet->index = txq->next;
ipw_hdr = packet->info.d_struct.data;
- hdr = (struct ieee80211_hdr *)packet->info.d_struct.txb->
+ hdr = (struct ieee80211_hdr_3addr *)packet->info.d_struct.txb->
fragments[0]->data;
if (priv->ieee->iw_mode == IW_MODE_INFRA) {
@@ -3274,7 +3269,8 @@ static irqreturn_t ipw2100_interrupt(int irq, void *data,
return IRQ_NONE;
}
-static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev)
+static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev,
+ int pri)
{
struct ipw2100_priv *priv = ieee80211_priv(dev);
struct list_head *element;
diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h
index 2a3cdbd50168aa..c9e99ce15d66f4 100644
--- a/drivers/net/wireless/ipw2100.h
+++ b/drivers/net/wireless/ipw2100.h
@@ -808,7 +808,7 @@ struct ipw2100_priv {
struct ipw2100_rx {
union {
unsigned char payload[IPW_RX_NIC_BUFFER_LENGTH];
- struct ieee80211_hdr header;
+ struct ieee80211_hdr_4addr header;
u32 status;
struct ipw2100_notification notification;
struct ipw2100_cmd_header command;
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index b7f275c00de3ce..de4e6c23e4b869 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -4904,7 +4904,7 @@ static void ipw_rx(struct ipw_priv *priv)
{
struct ipw_rx_mem_buffer *rxb;
struct ipw_rx_packet *pkt;
- struct ieee80211_hdr *header;
+ struct ieee80211_hdr_4addr *header;
u32 r, w, i;
u8 network_packet;
@@ -4967,8 +4967,9 @@ static void ipw_rx(struct ipw_priv *priv)
#endif
header =
- (struct ieee80211_hdr *)(rxb->skb->data +
- IPW_RX_FRAME_SIZE);
+ (struct ieee80211_hdr_4addr *)(rxb->skb->
+ data +
+ IPW_RX_FRAME_SIZE);
/* TODO: Check Ad-Hoc dest/source and make sure
* that we are actually parsing these packets
* correctly -- we should probably use the
@@ -5317,8 +5318,6 @@ static int ipw_wx_set_freq(struct net_device *dev,
IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m);
return ipw_set_channel(priv, (u8) fwrq->m);
-
- return 0;
}
static int ipw_wx_get_freq(struct net_device *dev,
@@ -6010,12 +6009,12 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
}
if (priv->adapter == IPW_2915ABG) {
- priv->ieee->abg_ture = 1;
+ priv->ieee->abg_true = 1;
if (mode & IEEE_A) {
band |= IEEE80211_52GHZ_BAND;
modulation |= IEEE80211_OFDM_MODULATION;
} else
- priv->ieee->abg_ture = 0;
+ priv->ieee->abg_true = 0;
} else {
if (mode & IEEE_A) {
IPW_WARNING("Attempt to set 2200BG into "
@@ -6023,20 +6022,20 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
return -EINVAL;
}
- priv->ieee->abg_ture = 0;
+ priv->ieee->abg_true = 0;
}
if (mode & IEEE_B) {
band |= IEEE80211_24GHZ_BAND;
modulation |= IEEE80211_CCK_MODULATION;
} else
- priv->ieee->abg_ture = 0;
+ priv->ieee->abg_true = 0;
if (mode & IEEE_G) {
band |= IEEE80211_24GHZ_BAND;
modulation |= IEEE80211_OFDM_MODULATION;
} else
- priv->ieee->abg_ture = 0;
+ priv->ieee->abg_true = 0;
priv->ieee->mode = mode;
priv->ieee->freq_band = band;
@@ -6325,7 +6324,7 @@ we need to heavily modify the ieee80211_skb_to_txb.
static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)
+ struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)
txb->fragments[0]->data;
int i = 0;
struct tfd_frame *tfd;
@@ -6448,7 +6447,7 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
}
static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb,
- struct net_device *dev)
+ struct net_device *dev, int pri)
{
struct ipw_priv *priv = ieee80211_priv(dev);
unsigned long flags;
@@ -7108,7 +7107,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
printk(KERN_INFO DRV_NAME
": Detected Intel PRO/Wireless 2915ABG Network "
"Connection\n");
- priv->ieee->abg_ture = 1;
+ priv->ieee->abg_true = 1;
band = IEEE80211_52GHZ_BAND | IEEE80211_24GHZ_BAND;
modulation = IEEE80211_OFDM_MODULATION |
IEEE80211_CCK_MODULATION;
@@ -7124,7 +7123,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
": Detected Intel PRO/Wireless 2200BG Network "
"Connection\n");
- priv->ieee->abg_ture = 0;
+ priv->ieee->abg_true = 0;
band = IEEE80211_24GHZ_BAND;
modulation = IEEE80211_OFDM_MODULATION |
IEEE80211_CCK_MODULATION;
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
index 5b00882133f919..e9cf32bf3e3174 100644
--- a/drivers/net/wireless/ipw2200.h
+++ b/drivers/net/wireless/ipw2200.h
@@ -1654,12 +1654,12 @@ static const long ipw_frequencies[] = {
#define IPW_MAX_CONFIG_RETRIES 10
-static inline u32 frame_hdr_len(struct ieee80211_hdr *hdr)
+static inline u32 frame_hdr_len(struct ieee80211_hdr_4addr *hdr)
{
u32 retval;
u16 fc;
- retval = sizeof(struct ieee80211_hdr);
+ retval = sizeof(struct ieee80211_hdr_3addr);
fc = le16_to_cpu(hdr->frame_ctl);
/*
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index ca6c03c89926ca..92793b958e327d 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -57,9 +57,7 @@
#include <linux/bitops.h>
#ifdef CONFIG_NET_RADIO
#include <linux/wireless.h>
-#if WIRELESS_EXT > 12
#include <net/iw_handler.h>
-#endif /* WIRELESS_EXT > 12 */
#endif
#include <pcmcia/cs_types.h>
@@ -225,10 +223,7 @@ static void update_stats(struct net_device *dev);
static struct net_device_stats *netwave_get_stats(struct net_device *dev);
/* Wireless extensions */
-#ifdef WIRELESS_EXT
static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev);
-#endif
-static int netwave_ioctl(struct net_device *, struct ifreq *, int);
static void set_multicast_list(struct net_device *dev);
@@ -260,26 +255,7 @@ static dev_link_t *dev_list;
because they generally can't be allocated dynamically.
*/
-#if WIRELESS_EXT <= 12
-/* Wireless extensions backward compatibility */
-
-/* Part of iw_handler prototype we need */
-struct iw_request_info
-{
- __u16 cmd; /* Wireless Extension command */
- __u16 flags; /* More to come ;-) */
-};
-
-/* Wireless Extension Backward compatibility - Jean II
- * If the new wireless device private ioctl range is not defined,
- * default to standard device private ioctl range */
-#ifndef SIOCIWFIRSTPRIV
-#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE
-#endif /* SIOCIWFIRSTPRIV */
-
-#else /* WIRELESS_EXT <= 12 */
static const struct iw_handler_def netwave_handler_def;
-#endif /* WIRELESS_EXT <= 12 */
#define SIOCGIPSNAP SIOCIWFIRSTPRIV + 1 /* Site Survey Snapshot */
@@ -319,9 +295,7 @@ typedef struct netwave_private {
struct timer_list watchdog; /* To avoid blocking state */
struct site_survey nss;
struct net_device_stats stats;
-#ifdef WIRELESS_EXT
struct iw_statistics iw_stats; /* Wireless stats */
-#endif
} netwave_private;
#ifdef NETWAVE_STATS
@@ -353,7 +327,6 @@ static inline void wait_WOC(unsigned int iobase)
while ((inb(iobase + NETWAVE_REG_ASR) & 0x8) != 0x8) ;
}
-#ifdef WIRELESS_EXT
static void netwave_snapshot(netwave_private *priv, u_char __iomem *ramBase,
kio_addr_t iobase) {
u_short resultBuffer;
@@ -376,9 +349,7 @@ static void netwave_snapshot(netwave_private *priv, u_char __iomem *ramBase,
sizeof(struct site_survey));
}
}
-#endif
-#ifdef WIRELESS_EXT
/*
* Function netwave_get_wireless_stats (dev)
*
@@ -411,7 +382,6 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev)
return &priv->iw_stats;
}
-#endif
/*
* Function netwave_attach (void)
@@ -471,13 +441,7 @@ static dev_link_t *netwave_attach(void)
dev->get_stats = &netwave_get_stats;
dev->set_multicast_list = &set_multicast_list;
/* wireless extensions */
-#if WIRELESS_EXT <= 16
- dev->get_wireless_stats = &netwave_get_wireless_stats;
-#endif /* WIRELESS_EXT <= 16 */
-#if WIRELESS_EXT > 12
dev->wireless_handlers = (struct iw_handler_def *)&netwave_handler_def;
-#endif /* WIRELESS_EXT > 12 */
- dev->do_ioctl = &netwave_ioctl;
dev->tx_timeout = &netwave_watchdog;
dev->watchdog_timeo = TX_TIMEOUT;
@@ -576,13 +540,8 @@ static int netwave_set_nwid(struct net_device *dev,
/* Disable interrupts & save flags */
spin_lock_irqsave(&priv->spinlock, flags);
-#if WIRELESS_EXT > 8
if(!wrqu->nwid.disabled) {
domain = wrqu->nwid.value;
-#else /* WIRELESS_EXT > 8 */
- if(wrqu->nwid.on) {
- domain = wrqu->nwid.nwid;
-#endif /* WIRELESS_EXT > 8 */
printk( KERN_DEBUG "Setting domain to 0x%x%02x\n",
(domain >> 8) & 0x01, domain & 0xff);
wait_WOC(iobase);
@@ -606,15 +565,9 @@ static int netwave_get_nwid(struct net_device *dev,
union iwreq_data *wrqu,
char *extra)
{
-#if WIRELESS_EXT > 8
wrqu->nwid.value = domain;
wrqu->nwid.disabled = 0;
wrqu->nwid.fixed = 1;
-#else /* WIRELESS_EXT > 8 */
- wrqu->nwid.nwid = domain;
- wrqu->nwid.on = 1;
-#endif /* WIRELESS_EXT > 8 */
-
return 0;
}
@@ -657,17 +610,11 @@ static int netwave_get_scramble(struct net_device *dev,
{
key[1] = scramble_key & 0xff;
key[0] = (scramble_key>>8) & 0xff;
-#if WIRELESS_EXT > 8
wrqu->encoding.flags = IW_ENCODE_ENABLED;
wrqu->encoding.length = 2;
-#else /* WIRELESS_EXT > 8 */
- wrqu->encoding.method = 1;
-#endif /* WIRELESS_EXT > 8 */
-
return 0;
}
-#if WIRELESS_EXT > 8
/*
* Wireless Handler : get mode
*/
@@ -683,7 +630,6 @@ static int netwave_get_mode(struct net_device *dev,
return 0;
}
-#endif /* WIRELESS_EXT > 8 */
/*
* Wireless Handler : get range info
@@ -702,11 +648,9 @@ static int netwave_get_range(struct net_device *dev,
/* Set all the info we don't care or don't know about to zero */
memset(range, 0, sizeof(struct iw_range));
-#if WIRELESS_EXT > 10
/* Set the Wireless Extension versions */
range->we_version_compiled = WIRELESS_EXT;
range->we_version_source = 9; /* Nothing for us in v10 and v11 */
-#endif /* WIRELESS_EXT > 10 */
/* Set information in the range struct */
range->throughput = 450 * 1000; /* don't argue on this ! */
@@ -720,16 +664,12 @@ static int netwave_get_range(struct net_device *dev,
range->max_qual.level = 255;
range->max_qual.noise = 0;
-#if WIRELESS_EXT > 7
range->num_bitrates = 1;
range->bitrate[0] = 1000000; /* 1 Mb/s */
-#endif /* WIRELESS_EXT > 7 */
-#if WIRELESS_EXT > 8
range->encoding_size[0] = 2; /* 16 bits scrambling */
range->num_encoding_sizes = 1;
range->max_encoding_tokens = 1; /* Only one key possible */
-#endif /* WIRELESS_EXT > 8 */
return ret;
}
@@ -775,8 +715,6 @@ static const struct iw_priv_args netwave_private_args[] = {
"getsitesurvey" },
};
-#if WIRELESS_EXT > 12
-
static const iw_handler netwave_handler[] =
{
NULL, /* SIOCSIWNAME */
@@ -839,131 +777,8 @@ static const struct iw_handler_def netwave_handler_def =
.standard = (iw_handler *) netwave_handler,
.private = (iw_handler *) netwave_private_handler,
.private_args = (struct iw_priv_args *) netwave_private_args,
-#if WIRELESS_EXT > 16
.get_wireless_stats = netwave_get_wireless_stats,
-#endif /* WIRELESS_EXT > 16 */
};
-#endif /* WIRELESS_EXT > 12 */
-
-/*
- * Function netwave_ioctl (dev, rq, cmd)
- *
- * Perform ioctl : config & info stuff
- * This is the stuff that are treated the wireless extensions (iwconfig)
- *
- */
-static int netwave_ioctl(struct net_device *dev, /* ioctl device */
- struct ifreq *rq, /* Data passed */
- int cmd) /* Ioctl number */
-{
- int ret = 0;
-#ifdef WIRELESS_EXT
-#if WIRELESS_EXT <= 12
- struct iwreq *wrq = (struct iwreq *) rq;
-#endif
-#endif
-
- DEBUG(0, "%s: ->netwave_ioctl(cmd=0x%X)\n", dev->name, cmd);
-
- /* Look what is the request */
- switch(cmd) {
- /* --------------- WIRELESS EXTENSIONS --------------- */
-#ifdef WIRELESS_EXT
-#if WIRELESS_EXT <= 12
- case SIOCGIWNAME:
- netwave_get_name(dev, NULL, &(wrq->u), NULL);
- break;
- case SIOCSIWNWID:
- ret = netwave_set_nwid(dev, NULL, &(wrq->u), NULL);
- break;
- case SIOCGIWNWID:
- ret = netwave_get_nwid(dev, NULL, &(wrq->u), NULL);
- break;
-#if WIRELESS_EXT > 8 /* Note : The API did change... */
- case SIOCGIWENCODE:
- /* Get scramble key */
- if(wrq->u.encoding.pointer != (caddr_t) 0)
- {
- char key[2];
- ret = netwave_get_scramble(dev, NULL, &(wrq->u), key);
- if(copy_to_user(wrq->u.encoding.pointer, key, 2))
- ret = -EFAULT;
- }
- break;
- case SIOCSIWENCODE:
- /* Set scramble key */
- if(wrq->u.encoding.pointer != (caddr_t) 0)
- {
- char key[2];
- if(copy_from_user(key, wrq->u.encoding.pointer, 2))
- {
- ret = -EFAULT;
- break;
- }
- ret = netwave_set_scramble(dev, NULL, &(wrq->u), key);
- }
- break;
- case SIOCGIWMODE:
- /* Mode of operation */
- ret = netwave_get_mode(dev, NULL, &(wrq->u), NULL);
- break;
-#else /* WIRELESS_EXT > 8 */
- case SIOCGIWENCODE:
- /* Get scramble key */
- ret = netwave_get_scramble(dev, NULL, &(wrq->u),
- (char *) &wrq->u.encoding.code);
- break;
- case SIOCSIWENCODE:
- /* Set scramble key */
- ret = netwave_set_scramble(dev, NULL, &(wrq->u),
- (char *) &wrq->u.encoding.code);
- break;
-#endif /* WIRELESS_EXT > 8 */
- case SIOCGIWRANGE:
- /* Basic checking... */
- if(wrq->u.data.pointer != (caddr_t) 0) {
- struct iw_range range;
- ret = netwave_get_range(dev, NULL, &(wrq->u), (char *) &range);
- if (copy_to_user(wrq->u.data.pointer, &range,
- sizeof(struct iw_range)))
- ret = -EFAULT;
- }
- break;
- case SIOCGIWPRIV:
- /* Basic checking... */
- if(wrq->u.data.pointer != (caddr_t) 0) {
- /* Set the number of ioctl available */
- wrq->u.data.length = sizeof(netwave_private_args) / sizeof(netwave_private_args[0]);
-
- /* Copy structure to the user buffer */
- if(copy_to_user(wrq->u.data.pointer,
- (u_char *) netwave_private_args,
- sizeof(netwave_private_args)))
- ret = -EFAULT;
- }
- break;
- case SIOCGIPSNAP:
- if(wrq->u.data.pointer != (caddr_t) 0) {
- char buffer[sizeof( struct site_survey)];
- ret = netwave_get_snap(dev, NULL, &(wrq->u), buffer);
- /* Copy structure to the user buffer */
- if(copy_to_user(wrq->u.data.pointer,
- buffer,
- sizeof( struct site_survey)))
- {
- printk(KERN_DEBUG "Bad buffer!\n");
- break;
- }
- }
- break;
-#endif /* WIRELESS_EXT <= 12 */
-#endif /* WIRELESS_EXT */
- default:
- ret = -EOPNOTSUPP;
- }
-
- return ret;
-}
/*
* Function netwave_pcmcia_config (link)
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 15ceaf615756a2..d3d4ec9e242e31 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -77,30 +77,16 @@
#define DRIVER_NAME "orinoco"
#include <linux/config.h>
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
#include <linux/netdevice.h>
-#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/wireless.h>
#include <net/iw_handler.h>
#include <net/ieee80211.h>
-#include <net/ieee80211.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include "hermes.h"
#include "hermes_rid.h"
#include "orinoco.h"
@@ -137,7 +123,7 @@ MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions");
/* We do this this way to avoid ifdefs in the actual code */
#ifdef WIRELESS_SPY
-#define SPY_NUMBER(priv) (priv->spy_number)
+#define SPY_NUMBER(priv) (priv->spy_data.spy_number)
#else
#define SPY_NUMBER(priv) 0
#endif /* WIRELESS_SPY */
@@ -216,31 +202,32 @@ static struct {
/********************************************************************/
/* Used in Event handling.
- * We avoid nested structres as they break on ARM -- Moustafa */
+ * We avoid nested structures as they break on ARM -- Moustafa */
struct hermes_tx_descriptor_802_11 {
/* hermes_tx_descriptor */
- u16 status;
- u16 reserved1;
- u16 reserved2;
- u32 sw_support;
+ __le16 status;
+ __le16 reserved1;
+ __le16 reserved2;
+ __le32 sw_support;
u8 retry_count;
u8 tx_rate;
- u16 tx_control;
+ __le16 tx_control;
- /* ieee802_11_hdr */
- u16 frame_ctl;
- u16 duration_id;
+ /* ieee80211_hdr */
+ __le16 frame_ctl;
+ __le16 duration_id;
u8 addr1[ETH_ALEN];
u8 addr2[ETH_ALEN];
u8 addr3[ETH_ALEN];
- u16 seq_ctl;
+ __le16 seq_ctl;
u8 addr4[ETH_ALEN];
- u16 data_len;
+
+ __le16 data_len;
/* ethhdr */
- unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
- unsigned char h_source[ETH_ALEN]; /* source ether addr */
- unsigned short h_proto; /* packet type ID field */
+ u8 h_dest[ETH_ALEN]; /* destination eth addr */
+ u8 h_source[ETH_ALEN]; /* source ether addr */
+ __be16 h_proto; /* packet type ID field */
/* p8022_hdr */
u8 dsap;
@@ -248,31 +235,31 @@ struct hermes_tx_descriptor_802_11 {
u8 ctrl;
u8 oui[3];
- u16 ethertype;
+ __be16 ethertype;
} __attribute__ ((packed));
/* Rx frame header except compatibility 802.3 header */
struct hermes_rx_descriptor {
/* Control */
- u16 status;
- u32 time;
+ __le16 status;
+ __le32 time;
u8 silence;
u8 signal;
u8 rate;
u8 rxflow;
- u32 reserved;
+ __le32 reserved;
/* 802.11 header */
- u16 frame_ctl;
- u16 duration_id;
+ __le16 frame_ctl;
+ __le16 duration_id;
u8 addr1[ETH_ALEN];
u8 addr2[ETH_ALEN];
u8 addr3[ETH_ALEN];
- u16 seq_ctl;
+ __le16 seq_ctl;
u8 addr4[ETH_ALEN];
/* Data length */
- u16 data_len;
+ __le16 data_len;
} __attribute__ ((packed));
/********************************************************************/
@@ -396,14 +383,14 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
/* If a spy address is defined, we report stats of the
* first spy address - Jean II */
if (SPY_NUMBER(priv)) {
- wstats->qual.qual = priv->spy_stat[0].qual;
- wstats->qual.level = priv->spy_stat[0].level;
- wstats->qual.noise = priv->spy_stat[0].noise;
- wstats->qual.updated = priv->spy_stat[0].updated;
+ wstats->qual.qual = priv->spy_data.spy_stat[0].qual;
+ wstats->qual.level = priv->spy_data.spy_stat[0].level;
+ wstats->qual.noise = priv->spy_data.spy_stat[0].noise;
+ wstats->qual.updated = priv->spy_data.spy_stat[0].updated;
}
} else {
struct {
- u16 qual, signal, noise;
+ __le16 qual, signal, noise;
} __attribute__ ((packed)) cq;
err = HERMES_READ_RECORD(hw, USER_BAP,
@@ -505,11 +492,9 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
/* Check packet length, pad short packets, round up odd length */
len = max_t(int, ALIGN(skb->len, 2), ETH_ZLEN);
- if (skb->len < len) {
- skb = skb_padto(skb, len);
- if (skb == NULL)
- goto fail;
- }
+ skb = skb_padto(skb, len);
+ if (skb == NULL)
+ goto fail;
len -= ETH_HLEN;
eh = (struct ethhdr *)skb->data;
@@ -634,16 +619,17 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
struct orinoco_private *priv = netdev_priv(dev);
struct net_device_stats *stats = &priv->stats;
u16 fid = hermes_read_regn(hw, TXCOMPLFID);
+ u16 status;
struct hermes_tx_descriptor_802_11 hdr;
int err = 0;
if (fid == DUMMY_FID)
return; /* Nothing's really happened */
- /* Read the frame header */
+ /* Read part of the frame header - we need status and addr1 */
err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
- sizeof(struct hermes_tx_descriptor) +
- sizeof(struct ieee80211_hdr),
+ offsetof(struct hermes_tx_descriptor_802_11,
+ addr2),
fid, 0);
hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
@@ -663,8 +649,8 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
* exceeded, because that's the only status that really mean
* that this particular node went away.
* Other errors means that *we* screwed up. - Jean II */
- hdr.status = le16_to_cpu(hdr.status);
- if (hdr.status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
+ status = le16_to_cpu(hdr.status);
+ if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
union iwreq_data wrqu;
/* Copy 802.11 dest address.
@@ -723,18 +709,13 @@ static inline int is_ethersnap(void *_hdr)
static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
int level, int noise)
{
- struct orinoco_private *priv = netdev_priv(dev);
- int i;
-
- /* Gather wireless spy statistics: for each packet, compare the
- * source address with out list, and if match, get the stats... */
- for (i = 0; i < priv->spy_number; i++)
- if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {
- priv->spy_stat[i].level = level - 0x95;
- priv->spy_stat[i].noise = noise - 0x95;
- priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0;
- priv->spy_stat[i].updated = 7;
- }
+ struct iw_quality wstats;
+ wstats.level = level - 0x95;
+ wstats.noise = noise - 0x95;
+ wstats.qual = (level > noise) ? (level - noise) : 0;
+ wstats.updated = 7;
+ /* Update spy records */
+ wireless_spy_update(dev, mac, &wstats);
}
static void orinoco_stat_gather(struct net_device *dev,
@@ -1055,7 +1036,7 @@ static void orinoco_join_ap(struct net_device *dev)
unsigned long flags;
struct join_req {
u8 bssid[ETH_ALEN];
- u16 channel;
+ __le16 channel;
} __attribute__ ((packed)) req;
const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
struct prism2_scan_apinfo *atom = NULL;
@@ -1070,7 +1051,7 @@ static void orinoco_join_ap(struct net_device *dev)
return;
if (orinoco_lock(priv, &flags) != 0)
- goto out;
+ goto fail_lock;
/* Sanity checks in case user changed something in the meantime */
if (! priv->bssid_fixed)
@@ -1115,8 +1096,10 @@ static void orinoco_join_ap(struct net_device *dev)
printk(KERN_ERR "%s: Error issuing join request\n", dev->name);
out:
- kfree(buf);
orinoco_unlock(priv, &flags);
+
+ fail_lock:
+ kfree(buf);
}
/* Send new BSSID to userspace */
@@ -1134,12 +1117,14 @@ static void orinoco_send_wevents(struct net_device *dev)
err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID,
ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
if (err != 0)
- return;
+ goto out;
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
/* Send event to user space */
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+
+ out:
orinoco_unlock(priv, &flags);
}
@@ -1148,8 +1133,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
struct orinoco_private *priv = netdev_priv(dev);
u16 infofid;
struct {
- u16 len;
- u16 type;
+ __le16 len;
+ __le16 type;
} __attribute__ ((packed)) info;
int len, type;
int err;
@@ -2464,6 +2449,10 @@ struct net_device *alloc_orinocodev(int sizeof_card,
dev->get_stats = orinoco_get_stats;
dev->ethtool_ops = &orinoco_ethtool_ops;
dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def;
+#ifdef WIRELESS_SPY
+ priv->wireless_data.spy_data = &priv->spy_data;
+ dev->wireless_data = &priv->wireless_data;
+#endif
dev->change_mtu = orinoco_change_mtu;
dev->set_multicast_list = orinoco_set_multicast_list;
/* we use the default eth_mac_addr for setting the MAC addr */
@@ -2835,7 +2824,7 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
}
}
- if ((priv->iw_mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){
+ if ((priv->iw_mode == IW_MODE_ADHOC) && (!SPY_NUMBER(priv))){
/* Quality stats meaningless in ad-hoc mode */
} else {
range->max_qual.qual = 0x8b - 0x2f;
@@ -2882,6 +2871,14 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
range->min_r_time = 0;
range->max_r_time = 65535 * 1000; /* ??? */
+ /* Event capability (kernel) */
+ IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
+ /* Event capability (driver) */
+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
+
TRACE_EXIT(dev->name);
return 0;
@@ -3841,92 +3838,6 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
return err;
}
-/* Spy is used for link quality/strength measurements in Ad-Hoc mode
- * Jean II */
-static int orinoco_ioctl_setspy(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *srq,
- char *extra)
-
-{
- struct orinoco_private *priv = netdev_priv(dev);
- struct sockaddr *address = (struct sockaddr *) extra;
- int number = srq->length;
- int i;
- unsigned long flags;
-
- /* Make sure nobody mess with the structure while we do */
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- /* orinoco_lock() doesn't disable interrupts, so make sure the
- * interrupt rx path don't get confused while we copy */
- priv->spy_number = 0;
-
- if (number > 0) {
- /* Extract the addresses */
- for (i = 0; i < number; i++)
- memcpy(priv->spy_address[i], address[i].sa_data,
- ETH_ALEN);
- /* Reset stats */
- memset(priv->spy_stat, 0,
- sizeof(struct iw_quality) * IW_MAX_SPY);
- /* Set number of addresses */
- priv->spy_number = number;
- }
-
- /* Now, let the others play */
- orinoco_unlock(priv, &flags);
-
- /* Do NOT call commit handler */
- return 0;
-}
-
-static int orinoco_ioctl_getspy(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *srq,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- struct sockaddr *address = (struct sockaddr *) extra;
- int number;
- int i;
- unsigned long flags;
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- number = priv->spy_number;
- /* Create address struct */
- for (i = 0; i < number; i++) {
- memcpy(address[i].sa_data, priv->spy_address[i], ETH_ALEN);
- address[i].sa_family = AF_UNIX;
- }
- if (number > 0) {
- /* Create address struct */
- for (i = 0; i < number; i++) {
- memcpy(address[i].sa_data, priv->spy_address[i],
- ETH_ALEN);
- address[i].sa_family = AF_UNIX;
- }
- /* Copy stats */
- /* In theory, we should disable irqs while copying the stats
- * because the rx path might update it in the middle...
- * Bah, who care ? - Jean II */
- memcpy(extra + (sizeof(struct sockaddr) * number),
- priv->spy_stat, sizeof(struct iw_quality) * number);
- }
- /* Reset updated flags. */
- for (i = 0; i < number; i++)
- priv->spy_stat[i].updated = 0;
-
- orinoco_unlock(priv, &flags);
-
- srq->length = number;
-
- return 0;
-}
-
/* Trigger a scan (look for other cells in the vicinity */
static int orinoco_ioctl_setscan(struct net_device *dev,
struct iw_request_info *info,
@@ -3999,7 +3910,7 @@ static int orinoco_ioctl_setscan(struct net_device *dev,
HERMES_HOSTSCAN_SYMBOL_BCAST);
break;
case FIRMWARE_TYPE_INTERSIL: {
- u16 req[3];
+ __le16 req[3];
req[0] = cpu_to_le16(0x3fff); /* All channels */
req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */
@@ -4073,7 +3984,7 @@ static inline int orinoco_translate_scan(struct net_device *dev,
case FIRMWARE_TYPE_INTERSIL:
offset = 4;
if (priv->has_hostscan) {
- atom_len = le16_to_cpup((u16 *)scan);
+ atom_len = le16_to_cpup((__le16 *)scan);
/* Sanity check for atom_len */
if (atom_len < sizeof(struct prism2_scan_apinfo)) {
printk(KERN_ERR "%s: Invalid atom_len in scan data: %d\n",
@@ -4357,8 +4268,10 @@ static const iw_handler orinoco_handler[] = {
[SIOCSIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setsens,
[SIOCGIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getsens,
[SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwrange,
- [SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setspy,
- [SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getspy,
+ [SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_set_spy,
+ [SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_get_spy,
+ [SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy,
+ [SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy,
[SIOCSIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setwap,
[SIOCGIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getwap,
[SIOCSIWSCAN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setscan,
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
index 2f213a7103fe70..7a17bb31fc896d 100644
--- a/drivers/net/wireless/orinoco.h
+++ b/drivers/net/wireless/orinoco.h
@@ -7,12 +7,11 @@
#ifndef _ORINOCO_H
#define _ORINOCO_H
-#define DRIVER_VERSION "0.15rc2"
+#define DRIVER_VERSION "0.15rc3"
-#include <linux/types.h>
-#include <linux/spinlock.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
+#include <net/iw_handler.h>
#include <linux/version.h>
#include "hermes.h"
@@ -28,7 +27,7 @@
#define ORINOCO_MAX_KEYS 4
struct orinoco_key {
- u16 len; /* always stored as little-endian */
+ __le16 len; /* always stored as little-endian */
char data[ORINOCO_MAX_KEY_SIZE];
} __attribute__ ((packed));
@@ -36,14 +35,14 @@ struct header_struct {
/* 802.3 */
u8 dest[ETH_ALEN];
u8 src[ETH_ALEN];
- u16 len;
+ __be16 len;
/* 802.2 */
u8 dsap;
u8 ssap;
u8 ctrl;
/* SNAP */
u8 oui[3];
- u16 ethertype;
+ unsigned short ethertype;
} __attribute__ ((packed));
typedef enum {
@@ -112,9 +111,8 @@ struct orinoco_private {
u16 pm_on, pm_mcast, pm_period, pm_timeout;
u16 preamble;
#ifdef WIRELESS_SPY
- int spy_number;
- u_char spy_address[IW_MAX_SPY][ETH_ALEN];
- struct iw_quality spy_stat[IW_MAX_SPY];
+ struct iw_spy_data spy_data; /* iwspy support */
+ struct iw_public_data wireless_data;
#endif
/* Configuration dependent variables */
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index bedd7f9f23e48c..dc1128a0097198 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -14,33 +14,16 @@
#define PFX DRIVER_NAME ": "
#include <linux/config.h>
-#ifdef __IN_PCMCIA_PACKAGE__
-#include <pcmcia/k_compat.h>
-#endif /* __IN_PCMCIA_PACKAGE__ */
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-
+#include <linux/delay.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
#include "orinoco.h"
/********************************************************************/
@@ -97,17 +80,8 @@ static dev_link_t *dev_list; /* = NULL */
/* Function prototypes */
/********************************************************************/
-/* device methods */
-static int orinoco_cs_hard_reset(struct orinoco_private *priv);
-
-/* PCMCIA gumpf */
-static void orinoco_cs_config(dev_link_t * link);
-static void orinoco_cs_release(dev_link_t * link);
-static int orinoco_cs_event(event_t event, int priority,
- event_callback_args_t * args);
-
-static dev_link_t *orinoco_cs_attach(void);
-static void orinoco_cs_detach(dev_link_t *);
+static void orinoco_cs_release(dev_link_t *link);
+static void orinoco_cs_detach(dev_link_t *link);
/********************************************************************/
/* Device methods */
@@ -603,49 +577,85 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
"Pavel Roskin <proski@gnu.org>, et al)";
static struct pcmcia_device_id orinoco_cs_ids[] = {
- PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300),
- PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a),
- PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001),
- PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305),
- PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613),
- PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673),
- PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001),
- PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300),
- PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021),
- PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005),
+ PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */
+ PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */
+ PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */
+ PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */
+ PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */
+ PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */
+ PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */
+ PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */
+ PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), /* Nortel Networks eMobility 802.11 Wireless Adapter */
+ PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */
+ PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */
+ PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */
+ PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */
+ PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */
+ PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */
+ PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */
+ PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */
+ PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */
+ PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */
+ PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */
+ PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */
+ PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */
+ PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */
+ PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), /* CONTEC FLEXSCAN/FX-DDS110-PCC */
+ PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), /* Conceptronic CON11Cpro, EMTAC A2424i */
+ PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */
+ PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */
+ PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9),
PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3),
- PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5),
+ PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2),
+ PCMCIA_DEVICE_PROD_ID123("AIRVAST", "IEEE 802.11b Wireless PCMCIA Card", "HFA3863", 0xea569531, 0x4bcb9645, 0x355cb092),
+ PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f),
+ PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842),
+ PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e),
PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169),
+ PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb),
PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3),
+ PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18),
PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
+ PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b),
+ PCMCIA_DEVICE_PROD_ID123("corega", "WL PCCL-11", "ISL37300P", 0x0a21501a, 0x59868926, 0xc9049a39),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae),
PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac),
PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab),
+ PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916),
+ PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146),
PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c),
+ PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
+ PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077),
PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18),
+ PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77),
+ PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf),
+ PCMCIA_DEVICE_PROD_ID123("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", 0x4b801a17, 0xf222ec2d, 0x630d52b2),
+ PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92),
+ PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395),
PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a),
PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410),
PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3),
PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01),
PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a),
+ PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1),
PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1),
+ PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767),
+ PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6),
+ PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed),
+ PCMCIA_DEVICE_PROD_ID123("PCMCIA", "11M WLAN Card v2.5", "ISL37300P", 0x281f1c5d, 0x6e440487, 0xc9049a39),
PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264),
+ PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178),
PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
- PCMCIA_DEVICE_PROD_ID1("Symbol Technologies", 0x3f02b4d6),
+ PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a),
+ PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
+ PCMCIA_DEVICE_PROD_ID123("The Linksys Group, Inc.", "Instant Wireless Network PC Card", "ISL37300P", 0xa5f472c2, 0x590eb502, 0xc9049a39),
+ PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee),
PCMCIA_DEVICE_NULL,
};
MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids);
@@ -656,8 +666,8 @@ static struct pcmcia_driver orinoco_driver = {
.name = DRIVER_NAME,
},
.attach = orinoco_cs_attach,
- .event = orinoco_cs_event,
.detach = orinoco_cs_detach,
+ .event = orinoco_cs_event,
.id_table = orinoco_cs_ids,
};
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c
index 86fa58e5cfac87..d8afd51ff8a590 100644
--- a/drivers/net/wireless/orinoco_nortel.c
+++ b/drivers/net/wireless/orinoco_nortel.c
@@ -40,29 +40,13 @@
#define PFX DRIVER_NAME ": "
#include <linux/config.h>
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/list.h>
+#include <linux/delay.h>
#include <linux/pci.h>
-#include <linux/fcntl.h>
-
#include <pcmcia/cisreg.h>
-#include "hermes.h"
#include "orinoco.h"
#define COR_OFFSET (0xe0) /* COR attribute offset of Prism2 PC card */
@@ -108,7 +92,7 @@ static int nortel_pci_cor_reset(struct orinoco_private *priv)
return 0;
}
-int nortel_pci_hw_init(struct nortel_pci_card *card)
+static int nortel_pci_hw_init(struct nortel_pci_card *card)
{
int i;
u32 reg;
diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c
index 42e03438291b8e..5362c214fc8e29 100644
--- a/drivers/net/wireless/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco_pci.c
@@ -93,28 +93,12 @@
#define PFX DRIVER_NAME ": "
#include <linux/config.h>
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/list.h>
+#include <linux/delay.h>
#include <linux/pci.h>
-#include <linux/fcntl.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include "hermes.h"
#include "orinoco.h"
/* All the magic there is from wlan-ng */
diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c
index 7ab05b89fb3f61..210e73776545d6 100644
--- a/drivers/net/wireless/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco_plx.c
@@ -117,29 +117,13 @@
#define PFX DRIVER_NAME ": "
#include <linux/config.h>
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/list.h>
+#include <linux/delay.h>
#include <linux/pci.h>
-#include <linux/fcntl.h>
-
#include <pcmcia/cisreg.h>
-#include "hermes.h"
#include "orinoco.h"
#define COR_OFFSET (0x3e0) /* COR attribute offset of Prism2 PC card */
diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c
index 85893f42445be7..5e68b7026186bc 100644
--- a/drivers/net/wireless/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco_tmd.c
@@ -53,29 +53,13 @@
#define PFX DRIVER_NAME ": "
#include <linux/config.h>
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/list.h>
+#include <linux/delay.h>
#include <linux/pci.h>
-#include <linux/fcntl.h>
-
#include <pcmcia/cisreg.h>
-#include "hermes.h"
#include "orinoco.h"
#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 9a8790e3580c64..5c1a1adf1ff8b2 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -462,14 +462,12 @@ prism54_get_range(struct net_device *ndev, struct iw_request_info *info,
/* txpower is supported in dBm's */
range->txpower_capa = IW_TXPOW_DBM;
-#if WIRELESS_EXT > 16
/* Event capability (kernel + driver) */
range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
IW_EVENT_CAPA_MASK(SIOCGIWAP));
range->event_capa[1] = IW_EVENT_CAPA_K_1;
range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVCUSTOM);
-#endif /* WIRELESS_EXT > 16 */
if (islpci_get_state(priv) < PRV_STATE_INIT)
return 0;
@@ -693,14 +691,13 @@ prism54_get_scan(struct net_device *ndev, struct iw_request_info *info,
extra + dwrq->length,
&(bsslist->bsslist[i]),
noise);
-#if WIRELESS_EXT > 16
+
/* Check if there is space for one more entry */
if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) {
/* Ask user space to try again with a bigger buffer */
rvalue = -E2BIG;
break;
}
-#endif /* WIRELESS_EXT > 16 */
}
kfree(bsslist);
@@ -2727,12 +2724,7 @@ const struct iw_handler_def prism54_handler_def = {
.standard = (iw_handler *) prism54_handler,
.private = (iw_handler *) prism54_private_handler,
.private_args = (struct iw_priv_args *) prism54_private_args,
-#if WIRELESS_EXT > 16
.get_wireless_stats = prism54_get_wireless_stats,
-#endif /* WIRELESS_EXT > 16 */
-#if WIRELESS_EXT == 16
- .spy_offset = offsetof(islpci_private, spy_data),
-#endif /* WIRELESS_EXT == 16 */
};
/* For wpa_supplicant */
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
index 6f13d4a8e2d338..6c9584a9f284dc 100644
--- a/drivers/net/wireless/prism54/islpci_dev.c
+++ b/drivers/net/wireless/prism54/islpci_dev.c
@@ -439,8 +439,7 @@ prism54_bring_down(islpci_private *priv)
wmb();
/* wait a while for the device to reset */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(50*HZ/1000);
+ schedule_timeout_uninterruptible(msecs_to_jiffies(50));
return 0;
}
@@ -491,8 +490,7 @@ islpci_reset_if(islpci_private *priv)
/* The software reset acknowledge needs about 220 msec here.
* Be conservative and wait for up to one second. */
- set_current_state(TASK_UNINTERRUPTIBLE);
- remaining = schedule_timeout(HZ);
+ remaining = schedule_timeout_uninterruptible(HZ);
if(remaining > 0) {
result = 0;
@@ -839,13 +837,9 @@ islpci_setup(struct pci_dev *pdev)
priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) ?
priv->monitor_type : ARPHRD_ETHER;
-#if WIRELESS_EXT > 16
/* Add pointers to enable iwspy support. */
priv->wireless_data.spy_data = &priv->spy_data;
ndev->wireless_data = &priv->wireless_data;
-#else /* WIRELESS_EXT > 16 */
- ndev->get_wireless_stats = &prism54_get_wireless_stats;
-#endif /* WIRELESS_EXT > 16 */
/* save the start and end address of the PCI memory area */
ndev->mem_start = (unsigned long) priv->device_base;
diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
index 32a1019f1b363e..efbed439795111 100644
--- a/drivers/net/wireless/prism54/islpci_dev.h
+++ b/drivers/net/wireless/prism54/islpci_dev.h
@@ -100,9 +100,7 @@ typedef struct {
struct iw_spy_data spy_data; /* iwspy support */
-#if WIRELESS_EXT > 16
struct iw_public_data wireless_data;
-#endif /* WIRELESS_EXT > 16 */
int monitor_type; /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_PRISM */
diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c
index b6f2e5a223be62..4937a5ad4b2cee 100644
--- a/drivers/net/wireless/prism54/islpci_mgt.c
+++ b/drivers/net/wireless/prism54/islpci_mgt.c
@@ -455,7 +455,7 @@ islpci_mgt_transaction(struct net_device *ndev,
struct islpci_mgmtframe **recvframe)
{
islpci_private *priv = netdev_priv(ndev);
- const long wait_cycle_jiffies = (ISL38XX_WAIT_CYCLE * 10 * HZ) / 1000;
+ const long wait_cycle_jiffies = msecs_to_jiffies(ISL38XX_WAIT_CYCLE * 10);
long timeout_left = ISL38XX_MAX_WAIT_CYCLES * wait_cycle_jiffies;
int err;
DEFINE_WAIT(wait);
@@ -475,8 +475,7 @@ islpci_mgt_transaction(struct net_device *ndev,
int timeleft;
struct islpci_mgmtframe *frame;
- set_current_state(TASK_UNINTERRUPTIBLE);
- timeleft = schedule_timeout(wait_cycle_jiffies);
+ timeleft = schedule_timeout_uninterruptible(wait_cycle_jiffies);
frame = xchg(&priv->mgmt_received, NULL);
if (frame) {
if (frame->header->oid == oid) {
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index e9c5ea0f5535da..70fd6fd8feb9bd 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -1649,28 +1649,28 @@ static iw_stats * ray_get_wireless_stats(struct net_device * dev)
*/
static const iw_handler ray_handler[] = {
- [SIOCSIWCOMMIT-SIOCIWFIRST] (iw_handler) ray_commit,
- [SIOCGIWNAME -SIOCIWFIRST] (iw_handler) ray_get_name,
- [SIOCSIWFREQ -SIOCIWFIRST] (iw_handler) ray_set_freq,
- [SIOCGIWFREQ -SIOCIWFIRST] (iw_handler) ray_get_freq,
- [SIOCSIWMODE -SIOCIWFIRST] (iw_handler) ray_set_mode,
- [SIOCGIWMODE -SIOCIWFIRST] (iw_handler) ray_get_mode,
- [SIOCGIWRANGE -SIOCIWFIRST] (iw_handler) ray_get_range,
+ [SIOCSIWCOMMIT-SIOCIWFIRST] = (iw_handler) ray_commit,
+ [SIOCGIWNAME -SIOCIWFIRST] = (iw_handler) ray_get_name,
+ [SIOCSIWFREQ -SIOCIWFIRST] = (iw_handler) ray_set_freq,
+ [SIOCGIWFREQ -SIOCIWFIRST] = (iw_handler) ray_get_freq,
+ [SIOCSIWMODE -SIOCIWFIRST] = (iw_handler) ray_set_mode,
+ [SIOCGIWMODE -SIOCIWFIRST] = (iw_handler) ray_get_mode,
+ [SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) ray_get_range,
#ifdef WIRELESS_SPY
- [SIOCSIWSPY -SIOCIWFIRST] (iw_handler) iw_handler_set_spy,
- [SIOCGIWSPY -SIOCIWFIRST] (iw_handler) iw_handler_get_spy,
- [SIOCSIWTHRSPY-SIOCIWFIRST] (iw_handler) iw_handler_set_thrspy,
- [SIOCGIWTHRSPY-SIOCIWFIRST] (iw_handler) iw_handler_get_thrspy,
+ [SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_set_spy,
+ [SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_get_spy,
+ [SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy,
+ [SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy,
#endif /* WIRELESS_SPY */
- [SIOCGIWAP -SIOCIWFIRST] (iw_handler) ray_get_wap,
- [SIOCSIWESSID -SIOCIWFIRST] (iw_handler) ray_set_essid,
- [SIOCGIWESSID -SIOCIWFIRST] (iw_handler) ray_get_essid,
- [SIOCSIWRATE -SIOCIWFIRST] (iw_handler) ray_set_rate,
- [SIOCGIWRATE -SIOCIWFIRST] (iw_handler) ray_get_rate,
- [SIOCSIWRTS -SIOCIWFIRST] (iw_handler) ray_set_rts,
- [SIOCGIWRTS -SIOCIWFIRST] (iw_handler) ray_get_rts,
- [SIOCSIWFRAG -SIOCIWFIRST] (iw_handler) ray_set_frag,
- [SIOCGIWFRAG -SIOCIWFIRST] (iw_handler) ray_get_frag,
+ [SIOCGIWAP -SIOCIWFIRST] = (iw_handler) ray_get_wap,
+ [SIOCSIWESSID -SIOCIWFIRST] = (iw_handler) ray_set_essid,
+ [SIOCGIWESSID -SIOCIWFIRST] = (iw_handler) ray_get_essid,
+ [SIOCSIWRATE -SIOCIWFIRST] = (iw_handler) ray_set_rate,
+ [SIOCGIWRATE -SIOCIWFIRST] = (iw_handler) ray_get_rate,
+ [SIOCSIWRTS -SIOCIWFIRST] = (iw_handler) ray_set_rts,
+ [SIOCGIWRTS -SIOCIWFIRST] = (iw_handler) ray_get_rts,
+ [SIOCSIWFRAG -SIOCIWFIRST] = (iw_handler) ray_set_frag,
+ [SIOCGIWFRAG -SIOCIWFIRST] = (iw_handler) ray_get_frag,
};
#define SIOCSIPFRAMING SIOCIWFIRSTPRIV /* Set framing mode */
@@ -1678,9 +1678,9 @@ static const iw_handler ray_handler[] = {
#define SIOCGIPCOUNTRY SIOCIWFIRSTPRIV + 3 /* Get country code */
static const iw_handler ray_private_handler[] = {
- [0] (iw_handler) ray_set_framing,
- [1] (iw_handler) ray_get_framing,
- [3] (iw_handler) ray_get_country,
+ [0] = (iw_handler) ray_set_framing,
+ [1] = (iw_handler) ray_get_framing,
+ [3] = (iw_handler) ray_get_country,
};
static const struct iw_priv_args ray_private_args[] = {
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index 39c6cdf7f3f736..b1bbc8e8e91f43 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -22,58 +22,23 @@
#define PFX DRIVER_NAME ": "
#include <linux/config.h>
-#ifdef __IN_PCMCIA_PACKAGE__
-#include <pcmcia/k_compat.h>
-#endif /* __IN_PCMCIA_PACKAGE__ */
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-
+#include <linux/delay.h>
+#include <linux/firmware.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
#include "orinoco.h"
-/*
- * If SPECTRUM_FW_INCLUDED is defined, the firmware is hardcoded into
- * the driver. Use get_symbol_fw script to generate spectrum_fw.h and
- * copy it to the same directory as spectrum_cs.c.
- *
- * If SPECTRUM_FW_INCLUDED is not defined, the firmware is loaded at the
- * runtime using hotplug. Use the same get_symbol_fw script to generate
- * files symbol_sp24t_prim_fw symbol_sp24t_sec_fw, copy them to the
- * hotplug firmware directory (typically /usr/lib/hotplug/firmware) and
- * make sure that you have hotplug installed and enabled in the kernel.
- */
-/* #define SPECTRUM_FW_INCLUDED 1 */
-
-#ifdef SPECTRUM_FW_INCLUDED
-/* Header with the firmware */
-#include "spectrum_fw.h"
-#else /* !SPECTRUM_FW_INCLUDED */
-#include <linux/firmware.h>
static unsigned char *primsym;
static unsigned char *secsym;
static const char primary_fw_name[] = "symbol_sp24t_prim_fw";
static const char secondary_fw_name[] = "symbol_sp24t_sec_fw";
-#endif /* !SPECTRUM_FW_INCLUDED */
/********************************************************************/
/* Module stuff */
@@ -124,17 +89,8 @@ static dev_link_t *dev_list; /* = NULL */
/* Function prototypes */
/********************************************************************/
-/* device methods */
-static int spectrum_cs_hard_reset(struct orinoco_private *priv);
-
-/* PCMCIA gumpf */
-static void spectrum_cs_config(dev_link_t * link);
-static void spectrum_cs_release(dev_link_t * link);
-static int spectrum_cs_event(event_t event, int priority,
- event_callback_args_t * args);
-
-static dev_link_t *spectrum_cs_attach(void);
-static void spectrum_cs_detach(dev_link_t *);
+static void spectrum_cs_release(dev_link_t *link);
+static void spectrum_cs_detach(dev_link_t *link);
/********************************************************************/
/* Firmware downloader */
@@ -182,8 +138,8 @@ static void spectrum_cs_detach(dev_link_t *);
* Each block has the following structure.
*/
struct dblock {
- u32 _addr; /* adapter address where to write the block */
- u16 _len; /* length of the data only, in bytes */
+ __le32 _addr; /* adapter address where to write the block */
+ __le16 _len; /* length of the data only, in bytes */
char data[0]; /* data to be written */
} __attribute__ ((packed));
@@ -193,9 +149,9 @@ struct dblock {
* items with matching ID should be written.
*/
struct pdr {
- u32 _id; /* record ID */
- u32 _addr; /* adapter address where to write the data */
- u32 _len; /* expected length of the data, in bytes */
+ __le32 _id; /* record ID */
+ __le32 _addr; /* adapter address where to write the data */
+ __le32 _len; /* expected length of the data, in bytes */
char next[0]; /* next PDR starts here */
} __attribute__ ((packed));
@@ -206,8 +162,8 @@ struct pdr {
* be plugged into the secondary firmware.
*/
struct pdi {
- u16 _len; /* length of ID and data, in words */
- u16 _id; /* record ID */
+ __le16 _len; /* length of ID and data, in words */
+ __le16 _id; /* record ID */
char data[0]; /* plug data */
} __attribute__ ((packed));;
@@ -414,7 +370,7 @@ spectrum_plug_pdi(hermes_t *hw, struct pdr *first_pdr, struct pdi *pdi)
/* Read PDA from the adapter */
static int
-spectrum_read_pda(hermes_t *hw, u16 *pda, int pda_len)
+spectrum_read_pda(hermes_t *hw, __le16 *pda, int pda_len)
{
int ret;
int pda_size;
@@ -445,7 +401,7 @@ spectrum_read_pda(hermes_t *hw, u16 *pda, int pda_len)
/* Parse PDA and write the records into the adapter */
static int
spectrum_apply_pda(hermes_t *hw, const struct dblock *first_block,
- u16 *pda)
+ __le16 *pda)
{
int ret;
struct pdi *pdi;
@@ -511,7 +467,7 @@ spectrum_dl_image(hermes_t *hw, dev_link_t *link,
const struct dblock *first_block;
/* Plug Data Area (PDA) */
- u16 pda[PDA_WORDS];
+ __le16 pda[PDA_WORDS];
/* Binary block begins after the 0x1A marker */
ptr = image;
@@ -571,8 +527,6 @@ spectrum_dl_firmware(hermes_t *hw, dev_link_t *link)
{
int ret;
client_handle_t handle = link->handle;
-
-#ifndef SPECTRUM_FW_INCLUDED
const struct firmware *fw_entry;
if (request_firmware(&fw_entry, primary_fw_name,
@@ -592,7 +546,6 @@ spectrum_dl_firmware(hermes_t *hw, dev_link_t *link)
secondary_fw_name);
return -ENOENT;
}
-#endif
/* Load primary firmware */
ret = spectrum_dl_image(hw, link, primsym);
@@ -1085,7 +1038,7 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
static struct pcmcia_device_id spectrum_cs_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4100 */
PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */
- PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0001), /* Intel PRO/Wireless 2011B */
+ PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless LAN PC Card", 0x816cc815, 0x6fbf459a), /* 2011B, not 2011 */
PCMCIA_DEVICE_NULL,
};
MODULE_DEVICE_TABLE(pcmcia, spectrum_cs_ids);
@@ -1096,8 +1049,8 @@ static struct pcmcia_driver orinoco_driver = {
.name = DRIVER_NAME,
},
.attach = spectrum_cs_attach,
- .event = spectrum_cs_event,
.detach = spectrum_cs_detach,
+ .event = spectrum_cs_event,
.id_table = spectrum_cs_ids,
};
diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
index 7a5e20a17890c8..b0d8b5b0315276 100644
--- a/drivers/net/wireless/wavelan.c
+++ b/drivers/net/wireless/wavelan.c
@@ -430,7 +430,6 @@ static void fee_read(unsigned long ioaddr, /* I/O port of the card */
}
}
-#ifdef WIRELESS_EXT /* if the wireless extension exists in the kernel */
/*------------------------------------------------------------------*/
/*
@@ -514,7 +513,6 @@ static void fee_write(unsigned long ioaddr, /* I/O port of the card */
fee_wait(ioaddr, 10, 100);
#endif /* EEPROM_IS_PROTECTED */
}
-#endif /* WIRELESS_EXT */
/************************ I82586 SUBROUTINES *************************/
/*
@@ -973,11 +971,9 @@ static void wv_mmc_show(struct net_device * dev)
mmc_read(ioaddr, 0, (u8 *) & m, sizeof(m));
mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
-#ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */
/* Don't forget to update statistics */
lp->wstats.discard.nwid +=
(m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
-#endif /* WIRELESS_EXT */
printk(KERN_DEBUG "##### WaveLAN modem status registers: #####\n");
#ifdef DEBUG_SHOW_UNUSED
@@ -1499,7 +1495,6 @@ static int wavelan_set_mac_address(struct net_device * dev, void *addr)
}
#endif /* SET_MAC_ADDRESS */
-#ifdef WIRELESS_EXT /* if wireless extensions exist in the kernel */
/*------------------------------------------------------------------*/
/*
@@ -2473,7 +2468,6 @@ static iw_stats *wavelan_get_wireless_stats(struct net_device * dev)
#endif
return &lp->wstats;
}
-#endif /* WIRELESS_EXT */
/************************* PACKET RECEPTION *************************/
/*
@@ -4194,11 +4188,9 @@ static int __init wavelan_config(struct net_device *dev, unsigned short ioaddr)
dev->set_mac_address = &wavelan_set_mac_address;
#endif /* SET_MAC_ADDRESS */
-#ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */
dev->wireless_handlers = &wavelan_handler_def;
lp->wireless_data.spy_data = &lp->spy_data;
dev->wireless_data = &lp->wireless_data;
-#endif
dev->mtu = WAVELAN_MTU;
diff --git a/drivers/net/wireless/wavelan.p.h b/drivers/net/wireless/wavelan.p.h
index 509ff22a6caa67..166e28b9a4f7fc 100644
--- a/drivers/net/wireless/wavelan.p.h
+++ b/drivers/net/wireless/wavelan.p.h
@@ -409,11 +409,9 @@
#define MULTICAST_AVOID /* Avoid extra multicast (I'm sceptical). */
#undef SET_MAC_ADDRESS /* Experimental */
-#ifdef WIRELESS_EXT /* If wireless extensions exist in the kernel */
/* Warning: this stuff will slow down the driver. */
#define WIRELESS_SPY /* Enable spying addresses. */
#undef HISTOGRAM /* Enable histogram of signal level. */
-#endif
/****************************** DEBUG ******************************/
@@ -506,12 +504,10 @@ struct net_local
u_short tx_first_free;
u_short tx_first_in_use;
-#ifdef WIRELESS_EXT
iw_stats wstats; /* Wireless-specific statistics */
struct iw_spy_data spy_data;
struct iw_public_data wireless_data;
-#endif
#ifdef HISTOGRAM
int his_number; /* number of intervals */
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 183c4732ef65ca..4b3c98f5c564fb 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -415,7 +415,6 @@ fee_read(u_long base, /* i/o port of the card */
}
}
-#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */
/*------------------------------------------------------------------*/
/*
@@ -500,7 +499,6 @@ fee_write(u_long base, /* i/o port of the card */
fee_wait(base, 10, 100);
#endif /* EEPROM_IS_PROTECTED */
}
-#endif /* WIRELESS_EXT */
/******************* WaveLAN Roaming routines... ********************/
@@ -1161,10 +1159,8 @@ wv_mmc_show(struct net_device * dev)
mmc_read(base, 0, (u_char *)&m, sizeof(m));
mmc_out(base, mmwoff(0, mmw_freeze), 0);
-#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */
/* Don't forget to update statistics */
lp->wstats.discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
-#endif /* WIRELESS_EXT */
spin_unlock_irqrestore(&lp->spinlock, flags);
@@ -1550,7 +1546,6 @@ wavelan_set_mac_address(struct net_device * dev,
}
#endif /* SET_MAC_ADDRESS */
-#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */
/*------------------------------------------------------------------*/
/*
@@ -2793,7 +2788,6 @@ wavelan_get_wireless_stats(struct net_device * dev)
#endif
return &lp->wstats;
}
-#endif /* WIRELESS_EXT */
/************************* PACKET RECEPTION *************************/
/*
@@ -4679,11 +4673,9 @@ wavelan_attach(void)
dev->watchdog_timeo = WATCHDOG_JIFFIES;
SET_ETHTOOL_OPS(dev, &ops);
-#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */
dev->wireless_handlers = &wavelan_handler_def;
lp->wireless_data.spy_data = &lp->spy_data;
dev->wireless_data = &lp->wireless_data;
-#endif
/* Other specific data */
dev->mtu = WAVELAN_MTU;
diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
index 01d882be8790c1..724a715089c996 100644
--- a/drivers/net/wireless/wavelan_cs.p.h
+++ b/drivers/net/wireless/wavelan_cs.p.h
@@ -472,11 +472,9 @@
#define MULTICAST_AVOID /* Avoid extra multicast (I'm sceptical) */
#undef SET_MAC_ADDRESS /* Experimental */
-#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */
/* Warning : these stuff will slow down the driver... */
#define WIRELESS_SPY /* Enable spying addresses */
#undef HISTOGRAM /* Enable histogram of sig level... */
-#endif
/****************************** DEBUG ******************************/
@@ -624,12 +622,10 @@ struct net_local
int rfp; /* Last DMA machine receive pointer */
int overrunning; /* Receiver overrun flag */
-#ifdef WIRELESS_EXT
iw_stats wstats; /* Wireless specific stats */
struct iw_spy_data spy_data;
struct iw_public_data wireless_data;
-#endif
#ifdef HISTOGRAM
int his_number; /* Number of intervals */
diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h
index 7fcbe589c3f2bf..4303c50c2ab619 100644
--- a/drivers/net/wireless/wl3501.h
+++ b/drivers/net/wireless/wl3501.h
@@ -548,7 +548,7 @@ struct wl3501_80211_tx_plcp_hdr {
struct wl3501_80211_tx_hdr {
struct wl3501_80211_tx_plcp_hdr pclp_hdr;
- struct ieee80211_hdr mac_hdr;
+ struct ieee80211_hdr_4addr mac_hdr;
} __attribute__ ((packed));
/*
diff --git a/drivers/parisc/asp.c b/drivers/parisc/asp.c
index 388609967133f4..558420bc9f8811 100644
--- a/drivers/parisc/asp.c
+++ b/drivers/parisc/asp.c
@@ -77,12 +77,12 @@ asp_init_chip(struct parisc_device *dev)
struct gsc_irq gsc_irq;
int ret;
- asp.version = gsc_readb(dev->hpa + ASP_VER_OFFSET) & 0xf;
+ asp.version = gsc_readb(dev->hpa.start + ASP_VER_OFFSET) & 0xf;
asp.name = (asp.version == 1) ? "Asp" : "Cutoff";
asp.hpa = ASP_INTERRUPT_ADDR;
printk(KERN_INFO "%s version %d at 0x%lx found.\n",
- asp.name, asp.version, dev->hpa);
+ asp.name, asp.version, dev->hpa.start);
/* the IRQ ASP should use */
ret = -EBUSY;
@@ -126,7 +126,7 @@ static struct parisc_device_id asp_tbl[] = {
};
struct parisc_driver asp_driver = {
- .name = "Asp",
+ .name = "asp",
.id_table = asp_tbl,
.probe = asp_init_chip,
};
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index 0e98a9d9834cb5..9e0229f7e25fbe 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -100,9 +100,9 @@
#define DBG_RUN_SG(x...)
#endif
-#define CCIO_INLINE /* inline */
-#define WRITE_U32(value, addr) gsc_writel(value, (u32 *)(addr))
-#define READ_U32(addr) gsc_readl((u32 *)(addr))
+#define CCIO_INLINE inline
+#define WRITE_U32(value, addr) __raw_writel(value, addr)
+#define READ_U32(addr) __raw_readl(addr)
#define U2_IOA_RUNWAY 0x580
#define U2_BC_GSC 0x501
@@ -115,28 +115,28 @@
struct ioa_registers {
/* Runway Supervisory Set */
- volatile int32_t unused1[12];
- volatile uint32_t io_command; /* Offset 12 */
- volatile uint32_t io_status; /* Offset 13 */
- volatile uint32_t io_control; /* Offset 14 */
- volatile int32_t unused2[1];
+ int32_t unused1[12];
+ uint32_t io_command; /* Offset 12 */
+ uint32_t io_status; /* Offset 13 */
+ uint32_t io_control; /* Offset 14 */
+ int32_t unused2[1];
/* Runway Auxiliary Register Set */
- volatile uint32_t io_err_resp; /* Offset 0 */
- volatile uint32_t io_err_info; /* Offset 1 */
- volatile uint32_t io_err_req; /* Offset 2 */
- volatile uint32_t io_err_resp_hi; /* Offset 3 */
- volatile uint32_t io_tlb_entry_m; /* Offset 4 */
- volatile uint32_t io_tlb_entry_l; /* Offset 5 */
- volatile uint32_t unused3[1];
- volatile uint32_t io_pdir_base; /* Offset 7 */
- volatile uint32_t io_io_low_hv; /* Offset 8 */
- volatile uint32_t io_io_high_hv; /* Offset 9 */
- volatile uint32_t unused4[1];
- volatile uint32_t io_chain_id_mask; /* Offset 11 */
- volatile uint32_t unused5[2];
- volatile uint32_t io_io_low; /* Offset 14 */
- volatile uint32_t io_io_high; /* Offset 15 */
+ uint32_t io_err_resp; /* Offset 0 */
+ uint32_t io_err_info; /* Offset 1 */
+ uint32_t io_err_req; /* Offset 2 */
+ uint32_t io_err_resp_hi; /* Offset 3 */
+ uint32_t io_tlb_entry_m; /* Offset 4 */
+ uint32_t io_tlb_entry_l; /* Offset 5 */
+ uint32_t unused3[1];
+ uint32_t io_pdir_base; /* Offset 7 */
+ uint32_t io_io_low_hv; /* Offset 8 */
+ uint32_t io_io_high_hv; /* Offset 9 */
+ uint32_t unused4[1];
+ uint32_t io_chain_id_mask; /* Offset 11 */
+ uint32_t unused5[2];
+ uint32_t io_io_low; /* Offset 14 */
+ uint32_t io_io_high; /* Offset 15 */
};
/*
@@ -226,7 +226,7 @@ struct ioa_registers {
*/
struct ioc {
- struct ioa_registers *ioc_hpa; /* I/O MMU base address */
+ struct ioa_registers __iomem *ioc_regs; /* I/O MMU base address */
u8 *res_map; /* resource map, bit == pdir entry */
u64 *pdir_base; /* physical base address */
u32 pdir_size; /* bytes, function of IOV Space size */
@@ -595,7 +595,7 @@ ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
** Grab virtual index [0:11]
** Deposit virt_idx bits into I/O PDIR word
*/
- asm volatile ("lci 0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba));
+ asm volatile ("lci %%r0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba));
asm volatile ("extru %1,19,12,%0" : "+r" (ci) : "r" (ci));
asm volatile ("depw %1,15,12,%0" : "+r" (pa) : "r" (ci));
@@ -613,7 +613,7 @@ ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
** the real mode coherence index generation of U2, the PDIR entry
** must be flushed to memory to retain coherence."
*/
- asm volatile("fdc 0(%0)" : : "r" (pdir_ptr));
+ asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr));
asm volatile("sync");
}
@@ -636,7 +636,7 @@ ccio_clear_io_tlb(struct ioc *ioc, dma_addr_t iovp, size_t byte_cnt)
byte_cnt += chain_size;
while(byte_cnt > chain_size) {
- WRITE_U32(CMD_TLB_PURGE | iovp, &ioc->ioc_hpa->io_command);
+ WRITE_U32(CMD_TLB_PURGE | iovp, &ioc->ioc_regs->io_command);
iovp += chain_size;
byte_cnt -= chain_size;
}
@@ -684,7 +684,7 @@ ccio_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
** Hopefully someone figures out how to patch (NOP) the
** FDC/SYNC out at boot time.
*/
- asm volatile("fdc 0(%0)" : : "r" (pdir_ptr[7]));
+ asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr[7]));
iovp += IOVP_SIZE;
byte_cnt -= IOVP_SIZE;
@@ -836,7 +836,7 @@ ccio_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
* This function implements the pci_alloc_consistent function.
*/
static void *
-ccio_alloc_consistent(struct device *dev, size_t size, dma_addr_t *dma_handle, int flag)
+ccio_alloc_consistent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag)
{
void *ret;
#if 0
@@ -1251,7 +1251,7 @@ static struct parisc_device_id ccio_tbl[] = {
static int ccio_probe(struct parisc_device *dev);
static struct parisc_driver ccio_driver = {
- .name = "U2:Uturn",
+ .name = "ccio",
.id_table = ccio_tbl,
.probe = ccio_probe,
};
@@ -1314,14 +1314,13 @@ ccio_ioc_init(struct ioc *ioc)
ioc->pdir_size = (iova_space_size / IOVP_SIZE) * sizeof(u64);
- BUG_ON(ioc->pdir_size >= 4 * 1024 * 1024); /* max pdir size < 4MB */
+ BUG_ON(ioc->pdir_size > 8 * 1024 * 1024); /* max pdir size <= 8MB */
/* Verify it's a power of two */
BUG_ON((1 << get_order(ioc->pdir_size)) != (ioc->pdir_size >> PAGE_SHIFT));
- DBG_INIT("%s() hpa 0x%lx mem %luMB IOV %dMB (%d bits)\n",
- __FUNCTION__,
- ioc->ioc_hpa,
+ DBG_INIT("%s() hpa 0x%p mem %luMB IOV %dMB (%d bits)\n",
+ __FUNCTION__, ioc->ioc_regs,
(unsigned long) num_physpages >> (20 - PAGE_SHIFT),
iova_space_size>>20,
iov_order + PAGE_SHIFT);
@@ -1329,13 +1328,12 @@ ccio_ioc_init(struct ioc *ioc)
ioc->pdir_base = (u64 *)__get_free_pages(GFP_KERNEL,
get_order(ioc->pdir_size));
if(NULL == ioc->pdir_base) {
- panic("%s:%s() could not allocate I/O Page Table\n", __FILE__,
- __FUNCTION__);
+ panic("%s() could not allocate I/O Page Table\n", __FUNCTION__);
}
memset(ioc->pdir_base, 0, ioc->pdir_size);
BUG_ON((((unsigned long)ioc->pdir_base) & PAGE_MASK) != (unsigned long)ioc->pdir_base);
- DBG_INIT(" base %p", ioc->pdir_base);
+ DBG_INIT(" base %p\n", ioc->pdir_base);
/* resource map size dictated by pdir_size */
ioc->res_size = (ioc->pdir_size / sizeof(u64)) >> 3;
@@ -1344,8 +1342,7 @@ ccio_ioc_init(struct ioc *ioc)
ioc->res_map = (u8 *)__get_free_pages(GFP_KERNEL,
get_order(ioc->res_size));
if(NULL == ioc->res_map) {
- panic("%s:%s() could not allocate resource map\n", __FILE__,
- __FUNCTION__);
+ panic("%s() could not allocate resource map\n", __FUNCTION__);
}
memset(ioc->res_map, 0, ioc->res_size);
@@ -1366,44 +1363,58 @@ ccio_ioc_init(struct ioc *ioc)
** Initialize IOA hardware
*/
WRITE_U32(CCIO_CHAINID_MASK << ioc->chainid_shift,
- &ioc->ioc_hpa->io_chain_id_mask);
+ &ioc->ioc_regs->io_chain_id_mask);
WRITE_U32(virt_to_phys(ioc->pdir_base),
- &ioc->ioc_hpa->io_pdir_base);
+ &ioc->ioc_regs->io_pdir_base);
/*
** Go to "Virtual Mode"
*/
- WRITE_U32(IOA_NORMAL_MODE, &ioc->ioc_hpa->io_control);
+ WRITE_U32(IOA_NORMAL_MODE, &ioc->ioc_regs->io_control);
/*
** Initialize all I/O TLB entries to 0 (Valid bit off).
*/
- WRITE_U32(0, &ioc->ioc_hpa->io_tlb_entry_m);
- WRITE_U32(0, &ioc->ioc_hpa->io_tlb_entry_l);
+ WRITE_U32(0, &ioc->ioc_regs->io_tlb_entry_m);
+ WRITE_U32(0, &ioc->ioc_regs->io_tlb_entry_l);
for(i = 1 << CCIO_CHAINID_SHIFT; i ; i--) {
WRITE_U32((CMD_TLB_DIRECT_WRITE | (i << ioc->chainid_shift)),
- &ioc->ioc_hpa->io_command);
+ &ioc->ioc_regs->io_command);
}
}
static void
-ccio_init_resource(struct resource *res, char *name, unsigned long ioaddr)
+ccio_init_resource(struct resource *res, char *name, void __iomem *ioaddr)
{
int result;
res->parent = NULL;
res->flags = IORESOURCE_MEM;
- res->start = (unsigned long)(signed) __raw_readl(ioaddr) << 16;
- res->end = (unsigned long)(signed) (__raw_readl(ioaddr + 4) << 16) - 1;
+ /*
+ * bracing ((signed) ...) are required for 64bit kernel because
+ * we only want to sign extend the lower 16 bits of the register.
+ * The upper 16-bits of range registers are hardcoded to 0xffff.
+ */
+ res->start = (unsigned long)((signed) READ_U32(ioaddr) << 16);
+ res->end = (unsigned long)((signed) (READ_U32(ioaddr + 4) << 16) - 1);
res->name = name;
+ /*
+ * Check if this MMIO range is disable
+ */
if (res->end + 1 == res->start)
return;
- result = request_resource(&iomem_resource, res);
+
+ /* On some platforms (e.g. K-Class), we have already registered
+ * resources for devices reported by firmware. Some are children
+ * of ccio.
+ * "insert" ccio ranges in the mmio hierarchy (/proc/iomem).
+ */
+ result = insert_resource(&iomem_resource, res);
if (result < 0) {
- printk(KERN_ERR "%s: failed to claim CCIO bus address space (%08lx,%08lx)\n",
- __FILE__, res->start, res->end);
+ printk(KERN_ERR "%s() failed to claim CCIO bus address space (%08lx,%08lx)\n",
+ __FUNCTION__, res->start, res->end);
}
}
@@ -1414,9 +1425,8 @@ static void __init ccio_init_resources(struct ioc *ioc)
sprintf(name, "GSC Bus [%d/]", ioc->hw_path);
- ccio_init_resource(res, name, (unsigned long)&ioc->ioc_hpa->io_io_low);
- ccio_init_resource(res + 1, name,
- (unsigned long)&ioc->ioc_hpa->io_io_low_hv);
+ ccio_init_resource(res, name, &ioc->ioc_regs->io_io_low);
+ ccio_init_resource(res + 1, name, &ioc->ioc_regs->io_io_low_hv);
}
static int new_ioc_area(struct resource *res, unsigned long size,
@@ -1427,7 +1437,12 @@ static int new_ioc_area(struct resource *res, unsigned long size,
res->start = (max - size + 1) &~ (align - 1);
res->end = res->start + size;
- if (!request_resource(&iomem_resource, res))
+
+ /* We might be trying to expand the MMIO range to include
+ * a child device that has already registered it's MMIO space.
+ * Use "insert" instead of request_resource().
+ */
+ if (!insert_resource(&iomem_resource, res))
return 0;
return new_ioc_area(res, size, min, max - size, align);
@@ -1486,15 +1501,15 @@ int ccio_allocate_resource(const struct parisc_device *dev,
if (!expand_ioc_area(parent, size, min, max, align)) {
__raw_writel(((parent->start)>>16) | 0xffff0000,
- (unsigned long)&(ioc->ioc_hpa->io_io_low));
+ &ioc->ioc_regs->io_io_low);
__raw_writel(((parent->end)>>16) | 0xffff0000,
- (unsigned long)&(ioc->ioc_hpa->io_io_high));
+ &ioc->ioc_regs->io_io_high);
} else if (!expand_ioc_area(parent + 1, size, min, max, align)) {
parent++;
__raw_writel(((parent->start)>>16) | 0xffff0000,
- (unsigned long)&(ioc->ioc_hpa->io_io_low_hv));
+ &ioc->ioc_regs->io_io_low_hv);
__raw_writel(((parent->end)>>16) | 0xffff0000,
- (unsigned long)&(ioc->ioc_hpa->io_io_high_hv));
+ &ioc->ioc_regs->io_io_high_hv);
} else {
return -EBUSY;
}
@@ -1521,7 +1536,12 @@ int ccio_request_resource(const struct parisc_device *dev,
return -EBUSY;
}
- return request_resource(parent, res);
+ /* "transparent" bus bridges need to register MMIO resources
+ * firmware assigned them. e.g. children of hppb.c (e.g. K-class)
+ * registered their resources in the PDC "bus walk" (See
+ * arch/parisc/kernel/inventory.c).
+ */
+ return insert_resource(parent, res);
}
/**
@@ -1546,7 +1566,7 @@ static int ccio_probe(struct parisc_device *dev)
ioc->name = dev->id.hversion == U2_IOA_RUNWAY ? "U2" : "UTurn";
- printk(KERN_INFO "Found %s at 0x%lx\n", ioc->name, dev->hpa);
+ printk(KERN_INFO "Found %s at 0x%lx\n", ioc->name, dev->hpa.start);
for (i = 0; i < ioc_count; i++) {
ioc_p = &(*ioc_p)->next;
@@ -1554,7 +1574,7 @@ static int ccio_probe(struct parisc_device *dev)
*ioc_p = ioc;
ioc->hw_path = dev->hw_path;
- ioc->ioc_hpa = (struct ioa_registers *)dev->hpa;
+ ioc->ioc_regs = ioremap(dev->hpa.start, 4096);
ccio_ioc_init(ioc);
ccio_init_resources(ioc);
hppa_dma_ops = &ccio_ops;
diff --git a/drivers/parisc/ccio-rm-dma.c b/drivers/parisc/ccio-rm-dma.c
index 57e6385976e2b1..356b8357bcccef 100644
--- a/drivers/parisc/ccio-rm-dma.c
+++ b/drivers/parisc/ccio-rm-dma.c
@@ -167,7 +167,7 @@ ccio_probe(struct parisc_device *dev)
{
printk(KERN_INFO "%s found %s at 0x%lx\n", MODULE_NAME,
dev->id.hversion == U2_BC_GSC ? "U2" : "UTurn",
- dev->hpa);
+ dev->hpa.start);
/*
** FIXME - should check U2 registers to verify it's really running
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 2f2dbef2c3b7bf..5ab75334c57968 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -178,6 +178,8 @@ static int dino_cfg_read(struct pci_bus *bus, unsigned int devfn, int where,
void __iomem *base_addr = d->hba.base_addr;
unsigned long flags;
+ DBG("%s: %p, %d, %d, %d\n", __FUNCTION__, base_addr, devfn, where,
+ size);
spin_lock_irqsave(&d->dinosaur_pen, flags);
/* tell HW which CFG address */
@@ -211,6 +213,8 @@ static int dino_cfg_write(struct pci_bus *bus, unsigned int devfn, int where,
void __iomem *base_addr = d->hba.base_addr;
unsigned long flags;
+ DBG("%s: %p, %d, %d, %d\n", __FUNCTION__, base_addr, devfn, where,
+ size);
spin_lock_irqsave(&d->dinosaur_pen, flags);
/* avoid address stepping feature */
@@ -295,7 +299,7 @@ static void dino_disable_irq(unsigned int irq)
struct dino_device *dino_dev = irq_desc[irq].handler_data;
int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, irq);
- DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, irq_dev, irq);
+ DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq);
/* Clear the matching bit in the IMR register */
dino_dev->imr &= ~(DINO_MASK_IRQ(local_irq));
@@ -308,7 +312,7 @@ static void dino_enable_irq(unsigned int irq)
int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, irq);
u32 tmp;
- DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, irq_dev, irq);
+ DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq);
/*
** clear pending IRQ bits
@@ -490,7 +494,7 @@ dino_card_setup(struct pci_bus *bus, void __iomem *base_addr)
if (res->start == F_EXTEND(0xf0000000UL | (i * _8MB)))
break;
}
- DBG("DINO GSC WRITE i=%d, start=%lx, dino addr = %lx\n",
+ DBG("DINO GSC WRITE i=%d, start=%lx, dino addr = %p\n",
i, res->start, base_addr + DINO_IO_ADDR_EN);
__raw_writel(1 << i, base_addr + DINO_IO_ADDR_EN);
}
@@ -683,6 +687,14 @@ static void __init
dino_card_init(struct dino_device *dino_dev)
{
u32 brdg_feat = 0x00784e05;
+ unsigned long status;
+
+ status = __raw_readl(dino_dev->hba.base_addr+DINO_IO_STATUS);
+ if (status & 0x0000ff80) {
+ __raw_writel(0x00000005,
+ dino_dev->hba.base_addr+DINO_IO_COMMAND);
+ udelay(1);
+ }
__raw_writel(0x00000000, dino_dev->hba.base_addr+DINO_GMASK);
__raw_writel(0x00000001, dino_dev->hba.base_addr+DINO_IO_FBB_EN);
@@ -902,15 +914,15 @@ void ccio_cujo20_fixup(struct parisc_device *dev, u32 iovp);
** If so, initialize the chip appropriately (card-mode vs bridge mode).
** Much of the initialization is common though.
*/
-static int __init
-dino_driver_callback(struct parisc_device *dev)
+static int __init dino_probe(struct parisc_device *dev)
{
struct dino_device *dino_dev; // Dino specific control struct
const char *version = "unknown";
char *name;
int is_cujo = 0;
struct pci_bus *bus;
-
+ unsigned long hpa = dev->hpa.start;
+
name = "Dino";
if (is_card_dino(&dev->id)) {
version = "3.x (card mode)";
@@ -928,11 +940,11 @@ dino_driver_callback(struct parisc_device *dev)
}
}
- printk("%s version %s found at 0x%lx\n", name, version, dev->hpa);
+ printk("%s version %s found at 0x%lx\n", name, version, hpa);
- if (!request_mem_region(dev->hpa, PAGE_SIZE, name)) {
+ if (!request_mem_region(hpa, PAGE_SIZE, name)) {
printk(KERN_ERR "DINO: Hey! Someone took my MMIO space (0x%ld)!\n",
- dev->hpa);
+ hpa);
return 1;
}
@@ -940,12 +952,12 @@ dino_driver_callback(struct parisc_device *dev)
if (is_cujo && dev->id.hversion_rev == 1) {
#ifdef CONFIG_IOMMU_CCIO
printk(KERN_WARNING "Enabling Cujo 2.0 bug workaround\n");
- if (dev->hpa == (unsigned long)CUJO_RAVEN_ADDR) {
+ if (hpa == (unsigned long)CUJO_RAVEN_ADDR) {
ccio_cujo20_fixup(dev, CUJO_RAVEN_BADPAGE);
- } else if (dev->hpa == (unsigned long)CUJO_FIREHAWK_ADDR) {
+ } else if (hpa == (unsigned long)CUJO_FIREHAWK_ADDR) {
ccio_cujo20_fixup(dev, CUJO_FIREHAWK_BADPAGE);
} else {
- printk("Don't recognise Cujo at address 0x%lx, not enabling workaround\n", dev->hpa);
+ printk("Don't recognise Cujo at address 0x%lx, not enabling workaround\n", hpa);
}
#endif
} else if (!is_cujo && !is_card_dino(&dev->id) &&
@@ -970,7 +982,7 @@ dino_driver_callback(struct parisc_device *dev)
memset(dino_dev, 0, sizeof(struct dino_device));
dino_dev->hba.dev = dev;
- dino_dev->hba.base_addr = ioremap(dev->hpa, 4096); /* faster access */
+ dino_dev->hba.base_addr = ioremap(hpa, 4096);
dino_dev->hba.lmmio_space_offset = 0; /* CPU addrs == bus addrs */
spin_lock_init(&dino_dev->dinosaur_pen);
dino_dev->hba.iommu = ccio_get_iommu(dev);
@@ -1027,9 +1039,9 @@ static struct parisc_device_id dino_tbl[] = {
};
static struct parisc_driver dino_driver = {
- .name = "Dino",
+ .name = "dino",
.id_table = dino_tbl,
- .probe = dino_driver_callback,
+ .probe = dino_probe,
};
/*
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index 043d47aea75b6a..6362bf99eff6e3 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -315,7 +315,7 @@ static int __devinit eisa_probe(struct parisc_device *dev)
char *name = is_mongoose(dev) ? "Mongoose" : "Wax";
printk(KERN_INFO "%s EISA Adapter found at 0x%08lx\n",
- name, dev->hpa);
+ name, dev->hpa.start);
eisa_dev.hba.dev = dev;
eisa_dev.hba.iommu = ccio_get_iommu(dev);
@@ -397,7 +397,7 @@ static struct parisc_device_id eisa_tbl[] = {
MODULE_DEVICE_TABLE(parisc, eisa_tbl);
static struct parisc_driver eisa_driver = {
- .name = "EISA Bus Adapter",
+ .name = "eisa_ba",
.id_table = eisa_tbl,
.probe = eisa_probe,
};
diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c
index af5e02526a18df..16d40f95978d13 100644
--- a/drivers/parisc/gsc.c
+++ b/drivers/parisc/gsc.c
@@ -183,12 +183,20 @@ void gsc_asic_assign_irq(struct gsc_asic *asic, int local_irq, int *irqp)
*irqp = irq;
}
+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;
+}
+
void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl,
void (*choose_irq)(struct parisc_device *, void *))
{
struct device *dev;
+ struct klist_iter i;
- list_for_each_entry(dev, &parent->dev.children, node) {
+ klist_iter_init(&parent->dev.klist_children, &i);
+ while ((dev = next_device(&i))) {
struct parisc_device *padev = to_parisc_device(dev);
/* work-around for 715/64 and others which have parent
@@ -197,6 +205,7 @@ void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl,
return gsc_fixup_irqs(padev, ctrl, choose_irq);
choose_irq(padev, ctrl);
}
+ klist_iter_exit(&i);
}
int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic)
diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c
index e869c6020370a7..5edf93f8075762 100644
--- a/drivers/parisc/hppb.c
+++ b/drivers/parisc/hppb.c
@@ -68,14 +68,14 @@ static int hppb_probe(struct parisc_device *dev)
memset(card->next, '\0', sizeof(struct hppb_card));
card = card->next;
}
- printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa);
+ printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa.start);
- card->hpa = dev->hpa;
+ card->hpa = dev->hpa.start;
card->mmio_region.name = "HP-PB Bus";
card->mmio_region.flags = IORESOURCE_MEM;
- card->mmio_region.start = __raw_readl(dev->hpa + IO_IO_LOW);
- card->mmio_region.end = __raw_readl(dev->hpa + IO_IO_HIGH) - 1;
+ card->mmio_region.start = gsc_readl(dev->hpa.start + IO_IO_LOW);
+ card->mmio_region.end = gsc_readl(dev->hpa.start + IO_IO_HIGH) - 1;
status = ccio_request_resource(dev, &card->mmio_region);
if(status < 0) {
@@ -93,7 +93,7 @@ static struct parisc_device_id hppb_tbl[] = {
};
static struct parisc_driver hppb_driver = {
- .name = "Gecko Boa",
+ .name = "gecko_boa",
.id_table = hppb_tbl,
.probe = hppb_probe,
};
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 7a57c1b8373f04..a39fbfef789a9a 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -244,7 +244,7 @@ static struct irt_entry *iosapic_alloc_irt(int num_entries)
* 4-byte alignment on 32-bit kernels
*/
a = (unsigned long)kmalloc(sizeof(struct irt_entry) * num_entries + 8, GFP_KERNEL);
- a = (a + 7) & ~7;
+ a = (a + 7UL) & ~7UL;
return (struct irt_entry *)a;
}
diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c
index cb84a4e84a2fd5..a8c20396ffbe68 100644
--- a/drivers/parisc/lasi.c
+++ b/drivers/parisc/lasi.c
@@ -175,7 +175,7 @@ lasi_init_chip(struct parisc_device *dev)
return -ENOMEM;
lasi->name = "Lasi";
- lasi->hpa = dev->hpa;
+ lasi->hpa = dev->hpa.start;
/* Check the 4-bit (yes, only 4) version register */
lasi->version = gsc_readl(lasi->hpa + LASI_VER) & 0xf;
@@ -233,7 +233,7 @@ static struct parisc_device_id lasi_tbl[] = {
};
struct parisc_driver lasi_driver = {
- .name = "Lasi",
+ .name = "lasi",
.id_table = lasi_tbl,
.probe = lasi_init_chip,
};
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index 7fdd80b7eb479b..5e495dcbc58a5c 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -1288,7 +1288,7 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
** Adjust "window" for this rope.
*/
rsize /= ROPES_PER_IOC;
- r->start += (rsize + 1) * LBA_NUM(pa_dev->hpa);
+ r->start += (rsize + 1) * LBA_NUM(pa_dev->hpa.start);
r->end = r->start + rsize;
} else {
r->end = r->start = 0; /* Not enabled. */
@@ -1458,7 +1458,7 @@ lba_driver_probe(struct parisc_device *dev)
u32 func_class;
void *tmp_obj;
char *version;
- void __iomem *addr = ioremap(dev->hpa, 4096);
+ void __iomem *addr = ioremap(dev->hpa.start, 4096);
/* Read HW Rev First */
func_class = READ_REG32(addr + LBA_FCLASS);
@@ -1476,7 +1476,7 @@ lba_driver_probe(struct parisc_device *dev)
}
printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n",
- MODULE_NAME, version, func_class & 0xf, dev->hpa);
+ MODULE_NAME, version, func_class & 0xf, dev->hpa.start);
if (func_class < 2) {
printk(KERN_WARNING "Can't support LBA older than "
@@ -1503,17 +1503,17 @@ lba_driver_probe(struct parisc_device *dev)
* but for the mask for func_class.
*/
printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n",
- MODULE_NAME, version, func_class & 0xff, dev->hpa);
+ MODULE_NAME, version, func_class & 0xff, dev->hpa.start);
cfg_ops = &mercury_cfg_ops;
} else {
- printk(KERN_ERR "Unknown LBA found at 0x%lx\n", dev->hpa);
+ printk(KERN_ERR "Unknown LBA found at 0x%lx\n", dev->hpa.start);
return -ENODEV;
}
/*
** Tell I/O SAPIC driver we have a IRQ handler/region.
*/
- tmp_obj = iosapic_register(dev->hpa + LBA_IOSAPIC_BASE);
+ tmp_obj = iosapic_register(dev->hpa.start + LBA_IOSAPIC_BASE);
/* NOTE: PCI devices (e.g. 103c:1005 graphics card) which don't
** have an IRT entry will get NULL back from iosapic code.
@@ -1635,7 +1635,7 @@ void __init lba_init(void)
*/
void lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask)
{
- void __iomem * base_addr = ioremap(lba->hpa, 4096);
+ void __iomem * base_addr = ioremap(lba->hpa.start, 4096);
imask <<= 2; /* adjust for hints - 2 more bits */
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 286902298e3361..95bd07b8b61b6b 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -18,6 +18,9 @@
* Changes:
* - Audit copy_from_user in led_proc_write.
* Daniele Bellucci <bellucda@tiscali.it>
+ * - Switch from using a tasklet to a work queue, so the led_LCD_driver
+ * can sleep.
+ * David Pye <dmp@davidmpye.dyndns.org>
*/
#include <linux/config.h>
@@ -37,6 +40,7 @@
#include <linux/proc_fs.h>
#include <linux/ctype.h>
#include <linux/blkdev.h>
+#include <linux/workqueue.h>
#include <linux/rcupdate.h>
#include <asm/io.h>
#include <asm/processor.h>
@@ -47,25 +51,30 @@
#include <asm/uaccess.h>
/* The control of the LEDs and LCDs on PARISC-machines have to be done
- completely in software. The necessary calculations are done in a tasklet
- which is scheduled at every timer interrupt and since the calculations
- may consume relatively much CPU-time some of the calculations can be
+ completely in software. The necessary calculations are done in a work queue
+ task which is scheduled regularly, and since the calculations may consume a
+ relatively large amount of CPU time, some of the calculations can be
turned off with the following variables (controlled via procfs) */
static int led_type = -1;
-static int led_heartbeat = 1;
-static int led_diskio = 1;
-static int led_lanrxtx = 1;
+static unsigned char lastleds; /* LED state from most recent update */
+static unsigned int led_heartbeat = 1;
+static unsigned int led_diskio = 1;
+static unsigned int led_lanrxtx = 1;
static char lcd_text[32];
static char lcd_text_default[32];
+
+static struct workqueue_struct *led_wq;
+static void led_work_func(void *);
+static DECLARE_WORK(led_task, led_work_func, NULL);
+
#if 0
#define DPRINTK(x) printk x
#else
#define DPRINTK(x)
#endif
-
struct lcd_block {
unsigned char command; /* stores the command byte */
unsigned char on; /* value for turning LED on */
@@ -116,12 +125,27 @@ lcd_info __attribute__((aligned(8))) =
#define LCD_DATA_REG lcd_info.lcd_data_reg_addr
#define LED_DATA_REG lcd_info.lcd_cmd_reg_addr /* LASI & ASP only */
+#define LED_HASLCD 1
+#define LED_NOLCD 0
+
+/* The workqueue must be created at init-time */
+static int start_task(void)
+{
+ /* Display the default text now */
+ if (led_type == LED_HASLCD) lcd_print( lcd_text_default );
+
+ /* Create the work queue and queue the LED task */
+ led_wq = create_singlethread_workqueue("led_wq");
+ queue_work(led_wq, &led_task);
+
+ return 0;
+}
+
+device_initcall(start_task);
/* ptr to LCD/LED-specific function */
static void (*led_func_ptr) (unsigned char);
-#define LED_HASLCD 1
-#define LED_NOLCD 0
#ifdef CONFIG_PROC_FS
static int led_proc_read(char *page, char **start, off_t off, int count,
int *eof, void *data)
@@ -286,52 +310,35 @@ static void led_LASI_driver(unsigned char leds)
/*
**
** led_LCD_driver()
- **
- ** The logic of the LCD driver is, that we write at every scheduled call
- ** only to one of LCD_CMD_REG _or_ LCD_DATA_REG - registers.
- ** That way we don't need to let this tasklet busywait for min_cmd_delay
- ** milliseconds.
- **
- ** TODO: check the value of "min_cmd_delay" against the value of HZ.
**
*/
static void led_LCD_driver(unsigned char leds)
{
- static int last_index; /* 0:heartbeat, 1:disk, 2:lan_in, 3:lan_out */
- static int last_was_cmd;/* 0: CMD was written last, 1: DATA was last */
- struct lcd_block *block_ptr;
- int value;
-
- switch (last_index) {
- case 0: block_ptr = &lcd_info.heartbeat;
- value = leds & LED_HEARTBEAT;
- break;
- case 1: block_ptr = &lcd_info.disk_io;
- value = leds & LED_DISK_IO;
- break;
- case 2: block_ptr = &lcd_info.lan_rcv;
- value = leds & LED_LAN_RCV;
- break;
- case 3: block_ptr = &lcd_info.lan_tx;
- value = leds & LED_LAN_TX;
- break;
- default: /* should never happen: */
- return;
- }
-
- if (last_was_cmd) {
- /* write the value to the LCD data port */
- gsc_writeb( value ? block_ptr->on : block_ptr->off, LCD_DATA_REG );
- } else {
- /* write the command-byte to the LCD command register */
- gsc_writeb( block_ptr->command, LCD_CMD_REG );
- }
+ static int i;
+ static unsigned char mask[4] = { LED_HEARTBEAT, LED_DISK_IO,
+ LED_LAN_RCV, LED_LAN_TX };
- /* now update the vars for the next interrupt iteration */
- if (++last_was_cmd == 2) { /* switch between cmd & data */
- last_was_cmd = 0;
- if (++last_index == 4)
- last_index = 0; /* switch back to heartbeat index */
+ static struct lcd_block * blockp[4] = {
+ &lcd_info.heartbeat,
+ &lcd_info.disk_io,
+ &lcd_info.lan_rcv,
+ &lcd_info.lan_tx
+ };
+
+ /* Convert min_cmd_delay to milliseconds */
+ unsigned int msec_cmd_delay = 1 + (lcd_info.min_cmd_delay / 1000);
+
+ for (i=0; i<4; ++i)
+ {
+ if ((leds & mask[i]) != (lastleds & mask[i]))
+ {
+ gsc_writeb( blockp[i]->command, LCD_CMD_REG );
+ msleep(msec_cmd_delay);
+
+ gsc_writeb( leds & mask[i] ? blockp[i]->on :
+ blockp[i]->off, LCD_DATA_REG );
+ msleep(msec_cmd_delay);
+ }
}
}
@@ -356,7 +363,7 @@ static __inline__ int led_get_net_activity(void)
rx_total = tx_total = 0;
- /* we are running as tasklet, so locking dev_base
+ /* we are running as a workqueue task, so locking dev_base
* for reading should be OK */
read_lock(&dev_base_lock);
rcu_read_lock();
@@ -405,7 +412,7 @@ static __inline__ int led_get_diskio_activity(void)
static unsigned long last_pgpgin, last_pgpgout;
struct page_state pgstat;
int changed;
-
+
get_full_page_state(&pgstat); /* get no of sectors in & out */
/* Just use a very simple calculation here. Do not care about overflow,
@@ -413,86 +420,70 @@ static __inline__ int led_get_diskio_activity(void)
changed = (pgstat.pgpgin != last_pgpgin) || (pgstat.pgpgout != last_pgpgout);
last_pgpgin = pgstat.pgpgin;
last_pgpgout = pgstat.pgpgout;
-
+
return (changed ? LED_DISK_IO : 0);
}
/*
- ** led_tasklet_func()
+ ** led_work_func()
**
- ** is scheduled at every timer interrupt from time.c and
- ** updates the chassis LCD/LED
+ ** manages when and which chassis LCD/LED gets updated
TODO:
- display load average (older machines like 715/64 have 4 "free" LED's for that)
- optimizations
*/
-#define HEARTBEAT_LEN (HZ*6/100)
-#define HEARTBEAT_2ND_RANGE_START (HZ*22/100)
+#define HEARTBEAT_LEN (HZ*10/100)
+#define HEARTBEAT_2ND_RANGE_START (HZ*28/100)
#define HEARTBEAT_2ND_RANGE_END (HEARTBEAT_2ND_RANGE_START + HEARTBEAT_LEN)
-#define NORMALIZED_COUNT(count) (count/(HZ/100))
+#define LED_UPDATE_INTERVAL (1 + (HZ*19/1000))
-static void led_tasklet_func(unsigned long unused)
+static void led_work_func (void *unused)
{
- static unsigned char lastleds;
- unsigned char currentleds; /* stores current value of the LEDs */
- static unsigned long count; /* static incremented value, not wrapped */
+ static unsigned long last_jiffies;
static unsigned long count_HZ; /* counter in range 0..HZ */
+ unsigned char currentleds = 0; /* stores current value of the LEDs */
/* exit if not initialized */
if (!led_func_ptr)
return;
- /* increment the local counters */
- ++count;
- if (++count_HZ == HZ)
+ /* increment the heartbeat timekeeper */
+ count_HZ += jiffies - last_jiffies;
+ last_jiffies = jiffies;
+ if (count_HZ >= HZ)
count_HZ = 0;
- currentleds = lastleds;
-
- if (led_heartbeat)
- {
- /* flash heartbeat-LED like a real heart (2 x short then a long delay) */
- if (count_HZ<HEARTBEAT_LEN ||
- (count_HZ>=HEARTBEAT_2ND_RANGE_START && count_HZ<HEARTBEAT_2ND_RANGE_END))
- currentleds |= LED_HEARTBEAT;
- else
- currentleds &= ~LED_HEARTBEAT;
- }
-
- /* look for network activity and flash LEDs respectively */
- if (led_lanrxtx && ((NORMALIZED_COUNT(count)+(8/2)) & 7) == 0)
+ if (likely(led_heartbeat))
{
- currentleds &= ~(LED_LAN_RCV | LED_LAN_TX);
- currentleds |= led_get_net_activity();
+ /* flash heartbeat-LED like a real heart
+ * (2 x short then a long delay)
+ */
+ if (count_HZ < HEARTBEAT_LEN ||
+ (count_HZ >= HEARTBEAT_2ND_RANGE_START &&
+ count_HZ < HEARTBEAT_2ND_RANGE_END))
+ currentleds |= LED_HEARTBEAT;
}
- /* avoid to calculate diskio-stats at same irq as netio-stats */
- if (led_diskio && (NORMALIZED_COUNT(count) & 7) == 0)
- {
- currentleds &= ~LED_DISK_IO;
- currentleds |= led_get_diskio_activity();
- }
+ if (likely(led_lanrxtx)) currentleds |= led_get_net_activity();
+ if (likely(led_diskio)) currentleds |= led_get_diskio_activity();
/* blink all LEDs twice a second if we got an Oops (HPMC) */
- if (oops_in_progress) {
+ if (unlikely(oops_in_progress))
currentleds = (count_HZ<=(HZ/2)) ? 0 : 0xff;
- }
-
- /* update the LCD/LEDs */
- if (currentleds != lastleds) {
- led_func_ptr(currentleds);
- lastleds = currentleds;
- }
-}
-/* main led tasklet struct (scheduled from time.c) */
-DECLARE_TASKLET_DISABLED(led_tasklet, led_tasklet_func, 0);
+ if (currentleds != lastleds)
+ {
+ led_func_ptr(currentleds); /* Update the LCD/LEDs */
+ lastleds = currentleds;
+ }
+ queue_delayed_work(led_wq, &led_task, LED_UPDATE_INTERVAL);
+}
/*
** led_halt()
@@ -522,9 +513,13 @@ static int led_halt(struct notifier_block *nb, unsigned long event, void *buf)
default: return NOTIFY_DONE;
}
- /* completely stop the LED/LCD tasklet */
- tasklet_disable(&led_tasklet);
-
+ /* Cancel the work item and delete the queue */
+ if (led_wq) {
+ cancel_rearming_delayed_workqueue(led_wq, &led_task);
+ destroy_workqueue(led_wq);
+ led_wq = NULL;
+ }
+
if (lcd_info.model == DISPLAY_MODEL_LCD)
lcd_print(txt);
else
@@ -559,7 +554,6 @@ int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long d
printk(KERN_INFO "LCD display at %lx,%lx registered\n",
LCD_CMD_REG , LCD_DATA_REG);
led_func_ptr = led_LCD_driver;
- lcd_print( lcd_text_default );
led_type = LED_HASLCD;
break;
@@ -589,9 +583,11 @@ int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long d
initialized++;
register_reboot_notifier(&led_notifier);
- /* start the led tasklet for the first time */
- tasklet_enable(&led_tasklet);
-
+ /* Ensure the work is queued */
+ if (led_wq) {
+ queue_work(led_wq, &led_task);
+ }
+
return 0;
}
@@ -626,8 +622,8 @@ void __init register_led_regions(void)
** lcd_print()
**
** Displays the given string on the LCD-Display of newer machines.
- ** lcd_print() disables the timer-based led tasklet during its
- ** execution and enables it afterwards again.
+ ** lcd_print() disables/enables the timer-based led work queue to
+ ** avoid a race condition while writing the CMD/DATA register pair.
**
*/
int lcd_print( char *str )
@@ -637,12 +633,13 @@ int lcd_print( char *str )
if (!led_func_ptr || lcd_info.model != DISPLAY_MODEL_LCD)
return 0;
- /* temporarily disable the led tasklet */
- tasklet_disable(&led_tasklet);
+ /* temporarily disable the led work task */
+ if (led_wq)
+ cancel_rearming_delayed_workqueue(led_wq, &led_task);
/* copy display string to buffer for procfs */
strlcpy(lcd_text, str, sizeof(lcd_text));
-
+
/* Set LCD Cursor to 1st character */
gsc_writeb(lcd_info.reset_cmd1, LCD_CMD_REG);
udelay(lcd_info.min_cmd_delay);
@@ -656,8 +653,10 @@ int lcd_print( char *str )
udelay(lcd_info.min_cmd_delay);
}
- /* re-enable the led tasklet */
- tasklet_enable(&led_tasklet);
+ /* re-queue the work */
+ if (led_wq) {
+ queue_work(led_wq, &led_task);
+ }
return lcd_info.lcd_width;
}
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 67c8f3b44848d7..273a7417972047 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -536,7 +536,7 @@ pdcs_info_read(struct subsystem *entry, char *buf)
out += sprintf(out, "Memory tested: ");
if ((result & 0x0F) < 0x0E)
- out += sprintf(out, "%.3f MB", 0.256*(1<<(result & 0x0F)));
+ out += sprintf(out, "%d kB", (1<<(result & 0x0F))*256);
else
out += sprintf(out, "All");
out += sprintf(out, "\n");
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 82ea68b55df4f4..c85653f315aad4 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -91,8 +91,8 @@ extern struct proc_dir_entry * proc_mckinley_root;
#define DBG_RES(x...)
#endif
-#if defined(__LP64__) && !defined(CONFIG_PDC_NARROW)
-/* "low end" PA8800 machines use ZX1 chipset */
+#if defined(CONFIG_64BIT)
+/* "low end" PA8800 machines use ZX1 chipset: PAT PDC and only run 64-bit */
#define ZX1_SUPPORT
#endif
@@ -231,7 +231,7 @@ struct ioc {
spinlock_t res_lock;
unsigned int res_bitshift; /* from the LEFT! */
unsigned int res_size; /* size of resource map in bytes */
-#if SBA_HINT_SUPPORT
+#ifdef SBA_HINT_SUPPORT
/* FIXME : DMA HINTs not used */
unsigned long hint_mask_pdir; /* bits used for DMA hints */
unsigned int hint_shift_pdir;
@@ -294,7 +294,7 @@ static unsigned long piranha_bad_128k = 0;
/* Looks nice and keeps the compiler happy */
#define SBA_DEV(d) ((struct sba_device *) (d))
-#if SBA_AGP_SUPPORT
+#ifdef SBA_AGP_SUPPORT
static int reserve_sba_gart = 1;
#endif
@@ -314,7 +314,7 @@ static int reserve_sba_gart = 1;
#define WRITE_REG32(val, addr) __raw_writel(cpu_to_le32(val), addr)
#define WRITE_REG64(val, addr) __raw_writeq(cpu_to_le64(val), addr)
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
#define READ_REG(addr) READ_REG64(addr)
#define WRITE_REG(value, addr) WRITE_REG64(value, addr)
#else
@@ -324,7 +324,7 @@ static int reserve_sba_gart = 1;
#ifdef DEBUG_SBA_INIT
-/* NOTE: When __LP64__ isn't defined, READ_REG64() is two 32-bit reads */
+/* NOTE: When CONFIG_64BIT isn't defined, READ_REG64() is two 32-bit reads */
/**
* sba_dump_ranges - debugging only - print ranges assigned to this IOA
@@ -364,7 +364,7 @@ static void sba_dump_tlb(void __iomem *hpa)
#else
#define sba_dump_ranges(x)
#define sba_dump_tlb(x)
-#endif
+#endif /* DEBUG_SBA_INIT */
#ifdef ASSERT_PDIR_SANITY
@@ -674,7 +674,7 @@ sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size)
*
***************************************************************/
-#if SBA_HINT_SUPPORT
+#ifdef SBA_HINT_SUPPORT
#define SBA_DMA_HINT(ioc, val) ((val) << (ioc)->hint_shift_pdir)
#endif
@@ -743,9 +743,8 @@ sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
* (bit #61, big endian), we have to flush and sync every time
* IO-PDIR is changed in Ike/Astro.
*/
- if (ioc_needs_fdc) {
- asm volatile("fdc 0(%%sr1,%0)\n\tsync" : : "r" (pdir_ptr));
- }
+ if (ioc_needs_fdc)
+ asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr));
}
@@ -769,42 +768,57 @@ static SBA_INLINE void
sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
{
u32 iovp = (u32) SBA_IOVP(ioc,iova);
-
- /* Even though this is a big-endian machine, the entries
- ** in the iopdir are little endian. That's why we clear the byte
- ** at +7 instead of at +0.
- */
- int off = PDIR_INDEX(iovp)*sizeof(u64)+7;
+ u64 *pdir_ptr = &ioc->pdir_base[PDIR_INDEX(iovp)];
#ifdef ASSERT_PDIR_SANITY
- /* Assert first pdir entry is set */
- if (0x80 != (((u8 *) ioc->pdir_base)[off])) {
+ /* Assert first pdir entry is set.
+ **
+ ** Even though this is a big-endian machine, the entries
+ ** in the iopdir are little endian. That's why we look at
+ ** the byte at +7 instead of at +0.
+ */
+ if (0x80 != (((u8 *) pdir_ptr)[7])) {
sba_dump_pdir_entry(ioc,"sba_mark_invalid()", PDIR_INDEX(iovp));
}
#endif
- if (byte_cnt <= IOVP_SIZE)
+ if (byte_cnt > IOVP_SIZE)
{
- iovp |= IOVP_SHIFT; /* set "size" field for PCOM */
+#if 0
+ unsigned long entries_per_cacheline = ioc_needs_fdc ?
+ L1_CACHE_ALIGN(((unsigned long) pdir_ptr))
+ - (unsigned long) pdir_ptr;
+ : 262144;
+#endif
- /*
- ** clear I/O PDIR entry "valid" bit
- ** Do NOT clear the rest - save it for debugging.
- ** We should only clear bits that have previously
- ** been enabled.
- */
- ((u8 *)(ioc->pdir_base))[off] = 0;
- } else {
- u32 t = get_order(byte_cnt) + PAGE_SHIFT;
+ /* set "size" field for PCOM */
+ iovp |= get_order(byte_cnt) + PAGE_SHIFT;
- iovp |= t;
do {
/* clear I/O Pdir entry "valid" bit first */
- ((u8 *)(ioc->pdir_base))[off] = 0;
- off += sizeof(u64);
+ ((u8 *) pdir_ptr)[7] = 0;
+ if (ioc_needs_fdc) {
+ asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr));
+#if 0
+ entries_per_cacheline = L1_CACHE_SHIFT - 3;
+#endif
+ }
+ pdir_ptr++;
byte_cnt -= IOVP_SIZE;
- } while (byte_cnt > 0);
- }
+ } while (byte_cnt > IOVP_SIZE);
+ } else
+ iovp |= IOVP_SHIFT; /* set "size" field for PCOM */
+
+ /*
+ ** clear I/O PDIR entry "valid" bit.
+ ** We have to R/M/W the cacheline regardless how much of the
+ ** pdir entry that we clobber.
+ ** The rest of the entry would be useful for debugging if we
+ ** could dump core on HPMC.
+ */
+ ((u8 *) pdir_ptr)[7] = 0;
+ if (ioc_needs_fdc)
+ asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr));
WRITE_REG( SBA_IOVA(ioc, iovp, 0, 0), ioc->ioc_hpa+IOC_PCOM);
}
@@ -819,18 +833,29 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
static int sba_dma_supported( struct device *dev, u64 mask)
{
struct ioc *ioc;
+
if (dev == NULL) {
printk(KERN_ERR MODULE_NAME ": EISA/ISA/et al not supported\n");
BUG();
return(0);
}
- ioc = GET_IOC(dev);
+ /* Documentation/DMA-mapping.txt tells drivers to try 64-bit first,
+ * then fall back to 32-bit if that fails.
+ * We are just "encouraging" 32-bit DMA masks here since we can
+ * never allow IOMMU bypass unless we add special support for ZX1.
+ */
+ if (mask > ~0U)
+ return 0;
- /* check if mask is > than the largest IO Virt Address */
+ ioc = GET_IOC(dev);
- return((int) (mask >= (ioc->ibase +
- (ioc->pdir_size / sizeof(u64) * IOVP_SIZE) )));
+ /*
+ * check if mask is >= than the current max IO Virt Address
+ * The max IO Virt address will *always* < 30 bits.
+ */
+ return((int)(mask >= (ioc->ibase - 1 +
+ (ioc->pdir_size / sizeof(u64) * IOVP_SIZE) )));
}
@@ -898,11 +923,17 @@ sba_map_single(struct device *dev, void *addr, size_t size,
size -= IOVP_SIZE;
pdir_start++;
}
- /* form complete address */
+
+ /* force FDC ops in io_pdir_entry() to be visible to IOMMU */
+ if (ioc_needs_fdc)
+ asm volatile("sync" : : );
+
#ifdef ASSERT_PDIR_SANITY
sba_check_pdir(ioc,"Check after sba_map_single()");
#endif
spin_unlock_irqrestore(&ioc->res_lock, flags);
+
+ /* form complete address */
return SBA_IOVA(ioc, iovp, offset, DEFAULT_DMA_HINT_REG);
}
@@ -958,12 +989,19 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
d--;
}
ioc->saved_cnt = 0;
+
READ_REG(ioc->ioc_hpa+IOC_PCOM); /* flush purges */
}
#else /* DELAYED_RESOURCE_CNT == 0 */
sba_free_range(ioc, iova, size);
+
+ /* If fdc's were issued, force fdc's to be visible now */
+ if (ioc_needs_fdc)
+ asm volatile("sync" : : );
+
READ_REG(ioc->ioc_hpa+IOC_PCOM); /* flush purges */
#endif /* DELAYED_RESOURCE_CNT == 0 */
+
spin_unlock_irqrestore(&ioc->res_lock, flags);
/* XXX REVISIT for 2.5 Linux - need syncdma for zero-copy support.
@@ -986,7 +1024,7 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
* See Documentation/DMA-mapping.txt
*/
static void *sba_alloc_consistent(struct device *hwdev, size_t size,
- dma_addr_t *dma_handle, int gfp)
+ dma_addr_t *dma_handle, gfp_t gfp)
{
void *ret;
@@ -1106,6 +1144,10 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
*/
filled = iommu_fill_pdir(ioc, sglist, nents, 0, sba_io_pdir_entry);
+ /* force FDC ops in io_pdir_entry() to be visible to IOMMU */
+ if (ioc_needs_fdc)
+ asm volatile("sync" : : );
+
#ifdef ASSERT_PDIR_SANITY
if (sba_check_pdir(ioc,"Check after sba_map_sg()"))
{
@@ -1234,8 +1276,10 @@ sba_alloc_pdir(unsigned int pdir_size)
unsigned long pdir_order = get_order(pdir_size);
pdir_base = __get_free_pages(GFP_KERNEL, pdir_order);
- if (NULL == (void *) pdir_base)
- panic("sba_ioc_init() could not allocate I/O Page Table\n");
+ if (NULL == (void *) pdir_base) {
+ panic("%s() could not allocate I/O Page Table\n",
+ __FUNCTION__);
+ }
/* If this is not PA8700 (PCX-W2)
** OR newer than ver 2.2
@@ -1322,19 +1366,29 @@ sba_alloc_pdir(unsigned int pdir_size)
return (void *) pdir_base;
}
+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;
+}
+
/* setup Mercury or Elroy IBASE/IMASK registers. */
-static void setup_ibase_imask(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
+static void
+setup_ibase_imask(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
{
- /* lba_set_iregs() is in drivers/parisc/lba_pci.c */
+ /* lba_set_iregs() is in drivers/parisc/lba_pci.c */
extern void lba_set_iregs(struct parisc_device *, u32, u32);
struct device *dev;
+ struct klist_iter i;
- list_for_each_entry(dev, &sba->dev.children, node) {
+ klist_iter_init(&sba->dev.klist_children, &i);
+ while ((dev = next_device(&i))) {
struct parisc_device *lba = to_parisc_device(dev);
- int rope_num = (lba->hpa >> 13) & 0xf;
+ int rope_num = (lba->hpa.start >> 13) & 0xf;
if (rope_num >> 3 == ioc_num)
lba_set_iregs(lba, ioc->ibase, ioc->imask);
}
+ klist_iter_exit(&i);
}
static void
@@ -1343,7 +1397,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
u32 iova_space_mask;
u32 iova_space_size;
int iov_order, tcnfg;
-#if SBA_AGP_SUPPORT
+#ifdef SBA_AGP_SUPPORT
int agp_found = 0;
#endif
/*
@@ -1380,7 +1434,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
DBG_INIT("%s() pdir %p size %x\n",
__FUNCTION__, ioc->pdir_base, ioc->pdir_size);
-#if SBA_HINT_SUPPORT
+#ifdef SBA_HINT_SUPPORT
ioc->hint_shift_pdir = iov_order + PAGE_SHIFT;
ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT));
@@ -1404,7 +1458,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
WRITE_REG(ioc->imask, ioc->ioc_hpa + IOC_IMASK);
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
/*
** Setting the upper bits makes checking for bypass addresses
** a little faster later on.
@@ -1437,7 +1491,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
*/
WRITE_REG(ioc->ibase | 31, ioc->ioc_hpa + IOC_PCOM);
-#if SBA_AGP_SUPPORT
+#ifdef SBA_AGP_SUPPORT
/*
** If an AGP device is present, only use half of the IOV space
** for PCI DMA. Unfortunately we can't know ahead of time
@@ -1489,11 +1543,9 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
if (iova_space_size < (1 << (20 - PAGE_SHIFT))) {
iova_space_size = 1 << (20 - PAGE_SHIFT);
}
-#ifdef __LP64__
else if (iova_space_size > (1 << (30 - PAGE_SHIFT))) {
iova_space_size = 1 << (30 - PAGE_SHIFT);
}
-#endif
/*
** iova space must be log2() in size.
@@ -1519,7 +1571,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
DBG_INIT("%s() pdir %p size %x\n",
__FUNCTION__, ioc->pdir_base, pdir_size);
-#if SBA_HINT_SUPPORT
+#ifdef SBA_HINT_SUPPORT
/* FIXME : DMA HINTs not used */
ioc->hint_shift_pdir = iov_order + PAGE_SHIFT;
ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT));
@@ -1590,7 +1642,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
static void __iomem *ioc_remap(struct sba_device *sba_dev, int offset)
{
- return ioremap(sba_dev->dev->hpa + offset, SBA_FUNC_SIZE);
+ return ioremap(sba_dev->dev->hpa.start + offset, SBA_FUNC_SIZE);
}
static void sba_hw_init(struct sba_device *sba_dev)
@@ -1968,7 +2020,7 @@ sba_driver_callback(struct parisc_device *dev)
u32 func_class;
int i;
char *version;
- void __iomem *sba_addr = ioremap(dev->hpa, SBA_FUNC_SIZE);
+ void __iomem *sba_addr = ioremap(dev->hpa.start, SBA_FUNC_SIZE);
sba_dump_ranges(sba_addr);
@@ -2010,7 +2062,7 @@ sba_driver_callback(struct parisc_device *dev)
}
printk(KERN_INFO "%s found %s at 0x%lx\n",
- MODULE_NAME, version, dev->hpa);
+ MODULE_NAME, version, dev->hpa.start);
sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL);
if (!sba_dev) {
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index e0efed796b9231..bab3bcabcb6ee6 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -11,6 +11,7 @@
* (C) Copyright 2000 Alex deVries <alex@onefishtwo.ca>
* (C) Copyright 2001 John Marvin <jsm fc hp com>
* (C) Copyright 2003 Grant Grundler <grundler parisc-linux org>
+ * (C) Copyright 2005 Kyle McMartin <kyle@parisc-linux.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -405,6 +406,7 @@ static void __devinit superio_serial_init(void)
serial[0].iobase = sio_dev.sp1_base;
serial[0].irq = SP1_IRQ;
+ spin_lock_init(&serial[0].lock);
retval = early_serial_setup(&serial[0]);
if (retval < 0) {
@@ -414,6 +416,7 @@ static void __devinit superio_serial_init(void)
serial[1].iobase = sio_dev.sp2_base;
serial[1].irq = SP2_IRQ;
+ spin_lock_init(&serial[1].lock);
retval = early_serial_setup(&serial[1]);
if (retval < 0)
diff --git a/drivers/parisc/wax.c b/drivers/parisc/wax.c
index e547d7d024d8b5..17dce2adf7fe96 100644
--- a/drivers/parisc/wax.c
+++ b/drivers/parisc/wax.c
@@ -81,7 +81,7 @@ wax_init_chip(struct parisc_device *dev)
return -ENOMEM;
wax->name = "wax";
- wax->hpa = dev->hpa;
+ wax->hpa = dev->hpa.start;
wax->version = 0; /* gsc_readb(wax->hpa+WAX_VER); */
printk(KERN_INFO "%s at 0x%lx found.\n", wax->name, wax->hpa);
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index 02d72acd1c8965..fde29a75f8884d 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -359,11 +359,12 @@ static int __devinit parport_init_chip(struct parisc_device *dev)
unsigned long port;
if (!dev->irq) {
- printk("IRQ not found for parallel device at 0x%lx\n", dev->hpa);
+ printk(KERN_WARNING "IRQ not found for parallel device at 0x%lx\n",
+ dev->hpa.start);
return -ENODEV;
}
- port = dev->hpa + PARPORT_GSC_OFFSET;
+ port = dev->hpa.start + PARPORT_GSC_OFFSET;
/* some older machines with ASP-chip don't support
* the enhanced parport modes.
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 393e0cee91a93c..14f05d22bb70bc 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -61,7 +61,7 @@ static int pcie_port_remove_service(struct device *dev)
static void pcie_port_shutdown_service(struct device *dev) {}
-static int pcie_port_suspend_service(struct device *dev, pm_message_t state, u32 level)
+static int pcie_port_suspend_service(struct device *dev, pm_message_t state)
{
struct pcie_device *pciedev;
struct pcie_port_service_driver *driver;
@@ -76,7 +76,7 @@ static int pcie_port_suspend_service(struct device *dev, pm_message_t state, u32
return 0;
}
-static int pcie_port_resume_service(struct device *dev, u32 level)
+static int pcie_port_resume_service(struct device *dev)
{
struct pcie_device *pciedev;
struct pcie_port_service_driver *driver;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index a6a630a950d09c..7992bc8cc6a4dd 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -241,7 +241,8 @@ static void __devinit quirk_s3_64M(struct pci_dev *dev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M );
-static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region, unsigned size, int nr)
+static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
+ unsigned size, int nr, const char *name)
{
region &= ~(size-1);
if (region) {
@@ -259,6 +260,7 @@ static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region, unsi
pcibios_bus_to_resource(dev, res, &bus_region);
pci_claim_resource(dev, nr);
+ printk("PCI quirk: region %04x-%04x claimed by %s\n", region, region + size - 1, name);
}
}
@@ -291,25 +293,98 @@ static void __devinit quirk_ali7101_acpi(struct pci_dev *dev)
u16 region;
pci_read_config_word(dev, 0xE0, &region);
- quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES);
+ quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "ali7101 ACPI");
pci_read_config_word(dev, 0xE2, &region);
- quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1);
+ quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1, "ali7101 SMB");
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, quirk_ali7101_acpi );
+static void piix4_io_quirk(struct pci_dev *dev, const char *name, unsigned int port, unsigned int enable)
+{
+ u32 devres;
+ u32 mask, size, base;
+
+ pci_read_config_dword(dev, port, &devres);
+ if ((devres & enable) != enable)
+ return;
+ mask = (devres >> 16) & 15;
+ base = devres & 0xffff;
+ size = 16;
+ for (;;) {
+ unsigned bit = size >> 1;
+ if ((bit & mask) == bit)
+ break;
+ size = bit;
+ }
+ /*
+ * For now we only print it out. Eventually we'll want to
+ * reserve it (at least if it's in the 0x1000+ range), but
+ * let's get enough confirmation reports first.
+ */
+ base &= -size;
+ printk("%s PIO at %04x-%04x\n", name, base, base + size - 1);
+}
+
+static void piix4_mem_quirk(struct pci_dev *dev, const char *name, unsigned int port, unsigned int enable)
+{
+ u32 devres;
+ u32 mask, size, base;
+
+ pci_read_config_dword(dev, port, &devres);
+ if ((devres & enable) != enable)
+ return;
+ base = devres & 0xffff0000;
+ mask = (devres & 0x3f) << 16;
+ size = 128 << 16;
+ for (;;) {
+ unsigned bit = size >> 1;
+ if ((bit & mask) == bit)
+ break;
+ size = bit;
+ }
+ /*
+ * For now we only print it out. Eventually we'll want to
+ * reserve it, but let's get enough confirmation reports first.
+ */
+ base &= -size;
+ printk("%s MMIO at %04x-%04x\n", name, base, base + size - 1);
+}
+
/*
* PIIX4 ACPI: Two IO regions pointed to by longwords at
* 0x40 (64 bytes of ACPI registers)
* 0x90 (32 bytes of SMB registers)
+ * and a few strange programmable PIIX4 device resources.
*/
static void __devinit quirk_piix4_acpi(struct pci_dev *dev)
{
- u32 region;
+ u32 region, res_a;
pci_read_config_dword(dev, 0x40, &region);
- quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES);
+ quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "PIIX4 ACPI");
pci_read_config_dword(dev, 0x90, &region);
- quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1);
+ quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1, "PIIX4 SMB");
+
+ /* Device resource A has enables for some of the other ones */
+ pci_read_config_dword(dev, 0x5c, &res_a);
+
+ piix4_io_quirk(dev, "PIIX4 devres B", 0x60, 3 << 21);
+ piix4_io_quirk(dev, "PIIX4 devres C", 0x64, 3 << 21);
+
+ /* Device resource D is just bitfields for static resources */
+
+ /* Device 12 enabled? */
+ if (res_a & (1 << 29)) {
+ piix4_io_quirk(dev, "PIIX4 devres E", 0x68, 1 << 20);
+ piix4_mem_quirk(dev, "PIIX4 devres F", 0x6c, 1 << 7);
+ }
+ /* Device 13 enabled? */
+ if (res_a & (1 << 30)) {
+ piix4_io_quirk(dev, "PIIX4 devres G", 0x70, 1 << 20);
+ piix4_mem_quirk(dev, "PIIX4 devres H", 0x74, 1 << 7);
+ }
+ piix4_io_quirk(dev, "PIIX4 devres I", 0x78, 1 << 20);
+ piix4_io_quirk(dev, "PIIX4 devres J", 0x7c, 1 << 20);
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi );
@@ -323,10 +398,10 @@ static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev)
u32 region;
pci_read_config_dword(dev, 0x40, &region);
- quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES);
+ quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH4 ACPI/GPIO/TCO");
pci_read_config_dword(dev, 0x58, &region);
- quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1);
+ quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH4 GPIO");
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, quirk_ich4_lpc_acpi );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, quirk_ich4_lpc_acpi );
@@ -352,7 +427,7 @@ static void __devinit quirk_vt82c586_acpi(struct pci_dev *dev)
if (rev & 0x10) {
pci_read_config_dword(dev, 0x48, &region);
region &= PCI_BASE_ADDRESS_IO_MASK;
- quirk_io_region(dev, region, 256, PCI_BRIDGE_RESOURCES);
+ quirk_io_region(dev, region, 256, PCI_BRIDGE_RESOURCES, "vt82c586 ACPI");
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt82c586_acpi );
@@ -372,11 +447,11 @@ static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev)
pci_read_config_word(dev, 0x70, &hm);
hm &= PCI_BASE_ADDRESS_IO_MASK;
- quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1);
+ quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1, "vt82c868 HW-mon");
pci_read_config_dword(dev, 0x90, &smb);
smb &= PCI_BASE_ADDRESS_IO_MASK;
- quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2);
+ quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c868 SMB");
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi );
@@ -391,11 +466,11 @@ static void __devinit quirk_vt8235_acpi(struct pci_dev *dev)
pci_read_config_word(dev, 0x88, &pm);
pm &= PCI_BASE_ADDRESS_IO_MASK;
- quirk_io_region(dev, pm, 128, PCI_BRIDGE_RESOURCES);
+ quirk_io_region(dev, pm, 128, PCI_BRIDGE_RESOURCES, "vt8235 PM");
pci_read_config_word(dev, 0xd0, &smb);
smb &= PCI_BASE_ADDRESS_IO_MASK;
- quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 1);
+ quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 1, "vt8235 SMB");
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, quirk_vt8235_acpi);
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
index 470ef756252eb2..d90a634cebf5ac 100644
--- a/drivers/pcmcia/au1000_generic.c
+++ b/drivers/pcmcia/au1000_generic.c
@@ -519,30 +519,13 @@ static int au1x00_drv_pcmcia_probe(struct device *dev)
}
-static int au1x00_drv_pcmcia_suspend(struct device *dev, pm_message_t state, u32 level)
-{
- int ret = 0;
- if (level == SUSPEND_SAVE_STATE)
- ret = pcmcia_socket_dev_suspend(dev, state);
- return ret;
-}
-
-static int au1x00_drv_pcmcia_resume(struct device *dev, u32 level)
-{
- int ret = 0;
- if (level == RESUME_RESTORE_STATE)
- ret = pcmcia_socket_dev_resume(dev);
- return ret;
-}
-
-
static struct device_driver au1x00_pcmcia_driver = {
.probe = au1x00_drv_pcmcia_probe,
.remove = au1x00_drv_pcmcia_remove,
.name = "au1x00-pcmcia",
.bus = &platform_bus_type,
- .suspend = au1x00_drv_pcmcia_suspend,
- .resume = au1x00_drv_pcmcia_resume
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
static struct platform_device au1x00_device = {
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 080608c7381a74..39d096b52926fb 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -1157,7 +1157,8 @@ static struct pcmcia_callback pcmcia_bus_callback = {
.requery = pcmcia_bus_rescan,
};
-static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
+static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev,
+ struct class_interface *class_intf)
{
struct pcmcia_socket *socket = class_get_devdata(class_dev);
int ret;
@@ -1192,7 +1193,8 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
return 0;
}
-static void pcmcia_bus_remove_socket(struct class_device *class_dev)
+static void pcmcia_bus_remove_socket(struct class_device *class_dev,
+ struct class_interface *class_intf)
{
struct pcmcia_socket *socket = class_get_devdata(class_dev);
diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
index 316f8bcc878be6..b57a0b98b4d6b8 100644
--- a/drivers/pcmcia/hd64465_ss.c
+++ b/drivers/pcmcia/hd64465_ss.c
@@ -844,27 +844,11 @@ static void hs_exit_socket(hs_socket_t *sp)
local_irq_restore(flags);
}
-static int hd64465_suspend(struct device *dev, pm_message_t state, u32 level)
-{
- int ret = 0;
- if (level == SUSPEND_SAVE_STATE)
- ret = pcmcia_socket_dev_suspend(dev, state);
- return ret;
-}
-
-static int hd64465_resume(struct device *dev, u32 level)
-{
- int ret = 0;
- if (level == RESUME_RESTORE_STATE)
- ret = pcmcia_socket_dev_resume(dev);
- return ret;
-}
-
static struct device_driver hd64465_driver = {
.name = "hd64465-pcmcia",
.bus = &platform_bus_type,
- .suspend = hd64465_suspend,
- .resume = hd64465_resume,
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
static struct platform_device hd64465_device = {
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index a713015e8228cb..4a41f67d185d9f 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -1332,27 +1332,11 @@ static struct pccard_operations pcic_operations = {
/*====================================================================*/
-static int i82365_suspend(struct device *dev, pm_message_t state, u32 level)
-{
- int ret = 0;
- if (level == SUSPEND_SAVE_STATE)
- ret = pcmcia_socket_dev_suspend(dev, state);
- return ret;
-}
-
-static int i82365_resume(struct device *dev, u32 level)
-{
- int ret = 0;
- if (level == RESUME_RESTORE_STATE)
- ret = pcmcia_socket_dev_resume(dev);
- return ret;
-}
-
static struct device_driver i82365_driver = {
.name = "i82365",
.bus = &platform_bus_type,
- .suspend = i82365_suspend,
- .resume = i82365_resume,
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
static struct platform_device i82365_device = {
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 65f3ee3d4d3c6e..c6ed70ea4812ec 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -731,28 +731,11 @@ static struct pccard_operations pcc_operations = {
/*====================================================================*/
-static int m32r_pcc_suspend(struct device *dev, pm_message_t state, u32 level)
-{
- int ret = 0;
- if (level == SUSPEND_SAVE_STATE)
- ret = pcmcia_socket_dev_suspend(dev, state);
- return ret;
-}
-
-static int m32r_pcc_resume(struct device *dev, u32 level)
-{
- int ret = 0;
- if (level == RESUME_RESTORE_STATE)
- ret = pcmcia_socket_dev_resume(dev);
- return ret;
-}
-
-
static struct device_driver pcc_driver = {
.name = "cfc",
.bus = &platform_bus_type,
- .suspend = m32r_pcc_suspend,
- .resume = m32r_pcc_resume,
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
static struct platform_device pcc_device = {
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index 7b14d7efd68c06..3397ff28de6aa7 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -695,28 +695,11 @@ static struct pccard_operations pcc_operations = {
/*====================================================================*/
-static int m32r_pcc_suspend(struct device *dev, pm_message_t state, u32 level)
-{
- int ret = 0;
- if (level == SUSPEND_SAVE_STATE)
- ret = pcmcia_socket_dev_suspend(dev, state);
- return ret;
-}
-
-static int m32r_pcc_resume(struct device *dev, u32 level)
-{
- int ret = 0;
- if (level == RESUME_RESTORE_STATE)
- ret = pcmcia_socket_dev_resume(dev);
- return ret;
-}
-
-
static struct device_driver pcc_driver = {
.name = "pcc",
.bus = &platform_bus_type,
- .suspend = m32r_pcc_suspend,
- .resume = m32r_pcc_resume,
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
static struct platform_device pcc_device = {
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index 94be9e51654e39..2558c3cc91eca9 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -329,27 +329,13 @@ static int __devexit omap_cf_remove(struct device *dev)
return 0;
}
-static int omap_cf_suspend(struct device *dev, pm_message_t mesg, u32 level)
-{
- if (level != SUSPEND_SAVE_STATE)
- return 0;
- return pcmcia_socket_dev_suspend(dev, mesg);
-}
-
-static int omap_cf_resume(struct device *dev, u32 level)
-{
- if (level != RESUME_RESTORE_STATE)
- return 0;
- return pcmcia_socket_dev_resume(dev);
-}
-
static struct device_driver omap_cf_driver = {
.name = (char *) driver_name,
.bus = &platform_bus_type,
.probe = omap_cf_probe,
.remove = __devexit_p(omap_cf_remove),
- .suspend = omap_cf_suspend,
- .resume = omap_cf_resume,
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
static int __init omap_cf_init(void)
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c
index 325c992f7d8f38..c2a12d53f6c76e 100644
--- a/drivers/pcmcia/pxa2xx_base.c
+++ b/drivers/pcmcia/pxa2xx_base.c
@@ -205,32 +205,20 @@ int pxa2xx_drv_pcmcia_probe(struct device *dev)
}
EXPORT_SYMBOL(pxa2xx_drv_pcmcia_probe);
-static int pxa2xx_drv_pcmcia_suspend(struct device *dev, pm_message_t state, u32 level)
+static int pxa2xx_drv_pcmcia_resume(struct device *dev)
{
- int ret = 0;
- if (level == SUSPEND_SAVE_STATE)
- ret = pcmcia_socket_dev_suspend(dev, state);
- return ret;
-}
+ struct pcmcia_low_level *ops = dev->platform_data;
+ int nr = ops ? ops->nr : 0;
-static int pxa2xx_drv_pcmcia_resume(struct device *dev, u32 level)
-{
- int ret = 0;
- if (level == RESUME_RESTORE_STATE)
- {
- struct pcmcia_low_level *ops = dev->platform_data;
- int nr = ops ? ops->nr : 0;
-
- MECR = nr > 1 ? MECR_CIT | MECR_NOS : (nr > 0 ? MECR_CIT : 0);
- ret = pcmcia_socket_dev_resume(dev);
- }
- return ret;
+ MECR = nr > 1 ? MECR_CIT | MECR_NOS : (nr > 0 ? MECR_CIT : 0);
+
+ return pcmcia_socket_dev_resume(dev);
}
static struct device_driver pxa2xx_pcmcia_driver = {
.probe = pxa2xx_drv_pcmcia_probe,
.remove = soc_common_drv_pcmcia_remove,
- .suspend = pxa2xx_drv_pcmcia_suspend,
+ .suspend = pcmcia_socket_dev_suspend,
.resume = pxa2xx_drv_pcmcia_resume,
.name = "pxa2xx-pcmcia",
.bus = &platform_bus_type,
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index f9a5c70284b5a8..fc87e7e2b6b800 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -994,7 +994,8 @@ static struct class_device_attribute *pccard_rsrc_attributes[] = {
NULL,
};
-static int __devinit pccard_sysfs_add_rsrc(struct class_device *class_dev)
+static int __devinit pccard_sysfs_add_rsrc(struct class_device *class_dev,
+ struct class_interface *class_intf)
{
struct pcmcia_socket *s = class_get_devdata(class_dev);
struct class_device_attribute **attr;
@@ -1011,7 +1012,8 @@ static int __devinit pccard_sysfs_add_rsrc(struct class_device *class_dev)
return ret;
}
-static void __devexit pccard_sysfs_remove_rsrc(struct class_device *class_dev)
+static void __devexit pccard_sysfs_remove_rsrc(struct class_device *class_dev,
+ struct class_interface *class_intf)
{
struct pcmcia_socket *s = class_get_devdata(class_dev);
struct class_device_attribute **attr;
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index d4ed508b38be5e..b768fa81f043f4 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -74,29 +74,13 @@ static int sa11x0_drv_pcmcia_probe(struct device *dev)
return ret;
}
-static int sa11x0_drv_pcmcia_suspend(struct device *dev, pm_message_t state, u32 level)
-{
- int ret = 0;
- if (level == SUSPEND_SAVE_STATE)
- ret = pcmcia_socket_dev_suspend(dev, state);
- return ret;
-}
-
-static int sa11x0_drv_pcmcia_resume(struct device *dev, u32 level)
-{
- int ret = 0;
- if (level == RESUME_RESTORE_STATE)
- ret = pcmcia_socket_dev_resume(dev);
- return ret;
-}
-
static struct device_driver sa11x0_pcmcia_driver = {
.probe = sa11x0_drv_pcmcia_probe,
.remove = soc_common_drv_pcmcia_remove,
.name = "sa11x0-pcmcia",
.bus = &platform_bus_type,
- .suspend = sa11x0_drv_pcmcia_suspend,
- .resume = sa11x0_drv_pcmcia_resume,
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
/* sa11x0_pcmcia_init()
diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c
index bb90a1448a53d0..81ded52c8959aa 100644
--- a/drivers/pcmcia/sa1111_generic.c
+++ b/drivers/pcmcia/sa1111_generic.c
@@ -122,7 +122,7 @@ void sa1111_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
static int pcmcia_probe(struct sa1111_dev *dev)
{
- char *base;
+ void __iomem *base;
if (!request_mem_region(dev->res.start, 512,
SA1111_DRIVER_NAME(dev)))
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index 1040a6c1a8a44c..4a3150a7854cce 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -341,7 +341,8 @@ static struct bin_attribute pccard_cis_attr = {
.write = pccard_store_cis,
};
-static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev)
+static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev,
+ struct class_interface *class_intf)
{
struct class_device_attribute **attr;
int ret = 0;
@@ -357,7 +358,8 @@ static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev)
return ret;
}
-static void __devexit pccard_sysfs_remove_socket(struct class_device *class_dev)
+static void __devexit pccard_sysfs_remove_socket(struct class_device *class_dev,
+ struct class_interface *class_intf)
{
struct class_device_attribute **attr;
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index d5a61eae61194a..f158b67f661007 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -372,27 +372,11 @@ static int __init get_tcic_id(void)
/*====================================================================*/
-static int tcic_drv_suspend(struct device *dev, pm_message_t state, u32 level)
-{
- int ret = 0;
- if (level == SUSPEND_SAVE_STATE)
- ret = pcmcia_socket_dev_suspend(dev, state);
- return ret;
-}
-
-static int tcic_drv_resume(struct device *dev, u32 level)
-{
- int ret = 0;
- if (level == RESUME_RESTORE_STATE)
- ret = pcmcia_socket_dev_resume(dev);
- return ret;
-}
-
static struct device_driver tcic_driver = {
.name = "tcic-pcmcia",
.bus = &platform_bus_type,
- .suspend = tcic_drv_suspend,
- .resume = tcic_drv_resume,
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
static struct platform_device tcic_device = {
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index 17bb2da6752bc0..3d2dca675e02bc 100644
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -774,31 +774,11 @@ static int __devinit vrc4171_card_setup(char *options)
__setup("vrc4171_card=", vrc4171_card_setup);
-static int vrc4171_card_suspend(struct device *dev, pm_message_t state, u32 level)
-{
- int retval = 0;
-
- if (level == SUSPEND_SAVE_STATE)
- retval = pcmcia_socket_dev_suspend(dev, state);
-
- return retval;
-}
-
-static int vrc4171_card_resume(struct device *dev, u32 level)
-{
- int retval = 0;
-
- if (level == RESUME_RESTORE_STATE)
- retval = pcmcia_socket_dev_resume(dev);
-
- return retval;
-}
-
static struct device_driver vrc4171_card_driver = {
.name = vrc4171_card_name,
.bus = &platform_bus_type,
- .suspend = vrc4171_card_suspend,
- .resume = vrc4171_card_resume,
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
static int __devinit vrc4171_card_init(void)
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index db9f952f9e3c2a..ec6ab65f087227 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -151,6 +151,40 @@ static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)
readb(socket->base + 0x800 + reg + 1);
}
+static ssize_t show_yenta_registers(struct device *yentadev, struct device_attribute *attr, char *buf)
+{
+ struct pci_dev *dev = to_pci_dev(yentadev);
+ struct yenta_socket *socket = pci_get_drvdata(dev);
+ int offset = 0, i;
+
+ offset = snprintf(buf, PAGE_SIZE, "CB registers:");
+ for (i = 0; i < 0x24; i += 4) {
+ unsigned val;
+ if (!(i & 15))
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n%02x:", i);
+ val = cb_readl(socket, i);
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, " %08x", val);
+ }
+
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n\nExCA registers:");
+ for (i = 0; i < 0x45; i++) {
+ unsigned char val;
+ if (!(i & 7)) {
+ if (i & 8) {
+ memcpy(buf + offset, " -", 2);
+ offset += 2;
+ } else
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n%02x:", i);
+ }
+ val = exca_readb(socket, i);
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, " %02x", val);
+ }
+ buf[offset++] = '\n';
+ return offset;
+}
+
+static DEVICE_ATTR(yenta_registers, S_IRUSR, show_yenta_registers, NULL);
+
/*
* Ugh, mixed-mode cardbus and 16-bit pccard state: things depend
* on what kind of card is inserted..
@@ -765,6 +799,9 @@ static void yenta_close(struct pci_dev *dev)
{
struct yenta_socket *sock = pci_get_drvdata(dev);
+ /* Remove the register attributes */
+ device_remove_file(&dev->dev, &dev_attr_yenta_registers);
+
/* we don't want a dying socket registered */
pcmcia_unregister_socket(&sock->socket);
@@ -1138,8 +1175,11 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
/* Register it with the pcmcia layer.. */
ret = pcmcia_register_socket(&socket->socket);
- if (ret == 0)
+ if (ret == 0) {
+ /* Add the yenta register attributes */
+ device_create_file(&dev->dev, &dev_attr_yenta_registers);
goto out;
+ }
unmap:
iounmap(socket->base);
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index ed0cb1f15b4c1b..fcaee447d6fe58 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -72,6 +72,7 @@ struct tape_class_device *register_tape_dev(
tcd->class_device = class_device_create(
tape_class,
+ NULL,
tcd->char_device->dev,
device,
"%s", tcd->device_name
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index 491f00c032e88d..a107fec4457a01 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -787,6 +787,7 @@ vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) {
return ret;
}
priv->class_device = class_device_create(
+ NULL,
vmlogrdr_class,
MKDEV(vmlogrdr_major, priv->minor_num),
dev,
diff --git a/drivers/s390/net/fsm.c b/drivers/s390/net/fsm.c
index fa09440d82e549..38f50b7129a24f 100644
--- a/drivers/s390/net/fsm.c
+++ b/drivers/s390/net/fsm.c
@@ -16,7 +16,7 @@ MODULE_LICENSE("GPL");
fsm_instance *
init_fsm(char *name, const char **state_names, const char **event_names, int nr_states,
- int nr_events, const fsm_node *tmpl, int tmpl_len, int order)
+ int nr_events, const fsm_node *tmpl, int tmpl_len, gfp_t order)
{
int i;
fsm_instance *this;
diff --git a/drivers/s390/net/fsm.h b/drivers/s390/net/fsm.h
index f9a011001eb693..1b8a7e7c34f3cd 100644
--- a/drivers/s390/net/fsm.h
+++ b/drivers/s390/net/fsm.h
@@ -110,7 +110,7 @@ extern fsm_instance *
init_fsm(char *name, const char **state_names,
const char **event_names,
int nr_states, int nr_events, const fsm_node *tmpl,
- int tmpl_len, int order);
+ int tmpl_len, gfp_t order);
/**
* Releases an FSM
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index 9963479ba89f71..38a2441564d7d8 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -275,6 +275,10 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT, \
QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT, \
QETH_MAX_QUEUES,0x103}, \
+ {0x1731,0x06,0x1732,0x06,QETH_CARD_TYPE_OSN,0, \
+ QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
+ QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
+ QETH_MAX_QUEUES,0}, \
{0,0,0,0,0,0,0,0,0}}
#define QETH_REAL_CARD 1
@@ -363,10 +367,22 @@ struct qeth_hdr_layer2 {
__u8 reserved2[16];
} __attribute__ ((packed));
+struct qeth_hdr_osn {
+ __u8 id;
+ __u8 reserved;
+ __u16 seq_no;
+ __u16 reserved2;
+ __u16 control_flags;
+ __u16 pdu_length;
+ __u8 reserved3[18];
+ __u32 ccid;
+} __attribute__ ((packed));
+
struct qeth_hdr {
union {
struct qeth_hdr_layer2 l2;
struct qeth_hdr_layer3 l3;
+ struct qeth_hdr_osn osn;
} hdr;
} __attribute__ ((packed));
@@ -413,6 +429,7 @@ enum qeth_header_ids {
QETH_HEADER_TYPE_LAYER3 = 0x01,
QETH_HEADER_TYPE_LAYER2 = 0x02,
QETH_HEADER_TYPE_TSO = 0x03,
+ QETH_HEADER_TYPE_OSN = 0x04,
};
/* flags for qeth_hdr.ext_flags */
#define QETH_HDR_EXT_VLAN_FRAME 0x01
@@ -582,7 +599,6 @@ enum qeth_card_states {
* Protocol versions
*/
enum qeth_prot_versions {
- QETH_PROT_SNA = 0x0001,
QETH_PROT_IPV4 = 0x0004,
QETH_PROT_IPV6 = 0x0006,
};
@@ -761,6 +777,11 @@ enum qeth_threads {
QETH_RECOVER_THREAD = 2,
};
+struct qeth_osn_info {
+ int (*assist_cb)(struct net_device *dev, void *data);
+ int (*data_cb)(struct sk_buff *skb);
+};
+
struct qeth_card {
struct list_head list;
enum qeth_card_states state;
@@ -803,6 +824,7 @@ struct qeth_card {
int use_hard_stop;
int (*orig_hard_header)(struct sk_buff *,struct net_device *,
unsigned short,void *,void *,unsigned);
+ struct qeth_osn_info osn_info;
};
struct qeth_card_list_struct {
@@ -916,10 +938,12 @@ qeth_get_hlen(__u8 link_type)
static inline unsigned short
qeth_get_netdev_flags(struct qeth_card *card)
{
- if (card->options.layer2)
+ if (card->options.layer2 &&
+ (card->info.type == QETH_CARD_TYPE_OSAE))
return 0;
switch (card->info.type) {
case QETH_CARD_TYPE_IQD:
+ case QETH_CARD_TYPE_OSN:
return IFF_NOARP;
#ifdef CONFIG_QETH_IPV6
default:
@@ -956,9 +980,10 @@ static inline int
qeth_get_max_mtu_for_card(int cardtype)
{
switch (cardtype) {
+
case QETH_CARD_TYPE_UNKNOWN:
- return 61440;
case QETH_CARD_TYPE_OSAE:
+ case QETH_CARD_TYPE_OSN:
return 61440;
case QETH_CARD_TYPE_IQD:
return 57344;
@@ -1004,6 +1029,7 @@ qeth_mtu_is_valid(struct qeth_card * card, int mtu)
case QETH_CARD_TYPE_IQD:
return ((mtu >= 576) &&
(mtu <= card->info.max_mtu + 4096 - 32));
+ case QETH_CARD_TYPE_OSN:
case QETH_CARD_TYPE_UNKNOWN:
default:
return 1;
@@ -1015,6 +1041,7 @@ qeth_get_arphdr_type(int cardtype, int linktype)
{
switch (cardtype) {
case QETH_CARD_TYPE_OSAE:
+ case QETH_CARD_TYPE_OSN:
switch (linktype) {
case QETH_LINK_TYPE_LANE_TR:
case QETH_LINK_TYPE_HSTR:
@@ -1182,4 +1209,16 @@ qeth_fill_header(struct qeth_card *, struct qeth_hdr *,
extern void
qeth_flush_buffers(struct qeth_qdio_out_q *, int, int, int);
+extern int
+qeth_osn_assist(struct net_device *, void *, int);
+
+extern int
+qeth_osn_register(unsigned char *read_dev_no,
+ struct net_device **,
+ int (*assist_cb)(struct net_device *, void *),
+ int (*data_cb)(struct sk_buff *));
+
+extern void
+qeth_osn_deregister(struct net_device *);
+
#endif /* __QETH_H__ */
diff --git a/drivers/s390/net/qeth_fs.h b/drivers/s390/net/qeth_fs.h
index 5c9a51ce91b628..c0b4c8d82c45e3 100644
--- a/drivers/s390/net/qeth_fs.h
+++ b/drivers/s390/net/qeth_fs.h
@@ -12,7 +12,7 @@
#ifndef __QETH_FS_H__
#define __QETH_FS_H__
-#define VERSION_QETH_FS_H "$Revision: 1.9 $"
+#define VERSION_QETH_FS_H "$Revision: 1.10 $"
extern const char *VERSION_QETH_PROC_C;
extern const char *VERSION_QETH_SYS_C;
@@ -43,6 +43,12 @@ extern void
qeth_remove_device_attributes(struct device *dev);
extern int
+qeth_create_device_attributes_osn(struct device *dev);
+
+extern void
+qeth_remove_device_attributes_osn(struct device *dev);
+
+extern int
qeth_create_driver_attributes(void);
extern void
@@ -108,6 +114,8 @@ qeth_get_cardname(struct qeth_card *card)
return " OSD Express";
case QETH_CARD_TYPE_IQD:
return " HiperSockets";
+ case QETH_CARD_TYPE_OSN:
+ return " OSN QDIO";
default:
return " unknown";
}
@@ -153,6 +161,8 @@ qeth_get_cardname_short(struct qeth_card *card)
}
case QETH_CARD_TYPE_IQD:
return "HiperSockets";
+ case QETH_CARD_TYPE_OSN:
+ return "OSN";
default:
return "unknown";
}
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index bd28e2438d7f51..692003c9f896fd 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -196,7 +196,6 @@ qeth_notifier_register(struct task_struct *p, int signum)
{
struct qeth_notify_list_struct *n_entry;
-
/*check first if entry already exists*/
spin_lock(&qeth_notify_lock);
list_for_each_entry(n_entry, &qeth_notify_list, list) {
@@ -1024,7 +1023,10 @@ qeth_set_intial_options(struct qeth_card *card)
card->options.fake_broadcast = 0;
card->options.add_hhlen = DEFAULT_ADD_HHLEN;
card->options.fake_ll = 0;
- card->options.layer2 = 0;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ card->options.layer2 = 1;
+ else
+ card->options.layer2 = 0;
}
/**
@@ -1113,19 +1115,20 @@ qeth_determine_card_type(struct qeth_card *card)
QETH_DBF_TEXT(setup, 2, "detcdtyp");
+ card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
+ card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
while (known_devices[i][4]) {
if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) &&
(CARD_RDEV(card)->id.dev_model == known_devices[i][3])) {
card->info.type = known_devices[i][4];
+ card->qdio.no_out_queues = known_devices[i][8];
+ card->info.is_multicast_different = known_devices[i][9];
if (is_1920_device(card)) {
PRINT_INFO("Priority Queueing not able "
"due to hardware limitations!\n");
card->qdio.no_out_queues = 1;
card->qdio.default_out_queue = 0;
- } else {
- card->qdio.no_out_queues = known_devices[i][8];
- }
- card->info.is_multicast_different = known_devices[i][9];
+ }
return 0;
}
i++;
@@ -1149,6 +1152,8 @@ qeth_probe_device(struct ccwgroup_device *gdev)
if (!get_device(dev))
return -ENODEV;
+ QETH_DBF_TEXT_(setup, 2, "%s", gdev->dev.bus_id);
+
card = qeth_alloc_card();
if (!card) {
put_device(dev);
@@ -1158,28 +1163,27 @@ qeth_probe_device(struct ccwgroup_device *gdev)
card->read.ccwdev = gdev->cdev[0];
card->write.ccwdev = gdev->cdev[1];
card->data.ccwdev = gdev->cdev[2];
-
- if ((rc = qeth_setup_card(card))){
- QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
- put_device(dev);
- qeth_free_card(card);
- return rc;
- }
gdev->dev.driver_data = card;
card->gdev = gdev;
gdev->cdev[0]->handler = qeth_irq;
gdev->cdev[1]->handler = qeth_irq;
gdev->cdev[2]->handler = qeth_irq;
- rc = qeth_create_device_attributes(dev);
- if (rc) {
+ if ((rc = qeth_determine_card_type(card))){
+ PRINT_WARN("%s: not a valid card type\n", __func__);
+ QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+ put_device(dev);
+ qeth_free_card(card);
+ return rc;
+ }
+ if ((rc = qeth_setup_card(card))){
+ QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
put_device(dev);
qeth_free_card(card);
return rc;
}
- if ((rc = qeth_determine_card_type(card))){
- PRINT_WARN("%s: not a valid card type\n", __func__);
- QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+ rc = qeth_create_device_attributes(dev);
+ if (rc) {
put_device(dev);
qeth_free_card(card);
return rc;
@@ -1660,6 +1664,8 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
netif_carrier_on(card->dev);
qeth_schedule_recovery(card);
return NULL;
+ case IPA_CMD_MODCCID:
+ return cmd;
case IPA_CMD_REGISTER_LOCAL_ADDR:
QETH_DBF_TEXT(trace,3, "irla");
break;
@@ -1721,6 +1727,14 @@ qeth_send_control_data_cb(struct qeth_channel *channel,
cmd = qeth_check_ipa_data(card, iob);
if ((cmd == NULL) && (card->state != CARD_STATE_DOWN))
goto out;
+ /*in case of OSN : check if cmd is set */
+ if (card->info.type == QETH_CARD_TYPE_OSN &&
+ cmd &&
+ cmd->hdr.command != IPA_CMD_STARTLAN &&
+ card->osn_info.assist_cb != NULL) {
+ card->osn_info.assist_cb(card->dev, cmd);
+ goto out;
+ }
spin_lock_irqsave(&card->lock, flags);
list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
@@ -1737,8 +1751,7 @@ qeth_send_control_data_cb(struct qeth_channel *channel,
keep_reply = reply->callback(card,
reply,
(unsigned long)cmd);
- }
- else
+ } else
keep_reply = reply->callback(card,
reply,
(unsigned long)iob);
@@ -1768,6 +1781,24 @@ out:
qeth_release_buffer(channel,iob);
}
+static inline void
+qeth_prepare_control_data(struct qeth_card *card, int len,
+struct qeth_cmd_buffer *iob)
+{
+ qeth_setup_ccw(&card->write,iob->data,len);
+ iob->callback = qeth_release_buffer;
+
+ memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
+ &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+ card->seqno.trans_hdr++;
+ memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data),
+ &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
+ card->seqno.pdu_hdr++;
+ memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
+ &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
+ QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
+}
+
static int
qeth_send_control_data(struct qeth_card *card, int len,
struct qeth_cmd_buffer *iob,
@@ -1778,24 +1809,11 @@ qeth_send_control_data(struct qeth_card *card, int len,
{
int rc;
unsigned long flags;
- struct qeth_reply *reply;
+ struct qeth_reply *reply = NULL;
struct timer_list timer;
QETH_DBF_TEXT(trace, 2, "sendctl");
- qeth_setup_ccw(&card->write,iob->data,len);
-
- memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
- &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
- card->seqno.trans_hdr++;
-
- memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data),
- &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
- card->seqno.pdu_hdr++;
- memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
- &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
- iob->callback = qeth_release_buffer;
-
reply = qeth_alloc_reply(card);
if (!reply) {
PRINT_WARN("Could no alloc qeth_reply!\n");
@@ -1810,10 +1828,6 @@ qeth_send_control_data(struct qeth_card *card, int len,
init_timer(&timer);
timer.function = qeth_cmd_timeout;
timer.data = (unsigned long) reply;
- if (IS_IPA(iob->data))
- timer.expires = jiffies + QETH_IPA_TIMEOUT;
- else
- timer.expires = jiffies + QETH_TIMEOUT;
init_waitqueue_head(&reply->wait_q);
spin_lock_irqsave(&card->lock, flags);
list_add_tail(&reply->list, &card->cmd_waiter_list);
@@ -1821,6 +1835,11 @@ qeth_send_control_data(struct qeth_card *card, int len,
QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
wait_event(card->wait_q,
atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0);
+ qeth_prepare_control_data(card, len, iob);
+ if (IS_IPA(iob->data))
+ timer.expires = jiffies + QETH_IPA_TIMEOUT;
+ else
+ timer.expires = jiffies + QETH_TIMEOUT;
QETH_DBF_TEXT(trace, 6, "noirqpnd");
spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
@@ -1848,6 +1867,62 @@ qeth_send_control_data(struct qeth_card *card, int len,
}
static int
+qeth_osn_send_control_data(struct qeth_card *card, int len,
+ struct qeth_cmd_buffer *iob)
+{
+ unsigned long flags;
+ int rc = 0;
+
+ QETH_DBF_TEXT(trace, 5, "osndctrd");
+
+ wait_event(card->wait_q,
+ atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0);
+ qeth_prepare_control_data(card, len, iob);
+ QETH_DBF_TEXT(trace, 6, "osnoirqp");
+ spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
+ rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
+ (addr_t) iob, 0, 0);
+ spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
+ if (rc){
+ PRINT_WARN("qeth_osn_send_control_data: "
+ "ccw_device_start rc = %i\n", rc);
+ QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+ qeth_release_buffer(iob->channel, iob);
+ atomic_set(&card->write.irq_pending, 0);
+ wake_up(&card->wait_q);
+ }
+ return rc;
+}
+
+static inline void
+qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+ char prot_type)
+{
+ memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+ memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1);
+ memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
+ &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+}
+
+static int
+qeth_osn_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+ int data_len)
+{
+ u16 s1, s2;
+
+QETH_DBF_TEXT(trace,4,"osndipa");
+
+ qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2);
+ s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len);
+ s2 = (u16)data_len;
+ memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
+ memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
+ memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
+ memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
+ return qeth_osn_send_control_data(card, s1, iob);
+}
+
+static int
qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
int (*reply_cb)
(struct qeth_card *,struct qeth_reply*, unsigned long),
@@ -1858,17 +1933,14 @@ qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
QETH_DBF_TEXT(trace,4,"sendipa");
- memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
-
if (card->options.layer2)
- prot_type = QETH_PROT_LAYER2;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ prot_type = QETH_PROT_OSN2;
+ else
+ prot_type = QETH_PROT_LAYER2;
else
prot_type = QETH_PROT_TCPIP;
-
- memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1);
- memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
- &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
-
+ qeth_prepare_ipa_cmd(card,iob,prot_type);
rc = qeth_send_control_data(card, IPA_CMD_LENGTH, iob,
reply_cb, reply_param);
return rc;
@@ -2010,7 +2082,10 @@ qeth_ulp_enable(struct qeth_card *card)
*(QETH_ULP_ENABLE_LINKNUM(iob->data)) =
(__u8) card->info.portno;
if (card->options.layer2)
- prot_type = QETH_PROT_LAYER2;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ prot_type = QETH_PROT_OSN2;
+ else
+ prot_type = QETH_PROT_LAYER2;
else
prot_type = QETH_PROT_TCPIP;
@@ -2100,15 +2175,21 @@ qeth_check_for_inbound_error(struct qeth_qdio_buffer *buf,
}
static inline struct sk_buff *
-qeth_get_skb(unsigned int length)
+qeth_get_skb(unsigned int length, struct qeth_hdr *hdr)
{
struct sk_buff* skb;
+ int add_len;
+
+ add_len = 0;
+ if (hdr->hdr.osn.id == QETH_HEADER_TYPE_OSN)
+ add_len = sizeof(struct qeth_hdr);
#ifdef CONFIG_QETH_VLAN
- if ((skb = dev_alloc_skb(length + VLAN_HLEN)))
- skb_reserve(skb, VLAN_HLEN);
-#else
- skb = dev_alloc_skb(length);
+ else
+ add_len = VLAN_HLEN;
#endif
+ skb = dev_alloc_skb(length + add_len);
+ if (skb && add_len)
+ skb_reserve(skb, add_len);
return skb;
}
@@ -2138,7 +2219,10 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
offset += sizeof(struct qeth_hdr);
if (card->options.layer2)
- skb_len = (*hdr)->hdr.l2.pkt_length;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ skb_len = (*hdr)->hdr.osn.pdu_length;
+ else
+ skb_len = (*hdr)->hdr.l2.pkt_length;
else
skb_len = (*hdr)->hdr.l3.length;
@@ -2146,15 +2230,15 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
return NULL;
if (card->options.fake_ll){
if(card->dev->type == ARPHRD_IEEE802_TR){
- if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR)))
+ if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR, *hdr)))
goto no_mem;
skb_reserve(skb,QETH_FAKE_LL_LEN_TR);
} else {
- if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH)))
+ if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH, *hdr)))
goto no_mem;
skb_reserve(skb,QETH_FAKE_LL_LEN_ETH);
}
- } else if (!(skb = qeth_get_skb(skb_len)))
+ } else if (!(skb = qeth_get_skb(skb_len, *hdr)))
goto no_mem;
data_ptr = element->addr + offset;
while (skb_len) {
@@ -2453,8 +2537,12 @@ qeth_process_inbound_buffer(struct qeth_card *card,
skb->dev = card->dev;
if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr);
- else
+ else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3)
qeth_rebuild_skb(card, skb, hdr);
+ else { /*in case of OSN*/
+ skb_push(skb, sizeof(struct qeth_hdr));
+ memcpy(skb->data, hdr, sizeof(struct qeth_hdr));
+ }
/* is device UP ? */
if (!(card->dev->flags & IFF_UP)){
dev_kfree_skb_any(skb);
@@ -2465,7 +2553,10 @@ qeth_process_inbound_buffer(struct qeth_card *card,
vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag);
else
#endif
- rxrc = netif_rx(skb);
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ rxrc = card->osn_info.data_cb(skb);
+ else
+ rxrc = netif_rx(skb);
card->dev->last_rx = jiffies;
card->stats.rx_packets++;
card->stats.rx_bytes += skb->len;
@@ -3150,8 +3241,6 @@ qeth_init_qdio_info(struct qeth_card *card)
INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list);
INIT_LIST_HEAD(&card->qdio.init_pool.entry_list);
/* outbound */
- card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
- card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
}
static int
@@ -3466,7 +3555,7 @@ qeth_mpc_initialize(struct qeth_card *card)
return 0;
out_qdio:
- qeth_qdio_clear_card(card, card->info.type==QETH_CARD_TYPE_OSAE);
+ qeth_qdio_clear_card(card, card->info.type!=QETH_CARD_TYPE_IQD);
return rc;
}
@@ -3491,6 +3580,9 @@ qeth_get_netdevice(enum qeth_card_types type, enum qeth_link_types linktype)
case QETH_CARD_TYPE_IQD:
dev = alloc_netdev(0, "hsi%d", ether_setup);
break;
+ case QETH_CARD_TYPE_OSN:
+ dev = alloc_netdev(0, "osn%d", ether_setup);
+ break;
default:
dev = alloc_etherdev(0);
}
@@ -3655,7 +3747,8 @@ qeth_open(struct net_device *dev)
if (card->state != CARD_STATE_SOFTSETUP)
return -ENODEV;
- if ( (card->options.layer2) &&
+ if ( (card->info.type != QETH_CARD_TYPE_OSN) &&
+ (card->options.layer2) &&
(!card->info.layer2_mac_registered)) {
QETH_DBF_TEXT(trace,4,"nomacadr");
return -EPERM;
@@ -3693,6 +3786,9 @@ qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
{
int cast_type = RTN_UNSPEC;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return cast_type;
+
if (skb->dst && skb->dst->neighbour){
cast_type = skb->dst->neighbour->type;
if ((cast_type == RTN_BROADCAST) ||
@@ -3782,13 +3878,16 @@ static inline int
qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
struct qeth_hdr **hdr, int ipv)
{
- int rc;
+ int rc = 0;
#ifdef CONFIG_QETH_VLAN
u16 *tag;
#endif
QETH_DBF_TEXT(trace, 6, "prepskb");
-
+ if (card->info.type == QETH_CARD_TYPE_OSN) {
+ *hdr = (struct qeth_hdr *)(*skb)->data;
+ return rc;
+ }
rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
if (rc)
return rc;
@@ -4291,8 +4390,14 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
}
}
}
+ if ((card->info.type == QETH_CARD_TYPE_OSN) &&
+ (skb->protocol == htons(ETH_P_IPV6))) {
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
cast_type = qeth_get_cast_type(card, skb);
- if ((cast_type == RTN_BROADCAST) && (card->info.broadcast_capable == 0)){
+ if ((cast_type == RTN_BROADCAST) &&
+ (card->info.broadcast_capable == 0)){
card->stats.tx_dropped++;
card->stats.tx_errors++;
dev_kfree_skb_any(skb);
@@ -4320,7 +4425,8 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc);
return rc;
}
- qeth_fill_header(card, hdr, skb, ipv, cast_type);
+ if (card->info.type != QETH_CARD_TYPE_OSN)
+ qeth_fill_header(card, hdr, skb, ipv, cast_type);
}
if (large_send == QETH_LARGE_SEND_EDDP) {
@@ -4381,6 +4487,7 @@ qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
case MII_BMCR: /* Basic mode control register */
rc = BMCR_FULLDPLX;
if ((card->info.link_type != QETH_LINK_TYPE_GBIT_ETH)&&
+ (card->info.link_type != QETH_LINK_TYPE_OSN) &&
(card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH))
rc |= BMCR_SPEED100;
break;
@@ -5004,6 +5111,9 @@ qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
(card->state != CARD_STATE_SOFTSETUP))
return -ENODEV;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return -EPERM;
+
switch (cmd){
case SIOC_QETH_ARP_SET_NO_ENTRIES:
if ( !capable(CAP_NET_ADMIN) ||
@@ -5329,6 +5439,9 @@ qeth_set_multicast_list(struct net_device *dev)
{
struct qeth_card *card = (struct qeth_card *) dev->priv;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return ;
+
QETH_DBF_TEXT(trace,3,"setmulti");
qeth_delete_mc_addresses(card);
qeth_add_multicast_ipv4(card);
@@ -5370,6 +5483,94 @@ qeth_get_addr_buffer(enum qeth_prot_versions prot)
return addr;
}
+int
+qeth_osn_assist(struct net_device *dev,
+ void *data,
+ int data_len)
+{
+ struct qeth_cmd_buffer *iob;
+ struct qeth_card *card;
+ int rc;
+
+ QETH_DBF_TEXT(trace, 2, "osnsdmc");
+ if (!dev)
+ return -ENODEV;
+ card = (struct qeth_card *)dev->priv;
+ if (!card)
+ return -ENODEV;
+ if ((card->state != CARD_STATE_UP) &&
+ (card->state != CARD_STATE_SOFTSETUP))
+ return -ENODEV;
+ iob = qeth_wait_for_buffer(&card->write);
+ memcpy(iob->data+IPA_PDU_HEADER_SIZE, data, data_len);
+ rc = qeth_osn_send_ipa_cmd(card, iob, data_len);
+ return rc;
+}
+
+static struct net_device *
+qeth_netdev_by_devno(unsigned char *read_dev_no)
+{
+ struct qeth_card *card;
+ struct net_device *ndev;
+ unsigned char *readno;
+ __u16 temp_dev_no, card_dev_no;
+ char *endp;
+ unsigned long flags;
+
+ ndev = NULL;
+ memcpy(&temp_dev_no, read_dev_no, 2);
+ read_lock_irqsave(&qeth_card_list.rwlock, flags);
+ list_for_each_entry(card, &qeth_card_list.list, list) {
+ readno = CARD_RDEV_ID(card);
+ readno += (strlen(readno) - 4);
+ card_dev_no = simple_strtoul(readno, &endp, 16);
+ if (card_dev_no == temp_dev_no) {
+ ndev = card->dev;
+ break;
+ }
+ }
+ read_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+ return ndev;
+}
+
+int
+qeth_osn_register(unsigned char *read_dev_no,
+ struct net_device **dev,
+ int (*assist_cb)(struct net_device *, void *),
+ int (*data_cb)(struct sk_buff *))
+{
+ struct qeth_card * card;
+
+ QETH_DBF_TEXT(trace, 2, "osnreg");
+ *dev = qeth_netdev_by_devno(read_dev_no);
+ if (*dev == NULL)
+ return -ENODEV;
+ card = (struct qeth_card *)(*dev)->priv;
+ if (!card)
+ return -ENODEV;
+ if ((assist_cb == NULL) || (data_cb == NULL))
+ return -EINVAL;
+ card->osn_info.assist_cb = assist_cb;
+ card->osn_info.data_cb = data_cb;
+ return 0;
+}
+
+void
+qeth_osn_deregister(struct net_device * dev)
+{
+ struct qeth_card *card;
+
+ QETH_DBF_TEXT(trace, 2, "osndereg");
+ if (!dev)
+ return;
+ card = (struct qeth_card *)dev->priv;
+ if (!card)
+ return;
+ card->osn_info.assist_cb = NULL;
+ card->osn_info.data_cb = NULL;
+ return;
+}
+
static void
qeth_delete_mc_addresses(struct qeth_card *card)
{
@@ -5700,6 +5901,12 @@ qeth_layer2_set_mac_address(struct net_device *dev, void *p)
QETH_DBF_TEXT(trace, 3, "setmcLY3");
return -EOPNOTSUPP;
}
+ if (card->info.type == QETH_CARD_TYPE_OSN) {
+ PRINT_WARN("Setting MAC address on %s is not supported.\n",
+ dev->name);
+ QETH_DBF_TEXT(trace, 3, "setmcOSN");
+ return -EOPNOTSUPP;
+ }
QETH_DBF_TEXT_(trace, 3, "%s", CARD_BUS_ID(card));
QETH_DBF_HEX(trace, 3, addr->sa_data, OSA_ADDR_LEN);
rc = qeth_layer2_send_delmac(card, &card->dev->dev_addr[0]);
@@ -6076,9 +6283,8 @@ qeth_netdev_init(struct net_device *dev)
qeth_get_hlen(card->info.link_type) + card->options.add_hhlen;
dev->addr_len = OSA_ADDR_LEN;
dev->mtu = card->info.initial_mtu;
-
- SET_ETHTOOL_OPS(dev, &qeth_ethtool_ops);
-
+ if (card->info.type != QETH_CARD_TYPE_OSN)
+ SET_ETHTOOL_OPS(dev, &qeth_ethtool_ops);
SET_MODULE_OWNER(dev);
return 0;
}
@@ -6095,6 +6301,7 @@ qeth_init_func_level(struct qeth_card *card)
QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT;
} else {
if (card->info.type == QETH_CARD_TYPE_IQD)
+ /*FIXME:why do we have same values for dis and ena for osae??? */
card->info.func_level =
QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT;
else
@@ -6124,7 +6331,7 @@ retry:
ccw_device_set_online(CARD_WDEV(card));
ccw_device_set_online(CARD_DDEV(card));
}
- rc = qeth_qdio_clear_card(card,card->info.type==QETH_CARD_TYPE_OSAE);
+ rc = qeth_qdio_clear_card(card,card->info.type!=QETH_CARD_TYPE_IQD);
if (rc == -ERESTARTSYS) {
QETH_DBF_TEXT(setup, 2, "break1");
return rc;
@@ -6176,8 +6383,8 @@ retry:
card->dev = qeth_get_netdevice(card->info.type,
card->info.link_type);
if (!card->dev){
- qeth_qdio_clear_card(card, card->info.type ==
- QETH_CARD_TYPE_OSAE);
+ qeth_qdio_clear_card(card, card->info.type !=
+ QETH_CARD_TYPE_IQD);
rc = -ENODEV;
QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
goto out;
@@ -7084,6 +7291,8 @@ qeth_softsetup_card(struct qeth_card *card)
return rc;
} else
card->lan_online = 1;
+ if (card->info.type==QETH_CARD_TYPE_OSN)
+ goto out;
if (card->options.layer2) {
card->dev->features |=
NETIF_F_HW_VLAN_FILTER |
@@ -7255,7 +7464,8 @@ qeth_stop_card(struct qeth_card *card, int recovery_mode)
if (card->read.state == CH_STATE_UP &&
card->write.state == CH_STATE_UP &&
(card->state == CARD_STATE_UP)) {
- if(recovery_mode) {
+ if (recovery_mode &&
+ card->info.type != QETH_CARD_TYPE_OSN) {
qeth_stop(card->dev);
} else {
rtnl_lock();
@@ -7437,7 +7647,8 @@ qeth_start_again(struct qeth_card *card, int recovery_mode)
{
QETH_DBF_TEXT(setup ,2, "startag");
- if(recovery_mode) {
+ if (recovery_mode &&
+ card->info.type != QETH_CARD_TYPE_OSN) {
qeth_open(card->dev);
} else {
rtnl_lock();
@@ -7469,33 +7680,36 @@ qeth_start_again(struct qeth_card *card, int recovery_mode)
static void qeth_make_parameters_consistent(struct qeth_card *card)
{
- if (card->options.layer2) {
- if (card->info.type == QETH_CARD_TYPE_IQD) {
- PRINT_ERR("Device %s does not support " \
- "layer 2 functionality. " \
- "Ignoring layer2 option.\n",CARD_BUS_ID(card));
- }
- IGNORE_PARAM_NEQ(route4.type, NO_ROUTER, NO_ROUTER,
- "Routing options are");
+ if (card->options.layer2 == 0)
+ return;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return;
+ if (card->info.type == QETH_CARD_TYPE_IQD) {
+ PRINT_ERR("Device %s does not support layer 2 functionality." \
+ " Ignoring layer2 option.\n",CARD_BUS_ID(card));
+ card->options.layer2 = 0;
+ return;
+ }
+ IGNORE_PARAM_NEQ(route4.type, NO_ROUTER, NO_ROUTER,
+ "Routing options are");
#ifdef CONFIG_QETH_IPV6
- IGNORE_PARAM_NEQ(route6.type, NO_ROUTER, NO_ROUTER,
- "Routing options are");
+ IGNORE_PARAM_NEQ(route6.type, NO_ROUTER, NO_ROUTER,
+ "Routing options are");
#endif
- IGNORE_PARAM_EQ(checksum_type, HW_CHECKSUMMING,
- QETH_CHECKSUM_DEFAULT,
- "Checksumming options are");
- IGNORE_PARAM_NEQ(broadcast_mode, QETH_TR_BROADCAST_ALLRINGS,
- QETH_TR_BROADCAST_ALLRINGS,
- "Broadcast mode options are");
- IGNORE_PARAM_NEQ(macaddr_mode, QETH_TR_MACADDR_NONCANONICAL,
- QETH_TR_MACADDR_NONCANONICAL,
- "Canonical MAC addr options are");
- IGNORE_PARAM_NEQ(fake_broadcast, 0, 0,
- "Broadcast faking options are");
- IGNORE_PARAM_NEQ(add_hhlen, DEFAULT_ADD_HHLEN,
- DEFAULT_ADD_HHLEN,"Option add_hhlen is");
- IGNORE_PARAM_NEQ(fake_ll, 0, 0,"Option fake_ll is");
- }
+ IGNORE_PARAM_EQ(checksum_type, HW_CHECKSUMMING,
+ QETH_CHECKSUM_DEFAULT,
+ "Checksumming options are");
+ IGNORE_PARAM_NEQ(broadcast_mode, QETH_TR_BROADCAST_ALLRINGS,
+ QETH_TR_BROADCAST_ALLRINGS,
+ "Broadcast mode options are");
+ IGNORE_PARAM_NEQ(macaddr_mode, QETH_TR_MACADDR_NONCANONICAL,
+ QETH_TR_MACADDR_NONCANONICAL,
+ "Canonical MAC addr options are");
+ IGNORE_PARAM_NEQ(fake_broadcast, 0, 0,
+ "Broadcast faking options are");
+ IGNORE_PARAM_NEQ(add_hhlen, DEFAULT_ADD_HHLEN,
+ DEFAULT_ADD_HHLEN,"Option add_hhlen is");
+ IGNORE_PARAM_NEQ(fake_ll, 0, 0,"Option fake_ll is");
}
@@ -7525,8 +7739,7 @@ __qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode)
return -EIO;
}
- if (card->options.layer2)
- qeth_make_parameters_consistent(card);
+ qeth_make_parameters_consistent(card);
if ((rc = qeth_hardsetup_card(card))){
QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
@@ -7585,6 +7798,7 @@ qeth_set_online(struct ccwgroup_device *gdev)
static struct ccw_device_id qeth_ids[] = {
{CCW_DEVICE(0x1731, 0x01), driver_info:QETH_CARD_TYPE_OSAE},
{CCW_DEVICE(0x1731, 0x05), driver_info:QETH_CARD_TYPE_IQD},
+ {CCW_DEVICE(0x1731, 0x06), driver_info:QETH_CARD_TYPE_OSN},
{},
};
MODULE_DEVICE_TABLE(ccw, qeth_ids);
@@ -8329,6 +8543,9 @@ again:
printk("qeth: removed\n");
}
+EXPORT_SYMBOL(qeth_osn_register);
+EXPORT_SYMBOL(qeth_osn_deregister);
+EXPORT_SYMBOL(qeth_osn_assist);
module_init(qeth_init);
module_exit(qeth_exit);
MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>");
diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c
index f685ecc7da99dc..30e053d3cac293 100644
--- a/drivers/s390/net/qeth_mpc.c
+++ b/drivers/s390/net/qeth_mpc.c
@@ -11,7 +11,7 @@
#include <asm/cio.h>
#include "qeth_mpc.h"
-const char *VERSION_QETH_MPC_C = "$Revision: 1.11 $";
+const char *VERSION_QETH_MPC_C = "$Revision: 1.12 $";
unsigned char IDX_ACTIVATE_READ[]={
0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00,
@@ -138,7 +138,9 @@ unsigned char IPA_PDU_HEADER[]={
sizeof(struct qeth_ipa_cmd)%256,
0x00,
sizeof(struct qeth_ipa_cmd)/256,
- sizeof(struct qeth_ipa_cmd),0x05, 0x77,0x77,0x77,0x77,
+ sizeof(struct qeth_ipa_cmd)%256,
+ 0x05,
+ 0x77,0x77,0x77,0x77,
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
0x01,0x00,
sizeof(struct qeth_ipa_cmd)/256,
diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h
index 3d916b5c5d09c4..7edc5f1fc0d24d 100644
--- a/drivers/s390/net/qeth_mpc.h
+++ b/drivers/s390/net/qeth_mpc.h
@@ -46,13 +46,16 @@ extern unsigned char IPA_PDU_HEADER[];
/* IP Assist related definitions */
/*****************************************************************************/
#define IPA_CMD_INITIATOR_HOST 0x00
-#define IPA_CMD_INITIATOR_HYDRA 0x01
+#define IPA_CMD_INITIATOR_OSA 0x01
+#define IPA_CMD_INITIATOR_HOST_REPLY 0x80
+#define IPA_CMD_INITIATOR_OSA_REPLY 0x81
#define IPA_CMD_PRIM_VERSION_NO 0x01
enum qeth_card_types {
QETH_CARD_TYPE_UNKNOWN = 0,
QETH_CARD_TYPE_OSAE = 10,
QETH_CARD_TYPE_IQD = 1234,
+ QETH_CARD_TYPE_OSN = 11,
};
#define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18
@@ -61,6 +64,7 @@ enum qeth_link_types {
QETH_LINK_TYPE_FAST_ETH = 0x01,
QETH_LINK_TYPE_HSTR = 0x02,
QETH_LINK_TYPE_GBIT_ETH = 0x03,
+ QETH_LINK_TYPE_OSN = 0x04,
QETH_LINK_TYPE_10GBIT_ETH = 0x10,
QETH_LINK_TYPE_LANE_ETH100 = 0x81,
QETH_LINK_TYPE_LANE_TR = 0x82,
@@ -111,6 +115,9 @@ enum qeth_ipa_cmds {
IPA_CMD_DELGMAC = 0x24,
IPA_CMD_SETVLAN = 0x25,
IPA_CMD_DELVLAN = 0x26,
+ IPA_CMD_SETCCID = 0x41,
+ IPA_CMD_DELCCID = 0x42,
+ IPA_CMD_MODCCID = 0x43,
IPA_CMD_SETIP = 0xb1,
IPA_CMD_DELIP = 0xb7,
IPA_CMD_QIPASSIST = 0xb2,
@@ -437,8 +444,9 @@ enum qeth_ipa_arp_return_codes {
#define QETH_ARP_DATA_SIZE 3968
#define QETH_ARP_CMD_LEN (QETH_ARP_DATA_SIZE + 8)
/* Helper functions */
-#define IS_IPA_REPLY(cmd) (cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST)
-
+#define IS_IPA_REPLY(cmd) ((cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) || \
+ (cmd->hdr.initiator == IPA_CMD_INITIATOR_OSA_REPLY))
+
/*****************************************************************************/
/* END OF IP Assist related definitions */
/*****************************************************************************/
@@ -483,6 +491,7 @@ extern unsigned char ULP_ENABLE[];
/* Layer 2 defintions */
#define QETH_PROT_LAYER2 0x08
#define QETH_PROT_TCPIP 0x03
+#define QETH_PROT_OSN2 0x0a
#define QETH_ULP_ENABLE_PROT_TYPE(buffer) (buffer+0x50)
#define QETH_IPA_CMD_PROT_TYPE(buffer) (buffer+0x19)
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
index dda105b73063d0..f91a02db57437b 100644
--- a/drivers/s390/net/qeth_sys.c
+++ b/drivers/s390/net/qeth_sys.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.54 $)
+ * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.55 $)
*
* Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to sysfs.
@@ -20,7 +20,7 @@
#include "qeth_mpc.h"
#include "qeth_fs.h"
-const char *VERSION_QETH_SYS_C = "$Revision: 1.54 $";
+const char *VERSION_QETH_SYS_C = "$Revision: 1.55 $";
/*****************************************************************************/
/* */
@@ -937,6 +937,19 @@ static struct attribute_group qeth_device_attr_group = {
.attrs = (struct attribute **)qeth_device_attrs,
};
+static struct device_attribute * qeth_osn_device_attrs[] = {
+ &dev_attr_state,
+ &dev_attr_chpid,
+ &dev_attr_if_name,
+ &dev_attr_card_type,
+ &dev_attr_buffer_count,
+ &dev_attr_recover,
+ NULL,
+};
+
+static struct attribute_group qeth_osn_device_attr_group = {
+ .attrs = (struct attribute **)qeth_osn_device_attrs,
+};
#define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store) \
struct device_attribute dev_attr_##_id = { \
@@ -1667,7 +1680,12 @@ int
qeth_create_device_attributes(struct device *dev)
{
int ret;
+ struct qeth_card *card = dev->driver_data;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return sysfs_create_group(&dev->kobj,
+ &qeth_osn_device_attr_group);
+
if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group)))
return ret;
if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group))){
@@ -1693,6 +1711,12 @@ qeth_create_device_attributes(struct device *dev)
void
qeth_remove_device_attributes(struct device *dev)
{
+ struct qeth_card *card = dev->driver_data;
+
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return sysfs_remove_group(&dev->kobj,
+ &qeth_osn_device_attr_group);
+
sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 3ee9b8b33be0de..9c9f162bd6edc6 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -489,11 +489,11 @@ config SCSI_SATA_NV
If unsure, say N.
-config SCSI_SATA_PROMISE
- tristate "Promise SATA TX2/TX4 support"
+config SCSI_PDC_ADMA
+ tristate "Pacific Digital ADMA support"
depends on SCSI_SATA && PCI
help
- This option enables support for Promise Serial ATA TX2/TX4.
+ This option enables support for Pacific Digital ADMA controllers
If unsure, say N.
@@ -505,6 +505,14 @@ config SCSI_SATA_QSTOR
If unsure, say N.
+config SCSI_SATA_PROMISE
+ tristate "Promise SATA TX2/TX4 support"
+ depends on SCSI_SATA && PCI
+ help
+ This option enables support for Promise Serial ATA TX2/TX4.
+
+ If unsure, say N.
+
config SCSI_SATA_SX4
tristate "Promise SATA SX4 support"
depends on SCSI_SATA && PCI && EXPERIMENTAL
@@ -521,6 +529,14 @@ config SCSI_SATA_SIL
If unsure, say N.
+config SCSI_SATA_SIL24
+ tristate "Silicon Image 3124/3132 SATA support"
+ depends on SCSI_SATA && PCI && EXPERIMENTAL
+ help
+ This option enables support for Silicon Image 3124/3132 Serial ATA.
+
+ If unsure, say N.
+
config SCSI_SATA_SIS
tristate "SiS 964/180 SATA support"
depends on SCSI_SATA && PCI && EXPERIMENTAL
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 48529d180ca886..2d4439826c08d9 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -130,6 +130,7 @@ obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o
obj-$(CONFIG_SCSI_SATA_PROMISE) += libata.o sata_promise.o
obj-$(CONFIG_SCSI_SATA_QSTOR) += libata.o sata_qstor.o
obj-$(CONFIG_SCSI_SATA_SIL) += libata.o sata_sil.o
+obj-$(CONFIG_SCSI_SATA_SIL24) += libata.o sata_sil24.o
obj-$(CONFIG_SCSI_SATA_VIA) += libata.o sata_via.o
obj-$(CONFIG_SCSI_SATA_VITESSE) += libata.o sata_vsc.o
obj-$(CONFIG_SCSI_SATA_SIS) += libata.o sata_sis.o
@@ -137,6 +138,7 @@ obj-$(CONFIG_SCSI_SATA_SX4) += libata.o sata_sx4.o
obj-$(CONFIG_SCSI_SATA_NV) += libata.o sata_nv.o
obj-$(CONFIG_SCSI_SATA_ULI) += libata.o sata_uli.o
obj-$(CONFIG_SCSI_SATA_MV) += libata.o sata_mv.o
+obj-$(CONFIG_SCSI_PDC_ADMA) += libata.o pdc_adma.o
obj-$(CONFIG_ARM) += arm/
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index c2c8fa828e24e9..fe8187d6f58be2 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -216,7 +216,7 @@ static Scsi_Host_Template ahci_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations ahci_ops = {
+static const struct ata_port_operations ahci_ops = {
.port_disable = ata_port_disable,
.check_status = ahci_check_status,
@@ -407,7 +407,7 @@ static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
return 0xffffffffU;
}
- return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
@@ -425,7 +425,7 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in,
return;
}
- writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
static void ahci_phy_reset(struct ata_port *ap)
@@ -453,14 +453,14 @@ static void ahci_phy_reset(struct ata_port *ap)
static u8 ahci_check_status(struct ata_port *ap)
{
- void *mmio = (void *) ap->ioaddr.cmd_addr;
+ void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
return readl(mmio + PORT_TFDATA) & 0xFF;
}
static u8 ahci_check_err(struct ata_port *ap)
{
- void *mmio = (void *) ap->ioaddr.cmd_addr;
+ void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
return (readl(mmio + PORT_TFDATA) >> 8) & 0xFF;
}
@@ -672,17 +672,36 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
for (i = 0; i < host_set->n_ports; i++) {
struct ata_port *ap;
- u32 tmp;
- VPRINTK("port %u\n", i);
+ if (!(irq_stat & (1 << i)))
+ continue;
+
ap = host_set->ports[i];
- tmp = irq_stat & (1 << i);
- if (tmp && ap) {
+ if (ap) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
- if (ahci_host_intr(ap, qc))
- irq_ack |= (1 << i);
+ if (!ahci_host_intr(ap, qc))
+ if (ata_ratelimit()) {
+ struct pci_dev *pdev =
+ to_pci_dev(ap->host_set->dev);
+ printk(KERN_WARNING
+ "ahci(%s): unhandled interrupt on port %u\n",
+ pci_name(pdev), i);
+ }
+
+ VPRINTK("port %u\n", i);
+ } else {
+ VPRINTK("port %u (no irq)\n", i);
+ if (ata_ratelimit()) {
+ struct pci_dev *pdev =
+ to_pci_dev(ap->host_set->dev);
+ printk(KERN_WARNING
+ "ahci(%s): interrupt on disabled port %u\n",
+ pci_name(pdev), i);
+ }
}
+
+ irq_ack |= (1 << i);
}
if (irq_ack) {
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index d71cef767cec78..be021478f41628 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -147,7 +147,7 @@ static Scsi_Host_Template piix_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations piix_pata_ops = {
+static const struct ata_port_operations piix_pata_ops = {
.port_disable = ata_port_disable,
.set_piomode = piix_set_piomode,
.set_dmamode = piix_set_dmamode,
@@ -177,7 +177,7 @@ static struct ata_port_operations piix_pata_ops = {
.host_stop = ata_host_stop,
};
-static struct ata_port_operations piix_sata_ops = {
+static const struct ata_port_operations piix_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index da6e51c7fe696d..540147cb51ce1a 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -936,7 +936,7 @@ static int ch_probe(struct device *dev)
if (init)
ch_init_elem(ch);
- class_device_create(ch_sysfs_class,
+ class_device_create(ch_sysfs_class, NULL,
MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
dev, "s%s", ch->name);
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
index c10e45b94b6269..3d13fdee4fc26e 100644
--- a/drivers/scsi/eata.c
+++ b/drivers/scsi/eata.c
@@ -1357,7 +1357,7 @@ static int port_detect(unsigned long port_base, unsigned int j,
for (i = 0; i < shost->can_queue; i++) {
size_t sz = shost->sg_tablesize *sizeof(struct sg_list);
- unsigned int gfp_mask = (shost->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC;
+ gfp_t gfp_mask = (shost->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC;
ha->cp[i].sglist = kmalloc(sz, gfp_mask);
if (!ha->cp[i].sglist) {
printk
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 02fe371b0ab871..f24d84538fd56a 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -287,7 +287,8 @@ static void scsi_host_dev_release(struct device *dev)
struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
{
struct Scsi_Host *shost;
- int gfp_mask = GFP_KERNEL, rval;
+ gfp_t gfp_mask = GFP_KERNEL;
+ int rval;
if (sht->unchecked_isa_dma && privsize)
gfp_mask |= __GFP_DMA;
diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
index 4cbb6187cc441f..459a4daebece31 100644
--- a/drivers/scsi/lasi700.c
+++ b/drivers/scsi/lasi700.c
@@ -98,7 +98,7 @@ MODULE_DEVICE_TABLE(parisc, lasi700_ids);
static int __init
lasi700_probe(struct parisc_device *dev)
{
- unsigned long base = dev->hpa + LASI_SCSI_CORE_OFFSET;
+ unsigned long base = dev->hpa.start + LASI_SCSI_CORE_OFFSET;
struct NCR_700_Host_Parameters *hostdata;
struct Scsi_Host *host;
@@ -125,8 +125,6 @@ lasi700_probe(struct parisc_device *dev)
hostdata->dmode_extra = DMODE_FC2;
}
- NCR_700_set_mem_mapped(hostdata);
-
host = NCR_700_detect(&lasi700_template, hostdata, &dev->dev);
if (!host)
goto out_kfree;
@@ -168,7 +166,7 @@ lasi700_driver_remove(struct parisc_device *dev)
}
static struct parisc_driver lasi700_driver = {
- .name = "Lasi SCSI",
+ .name = "lasi_scsi",
.id_table = lasi700_ids,
.probe = lasi700_probe,
.remove = __devexit_p(lasi700_driver_remove),
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index e5b01997117a99..f53d7b8ac33f41 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -48,6 +48,7 @@
#include <linux/completion.h>
#include <linux/suspend.h>
#include <linux/workqueue.h>
+#include <linux/jiffies.h>
#include <scsi/scsi.h>
#include "scsi.h"
#include "scsi_priv.h"
@@ -62,14 +63,15 @@
static unsigned int ata_busy_sleep (struct ata_port *ap,
unsigned long tmout_pat,
unsigned long tmout);
+static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev);
+static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev);
static void ata_set_mode(struct ata_port *ap);
static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev);
-static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift);
+static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift);
static int fgb(u32 bitmap);
-static int ata_choose_xfer_mode(struct ata_port *ap,
+static int ata_choose_xfer_mode(const struct ata_port *ap,
u8 *xfer_mode_out,
unsigned int *xfer_shift_out);
-static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat);
static void __ata_qc_complete(struct ata_queued_cmd *qc);
static unsigned int ata_unique_id = 1;
@@ -85,7 +87,7 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
/**
- * ata_tf_load - send taskfile registers to host controller
+ * ata_tf_load_pio - send taskfile registers to host controller
* @ap: Port to which output is sent
* @tf: ATA taskfile register set
*
@@ -95,7 +97,7 @@ MODULE_VERSION(DRV_VERSION);
* Inherited from caller.
*/
-static void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_load_pio(struct ata_port *ap, const struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@@ -153,7 +155,7 @@ static void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
* Inherited from caller.
*/
-static void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@@ -222,7 +224,7 @@ static void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
* LOCKING:
* Inherited from caller.
*/
-void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
+void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
{
if (ap->flags & ATA_FLAG_MMIO)
ata_tf_load_mmio(ap, tf);
@@ -242,7 +244,7 @@ void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
* spin_lock_irqsave(host_set lock)
*/
-static void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_exec_command_pio(struct ata_port *ap, const struct ata_taskfile *tf)
{
DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
@@ -263,7 +265,7 @@ static void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf)
* spin_lock_irqsave(host_set lock)
*/
-static void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
@@ -283,7 +285,7 @@ static void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
-void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf)
+void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
{
if (ap->flags & ATA_FLAG_MMIO)
ata_exec_command_mmio(ap, tf);
@@ -303,7 +305,7 @@ void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf)
* Obtains host_set lock.
*/
-static inline void ata_exec(struct ata_port *ap, struct ata_taskfile *tf)
+static inline void ata_exec(struct ata_port *ap, const struct ata_taskfile *tf)
{
unsigned long flags;
@@ -326,7 +328,7 @@ static inline void ata_exec(struct ata_port *ap, struct ata_taskfile *tf)
* Obtains host_set lock.
*/
-static void ata_tf_to_host(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_to_host(struct ata_port *ap, const struct ata_taskfile *tf)
{
ap->ops->tf_load(ap, tf);
@@ -346,7 +348,7 @@ static void ata_tf_to_host(struct ata_port *ap, struct ata_taskfile *tf)
* spin_lock_irqsave(host_set lock)
*/
-void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf)
+void ata_tf_to_host_nolock(struct ata_port *ap, const struct ata_taskfile *tf)
{
ap->ops->tf_load(ap, tf);
ap->ops->exec_command(ap, tf);
@@ -556,7 +558,7 @@ u8 ata_chk_err(struct ata_port *ap)
* Inherited from caller.
*/
-void ata_tf_to_fis(struct ata_taskfile *tf, u8 *fis, u8 pmp)
+void ata_tf_to_fis(const struct ata_taskfile *tf, u8 *fis, u8 pmp)
{
fis[0] = 0x27; /* Register - Host to Device FIS */
fis[1] = (pmp & 0xf) | (1 << 7); /* Port multiplier number,
@@ -597,7 +599,7 @@ void ata_tf_to_fis(struct ata_taskfile *tf, u8 *fis, u8 pmp)
* Inherited from caller.
*/
-void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf)
+void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf)
{
tf->command = fis[2]; /* status */
tf->feature = fis[3]; /* error */
@@ -615,79 +617,53 @@ void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf)
tf->hob_nsect = fis[13];
}
-/**
- * ata_prot_to_cmd - determine which read/write opcodes to use
- * @protocol: ATA_PROT_xxx taskfile protocol
- * @lba48: true is lba48 is present
- *
- * Given necessary input, determine which read/write commands
- * to use to transfer data.
- *
- * LOCKING:
- * None.
- */
-static int ata_prot_to_cmd(int protocol, int lba48)
-{
- int rcmd = 0, wcmd = 0;
-
- switch (protocol) {
- case ATA_PROT_PIO:
- if (lba48) {
- rcmd = ATA_CMD_PIO_READ_EXT;
- wcmd = ATA_CMD_PIO_WRITE_EXT;
- } else {
- rcmd = ATA_CMD_PIO_READ;
- wcmd = ATA_CMD_PIO_WRITE;
- }
- break;
-
- case ATA_PROT_DMA:
- if (lba48) {
- rcmd = ATA_CMD_READ_EXT;
- wcmd = ATA_CMD_WRITE_EXT;
- } else {
- rcmd = ATA_CMD_READ;
- wcmd = ATA_CMD_WRITE;
- }
- break;
-
- default:
- return -1;
- }
-
- return rcmd | (wcmd << 8);
-}
+static const u8 ata_rw_cmds[] = {
+ /* pio multi */
+ ATA_CMD_READ_MULTI,
+ ATA_CMD_WRITE_MULTI,
+ ATA_CMD_READ_MULTI_EXT,
+ ATA_CMD_WRITE_MULTI_EXT,
+ /* pio */
+ ATA_CMD_PIO_READ,
+ ATA_CMD_PIO_WRITE,
+ ATA_CMD_PIO_READ_EXT,
+ ATA_CMD_PIO_WRITE_EXT,
+ /* dma */
+ ATA_CMD_READ,
+ ATA_CMD_WRITE,
+ ATA_CMD_READ_EXT,
+ ATA_CMD_WRITE_EXT
+};
/**
- * ata_dev_set_protocol - set taskfile protocol and r/w commands
- * @dev: device to examine and configure
+ * ata_rwcmd_protocol - set taskfile r/w commands and protocol
+ * @qc: command to examine and configure
*
- * Examine the device configuration, after we have
- * read the identify-device page and configured the
- * data transfer mode. Set internal state related to
- * the ATA taskfile protocol (pio, pio mult, dma, etc.)
- * and calculate the proper read/write commands to use.
+ * Examine the device configuration and tf->flags to calculate
+ * the proper read/write commands and protocol to use.
*
* LOCKING:
* caller.
*/
-static void ata_dev_set_protocol(struct ata_device *dev)
+void ata_rwcmd_protocol(struct ata_queued_cmd *qc)
{
- int pio = (dev->flags & ATA_DFLAG_PIO);
- int lba48 = (dev->flags & ATA_DFLAG_LBA48);
- int proto, cmd;
+ struct ata_taskfile *tf = &qc->tf;
+ struct ata_device *dev = qc->dev;
- if (pio)
- proto = dev->xfer_protocol = ATA_PROT_PIO;
- else
- proto = dev->xfer_protocol = ATA_PROT_DMA;
+ int index, lba48, write;
+
+ lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0;
+ write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0;
- cmd = ata_prot_to_cmd(proto, lba48);
- if (cmd < 0)
- BUG();
+ if (dev->flags & ATA_DFLAG_PIO) {
+ tf->protocol = ATA_PROT_PIO;
+ index = dev->multi_count ? 0 : 4;
+ } else {
+ tf->protocol = ATA_PROT_DMA;
+ index = 8;
+ }
- dev->read_cmd = cmd & 0xff;
- dev->write_cmd = (cmd >> 8) & 0xff;
+ tf->command = ata_rw_cmds[index + lba48 + write];
}
static const char * xfer_mode_str[] = {
@@ -869,7 +845,7 @@ static unsigned int ata_devchk(struct ata_port *ap,
* the event of failure.
*/
-unsigned int ata_dev_classify(struct ata_taskfile *tf)
+unsigned int ata_dev_classify(const struct ata_taskfile *tf)
{
/* Apple's open source Darwin code hints that some devices only
* put a proper signature into the LBA mid/high registers,
@@ -961,7 +937,7 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device)
* caller.
*/
-void ata_dev_id_string(u16 *id, unsigned char *s,
+void ata_dev_id_string(const u16 *id, unsigned char *s,
unsigned int ofs, unsigned int len)
{
unsigned int c;
@@ -1078,7 +1054,7 @@ void ata_dev_select(struct ata_port *ap, unsigned int device,
* caller.
*/
-static inline void ata_dump_id(struct ata_device *dev)
+static inline void ata_dump_id(const struct ata_device *dev)
{
DPRINTK("49==0x%04x "
"53==0x%04x "
@@ -1106,6 +1082,31 @@ static inline void ata_dump_id(struct ata_device *dev)
dev->id[93]);
}
+/*
+ * Compute the PIO modes available for this device. This is not as
+ * trivial as it seems if we must consider early devices correctly.
+ *
+ * FIXME: pre IDE drive timing (do we care ?).
+ */
+
+static unsigned int ata_pio_modes(const struct ata_device *adev)
+{
+ u16 modes;
+
+ /* Usual case. Word 53 indicates word 88 is valid */
+ if (adev->id[ATA_ID_FIELD_VALID] & (1 << 2)) {
+ modes = adev->id[ATA_ID_PIO_MODES] & 0x03;
+ modes <<= 3;
+ modes |= 0x7;
+ return modes;
+ }
+
+ /* If word 88 isn't valid then Word 51 holds the PIO timing number
+ for the maximum. Turn it into a mask and return it */
+ modes = (2 << (adev->id[ATA_ID_OLD_PIO_MODES] & 0xFF)) - 1 ;
+ return modes;
+}
+
/**
* ata_dev_identify - obtain IDENTIFY x DEVICE page
* @ap: port on which device we wish to probe resides
@@ -1131,7 +1132,7 @@ static inline void ata_dump_id(struct ata_device *dev)
static void ata_dev_identify(struct ata_port *ap, unsigned int device)
{
struct ata_device *dev = &ap->device[device];
- unsigned int i;
+ unsigned int major_version;
u16 tmp;
unsigned long xfer_modes;
u8 status;
@@ -1229,9 +1230,9 @@ retry:
* common ATA, ATAPI feature tests
*/
- /* we require LBA and DMA support (bits 8 & 9 of word 49) */
- if (!ata_id_has_dma(dev->id) || !ata_id_has_lba(dev->id)) {
- printk(KERN_DEBUG "ata%u: no dma/lba\n", ap->id);
+ /* we require DMA support (bits 8 of word 49) */
+ if (!ata_id_has_dma(dev->id)) {
+ printk(KERN_DEBUG "ata%u: no dma\n", ap->id);
goto err_out_nosup;
}
@@ -1239,10 +1240,8 @@ retry:
xfer_modes = dev->id[ATA_ID_UDMA_MODES];
if (!xfer_modes)
xfer_modes = (dev->id[ATA_ID_MWDMA_MODES]) << ATA_SHIFT_MWDMA;
- if (!xfer_modes) {
- xfer_modes = (dev->id[ATA_ID_PIO_MODES]) << (ATA_SHIFT_PIO + 3);
- xfer_modes |= (0x7 << ATA_SHIFT_PIO);
- }
+ if (!xfer_modes)
+ xfer_modes = ata_pio_modes(dev);
ata_dump_id(dev);
@@ -1251,32 +1250,75 @@ retry:
if (!ata_id_is_ata(dev->id)) /* sanity check */
goto err_out_nosup;
+ /* get major version */
tmp = dev->id[ATA_ID_MAJOR_VER];
- for (i = 14; i >= 1; i--)
- if (tmp & (1 << i))
+ for (major_version = 14; major_version >= 1; major_version--)
+ if (tmp & (1 << major_version))
break;
- /* we require at least ATA-3 */
- if (i < 3) {
- printk(KERN_DEBUG "ata%u: no ATA-3\n", ap->id);
- goto err_out_nosup;
+ /*
+ * The exact sequence expected by certain pre-ATA4 drives is:
+ * SRST RESET
+ * IDENTIFY
+ * INITIALIZE DEVICE PARAMETERS
+ * anything else..
+ * Some drives were very specific about that exact sequence.
+ */
+ if (major_version < 4 || (!ata_id_has_lba(dev->id))) {
+ ata_dev_init_params(ap, dev);
+
+ /* current CHS translation info (id[53-58]) might be
+ * changed. reread the identify device info.
+ */
+ ata_dev_reread_id(ap, dev);
}
- if (ata_id_has_lba48(dev->id)) {
- dev->flags |= ATA_DFLAG_LBA48;
- dev->n_sectors = ata_id_u64(dev->id, 100);
- } else {
- dev->n_sectors = ata_id_u32(dev->id, 60);
+ if (ata_id_has_lba(dev->id)) {
+ dev->flags |= ATA_DFLAG_LBA;
+
+ if (ata_id_has_lba48(dev->id)) {
+ dev->flags |= ATA_DFLAG_LBA48;
+ dev->n_sectors = ata_id_u64(dev->id, 100);
+ } else {
+ dev->n_sectors = ata_id_u32(dev->id, 60);
+ }
+
+ /* print device info to dmesg */
+ printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s\n",
+ ap->id, device,
+ major_version,
+ ata_mode_string(xfer_modes),
+ (unsigned long long)dev->n_sectors,
+ dev->flags & ATA_DFLAG_LBA48 ? " LBA48" : " LBA");
+ } else {
+ /* CHS */
+
+ /* Default translation */
+ dev->cylinders = dev->id[1];
+ dev->heads = dev->id[3];
+ dev->sectors = dev->id[6];
+ dev->n_sectors = dev->cylinders * dev->heads * dev->sectors;
+
+ if (ata_id_current_chs_valid(dev->id)) {
+ /* Current CHS translation is valid. */
+ dev->cylinders = dev->id[54];
+ dev->heads = dev->id[55];
+ dev->sectors = dev->id[56];
+
+ dev->n_sectors = ata_id_u32(dev->id, 57);
+ }
+
+ /* print device info to dmesg */
+ printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors: CHS %d/%d/%d\n",
+ ap->id, device,
+ major_version,
+ ata_mode_string(xfer_modes),
+ (unsigned long long)dev->n_sectors,
+ (int)dev->cylinders, (int)dev->heads, (int)dev->sectors);
+
}
ap->host->max_cmd_len = 16;
-
- /* print device info to dmesg */
- printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu sectors:%s\n",
- ap->id, device,
- ata_mode_string(xfer_modes),
- (unsigned long long)dev->n_sectors,
- dev->flags & ATA_DFLAG_LBA48 ? " lba48" : "");
}
/* ATAPI-specific feature tests */
@@ -1310,7 +1352,7 @@ err_out:
}
-static inline u8 ata_dev_knobble(struct ata_port *ap)
+static inline u8 ata_dev_knobble(const struct ata_port *ap)
{
return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ap->device->id)));
}
@@ -1496,7 +1538,153 @@ void ata_port_disable(struct ata_port *ap)
ap->flags |= ATA_FLAG_PORT_DISABLED;
}
-static struct {
+/*
+ * This mode timing computation functionality is ported over from
+ * drivers/ide/ide-timing.h and was originally written by Vojtech Pavlik
+ */
+/*
+ * PIO 0-5, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds).
+ * These were taken from ATA/ATAPI-6 standard, rev 0a, except
+ * for PIO 5, which is a nonstandard extension and UDMA6, which
+ * is currently supported only by Maxtor drives.
+ */
+
+static const struct ata_timing ata_timing[] = {
+
+ { XFER_UDMA_6, 0, 0, 0, 0, 0, 0, 0, 15 },
+ { XFER_UDMA_5, 0, 0, 0, 0, 0, 0, 0, 20 },
+ { XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 30 },
+ { XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 45 },
+
+ { XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 60 },
+ { XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 },
+ { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 },
+
+/* { XFER_UDMA_SLOW, 0, 0, 0, 0, 0, 0, 0, 150 }, */
+
+ { XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 120, 0 },
+ { XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 150, 0 },
+ { XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 480, 0 },
+
+ { XFER_SW_DMA_2, 60, 0, 0, 0, 120, 120, 240, 0 },
+ { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 },
+ { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 },
+
+/* { XFER_PIO_5, 20, 50, 30, 100, 50, 30, 100, 0 }, */
+ { XFER_PIO_4, 25, 70, 25, 120, 70, 25, 120, 0 },
+ { XFER_PIO_3, 30, 80, 70, 180, 80, 70, 180, 0 },
+
+ { XFER_PIO_2, 30, 290, 40, 330, 100, 90, 240, 0 },
+ { XFER_PIO_1, 50, 290, 93, 383, 125, 100, 383, 0 },
+ { XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0 },
+
+/* { XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960, 0 }, */
+
+ { 0xFF }
+};
+
+#define ENOUGH(v,unit) (((v)-1)/(unit)+1)
+#define EZ(v,unit) ((v)?ENOUGH(v,unit):0)
+
+static void ata_timing_quantize(const struct ata_timing *t, struct ata_timing *q, int T, int UT)
+{
+ q->setup = EZ(t->setup * 1000, T);
+ q->act8b = EZ(t->act8b * 1000, T);
+ q->rec8b = EZ(t->rec8b * 1000, T);
+ q->cyc8b = EZ(t->cyc8b * 1000, T);
+ q->active = EZ(t->active * 1000, T);
+ q->recover = EZ(t->recover * 1000, T);
+ q->cycle = EZ(t->cycle * 1000, T);
+ q->udma = EZ(t->udma * 1000, UT);
+}
+
+void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b,
+ struct ata_timing *m, unsigned int what)
+{
+ if (what & ATA_TIMING_SETUP ) m->setup = max(a->setup, b->setup);
+ if (what & ATA_TIMING_ACT8B ) m->act8b = max(a->act8b, b->act8b);
+ if (what & ATA_TIMING_REC8B ) m->rec8b = max(a->rec8b, b->rec8b);
+ if (what & ATA_TIMING_CYC8B ) m->cyc8b = max(a->cyc8b, b->cyc8b);
+ if (what & ATA_TIMING_ACTIVE ) m->active = max(a->active, b->active);
+ if (what & ATA_TIMING_RECOVER) m->recover = max(a->recover, b->recover);
+ if (what & ATA_TIMING_CYCLE ) m->cycle = max(a->cycle, b->cycle);
+ if (what & ATA_TIMING_UDMA ) m->udma = max(a->udma, b->udma);
+}
+
+static const struct ata_timing* ata_timing_find_mode(unsigned short speed)
+{
+ const struct ata_timing *t;
+
+ for (t = ata_timing; t->mode != speed; t++)
+ if (t->mode == 0xFF)
+ return NULL;
+ return t;
+}
+
+int ata_timing_compute(struct ata_device *adev, unsigned short speed,
+ struct ata_timing *t, int T, int UT)
+{
+ const struct ata_timing *s;
+ struct ata_timing p;
+
+ /*
+ * Find the mode.
+ */
+
+ if (!(s = ata_timing_find_mode(speed)))
+ return -EINVAL;
+
+ /*
+ * If the drive is an EIDE drive, it can tell us it needs extended
+ * PIO/MW_DMA cycle timing.
+ */
+
+ if (adev->id[ATA_ID_FIELD_VALID] & 2) { /* EIDE drive */
+ memset(&p, 0, sizeof(p));
+ if(speed >= XFER_PIO_0 && speed <= XFER_SW_DMA_0) {
+ if (speed <= XFER_PIO_2) p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO];
+ else p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO_IORDY];
+ } else if(speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) {
+ p.cycle = adev->id[ATA_ID_EIDE_DMA_MIN];
+ }
+ ata_timing_merge(&p, t, t, ATA_TIMING_CYCLE | ATA_TIMING_CYC8B);
+ }
+
+ /*
+ * Convert the timing to bus clock counts.
+ */
+
+ ata_timing_quantize(s, t, T, UT);
+
+ /*
+ * Even in DMA/UDMA modes we still use PIO access for IDENTIFY, S.M.A.R.T
+ * and some other commands. We have to ensure that the DMA cycle timing is
+ * slower/equal than the fastest PIO timing.
+ */
+
+ if (speed > XFER_PIO_4) {
+ ata_timing_compute(adev, adev->pio_mode, &p, T, UT);
+ ata_timing_merge(&p, t, t, ATA_TIMING_ALL);
+ }
+
+ /*
+ * Lenghten active & recovery time so that cycle time is correct.
+ */
+
+ if (t->act8b + t->rec8b < t->cyc8b) {
+ t->act8b += (t->cyc8b - (t->act8b + t->rec8b)) / 2;
+ t->rec8b = t->cyc8b - t->act8b;
+ }
+
+ if (t->active + t->recover < t->cycle) {
+ t->active += (t->cycle - (t->active + t->recover)) / 2;
+ t->recover = t->cycle - t->active;
+ }
+
+ return 0;
+}
+
+static const struct {
unsigned int shift;
u8 base;
} xfer_mode_classes[] = {
@@ -1603,7 +1791,7 @@ static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode,
*/
static void ata_set_mode(struct ata_port *ap)
{
- unsigned int i, xfer_shift;
+ unsigned int xfer_shift;
u8 xfer_mode;
int rc;
@@ -1632,11 +1820,6 @@ static void ata_set_mode(struct ata_port *ap)
if (ap->ops->post_set_mode)
ap->ops->post_set_mode(ap);
- for (i = 0; i < 2; i++) {
- struct ata_device *dev = &ap->device[i];
- ata_dev_set_protocol(dev);
- }
-
return;
err_out:
@@ -1910,7 +2093,8 @@ err_out:
DPRINTK("EXIT\n");
}
-static void ata_pr_blacklisted(struct ata_port *ap, struct ata_device *dev)
+static void ata_pr_blacklisted(const struct ata_port *ap,
+ const struct ata_device *dev)
{
printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, disabling DMA\n",
ap->id, dev->devno);
@@ -1948,7 +2132,7 @@ static const char * ata_dma_blacklist [] = {
"_NEC DV5800A",
};
-static int ata_dma_blacklisted(struct ata_port *ap, struct ata_device *dev)
+static int ata_dma_blacklisted(const struct ata_device *dev)
{
unsigned char model_num[40];
char *s;
@@ -1973,9 +2157,9 @@ static int ata_dma_blacklisted(struct ata_port *ap, struct ata_device *dev)
return 0;
}
-static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift)
+static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift)
{
- struct ata_device *master, *slave;
+ const struct ata_device *master, *slave;
unsigned int mask;
master = &ap->device[0];
@@ -1987,14 +2171,14 @@ static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift)
mask = ap->udma_mask;
if (ata_dev_present(master)) {
mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff);
- if (ata_dma_blacklisted(ap, master)) {
+ if (ata_dma_blacklisted(master)) {
mask = 0;
ata_pr_blacklisted(ap, master);
}
}
if (ata_dev_present(slave)) {
mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff);
- if (ata_dma_blacklisted(ap, slave)) {
+ if (ata_dma_blacklisted(slave)) {
mask = 0;
ata_pr_blacklisted(ap, slave);
}
@@ -2004,14 +2188,14 @@ static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift)
mask = ap->mwdma_mask;
if (ata_dev_present(master)) {
mask &= (master->id[ATA_ID_MWDMA_MODES] & 0x07);
- if (ata_dma_blacklisted(ap, master)) {
+ if (ata_dma_blacklisted(master)) {
mask = 0;
ata_pr_blacklisted(ap, master);
}
}
if (ata_dev_present(slave)) {
mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07);
- if (ata_dma_blacklisted(ap, slave)) {
+ if (ata_dma_blacklisted(slave)) {
mask = 0;
ata_pr_blacklisted(ap, slave);
}
@@ -2075,7 +2259,7 @@ static int fgb(u32 bitmap)
* Zero on success, negative on error.
*/
-static int ata_choose_xfer_mode(struct ata_port *ap,
+static int ata_choose_xfer_mode(const struct ata_port *ap,
u8 *xfer_mode_out,
unsigned int *xfer_shift_out)
{
@@ -2144,6 +2328,110 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
}
/**
+ * ata_dev_reread_id - Reread the device identify device info
+ * @ap: port where the device is
+ * @dev: device to reread the identify device info
+ *
+ * LOCKING:
+ */
+
+static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev)
+{
+ DECLARE_COMPLETION(wait);
+ struct ata_queued_cmd *qc;
+ unsigned long flags;
+ int rc;
+
+ qc = ata_qc_new_init(ap, dev);
+ BUG_ON(qc == NULL);
+
+ ata_sg_init_one(qc, dev->id, sizeof(dev->id));
+ qc->dma_dir = DMA_FROM_DEVICE;
+
+ if (dev->class == ATA_DEV_ATA) {
+ qc->tf.command = ATA_CMD_ID_ATA;
+ DPRINTK("do ATA identify\n");
+ } else {
+ qc->tf.command = ATA_CMD_ID_ATAPI;
+ DPRINTK("do ATAPI identify\n");
+ }
+
+ qc->tf.flags |= ATA_TFLAG_DEVICE;
+ qc->tf.protocol = ATA_PROT_PIO;
+ qc->nsect = 1;
+
+ qc->waiting = &wait;
+ qc->complete_fn = ata_qc_complete_noop;
+
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ rc = ata_qc_issue(qc);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+ if (rc)
+ goto err_out;
+
+ wait_for_completion(&wait);
+
+ swap_buf_le16(dev->id, ATA_ID_WORDS);
+
+ ata_dump_id(dev);
+
+ DPRINTK("EXIT\n");
+
+ return;
+err_out:
+ ata_port_disable(ap);
+}
+
+/**
+ * ata_dev_init_params - Issue INIT DEV PARAMS command
+ * @ap: Port associated with device @dev
+ * @dev: Device to which command will be sent
+ *
+ * LOCKING:
+ */
+
+static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
+{
+ DECLARE_COMPLETION(wait);
+ struct ata_queued_cmd *qc;
+ int rc;
+ unsigned long flags;
+ u16 sectors = dev->id[6];
+ u16 heads = dev->id[3];
+
+ /* Number of sectors per track 1-255. Number of heads 1-16 */
+ if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16)
+ return;
+
+ /* set up init dev params taskfile */
+ DPRINTK("init dev params \n");
+
+ qc = ata_qc_new_init(ap, dev);
+ BUG_ON(qc == NULL);
+
+ qc->tf.command = ATA_CMD_INIT_DEV_PARAMS;
+ qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+ qc->tf.protocol = ATA_PROT_NODATA;
+ qc->tf.nsect = sectors;
+ qc->tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
+
+ qc->waiting = &wait;
+ qc->complete_fn = ata_qc_complete_noop;
+
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ rc = ata_qc_issue(qc);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+ if (rc)
+ ata_port_disable(ap);
+ else
+ wait_for_completion(&wait);
+
+ DPRINTK("EXIT\n");
+}
+
+/**
* ata_sg_clean - Unmap DMA memory associated with command
* @qc: Command containing DMA memory to be released
*
@@ -2413,32 +2701,32 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
/**
* ata_pio_poll -
- * @ap:
+ * @ap: the target ata_port
*
* LOCKING:
* None. (executing in kernel thread context)
*
* RETURNS:
- *
+ * timeout value to use
*/
static unsigned long ata_pio_poll(struct ata_port *ap)
{
u8 status;
- unsigned int poll_state = PIO_ST_UNKNOWN;
- unsigned int reg_state = PIO_ST_UNKNOWN;
- const unsigned int tmout_state = PIO_ST_TMOUT;
-
- switch (ap->pio_task_state) {
- case PIO_ST:
- case PIO_ST_POLL:
- poll_state = PIO_ST_POLL;
- reg_state = PIO_ST;
+ unsigned int poll_state = HSM_ST_UNKNOWN;
+ unsigned int reg_state = HSM_ST_UNKNOWN;
+ const unsigned int tmout_state = HSM_ST_TMOUT;
+
+ switch (ap->hsm_task_state) {
+ case HSM_ST:
+ case HSM_ST_POLL:
+ poll_state = HSM_ST_POLL;
+ reg_state = HSM_ST;
break;
- case PIO_ST_LAST:
- case PIO_ST_LAST_POLL:
- poll_state = PIO_ST_LAST_POLL;
- reg_state = PIO_ST_LAST;
+ case HSM_ST_LAST:
+ case HSM_ST_LAST_POLL:
+ poll_state = HSM_ST_LAST_POLL;
+ reg_state = HSM_ST_LAST;
break;
default:
BUG();
@@ -2448,20 +2736,20 @@ static unsigned long ata_pio_poll(struct ata_port *ap)
status = ata_chk_status(ap);
if (status & ATA_BUSY) {
if (time_after(jiffies, ap->pio_task_timeout)) {
- ap->pio_task_state = tmout_state;
+ ap->hsm_task_state = tmout_state;
return 0;
}
- ap->pio_task_state = poll_state;
+ ap->hsm_task_state = poll_state;
return ATA_SHORT_PAUSE;
}
- ap->pio_task_state = reg_state;
+ ap->hsm_task_state = reg_state;
return 0;
}
/**
- * ata_pio_complete -
- * @ap:
+ * ata_pio_complete - check if drive is busy or idle
+ * @ap: the target ata_port
*
* LOCKING:
* None. (executing in kernel thread context)
@@ -2480,14 +2768,14 @@ static int ata_pio_complete (struct ata_port *ap)
* we enter, BSY will be cleared in a chk-status or two. If not,
* the drive is probably seeking or something. Snooze for a couple
* msecs, then chk-status again. If still busy, fall back to
- * PIO_ST_POLL state.
+ * HSM_ST_POLL state.
*/
drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
msleep(2);
drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
- ap->pio_task_state = PIO_ST_LAST_POLL;
+ ap->hsm_task_state = HSM_ST_LAST_POLL;
ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
return 0;
}
@@ -2495,14 +2783,14 @@ static int ata_pio_complete (struct ata_port *ap)
drv_stat = ata_wait_idle(ap);
if (!ata_ok(drv_stat)) {
- ap->pio_task_state = PIO_ST_ERR;
+ ap->hsm_task_state = HSM_ST_ERR;
return 0;
}
qc = ata_qc_from_tag(ap, ap->active_tag);
assert(qc != NULL);
- ap->pio_task_state = PIO_ST_IDLE;
+ ap->hsm_task_state = HSM_ST_IDLE;
ata_poll_qc_complete(qc, drv_stat);
@@ -2513,7 +2801,7 @@ static int ata_pio_complete (struct ata_port *ap)
/**
- * swap_buf_le16 -
+ * swap_buf_le16 - swap halves of 16-words in place
* @buf: Buffer to swap
* @buf_words: Number of 16-bit words in buffer.
*
@@ -2522,6 +2810,7 @@ static int ata_pio_complete (struct ata_port *ap)
* vice-versa.
*
* LOCKING:
+ * Inherited from caller.
*/
void swap_buf_le16(u16 *buf, unsigned int buf_words)
{
@@ -2544,7 +2833,6 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
*
* LOCKING:
* Inherited from caller.
- *
*/
static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
@@ -2590,7 +2878,6 @@ static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
*
* LOCKING:
* Inherited from caller.
- *
*/
static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
@@ -2630,7 +2917,6 @@ static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
*
* LOCKING:
* Inherited from caller.
- *
*/
static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
@@ -2662,7 +2948,7 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
unsigned char *buf;
if (qc->cursect == (qc->nsect - 1))
- ap->pio_task_state = PIO_ST_LAST;
+ ap->hsm_task_state = HSM_ST_LAST;
page = sg[qc->cursg].page;
offset = sg[qc->cursg].offset + qc->cursg_ofs * ATA_SECT_SIZE;
@@ -2712,7 +2998,7 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
unsigned int offset, count;
if (qc->curbytes + bytes >= qc->nbytes)
- ap->pio_task_state = PIO_ST_LAST;
+ ap->hsm_task_state = HSM_ST_LAST;
next_sg:
if (unlikely(qc->cursg >= qc->n_elem)) {
@@ -2734,7 +3020,7 @@ next_sg:
for (i = 0; i < words; i++)
ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write);
- ap->pio_task_state = PIO_ST_LAST;
+ ap->hsm_task_state = HSM_ST_LAST;
return;
}
@@ -2783,7 +3069,6 @@ next_sg:
*
* LOCKING:
* Inherited from caller.
- *
*/
static void atapi_pio_bytes(struct ata_queued_cmd *qc)
@@ -2815,12 +3100,12 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
err_out:
printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n",
ap->id, dev->devno);
- ap->pio_task_state = PIO_ST_ERR;
+ ap->hsm_task_state = HSM_ST_ERR;
}
/**
- * ata_pio_sector -
- * @ap:
+ * ata_pio_block - start PIO on a block
+ * @ap: the target ata_port
*
* LOCKING:
* None. (executing in kernel thread context)
@@ -2832,19 +3117,19 @@ static void ata_pio_block(struct ata_port *ap)
u8 status;
/*
- * This is purely hueristic. This is a fast path.
+ * This is purely heuristic. This is a fast path.
* Sometimes when we enter, BSY will be cleared in
* a chk-status or two. If not, the drive is probably seeking
* or something. Snooze for a couple msecs, then
* chk-status again. If still busy, fall back to
- * PIO_ST_POLL state.
+ * HSM_ST_POLL state.
*/
status = ata_busy_wait(ap, ATA_BUSY, 5);
if (status & ATA_BUSY) {
msleep(2);
status = ata_busy_wait(ap, ATA_BUSY, 10);
if (status & ATA_BUSY) {
- ap->pio_task_state = PIO_ST_POLL;
+ ap->hsm_task_state = HSM_ST_POLL;
ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
return;
}
@@ -2856,7 +3141,7 @@ static void ata_pio_block(struct ata_port *ap)
if (is_atapi_taskfile(&qc->tf)) {
/* no more data to transfer or unsupported ATAPI command */
if ((status & ATA_DRQ) == 0) {
- ap->pio_task_state = PIO_ST_LAST;
+ ap->hsm_task_state = HSM_ST_LAST;
return;
}
@@ -2864,7 +3149,7 @@ static void ata_pio_block(struct ata_port *ap)
} else {
/* handle BSY=0, DRQ=0 as error */
if ((status & ATA_DRQ) == 0) {
- ap->pio_task_state = PIO_ST_ERR;
+ ap->hsm_task_state = HSM_ST_ERR;
return;
}
@@ -2884,7 +3169,7 @@ static void ata_pio_error(struct ata_port *ap)
printk(KERN_WARNING "ata%u: PIO error, drv_stat 0x%x\n",
ap->id, drv_stat);
- ap->pio_task_state = PIO_ST_IDLE;
+ ap->hsm_task_state = HSM_ST_IDLE;
ata_poll_qc_complete(qc, drv_stat | ATA_ERR);
}
@@ -2899,25 +3184,25 @@ fsm_start:
timeout = 0;
qc_completed = 0;
- switch (ap->pio_task_state) {
- case PIO_ST_IDLE:
+ switch (ap->hsm_task_state) {
+ case HSM_ST_IDLE:
return;
- case PIO_ST:
+ case HSM_ST:
ata_pio_block(ap);
break;
- case PIO_ST_LAST:
+ case HSM_ST_LAST:
qc_completed = ata_pio_complete(ap);
break;
- case PIO_ST_POLL:
- case PIO_ST_LAST_POLL:
+ case HSM_ST_POLL:
+ case HSM_ST_LAST_POLL:
timeout = ata_pio_poll(ap);
break;
- case PIO_ST_TMOUT:
- case PIO_ST_ERR:
+ case HSM_ST_TMOUT:
+ case HSM_ST_ERR:
ata_pio_error(ap);
return;
}
@@ -2928,52 +3213,6 @@ fsm_start:
goto fsm_start;
}
-static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
- struct scsi_cmnd *cmd)
-{
- DECLARE_COMPLETION(wait);
- struct ata_queued_cmd *qc;
- unsigned long flags;
- int rc;
-
- DPRINTK("ATAPI request sense\n");
-
- qc = ata_qc_new_init(ap, dev);
- BUG_ON(qc == NULL);
-
- /* FIXME: is this needed? */
- memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
-
- ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
- qc->dma_dir = DMA_FROM_DEVICE;
-
- memset(&qc->cdb, 0, ap->cdb_len);
- qc->cdb[0] = REQUEST_SENSE;
- qc->cdb[4] = SCSI_SENSE_BUFFERSIZE;
-
- qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
- qc->tf.command = ATA_CMD_PACKET;
-
- qc->tf.protocol = ATA_PROT_ATAPI;
- qc->tf.lbam = (8 * 1024) & 0xff;
- qc->tf.lbah = (8 * 1024) >> 8;
- qc->nbytes = SCSI_SENSE_BUFFERSIZE;
-
- qc->waiting = &wait;
- qc->complete_fn = ata_qc_complete_noop;
-
- spin_lock_irqsave(&ap->host_set->lock, flags);
- rc = ata_qc_issue(qc);
- spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
- if (rc)
- ata_port_disable(ap);
- else
- wait_for_completion(&wait);
-
- DPRINTK("EXIT\n");
-}
-
/**
* ata_qc_timeout - Handle timeout of queued command
* @qc: Command that timed out
@@ -3091,14 +3330,14 @@ void ata_eng_timeout(struct ata_port *ap)
DPRINTK("ENTER\n");
qc = ata_qc_from_tag(ap, ap->active_tag);
- if (!qc) {
+ if (qc)
+ ata_qc_timeout(qc);
+ else {
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
ap->id);
goto out;
}
- ata_qc_timeout(qc);
-
out:
DPRINTK("EXIT\n");
}
@@ -3155,15 +3394,12 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
qc->nbytes = qc->curbytes = 0;
ata_tf_init(ap, &qc->tf, dev->devno);
-
- if (dev->flags & ATA_DFLAG_LBA48)
- qc->tf.flags |= ATA_TFLAG_LBA48;
}
return qc;
}
-static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat)
+int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat)
{
return 0;
}
@@ -3201,7 +3437,6 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc)
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
- *
*/
void ata_qc_free(struct ata_queued_cmd *qc)
{
@@ -3221,7 +3456,6 @@ void ata_qc_free(struct ata_queued_cmd *qc)
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
- *
*/
void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
@@ -3360,7 +3594,7 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc)
case ATA_PROT_PIO: /* load tf registers, initiate polling pio */
ata_qc_set_polling(qc);
ata_tf_to_host_nolock(ap, &qc->tf);
- ap->pio_task_state = PIO_ST;
+ ap->hsm_task_state = HSM_ST;
queue_work(ata_wq, &ap->pio_task);
break;
@@ -3586,7 +3820,7 @@ u8 ata_bmdma_status(struct ata_port *ap)
void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
host_stat = readb(mmio + ATA_DMA_STATUS);
} else
- host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
return host_stat;
}
@@ -3715,7 +3949,6 @@ idle_irq:
*
* RETURNS:
* IRQ_NONE or IRQ_HANDLED.
- *
*/
irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
@@ -3806,7 +4039,7 @@ static void atapi_packet_task(void *_data)
ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
/* PIO commands are handled by polling */
- ap->pio_task_state = PIO_ST;
+ ap->hsm_task_state = HSM_ST;
queue_work(ata_wq, &ap->pio_task);
}
@@ -3827,6 +4060,7 @@ err_out:
* May be used as the port_start() entry in ata_port_operations.
*
* LOCKING:
+ * Inherited from caller.
*/
int ata_port_start (struct ata_port *ap)
@@ -3852,6 +4086,7 @@ int ata_port_start (struct ata_port *ap)
* May be used as the port_stop() entry in ata_port_operations.
*
* LOCKING:
+ * Inherited from caller.
*/
void ata_port_stop (struct ata_port *ap)
@@ -3874,6 +4109,7 @@ void ata_host_stop (struct ata_host_set *host_set)
* @do_unregister: 1 if we fully unregister, 0 to just stop the port
*
* LOCKING:
+ * Inherited from caller.
*/
static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister)
@@ -3901,12 +4137,11 @@ static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister)
*
* LOCKING:
* Inherited from caller.
- *
*/
static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
struct ata_host_set *host_set,
- struct ata_probe_ent *ent, unsigned int port_no)
+ const struct ata_probe_ent *ent, unsigned int port_no)
{
unsigned int i;
@@ -3962,10 +4197,9 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
*
* RETURNS:
* New ata_port on success, for NULL on error.
- *
*/
-static struct ata_port * ata_host_add(struct ata_probe_ent *ent,
+static struct ata_port * ata_host_add(const struct ata_probe_ent *ent,
struct ata_host_set *host_set,
unsigned int port_no)
{
@@ -4010,10 +4244,9 @@ err_out:
*
* RETURNS:
* Number of ports registered. Zero on error (no ports registered).
- *
*/
-int ata_device_add(struct ata_probe_ent *ent)
+int ata_device_add(const struct ata_probe_ent *ent)
{
unsigned int count = 0, i;
struct device *dev = ent->dev;
@@ -4113,7 +4346,7 @@ int ata_device_add(struct ata_probe_ent *ent)
for (i = 0; i < count; i++) {
struct ata_port *ap = host_set->ports[i];
- scsi_scan_host(ap->host);
+ ata_scsi_scan_host(ap);
}
dev_set_drvdata(dev, host_set);
@@ -4142,7 +4375,6 @@ err_out:
* Inherited from calling layer (may sleep).
*/
-
void ata_host_set_remove(struct ata_host_set *host_set)
{
struct ata_port *ap;
@@ -4232,7 +4464,7 @@ void ata_std_ports(struct ata_ioports *ioaddr)
}
static struct ata_probe_ent *
-ata_probe_ent_alloc(struct device *dev, struct ata_port_info *port)
+ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port)
{
struct ata_probe_ent *probe_ent;
@@ -4273,85 +4505,86 @@ void ata_pci_host_stop (struct ata_host_set *host_set)
* ata_pci_init_native_mode - Initialize native-mode driver
* @pdev: pci device to be initialized
* @port: array[2] of pointers to port info structures.
+ * @ports: bitmap of ports present
*
* Utility function which allocates and initializes an
* ata_probe_ent structure for a standard dual-port
* PIO-based IDE controller. The returned ata_probe_ent
* structure can be passed to ata_device_add(). The returned
* ata_probe_ent structure should then be freed with kfree().
+ *
+ * The caller need only pass the address of the primary port, the
+ * secondary will be deduced automatically. If the device has non
+ * standard secondary port mappings this function can be called twice,
+ * once for each interface.
*/
struct ata_probe_ent *
-ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
+ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int ports)
{
struct ata_probe_ent *probe_ent =
ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
+ int p = 0;
+
if (!probe_ent)
return NULL;
- probe_ent->n_ports = 2;
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
- probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
- probe_ent->port[0].altstatus_addr =
- probe_ent->port[0].ctl_addr =
- pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
- probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
-
- probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
- probe_ent->port[1].altstatus_addr =
- probe_ent->port[1].ctl_addr =
- pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
- probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+ if (ports & ATA_PORT_PRIMARY) {
+ probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 0);
+ probe_ent->port[p].altstatus_addr =
+ probe_ent->port[p].ctl_addr =
+ pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
+ probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4);
+ ata_std_ports(&probe_ent->port[p]);
+ p++;
+ }
- ata_std_ports(&probe_ent->port[0]);
- ata_std_ports(&probe_ent->port[1]);
+ if (ports & ATA_PORT_SECONDARY) {
+ probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 2);
+ probe_ent->port[p].altstatus_addr =
+ probe_ent->port[p].ctl_addr =
+ pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
+ probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+ ata_std_ports(&probe_ent->port[p]);
+ p++;
+ }
+ probe_ent->n_ports = p;
return probe_ent;
}
-static struct ata_probe_ent *
-ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port,
- struct ata_probe_ent **ppe2)
+static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, struct ata_port_info **port, int port_num)
{
- struct ata_probe_ent *probe_ent, *probe_ent2;
+ struct ata_probe_ent *probe_ent;
probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
if (!probe_ent)
return NULL;
- probe_ent2 = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[1]);
- if (!probe_ent2) {
- kfree(probe_ent);
- return NULL;
- }
-
- probe_ent->n_ports = 1;
- probe_ent->irq = 14;
- probe_ent->hard_port_no = 0;
probe_ent->legacy_mode = 1;
-
- probe_ent2->n_ports = 1;
- probe_ent2->irq = 15;
-
- probe_ent2->hard_port_no = 1;
- probe_ent2->legacy_mode = 1;
-
- probe_ent->port[0].cmd_addr = 0x1f0;
- probe_ent->port[0].altstatus_addr =
- probe_ent->port[0].ctl_addr = 0x3f6;
- probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
-
- probe_ent2->port[0].cmd_addr = 0x170;
- probe_ent2->port[0].altstatus_addr =
- probe_ent2->port[0].ctl_addr = 0x376;
- probe_ent2->port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
-
+ probe_ent->n_ports = 1;
+ probe_ent->hard_port_no = port_num;
+
+ switch(port_num)
+ {
+ case 0:
+ probe_ent->irq = 14;
+ probe_ent->port[0].cmd_addr = 0x1f0;
+ probe_ent->port[0].altstatus_addr =
+ probe_ent->port[0].ctl_addr = 0x3f6;
+ break;
+ case 1:
+ probe_ent->irq = 15;
+ probe_ent->port[0].cmd_addr = 0x170;
+ probe_ent->port[0].altstatus_addr =
+ probe_ent->port[0].ctl_addr = 0x376;
+ break;
+ }
+ probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4) + 8 * port_num;
ata_std_ports(&probe_ent->port[0]);
- ata_std_ports(&probe_ent2->port[0]);
-
- *ppe2 = probe_ent2;
return probe_ent;
}
@@ -4374,13 +4607,12 @@ ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port,
*
* RETURNS:
* Zero on success, negative on errno-based value on error.
- *
*/
int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
unsigned int n_ports)
{
- struct ata_probe_ent *probe_ent, *probe_ent2 = NULL;
+ struct ata_probe_ent *probe_ent = NULL, *probe_ent2 = NULL;
struct ata_port_info *port[2];
u8 tmp8, mask;
unsigned int legacy_mode = 0;
@@ -4397,7 +4629,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0
&& (pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
- /* TODO: support transitioning to native mode? */
+ /* TODO: What if one channel is in native mode ... */
pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
mask = (1 << 2) | (1 << 0);
if ((tmp8 & mask) != mask)
@@ -4405,11 +4637,20 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
}
/* FIXME... */
- if ((!legacy_mode) && (n_ports > 1)) {
- printk(KERN_ERR "ata: BUG: native mode, n_ports > 1\n");
- return -EINVAL;
+ if ((!legacy_mode) && (n_ports > 2)) {
+ printk(KERN_ERR "ata: BUG: native mode, n_ports > 2\n");
+ n_ports = 2;
+ /* For now */
}
+ /* FIXME: Really for ATA it isn't safe because the device may be
+ multi-purpose and we want to leave it alone if it was already
+ enabled. Secondly for shared use as Arjan says we want refcounting
+
+ Checking dev->is_enabled is insufficient as this is not set at
+ boot for the primary video which is BIOS enabled
+ */
+
rc = pci_enable_device(pdev);
if (rc)
return rc;
@@ -4420,6 +4661,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
goto err_out;
}
+ /* FIXME: Should use platform specific mappers for legacy port ranges */
if (legacy_mode) {
if (!request_region(0x1f0, 8, "libata")) {
struct resource *conflict, res;
@@ -4464,10 +4706,17 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
goto err_out_regions;
if (legacy_mode) {
- probe_ent = ata_pci_init_legacy_mode(pdev, port, &probe_ent2);
- } else
- probe_ent = ata_pci_init_native_mode(pdev, port);
- if (!probe_ent) {
+ if (legacy_mode & (1 << 0))
+ probe_ent = ata_pci_init_legacy_port(pdev, port, 0);
+ if (legacy_mode & (1 << 1))
+ probe_ent2 = ata_pci_init_legacy_port(pdev, port, 1);
+ } else {
+ if (n_ports == 2)
+ probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
+ else
+ probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY);
+ }
+ if (!probe_ent && !probe_ent2) {
rc = -ENOMEM;
goto err_out_regions;
}
@@ -4505,7 +4754,7 @@ err_out:
* @pdev: PCI device that was removed
*
* PCI layer indicates to libata via this hook that
- * hot-unplug or module unload event has occured.
+ * hot-unplug or module unload event has occurred.
* Handle this by unregistering all objects associated
* with this PCI device. Free those objects. Then finally
* release PCI resources and disable device.
@@ -4526,7 +4775,7 @@ void ata_pci_remove_one (struct pci_dev *pdev)
}
/* move to PCI subsystem */
-int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits)
+int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits)
{
unsigned long tmp = 0;
@@ -4579,6 +4828,27 @@ static void __exit ata_exit(void)
module_init(ata_init);
module_exit(ata_exit);
+static unsigned long ratelimit_time;
+static spinlock_t ata_ratelimit_lock = SPIN_LOCK_UNLOCKED;
+
+int ata_ratelimit(void)
+{
+ int rc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ata_ratelimit_lock, flags);
+
+ if (time_after(jiffies, ratelimit_time)) {
+ rc = 1;
+ ratelimit_time = jiffies + (HZ/5);
+ } else
+ rc = 0;
+
+ spin_unlock_irqrestore(&ata_ratelimit_lock, flags);
+
+ return rc;
+}
+
/*
* libata is essentially a library of internal helper functions for
* low-level ATA host controller drivers. As such, the API/ABI is
@@ -4620,6 +4890,7 @@ EXPORT_SYMBOL_GPL(sata_phy_reset);
EXPORT_SYMBOL_GPL(__sata_phy_reset);
EXPORT_SYMBOL_GPL(ata_bus_reset);
EXPORT_SYMBOL_GPL(ata_port_disable);
+EXPORT_SYMBOL_GPL(ata_ratelimit);
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
EXPORT_SYMBOL_GPL(ata_scsi_error);
@@ -4631,6 +4902,9 @@ EXPORT_SYMBOL_GPL(ata_dev_id_string);
EXPORT_SYMBOL_GPL(ata_dev_config);
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
+EXPORT_SYMBOL_GPL(ata_timing_compute);
+EXPORT_SYMBOL_GPL(ata_timing_merge);
+
#ifdef CONFIG_PCI
EXPORT_SYMBOL_GPL(pci_test_config_bits);
EXPORT_SYMBOL_GPL(ata_pci_host_stop);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 104fd9a63e734d..58858886d751c8 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -44,11 +44,19 @@
#include "libata.h"
-typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, u8 *scsicmd);
+typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd);
static struct ata_device *
-ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev);
+ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev);
+static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
+ void (*done)(struct scsi_cmnd *))
+{
+ ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x24, 0x0);
+ /* "Invalid field in cbd" */
+ done(cmd);
+}
+
/**
* ata_std_bios_param - generic bios head/sector/cylinder calculator used by sd.
* @sdev: SCSI device for which BIOS geometry is to be determined
@@ -182,7 +190,6 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
{
struct scsi_cmnd *cmd = qc->scsicmd;
u8 err = 0;
- unsigned char *sb = cmd->sense_buffer;
/* Based on the 3ware driver translation table */
static unsigned char sense_table[][4] = {
/* BBD|ECC|ID|MAR */
@@ -225,8 +232,6 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
};
int i = 0;
- cmd->result = SAM_STAT_CHECK_CONDITION;
-
/*
* Is this an error we can process/parse
*/
@@ -281,11 +286,9 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
/* Look for best matches first */
if((sense_table[i][0] & err) == sense_table[i][0])
{
- sb[0] = 0x70;
- sb[2] = sense_table[i][1];
- sb[7] = 0x0a;
- sb[12] = sense_table[i][2];
- sb[13] = sense_table[i][3];
+ ata_scsi_set_sense(cmd, sense_table[i][1] /* sk */,
+ sense_table[i][2] /* asc */,
+ sense_table[i][3] /* ascq */ );
return;
}
i++;
@@ -300,11 +303,9 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
{
if(stat_table[i][0] & drv_stat)
{
- sb[0] = 0x70;
- sb[2] = stat_table[i][1];
- sb[7] = 0x0a;
- sb[12] = stat_table[i][2];
- sb[13] = stat_table[i][3];
+ ata_scsi_set_sense(cmd, sense_table[i][1] /* sk */,
+ sense_table[i][2] /* asc */,
+ sense_table[i][3] /* ascq */ );
return;
}
i++;
@@ -313,15 +314,12 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat);
/* additional-sense-code[-qualifier] */
- sb[0] = 0x70;
- sb[2] = MEDIUM_ERROR;
- sb[7] = 0x0A;
if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
- sb[12] = 0x11; /* "unrecovered read error" */
- sb[13] = 0x04;
+ ata_scsi_set_sense(cmd, MEDIUM_ERROR, 0x11, 0x4);
+ /* "unrecovered read error" */
} else {
- sb[12] = 0x0C; /* "write error - */
- sb[13] = 0x02; /* auto-reallocation failed" */
+ ata_scsi_set_sense(cmd, MEDIUM_ERROR, 0xc, 0x2);
+ /* "write error - auto-reallocation failed" */
}
}
@@ -420,7 +418,7 @@ int ata_scsi_error(struct Scsi_Host *host)
*/
static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
- u8 *scsicmd)
+ const u8 *scsicmd)
{
struct ata_taskfile *tf = &qc->tf;
@@ -430,15 +428,26 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
; /* ignore IMMED bit, violates sat-r05 */
}
if (scsicmd[4] & 0x2)
- return 1; /* LOEJ bit set not supported */
+ goto invalid_fld; /* LOEJ bit set not supported */
if (((scsicmd[4] >> 4) & 0xf) != 0)
- return 1; /* power conditions not supported */
+ goto invalid_fld; /* power conditions not supported */
if (scsicmd[4] & 0x1) {
tf->nsect = 1; /* 1 sector, lba=0 */
- tf->lbah = 0x0;
- tf->lbam = 0x0;
- tf->lbal = 0x0;
- tf->device |= ATA_LBA;
+
+ if (qc->dev->flags & ATA_DFLAG_LBA) {
+ qc->tf.flags |= ATA_TFLAG_LBA;
+
+ tf->lbah = 0x0;
+ tf->lbam = 0x0;
+ tf->lbal = 0x0;
+ tf->device |= ATA_LBA;
+ } else {
+ /* CHS */
+ tf->lbal = 0x1; /* sect */
+ tf->lbam = 0x0; /* cyl low */
+ tf->lbah = 0x0; /* cyl high */
+ }
+
tf->command = ATA_CMD_VERIFY; /* READ VERIFY */
} else {
tf->nsect = 0; /* time period value (0 implies now) */
@@ -453,6 +462,11 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
*/
return 0;
+
+invalid_fld:
+ ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
+ /* "Invalid field in cbd" */
+ return 1;
}
@@ -471,14 +485,14 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
* Zero on success, non-zero on error.
*/
-static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
{
struct ata_taskfile *tf = &qc->tf;
tf->flags |= ATA_TFLAG_DEVICE;
tf->protocol = ATA_PROT_NODATA;
- if ((tf->flags & ATA_TFLAG_LBA48) &&
+ if ((qc->dev->flags & ATA_DFLAG_LBA48) &&
(ata_id_has_flush_ext(qc->dev->id)))
tf->command = ATA_CMD_FLUSH_EXT;
else
@@ -488,6 +502,99 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
}
/**
+ * scsi_6_lba_len - Get LBA and transfer length
+ * @scsicmd: SCSI command to translate
+ *
+ * Calculate LBA and transfer length for 6-byte commands.
+ *
+ * RETURNS:
+ * @plba: the LBA
+ * @plen: the transfer length
+ */
+
+static void scsi_6_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
+{
+ u64 lba = 0;
+ u32 len = 0;
+
+ VPRINTK("six-byte command\n");
+
+ lba |= ((u64)scsicmd[2]) << 8;
+ lba |= ((u64)scsicmd[3]);
+
+ len |= ((u32)scsicmd[4]);
+
+ *plba = lba;
+ *plen = len;
+}
+
+/**
+ * scsi_10_lba_len - Get LBA and transfer length
+ * @scsicmd: SCSI command to translate
+ *
+ * Calculate LBA and transfer length for 10-byte commands.
+ *
+ * RETURNS:
+ * @plba: the LBA
+ * @plen: the transfer length
+ */
+
+static void scsi_10_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
+{
+ u64 lba = 0;
+ u32 len = 0;
+
+ VPRINTK("ten-byte command\n");
+
+ lba |= ((u64)scsicmd[2]) << 24;
+ lba |= ((u64)scsicmd[3]) << 16;
+ lba |= ((u64)scsicmd[4]) << 8;
+ lba |= ((u64)scsicmd[5]);
+
+ len |= ((u32)scsicmd[7]) << 8;
+ len |= ((u32)scsicmd[8]);
+
+ *plba = lba;
+ *plen = len;
+}
+
+/**
+ * scsi_16_lba_len - Get LBA and transfer length
+ * @scsicmd: SCSI command to translate
+ *
+ * Calculate LBA and transfer length for 16-byte commands.
+ *
+ * RETURNS:
+ * @plba: the LBA
+ * @plen: the transfer length
+ */
+
+static void scsi_16_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
+{
+ u64 lba = 0;
+ u32 len = 0;
+
+ VPRINTK("sixteen-byte command\n");
+
+ lba |= ((u64)scsicmd[2]) << 56;
+ lba |= ((u64)scsicmd[3]) << 48;
+ lba |= ((u64)scsicmd[4]) << 40;
+ lba |= ((u64)scsicmd[5]) << 32;
+ lba |= ((u64)scsicmd[6]) << 24;
+ lba |= ((u64)scsicmd[7]) << 16;
+ lba |= ((u64)scsicmd[8]) << 8;
+ lba |= ((u64)scsicmd[9]);
+
+ len |= ((u32)scsicmd[10]) << 24;
+ len |= ((u32)scsicmd[11]) << 16;
+ len |= ((u32)scsicmd[12]) << 8;
+ len |= ((u32)scsicmd[13]);
+
+ *plba = lba;
+ *plen = len;
+}
+
+/**
* ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one
* @qc: Storage for translated ATA taskfile
* @scsicmd: SCSI command to translate
@@ -501,82 +608,110 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
* Zero on success, non-zero on error.
*/
-static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
{
struct ata_taskfile *tf = &qc->tf;
- unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
+ struct ata_device *dev = qc->dev;
u64 dev_sectors = qc->dev->n_sectors;
- u64 sect = 0;
- u32 n_sect = 0;
+ u64 block;
+ u32 n_block;
tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
tf->protocol = ATA_PROT_NODATA;
- tf->device |= ATA_LBA;
- if (scsicmd[0] == VERIFY) {
- sect |= ((u64)scsicmd[2]) << 24;
- sect |= ((u64)scsicmd[3]) << 16;
- sect |= ((u64)scsicmd[4]) << 8;
- sect |= ((u64)scsicmd[5]);
+ if (scsicmd[0] == VERIFY)
+ scsi_10_lba_len(scsicmd, &block, &n_block);
+ else if (scsicmd[0] == VERIFY_16)
+ scsi_16_lba_len(scsicmd, &block, &n_block);
+ else
+ goto invalid_fld;
- n_sect |= ((u32)scsicmd[7]) << 8;
- n_sect |= ((u32)scsicmd[8]);
- }
+ if (!n_block)
+ goto nothing_to_do;
+ if (block >= dev_sectors)
+ goto out_of_range;
+ if ((block + n_block) > dev_sectors)
+ goto out_of_range;
- else if (scsicmd[0] == VERIFY_16) {
- sect |= ((u64)scsicmd[2]) << 56;
- sect |= ((u64)scsicmd[3]) << 48;
- sect |= ((u64)scsicmd[4]) << 40;
- sect |= ((u64)scsicmd[5]) << 32;
- sect |= ((u64)scsicmd[6]) << 24;
- sect |= ((u64)scsicmd[7]) << 16;
- sect |= ((u64)scsicmd[8]) << 8;
- sect |= ((u64)scsicmd[9]);
-
- n_sect |= ((u32)scsicmd[10]) << 24;
- n_sect |= ((u32)scsicmd[11]) << 16;
- n_sect |= ((u32)scsicmd[12]) << 8;
- n_sect |= ((u32)scsicmd[13]);
- }
+ if (dev->flags & ATA_DFLAG_LBA) {
+ tf->flags |= ATA_TFLAG_LBA;
- else
- return 1;
+ if (dev->flags & ATA_DFLAG_LBA48) {
+ if (n_block > (64 * 1024))
+ goto invalid_fld;
- if (!n_sect)
- return 1;
- if (sect >= dev_sectors)
- return 1;
- if ((sect + n_sect) > dev_sectors)
- return 1;
- if (lba48) {
- if (n_sect > (64 * 1024))
- return 1;
- } else {
- if (n_sect > 256)
- return 1;
- }
+ /* use LBA48 */
+ tf->flags |= ATA_TFLAG_LBA48;
+ tf->command = ATA_CMD_VERIFY_EXT;
- if (lba48) {
- tf->command = ATA_CMD_VERIFY_EXT;
+ tf->hob_nsect = (n_block >> 8) & 0xff;
- tf->hob_nsect = (n_sect >> 8) & 0xff;
+ tf->hob_lbah = (block >> 40) & 0xff;
+ tf->hob_lbam = (block >> 32) & 0xff;
+ tf->hob_lbal = (block >> 24) & 0xff;
+ } else {
+ if (n_block > 256)
+ goto invalid_fld;
- tf->hob_lbah = (sect >> 40) & 0xff;
- tf->hob_lbam = (sect >> 32) & 0xff;
- tf->hob_lbal = (sect >> 24) & 0xff;
+ /* use LBA28 */
+ tf->command = ATA_CMD_VERIFY;
+
+ tf->device |= (block >> 24) & 0xf;
+ }
+
+ tf->nsect = n_block & 0xff;
+
+ tf->lbah = (block >> 16) & 0xff;
+ tf->lbam = (block >> 8) & 0xff;
+ tf->lbal = block & 0xff;
+
+ tf->device |= ATA_LBA;
} else {
+ /* CHS */
+ u32 sect, head, cyl, track;
+
+ if (n_block > 256)
+ goto invalid_fld;
+
+ /* Convert LBA to CHS */
+ track = (u32)block / dev->sectors;
+ cyl = track / dev->heads;
+ head = track % dev->heads;
+ sect = (u32)block % dev->sectors + 1;
+
+ DPRINTK("block %u track %u cyl %u head %u sect %u\n",
+ (u32)block, track, cyl, head, sect);
+
+ /* Check whether the converted CHS can fit.
+ Cylinder: 0-65535
+ Head: 0-15
+ Sector: 1-255*/
+ if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
+ goto out_of_range;
+
tf->command = ATA_CMD_VERIFY;
-
- tf->device |= (sect >> 24) & 0xf;
+ tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
+ tf->lbal = sect;
+ tf->lbam = cyl;
+ tf->lbah = cyl >> 8;
+ tf->device |= head;
}
- tf->nsect = n_sect & 0xff;
+ return 0;
+
+invalid_fld:
+ ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
+ /* "Invalid field in cbd" */
+ return 1;
- tf->lbah = (sect >> 16) & 0xff;
- tf->lbam = (sect >> 8) & 0xff;
- tf->lbal = sect & 0xff;
+out_of_range:
+ ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x21, 0x0);
+ /* "Logical Block Address out of range" */
+ return 1;
- return 0;
+nothing_to_do:
+ qc->scsicmd->result = SAM_STAT_GOOD;
+ return 1;
}
/**
@@ -599,106 +734,137 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
* Zero on success, non-zero on error.
*/
-static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
{
struct ata_taskfile *tf = &qc->tf;
- unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
+ struct ata_device *dev = qc->dev;
+ u64 block;
+ u32 n_block;
tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
- tf->protocol = qc->dev->xfer_protocol;
- tf->device |= ATA_LBA;
- if (scsicmd[0] == READ_10 || scsicmd[0] == READ_6 ||
- scsicmd[0] == READ_16) {
- tf->command = qc->dev->read_cmd;
- } else {
- tf->command = qc->dev->write_cmd;
+ if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 ||
+ scsicmd[0] == WRITE_16)
tf->flags |= ATA_TFLAG_WRITE;
- }
- if (scsicmd[0] == READ_10 || scsicmd[0] == WRITE_10) {
- if (lba48) {
- tf->hob_nsect = scsicmd[7];
- tf->hob_lbal = scsicmd[2];
+ /* Calculate the SCSI LBA and transfer length. */
+ switch (scsicmd[0]) {
+ case READ_10:
+ case WRITE_10:
+ scsi_10_lba_len(scsicmd, &block, &n_block);
+ break;
+ case READ_6:
+ case WRITE_6:
+ scsi_6_lba_len(scsicmd, &block, &n_block);
- qc->nsect = ((unsigned int)scsicmd[7] << 8) |
- scsicmd[8];
- } else {
- /* if we don't support LBA48 addressing, the request
- * -may- be too large. */
- if ((scsicmd[2] & 0xf0) || scsicmd[7])
- return 1;
+ /* for 6-byte r/w commands, transfer length 0
+ * means 256 blocks of data, not 0 block.
+ */
+ if (!n_block)
+ n_block = 256;
+ break;
+ case READ_16:
+ case WRITE_16:
+ scsi_16_lba_len(scsicmd, &block, &n_block);
+ break;
+ default:
+ DPRINTK("no-byte command\n");
+ goto invalid_fld;
+ }
- /* stores LBA27:24 in lower 4 bits of device reg */
- tf->device |= scsicmd[2];
+ /* Check and compose ATA command */
+ if (!n_block)
+ /* For 10-byte and 16-byte SCSI R/W commands, transfer
+ * length 0 means transfer 0 block of data.
+ * However, for ATA R/W commands, sector count 0 means
+ * 256 or 65536 sectors, not 0 sectors as in SCSI.
+ */
+ goto nothing_to_do;
- qc->nsect = scsicmd[8];
- }
+ if (dev->flags & ATA_DFLAG_LBA) {
+ tf->flags |= ATA_TFLAG_LBA;
- tf->nsect = scsicmd[8];
- tf->lbal = scsicmd[5];
- tf->lbam = scsicmd[4];
- tf->lbah = scsicmd[3];
+ if (dev->flags & ATA_DFLAG_LBA48) {
+ /* The request -may- be too large for LBA48. */
+ if ((block >> 48) || (n_block > 65536))
+ goto out_of_range;
- VPRINTK("ten-byte command\n");
- if (qc->nsect == 0) /* we don't support length==0 cmds */
- return 1;
- return 0;
- }
+ /* use LBA48 */
+ tf->flags |= ATA_TFLAG_LBA48;
- if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
- qc->nsect = tf->nsect = scsicmd[4];
- if (!qc->nsect) {
- qc->nsect = 256;
- if (lba48)
- tf->hob_nsect = 1;
- }
+ tf->hob_nsect = (n_block >> 8) & 0xff;
- tf->lbal = scsicmd[3];
- tf->lbam = scsicmd[2];
- tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */
+ tf->hob_lbah = (block >> 40) & 0xff;
+ tf->hob_lbam = (block >> 32) & 0xff;
+ tf->hob_lbal = (block >> 24) & 0xff;
+ } else {
+ /* use LBA28 */
- VPRINTK("six-byte command\n");
- return 0;
- }
+ /* The request -may- be too large for LBA28. */
+ if ((block >> 28) || (n_block > 256))
+ goto out_of_range;
- if (scsicmd[0] == READ_16 || scsicmd[0] == WRITE_16) {
- /* rule out impossible LBAs and sector counts */
- if (scsicmd[2] || scsicmd[3] || scsicmd[10] || scsicmd[11])
- return 1;
+ tf->device |= (block >> 24) & 0xf;
+ }
- if (lba48) {
- tf->hob_nsect = scsicmd[12];
- tf->hob_lbal = scsicmd[6];
- tf->hob_lbam = scsicmd[5];
- tf->hob_lbah = scsicmd[4];
+ ata_rwcmd_protocol(qc);
- qc->nsect = ((unsigned int)scsicmd[12] << 8) |
- scsicmd[13];
- } else {
- /* once again, filter out impossible non-zero values */
- if (scsicmd[4] || scsicmd[5] || scsicmd[12] ||
- (scsicmd[6] & 0xf0))
- return 1;
+ qc->nsect = n_block;
+ tf->nsect = n_block & 0xff;
- /* stores LBA27:24 in lower 4 bits of device reg */
- tf->device |= scsicmd[6];
+ tf->lbah = (block >> 16) & 0xff;
+ tf->lbam = (block >> 8) & 0xff;
+ tf->lbal = block & 0xff;
- qc->nsect = scsicmd[13];
- }
+ tf->device |= ATA_LBA;
+ } else {
+ /* CHS */
+ u32 sect, head, cyl, track;
+
+ /* The request -may- be too large for CHS addressing. */
+ if ((block >> 28) || (n_block > 256))
+ goto out_of_range;
+
+ ata_rwcmd_protocol(qc);
+
+ /* Convert LBA to CHS */
+ track = (u32)block / dev->sectors;
+ cyl = track / dev->heads;
+ head = track % dev->heads;
+ sect = (u32)block % dev->sectors + 1;
+
+ DPRINTK("block %u track %u cyl %u head %u sect %u\n",
+ (u32)block, track, cyl, head, sect);
+
+ /* Check whether the converted CHS can fit.
+ Cylinder: 0-65535
+ Head: 0-15
+ Sector: 1-255*/
+ if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
+ goto out_of_range;
+
+ qc->nsect = n_block;
+ tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
+ tf->lbal = sect;
+ tf->lbam = cyl;
+ tf->lbah = cyl >> 8;
+ tf->device |= head;
+ }
- tf->nsect = scsicmd[13];
- tf->lbal = scsicmd[9];
- tf->lbam = scsicmd[8];
- tf->lbah = scsicmd[7];
+ return 0;
- VPRINTK("sixteen-byte command\n");
- if (qc->nsect == 0) /* we don't support length==0 cmds */
- return 1;
- return 0;
- }
+invalid_fld:
+ ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
+ /* "Invalid field in cbd" */
+ return 1;
+
+out_of_range:
+ ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x21, 0x0);
+ /* "Logical Block Address out of range" */
+ return 1;
- DPRINTK("no-byte command\n");
+nothing_to_do:
+ qc->scsicmd->result = SAM_STAT_GOOD;
return 1;
}
@@ -731,6 +897,12 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
* This function sets up an ata_queued_cmd structure for the
* SCSI command, and sends that ata_queued_cmd to the hardware.
*
+ * The xlat_func argument (actor) returns 0 if ready to execute
+ * ATA command, else 1 to finish translation. If 1 is returned
+ * then cmd->result (and possibly cmd->sense_buffer) are assumed
+ * to be set reflecting an error condition or clean (early)
+ * termination.
+ *
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
@@ -747,7 +919,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
qc = ata_scsi_qc_new(ap, dev, cmd, done);
if (!qc)
- return;
+ goto err_mem;
/* data is present; dma-map it */
if (cmd->sc_data_direction == DMA_FROM_DEVICE ||
@@ -755,7 +927,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
if (unlikely(cmd->request_bufflen < 1)) {
printk(KERN_WARNING "ata%u(%u): WARNING: zero len r/w req\n",
ap->id, dev->devno);
- goto err_out;
+ goto err_did;
}
if (cmd->use_sg)
@@ -770,19 +942,28 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
qc->complete_fn = ata_scsi_qc_complete;
if (xlat_func(qc, scsicmd))
- goto err_out;
+ goto early_finish;
/* select device, send command to hardware */
if (ata_qc_issue(qc))
- goto err_out;
+ goto err_did;
VPRINTK("EXIT\n");
return;
-err_out:
+early_finish:
+ ata_qc_free(qc);
+ done(cmd);
+ DPRINTK("EXIT - early finish (good or error)\n");
+ return;
+
+err_did:
ata_qc_free(qc);
- ata_bad_cdb(cmd, done);
- DPRINTK("EXIT - badcmd\n");
+err_mem:
+ cmd->result = (DID_ERROR << 16);
+ done(cmd);
+ DPRINTK("EXIT - internal\n");
+ return;
}
/**
@@ -849,7 +1030,8 @@ static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
* Mapping the response buffer, calling the command's handler,
* and handling the handler's return value. This return value
* indicates whether the handler wishes the SCSI command to be
- * completed successfully, or not.
+ * completed successfully (0), or not (in which case cmd->result
+ * and sense buffer are assumed to be set).
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
@@ -868,12 +1050,9 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
rc = actor(args, rbuf, buflen);
ata_scsi_rbuf_put(cmd, rbuf);
- if (rc)
- ata_bad_cdb(cmd, args->done);
- else {
+ if (rc == 0)
cmd->result = SAM_STAT_GOOD;
- args->done(cmd);
- }
+ args->done(cmd);
}
/**
@@ -1179,8 +1358,16 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
* in the same manner)
*/
page_control = scsicmd[2] >> 6;
- if ((page_control != 0) && (page_control != 3))
- return 1;
+ switch (page_control) {
+ case 0: /* current */
+ break; /* supported */
+ case 3: /* saved */
+ goto saving_not_supp;
+ case 1: /* changeable */
+ case 2: /* defaults */
+ default:
+ goto invalid_fld;
+ }
if (six_byte)
output_len = 4;
@@ -1211,7 +1398,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
break;
default: /* invalid page code */
- return 1;
+ goto invalid_fld;
}
if (six_byte) {
@@ -1224,6 +1411,16 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
}
return 0;
+
+invalid_fld:
+ ata_scsi_set_sense(args->cmd, ILLEGAL_REQUEST, 0x24, 0x0);
+ /* "Invalid field in cbd" */
+ return 1;
+
+saving_not_supp:
+ ata_scsi_set_sense(args->cmd, ILLEGAL_REQUEST, 0x39, 0x0);
+ /* "Saving parameters not supported" */
+ return 1;
}
/**
@@ -1246,10 +1443,20 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
VPRINTK("ENTER\n");
- if (ata_id_has_lba48(args->id))
- n_sectors = ata_id_u64(args->id, 100);
- else
- n_sectors = ata_id_u32(args->id, 60);
+ if (ata_id_has_lba(args->id)) {
+ if (ata_id_has_lba48(args->id))
+ n_sectors = ata_id_u64(args->id, 100);
+ else
+ n_sectors = ata_id_u32(args->id, 60);
+ } else {
+ /* CHS default translation */
+ n_sectors = args->id[1] * args->id[3] * args->id[6];
+
+ if (ata_id_current_chs_valid(args->id))
+ /* CHS current translation */
+ n_sectors = ata_id_u32(args->id, 57);
+ }
+
n_sectors--; /* ATA TotalUserSectors - 1 */
if (args->cmd->cmnd[0] == READ_CAPACITY) {
@@ -1313,6 +1520,34 @@ unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
}
/**
+ * ata_scsi_set_sense - Set SCSI sense data and status
+ * @cmd: SCSI request to be handled
+ * @sk: SCSI-defined sense key
+ * @asc: SCSI-defined additional sense code
+ * @ascq: SCSI-defined additional sense code qualifier
+ *
+ * Helper function that builds a valid fixed format, current
+ * response code and the given sense key (sk), additional sense
+ * code (asc) and additional sense code qualifier (ascq) with
+ * a SCSI command status of %SAM_STAT_CHECK_CONDITION and
+ * DRIVER_SENSE set in the upper bits of scsi_cmnd::result .
+ *
+ * LOCKING:
+ * Not required
+ */
+
+void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
+{
+ cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
+ cmd->sense_buffer[0] = 0x70; /* fixed format, current */
+ cmd->sense_buffer[2] = sk;
+ cmd->sense_buffer[7] = 18 - 8; /* additional sense length */
+ cmd->sense_buffer[12] = asc;
+ cmd->sense_buffer[13] = ascq;
+}
+
+/**
* ata_scsi_badcmd - End a SCSI request with an error
* @cmd: SCSI request to be handled
* @done: SCSI command completion function
@@ -1330,30 +1565,84 @@ unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq)
{
DPRINTK("ENTER\n");
- cmd->result = SAM_STAT_CHECK_CONDITION;
-
- cmd->sense_buffer[0] = 0x70;
- cmd->sense_buffer[2] = ILLEGAL_REQUEST;
- cmd->sense_buffer[7] = 14 - 8; /* addnl. sense len. FIXME: correct? */
- cmd->sense_buffer[12] = asc;
- cmd->sense_buffer[13] = ascq;
+ ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, asc, ascq);
done(cmd);
}
+void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
+ struct scsi_cmnd *cmd)
+{
+ DECLARE_COMPLETION(wait);
+ struct ata_queued_cmd *qc;
+ unsigned long flags;
+ int rc;
+
+ DPRINTK("ATAPI request sense\n");
+
+ qc = ata_qc_new_init(ap, dev);
+ BUG_ON(qc == NULL);
+
+ /* FIXME: is this needed? */
+ memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
+
+ ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
+ qc->dma_dir = DMA_FROM_DEVICE;
+
+ memset(&qc->cdb, 0, ap->cdb_len);
+ qc->cdb[0] = REQUEST_SENSE;
+ qc->cdb[4] = SCSI_SENSE_BUFFERSIZE;
+
+ qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+ qc->tf.command = ATA_CMD_PACKET;
+
+ qc->tf.protocol = ATA_PROT_ATAPI;
+ qc->tf.lbam = (8 * 1024) & 0xff;
+ qc->tf.lbah = (8 * 1024) >> 8;
+ qc->nbytes = SCSI_SENSE_BUFFERSIZE;
+
+ qc->waiting = &wait;
+ qc->complete_fn = ata_qc_complete_noop;
+
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ rc = ata_qc_issue(qc);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+ if (rc)
+ ata_port_disable(ap);
+ else
+ wait_for_completion(&wait);
+
+ DPRINTK("EXIT\n");
+}
+
static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
{
struct scsi_cmnd *cmd = qc->scsicmd;
- if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) {
+ VPRINTK("ENTER, drv_stat == 0x%x\n", drv_stat);
+
+ if (unlikely(drv_stat & (ATA_BUSY | ATA_DRQ)))
+ ata_to_sense_error(qc, drv_stat);
+
+ else if (unlikely(drv_stat & ATA_ERR)) {
DPRINTK("request check condition\n");
+ /* FIXME: command completion with check condition
+ * but no sense causes the error handler to run,
+ * which then issues REQUEST SENSE, fills in the sense
+ * buffer, and completes the command (for the second
+ * time). We need to issue REQUEST SENSE some other
+ * way, to avoid completing the command twice.
+ */
cmd->result = SAM_STAT_CHECK_CONDITION;
qc->scsidone(cmd);
return 1;
- } else {
+ }
+
+ else {
u8 *scsicmd = cmd->cmnd;
if (scsicmd[0] == INQUIRY) {
@@ -1361,15 +1650,30 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
unsigned int buflen;
buflen = ata_scsi_rbuf_get(cmd, &buf);
- buf[2] = 0x5;
- buf[3] = (buf[3] & 0xf0) | 2;
+
+ /* ATAPI devices typically report zero for their SCSI version,
+ * and sometimes deviate from the spec WRT response data
+ * format. If SCSI version is reported as zero like normal,
+ * then we make the following fixups: 1) Fake MMC-5 version,
+ * to indicate to the Linux scsi midlayer this is a modern
+ * device. 2) Ensure response data format / ATAPI information
+ * are always correct.
+ */
+ /* FIXME: do we ever override EVPD pages and the like, with
+ * this code?
+ */
+ if (buf[2] == 0) {
+ buf[2] = 0x5;
+ buf[3] = 0x32;
+ }
+
ata_scsi_rbuf_put(cmd, buf);
}
+
cmd->result = SAM_STAT_GOOD;
}
qc->scsidone(cmd);
-
return 0;
}
/**
@@ -1384,7 +1688,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
* Zero on success, non-zero on failure.
*/
-static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
{
struct scsi_cmnd *cmd = qc->scsicmd;
struct ata_device *dev = qc->dev;
@@ -1453,7 +1757,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
*/
static struct ata_device *
-ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev)
+ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev)
{
struct ata_device *dev;
@@ -1610,7 +1914,7 @@ void ata_scsi_simulate(u16 *id,
void (*done)(struct scsi_cmnd *))
{
struct ata_scsi_args args;
- u8 *scsicmd = cmd->cmnd;
+ const u8 *scsicmd = cmd->cmnd;
args.id = id;
args.cmd = cmd;
@@ -1630,7 +1934,7 @@ void ata_scsi_simulate(u16 *id,
case INQUIRY:
if (scsicmd[1] & 2) /* is CmdDt set? */
- ata_bad_cdb(cmd, done);
+ ata_scsi_invalid_field(cmd, done);
else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */
ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std);
else if (scsicmd[2] == 0x00)
@@ -1640,7 +1944,7 @@ void ata_scsi_simulate(u16 *id,
else if (scsicmd[2] == 0x83)
ata_scsi_rbuf_fill(&args, ata_scsiop_inq_83);
else
- ata_bad_cdb(cmd, done);
+ ata_scsi_invalid_field(cmd, done);
break;
case MODE_SENSE:
@@ -1650,7 +1954,7 @@ void ata_scsi_simulate(u16 *id,
case MODE_SELECT: /* unconditionally return */
case MODE_SELECT_10: /* bad-field-in-cdb */
- ata_bad_cdb(cmd, done);
+ ata_scsi_invalid_field(cmd, done);
break;
case READ_CAPACITY:
@@ -1661,7 +1965,7 @@ void ata_scsi_simulate(u16 *id,
if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16)
ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
else
- ata_bad_cdb(cmd, done);
+ ata_scsi_invalid_field(cmd, done);
break;
case REPORT_LUNS:
@@ -1673,8 +1977,26 @@ void ata_scsi_simulate(u16 *id,
/* all other commands */
default:
- ata_bad_scsiop(cmd, done);
+ ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x20, 0x0);
+ /* "Invalid command operation code" */
+ done(cmd);
break;
}
}
+void ata_scsi_scan_host(struct ata_port *ap)
+{
+ struct ata_device *dev;
+ unsigned int i;
+
+ if (ap->flags & ATA_FLAG_PORT_DISABLED)
+ return;
+
+ for (i = 0; i < ATA_MAX_DEVICES; i++) {
+ dev = &ap->device[i];
+
+ if (ata_dev_present(dev))
+ scsi_scan_target(&ap->host->shost_gendev, 0, i, 0, 0);
+ }
+}
+
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index d608b3a0f6fe68..3d60190584ba00 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -39,18 +39,23 @@ struct ata_scsi_args {
/* libata-core.c */
extern int atapi_enabled;
+extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat);
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
struct ata_device *dev);
+extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc);
extern void ata_qc_free(struct ata_queued_cmd *qc);
extern int ata_qc_issue(struct ata_queued_cmd *qc);
extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
extern void ata_dev_select(struct ata_port *ap, unsigned int device,
unsigned int wait, unsigned int can_sleep);
-extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf);
+extern void ata_tf_to_host_nolock(struct ata_port *ap, const struct ata_taskfile *tf);
extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
/* libata-scsi.c */
+extern void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
+ struct scsi_cmnd *cmd);
+extern void ata_scsi_scan_host(struct ata_port *ap);
extern void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat);
extern int ata_scsi_error(struct Scsi_Host *host);
extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
@@ -76,18 +81,10 @@ extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *),
u8 asc, u8 ascq);
+extern void ata_scsi_set_sense(struct scsi_cmnd *cmd,
+ u8 sk, u8 asc, u8 ascq);
extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
unsigned int (*actor) (struct ata_scsi_args *args,
u8 *rbuf, unsigned int buflen));
-static inline void ata_bad_scsiop(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
-{
- ata_scsi_badcmd(cmd, done, 0x20, 0x00);
-}
-
-static inline void ata_bad_cdb(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
-{
- ata_scsi_badcmd(cmd, done, 0x24, 0x00);
-}
-
#endif /* __LIBATA_H__ */
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index 0aba13ceaacfe9..352df47bcaca10 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -39,7 +39,7 @@
#define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */
static void *
-lpfc_pool_kmalloc(unsigned int gfp_flags, void *data)
+lpfc_pool_kmalloc(gfp_t gfp_flags, void *data)
{
return kmalloc((unsigned long)data, gfp_flags);
}
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 3f2f2464fa6351..172839fce0eb3c 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -5146,7 +5146,8 @@ static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned
/* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
{
- int i, priority;
+ int i;
+ gfp_t priority;
struct osst_buffer *tb;
if (from_initialization)
@@ -5178,7 +5179,8 @@ static struct osst_buffer * new_tape_buffer( int from_initialization, int need_d
/* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
{
- int segs, nbr, max_segs, b_size, priority, order, got;
+ int segs, nbr, max_segs, b_size, order, got;
+ gfp_t priority;
if (STbuffer->buffer_size >= OS_FRAME_SIZE)
return 1;
@@ -5627,7 +5629,7 @@ static void osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape *
if (!osst_sysfs_valid) return;
- osst_class_member = class_device_create(osst_sysfs_class, dev, device, "%s", name);
+ osst_class_member = class_device_create(osst_sysfs_class, NULL, dev, device, "%s", name);
if (IS_ERR(osst_class_member)) {
printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
return;
diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c
new file mode 100644
index 00000000000000..9820f272f88929
--- /dev/null
+++ b/drivers/scsi/pdc_adma.c
@@ -0,0 +1,739 @@
+/*
+ * pdc_adma.c - Pacific Digital Corporation ADMA
+ *
+ * Maintained by: Mark Lord <mlord@pobox.com>
+ *
+ * Copyright 2005 Mark Lord
+ *
+ * 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, 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ *
+ * Supports ATA disks in single-packet ADMA mode.
+ * Uses PIO for everything else.
+ *
+ * TODO: Use ADMA transfers for ATAPI devices, when possible.
+ * This requires careful attention to a number of quirks of the chip.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <asm/io.h>
+#include <linux/libata.h>
+
+#define DRV_NAME "pdc_adma"
+#define DRV_VERSION "0.01"
+
+/* macro to calculate base address for ATA regs */
+#define ADMA_ATA_REGS(base,port_no) ((base) + ((port_no) * 0x40))
+
+/* macro to calculate base address for ADMA regs */
+#define ADMA_REGS(base,port_no) ((base) + 0x80 + ((port_no) * 0x20))
+
+enum {
+ ADMA_PORTS = 2,
+ ADMA_CPB_BYTES = 40,
+ ADMA_PRD_BYTES = LIBATA_MAX_PRD * 16,
+ ADMA_PKT_BYTES = ADMA_CPB_BYTES + ADMA_PRD_BYTES,
+
+ ADMA_DMA_BOUNDARY = 0xffffffff,
+
+ /* global register offsets */
+ ADMA_MODE_LOCK = 0x00c7,
+
+ /* per-channel register offsets */
+ ADMA_CONTROL = 0x0000, /* ADMA control */
+ ADMA_STATUS = 0x0002, /* ADMA status */
+ ADMA_CPB_COUNT = 0x0004, /* CPB count */
+ ADMA_CPB_CURRENT = 0x000c, /* current CPB address */
+ ADMA_CPB_NEXT = 0x000c, /* next CPB address */
+ ADMA_CPB_LOOKUP = 0x0010, /* CPB lookup table */
+ ADMA_FIFO_IN = 0x0014, /* input FIFO threshold */
+ ADMA_FIFO_OUT = 0x0016, /* output FIFO threshold */
+
+ /* ADMA_CONTROL register bits */
+ aNIEN = (1 << 8), /* irq mask: 1==masked */
+ aGO = (1 << 7), /* packet trigger ("Go!") */
+ aRSTADM = (1 << 5), /* ADMA logic reset */
+ aRSTA = (1 << 2), /* ATA hard reset */
+ aPIOMD4 = 0x0003, /* PIO mode 4 */
+
+ /* ADMA_STATUS register bits */
+ aPSD = (1 << 6),
+ aUIRQ = (1 << 4),
+ aPERR = (1 << 0),
+
+ /* CPB bits */
+ cDONE = (1 << 0),
+ cVLD = (1 << 0),
+ cDAT = (1 << 2),
+ cIEN = (1 << 3),
+
+ /* PRD bits */
+ pORD = (1 << 4),
+ pDIRO = (1 << 5),
+ pEND = (1 << 7),
+
+ /* ATA register flags */
+ rIGN = (1 << 5),
+ rEND = (1 << 7),
+
+ /* ATA register addresses */
+ ADMA_REGS_CONTROL = 0x0e,
+ ADMA_REGS_SECTOR_COUNT = 0x12,
+ ADMA_REGS_LBA_LOW = 0x13,
+ ADMA_REGS_LBA_MID = 0x14,
+ ADMA_REGS_LBA_HIGH = 0x15,
+ ADMA_REGS_DEVICE = 0x16,
+ ADMA_REGS_COMMAND = 0x17,
+
+ /* PCI device IDs */
+ board_1841_idx = 0, /* ADMA 2-port controller */
+};
+
+typedef enum { adma_state_idle, adma_state_pkt, adma_state_mmio } adma_state_t;
+
+struct adma_port_priv {
+ u8 *pkt;
+ dma_addr_t pkt_dma;
+ adma_state_t state;
+};
+
+static int adma_ata_init_one (struct pci_dev *pdev,
+ const struct pci_device_id *ent);
+static irqreturn_t adma_intr (int irq, void *dev_instance,
+ struct pt_regs *regs);
+static int adma_port_start(struct ata_port *ap);
+static void adma_host_stop(struct ata_host_set *host_set);
+static void adma_port_stop(struct ata_port *ap);
+static void adma_phy_reset(struct ata_port *ap);
+static void adma_qc_prep(struct ata_queued_cmd *qc);
+static int adma_qc_issue(struct ata_queued_cmd *qc);
+static int adma_check_atapi_dma(struct ata_queued_cmd *qc);
+static void adma_bmdma_stop(struct ata_queued_cmd *qc);
+static u8 adma_bmdma_status(struct ata_port *ap);
+static void adma_irq_clear(struct ata_port *ap);
+static void adma_eng_timeout(struct ata_port *ap);
+
+static Scsi_Host_Template adma_ata_sht = {
+ .module = THIS_MODULE,
+ .name = DRV_NAME,
+ .ioctl = ata_scsi_ioctl,
+ .queuecommand = ata_scsi_queuecmd,
+ .eh_strategy_handler = ata_scsi_error,
+ .can_queue = ATA_DEF_QUEUE,
+ .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = LIBATA_MAX_PRD,
+ .max_sectors = ATA_MAX_SECTORS,
+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+ .emulated = ATA_SHT_EMULATED,
+ .use_clustering = ENABLE_CLUSTERING,
+ .proc_name = DRV_NAME,
+ .dma_boundary = ADMA_DMA_BOUNDARY,
+ .slave_configure = ata_scsi_slave_config,
+ .bios_param = ata_std_bios_param,
+};
+
+static const struct ata_port_operations adma_ata_ops = {
+ .port_disable = ata_port_disable,
+ .tf_load = ata_tf_load,
+ .tf_read = ata_tf_read,
+ .check_status = ata_check_status,
+ .check_atapi_dma = adma_check_atapi_dma,
+ .exec_command = ata_exec_command,
+ .dev_select = ata_std_dev_select,
+ .phy_reset = adma_phy_reset,
+ .qc_prep = adma_qc_prep,
+ .qc_issue = adma_qc_issue,
+ .eng_timeout = adma_eng_timeout,
+ .irq_handler = adma_intr,
+ .irq_clear = adma_irq_clear,
+ .port_start = adma_port_start,
+ .port_stop = adma_port_stop,
+ .host_stop = adma_host_stop,
+ .bmdma_stop = adma_bmdma_stop,
+ .bmdma_status = adma_bmdma_status,
+};
+
+static struct ata_port_info adma_port_info[] = {
+ /* board_1841_idx */
+ {
+ .sht = &adma_ata_sht,
+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
+ ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO,
+ .pio_mask = 0x10, /* pio4 */
+ .udma_mask = 0x1f, /* udma0-4 */
+ .port_ops = &adma_ata_ops,
+ },
+};
+
+static struct pci_device_id adma_ata_pci_tbl[] = {
+ { PCI_VENDOR_ID_PDC, 0x1841, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_1841_idx },
+
+ { } /* terminate list */
+};
+
+static struct pci_driver adma_ata_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = adma_ata_pci_tbl,
+ .probe = adma_ata_init_one,
+ .remove = ata_pci_remove_one,
+};
+
+static int adma_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+ return 1; /* ATAPI DMA not yet supported */
+}
+
+static void adma_bmdma_stop(struct ata_queued_cmd *qc)
+{
+ /* nothing */
+}
+
+static u8 adma_bmdma_status(struct ata_port *ap)
+{
+ return 0;
+}
+
+static void adma_irq_clear(struct ata_port *ap)
+{
+ /* nothing */
+}
+
+static void adma_reset_engine(void __iomem *chan)
+{
+ /* reset ADMA to idle state */
+ writew(aPIOMD4 | aNIEN | aRSTADM, chan + ADMA_CONTROL);
+ udelay(2);
+ writew(aPIOMD4, chan + ADMA_CONTROL);
+ udelay(2);
+}
+
+static void adma_reinit_engine(struct ata_port *ap)
+{
+ struct adma_port_priv *pp = ap->private_data;
+ void __iomem *mmio_base = ap->host_set->mmio_base;
+ void __iomem *chan = ADMA_REGS(mmio_base, ap->port_no);
+
+ /* mask/clear ATA interrupts */
+ writeb(ATA_NIEN, (void __iomem *)ap->ioaddr.ctl_addr);
+ ata_check_status(ap);
+
+ /* reset the ADMA engine */
+ adma_reset_engine(chan);
+
+ /* set in-FIFO threshold to 0x100 */
+ writew(0x100, chan + ADMA_FIFO_IN);
+
+ /* set CPB pointer */
+ writel((u32)pp->pkt_dma, chan + ADMA_CPB_NEXT);
+
+ /* set out-FIFO threshold to 0x100 */
+ writew(0x100, chan + ADMA_FIFO_OUT);
+
+ /* set CPB count */
+ writew(1, chan + ADMA_CPB_COUNT);
+
+ /* read/discard ADMA status */
+ readb(chan + ADMA_STATUS);
+}
+
+static inline void adma_enter_reg_mode(struct ata_port *ap)
+{
+ void __iomem *chan = ADMA_REGS(ap->host_set->mmio_base, ap->port_no);
+
+ writew(aPIOMD4, chan + ADMA_CONTROL);
+ readb(chan + ADMA_STATUS); /* flush */
+}
+
+static void adma_phy_reset(struct ata_port *ap)
+{
+ struct adma_port_priv *pp = ap->private_data;
+
+ pp->state = adma_state_idle;
+ adma_reinit_engine(ap);
+ ata_port_probe(ap);
+ ata_bus_reset(ap);
+}
+
+static void adma_eng_timeout(struct ata_port *ap)
+{
+ struct adma_port_priv *pp = ap->private_data;
+
+ if (pp->state != adma_state_idle) /* healthy paranoia */
+ pp->state = adma_state_mmio;
+ adma_reinit_engine(ap);
+ ata_eng_timeout(ap);
+}
+
+static int adma_fill_sg(struct ata_queued_cmd *qc)
+{
+ struct scatterlist *sg = qc->sg;
+ struct ata_port *ap = qc->ap;
+ struct adma_port_priv *pp = ap->private_data;
+ u8 *buf = pp->pkt;
+ int nelem, i = (2 + buf[3]) * 8;
+ u8 pFLAGS = pORD | ((qc->tf.flags & ATA_TFLAG_WRITE) ? pDIRO : 0);
+
+ for (nelem = 0; nelem < qc->n_elem; nelem++,sg++) {
+ u32 addr;
+ u32 len;
+
+ addr = (u32)sg_dma_address(sg);
+ *(__le32 *)(buf + i) = cpu_to_le32(addr);
+ i += 4;
+
+ len = sg_dma_len(sg) >> 3;
+ *(__le32 *)(buf + i) = cpu_to_le32(len);
+ i += 4;
+
+ if ((nelem + 1) == qc->n_elem)
+ pFLAGS |= pEND;
+ buf[i++] = pFLAGS;
+ buf[i++] = qc->dev->dma_mode & 0xf;
+ buf[i++] = 0; /* pPKLW */
+ buf[i++] = 0; /* reserved */
+
+ *(__le32 *)(buf + i)
+ = (pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4);
+ i += 4;
+
+ VPRINTK("PRD[%u] = (0x%lX, 0x%X)\n", nelem,
+ (unsigned long)addr, len);
+ }
+ return i;
+}
+
+static void adma_qc_prep(struct ata_queued_cmd *qc)
+{
+ struct adma_port_priv *pp = qc->ap->private_data;
+ u8 *buf = pp->pkt;
+ u32 pkt_dma = (u32)pp->pkt_dma;
+ int i = 0;
+
+ VPRINTK("ENTER\n");
+
+ adma_enter_reg_mode(qc->ap);
+ if (qc->tf.protocol != ATA_PROT_DMA) {
+ ata_qc_prep(qc);
+ return;
+ }
+
+ buf[i++] = 0; /* Response flags */
+ buf[i++] = 0; /* reserved */
+ buf[i++] = cVLD | cDAT | cIEN;
+ i++; /* cLEN, gets filled in below */
+
+ *(__le32 *)(buf+i) = cpu_to_le32(pkt_dma); /* cNCPB */
+ i += 4; /* cNCPB */
+ i += 4; /* cPRD, gets filled in below */
+
+ buf[i++] = 0; /* reserved */
+ buf[i++] = 0; /* reserved */
+ buf[i++] = 0; /* reserved */
+ buf[i++] = 0; /* reserved */
+
+ /* ATA registers; must be a multiple of 4 */
+ buf[i++] = qc->tf.device;
+ buf[i++] = ADMA_REGS_DEVICE;
+ if ((qc->tf.flags & ATA_TFLAG_LBA48)) {
+ buf[i++] = qc->tf.hob_nsect;
+ buf[i++] = ADMA_REGS_SECTOR_COUNT;
+ buf[i++] = qc->tf.hob_lbal;
+ buf[i++] = ADMA_REGS_LBA_LOW;
+ buf[i++] = qc->tf.hob_lbam;
+ buf[i++] = ADMA_REGS_LBA_MID;
+ buf[i++] = qc->tf.hob_lbah;
+ buf[i++] = ADMA_REGS_LBA_HIGH;
+ }
+ buf[i++] = qc->tf.nsect;
+ buf[i++] = ADMA_REGS_SECTOR_COUNT;
+ buf[i++] = qc->tf.lbal;
+ buf[i++] = ADMA_REGS_LBA_LOW;
+ buf[i++] = qc->tf.lbam;
+ buf[i++] = ADMA_REGS_LBA_MID;
+ buf[i++] = qc->tf.lbah;
+ buf[i++] = ADMA_REGS_LBA_HIGH;
+ buf[i++] = 0;
+ buf[i++] = ADMA_REGS_CONTROL;
+ buf[i++] = rIGN;
+ buf[i++] = 0;
+ buf[i++] = qc->tf.command;
+ buf[i++] = ADMA_REGS_COMMAND | rEND;
+
+ buf[3] = (i >> 3) - 2; /* cLEN */
+ *(__le32 *)(buf+8) = cpu_to_le32(pkt_dma + i); /* cPRD */
+
+ i = adma_fill_sg(qc);
+ wmb(); /* flush PRDs and pkt to memory */
+#if 0
+ /* dump out CPB + PRDs for debug */
+ {
+ int j, len = 0;
+ static char obuf[2048];
+ for (j = 0; j < i; ++j) {
+ len += sprintf(obuf+len, "%02x ", buf[j]);
+ if ((j & 7) == 7) {
+ printk("%s\n", obuf);
+ len = 0;
+ }
+ }
+ if (len)
+ printk("%s\n", obuf);
+ }
+#endif
+}
+
+static inline void adma_packet_start(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ void __iomem *chan = ADMA_REGS(ap->host_set->mmio_base, ap->port_no);
+
+ VPRINTK("ENTER, ap %p\n", ap);
+
+ /* fire up the ADMA engine */
+ writew(aPIOMD4 | aGO, chan + ADMA_CONTROL);
+}
+
+static int adma_qc_issue(struct ata_queued_cmd *qc)
+{
+ struct adma_port_priv *pp = qc->ap->private_data;
+
+ switch (qc->tf.protocol) {
+ case ATA_PROT_DMA:
+ pp->state = adma_state_pkt;
+ adma_packet_start(qc);
+ return 0;
+
+ case ATA_PROT_ATAPI_DMA:
+ BUG();
+ break;
+
+ default:
+ break;
+ }
+
+ pp->state = adma_state_mmio;
+ return ata_qc_issue_prot(qc);
+}
+
+static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set)
+{
+ unsigned int handled = 0, port_no;
+ u8 __iomem *mmio_base = host_set->mmio_base;
+
+ for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
+ struct ata_port *ap = host_set->ports[port_no];
+ struct adma_port_priv *pp;
+ struct ata_queued_cmd *qc;
+ void __iomem *chan = ADMA_REGS(mmio_base, port_no);
+ u8 drv_stat, status = readb(chan + ADMA_STATUS);
+
+ if (status == 0)
+ continue;
+ handled = 1;
+ adma_enter_reg_mode(ap);
+ if ((ap->flags & ATA_FLAG_PORT_DISABLED))
+ continue;
+ pp = ap->private_data;
+ if (!pp || pp->state != adma_state_pkt)
+ continue;
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+ drv_stat = 0;
+ if ((status & (aPERR | aPSD | aUIRQ)))
+ drv_stat = ATA_ERR;
+ else if (pp->pkt[0] != cDONE)
+ drv_stat = ATA_ERR;
+ ata_qc_complete(qc, drv_stat);
+ }
+ return handled;
+}
+
+static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set)
+{
+ unsigned int handled = 0, port_no;
+
+ for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
+ struct ata_port *ap;
+ ap = host_set->ports[port_no];
+ if (ap && (!(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)))) {
+ struct ata_queued_cmd *qc;
+ struct adma_port_priv *pp = ap->private_data;
+ if (!pp || pp->state != adma_state_mmio)
+ continue;
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+ if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+
+ /* check main status, clearing INTRQ */
+ u8 status = ata_chk_status(ap);
+ if ((status & ATA_BUSY))
+ continue;
+ DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
+ ap->id, qc->tf.protocol, status);
+
+ /* complete taskfile transaction */
+ pp->state = adma_state_idle;
+ ata_qc_complete(qc, status);
+ handled = 1;
+ }
+ }
+ }
+ return handled;
+}
+
+static irqreturn_t adma_intr(int irq, void *dev_instance, struct pt_regs *regs)
+{
+ struct ata_host_set *host_set = dev_instance;
+ unsigned int handled = 0;
+
+ VPRINTK("ENTER\n");
+
+ spin_lock(&host_set->lock);
+ handled = adma_intr_pkt(host_set) | adma_intr_mmio(host_set);
+ spin_unlock(&host_set->lock);
+
+ VPRINTK("EXIT\n");
+
+ return IRQ_RETVAL(handled);
+}
+
+static void adma_ata_setup_port(struct ata_ioports *port, unsigned long base)
+{
+ port->cmd_addr =
+ port->data_addr = base + 0x000;
+ port->error_addr =
+ port->feature_addr = base + 0x004;
+ port->nsect_addr = base + 0x008;
+ port->lbal_addr = base + 0x00c;
+ port->lbam_addr = base + 0x010;
+ port->lbah_addr = base + 0x014;
+ port->device_addr = base + 0x018;
+ port->status_addr =
+ port->command_addr = base + 0x01c;
+ port->altstatus_addr =
+ port->ctl_addr = base + 0x038;
+}
+
+static int adma_port_start(struct ata_port *ap)
+{
+ struct device *dev = ap->host_set->dev;
+ struct adma_port_priv *pp;
+ int rc;
+
+ rc = ata_port_start(ap);
+ if (rc)
+ return rc;
+ adma_enter_reg_mode(ap);
+ rc = -ENOMEM;
+ pp = kcalloc(1, sizeof(*pp), GFP_KERNEL);
+ if (!pp)
+ goto err_out;
+ pp->pkt = dma_alloc_coherent(dev, ADMA_PKT_BYTES, &pp->pkt_dma,
+ GFP_KERNEL);
+ if (!pp->pkt)
+ goto err_out_kfree;
+ /* paranoia? */
+ if ((pp->pkt_dma & 7) != 0) {
+ printk("bad alignment for pp->pkt_dma: %08x\n",
+ (u32)pp->pkt_dma);
+ goto err_out_kfree2;
+ }
+ memset(pp->pkt, 0, ADMA_PKT_BYTES);
+ ap->private_data = pp;
+ adma_reinit_engine(ap);
+ return 0;
+
+err_out_kfree2:
+ kfree(pp);
+err_out_kfree:
+ kfree(pp);
+err_out:
+ ata_port_stop(ap);
+ return rc;
+}
+
+static void adma_port_stop(struct ata_port *ap)
+{
+ struct device *dev = ap->host_set->dev;
+ struct adma_port_priv *pp = ap->private_data;
+
+ adma_reset_engine(ADMA_REGS(ap->host_set->mmio_base, ap->port_no));
+ if (pp != NULL) {
+ ap->private_data = NULL;
+ if (pp->pkt != NULL)
+ dma_free_coherent(dev, ADMA_PKT_BYTES,
+ pp->pkt, pp->pkt_dma);
+ kfree(pp);
+ }
+ ata_port_stop(ap);
+}
+
+static void adma_host_stop(struct ata_host_set *host_set)
+{
+ unsigned int port_no;
+
+ for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
+ adma_reset_engine(ADMA_REGS(host_set->mmio_base, port_no));
+
+ ata_pci_host_stop(host_set);
+}
+
+static void adma_host_init(unsigned int chip_id,
+ struct ata_probe_ent *probe_ent)
+{
+ unsigned int port_no;
+ void __iomem *mmio_base = probe_ent->mmio_base;
+
+ /* enable/lock aGO operation */
+ writeb(7, mmio_base + ADMA_MODE_LOCK);
+
+ /* reset the ADMA logic */
+ for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
+ adma_reset_engine(ADMA_REGS(mmio_base, port_no));
+}
+
+static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
+{
+ int rc;
+
+ rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (rc) {
+ printk(KERN_ERR DRV_NAME
+ "(%s): 32-bit DMA enable failed\n",
+ pci_name(pdev));
+ return rc;
+ }
+ rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (rc) {
+ printk(KERN_ERR DRV_NAME
+ "(%s): 32-bit consistent DMA enable failed\n",
+ pci_name(pdev));
+ return rc;
+ }
+ return 0;
+}
+
+static int adma_ata_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ static int printed_version;
+ struct ata_probe_ent *probe_ent = NULL;
+ void __iomem *mmio_base;
+ unsigned int board_idx = (unsigned int) ent->driver_data;
+ int rc, port_no;
+
+ if (!printed_version++)
+ printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+ rc = pci_enable_device(pdev);
+ if (rc)
+ return rc;
+
+ rc = pci_request_regions(pdev, DRV_NAME);
+ if (rc)
+ goto err_out;
+
+ if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0) {
+ rc = -ENODEV;
+ goto err_out_regions;
+ }
+
+ mmio_base = pci_iomap(pdev, 4, 0);
+ if (mmio_base == NULL) {
+ rc = -ENOMEM;
+ goto err_out_regions;
+ }
+
+ rc = adma_set_dma_masks(pdev, mmio_base);
+ if (rc)
+ goto err_out_iounmap;
+
+ probe_ent = kcalloc(1, sizeof(*probe_ent), GFP_KERNEL);
+ if (probe_ent == NULL) {
+ rc = -ENOMEM;
+ goto err_out_iounmap;
+ }
+
+ probe_ent->dev = pci_dev_to_dev(pdev);
+ INIT_LIST_HEAD(&probe_ent->node);
+
+ probe_ent->sht = adma_port_info[board_idx].sht;
+ probe_ent->host_flags = adma_port_info[board_idx].host_flags;
+ probe_ent->pio_mask = adma_port_info[board_idx].pio_mask;
+ probe_ent->mwdma_mask = adma_port_info[board_idx].mwdma_mask;
+ probe_ent->udma_mask = adma_port_info[board_idx].udma_mask;
+ probe_ent->port_ops = adma_port_info[board_idx].port_ops;
+
+ probe_ent->irq = pdev->irq;
+ probe_ent->irq_flags = SA_SHIRQ;
+ probe_ent->mmio_base = mmio_base;
+ probe_ent->n_ports = ADMA_PORTS;
+
+ for (port_no = 0; port_no < probe_ent->n_ports; ++port_no) {
+ adma_ata_setup_port(&probe_ent->port[port_no],
+ ADMA_ATA_REGS((unsigned long)mmio_base, port_no));
+ }
+
+ pci_set_master(pdev);
+
+ /* initialize adapter */
+ adma_host_init(board_idx, probe_ent);
+
+ rc = ata_device_add(probe_ent);
+ kfree(probe_ent);
+ if (rc != ADMA_PORTS)
+ goto err_out_iounmap;
+ return 0;
+
+err_out_iounmap:
+ pci_iounmap(pdev, mmio_base);
+err_out_regions:
+ pci_release_regions(pdev);
+err_out:
+ pci_disable_device(pdev);
+ return rc;
+}
+
+static int __init adma_ata_init(void)
+{
+ return pci_module_init(&adma_ata_pci_driver);
+}
+
+static void __exit adma_ata_exit(void)
+{
+ pci_unregister_driver(&adma_ata_pci_driver);
+}
+
+MODULE_AUTHOR("Mark Lord");
+MODULE_DESCRIPTION("Pacific Digital Corporation ADMA low-level driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, adma_ata_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(adma_ata_init);
+module_exit(adma_ata_exit);
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 1ed32e7b547209..e451941ad81d11 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -52,7 +52,7 @@ extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *);
extern int qla24xx_load_risc_flash(scsi_qla_host_t *, uint32_t *);
extern int qla24xx_load_risc_hotplug(scsi_qla_host_t *, uint32_t *);
-extern fc_port_t *qla2x00_alloc_fcport(scsi_qla_host_t *, int);
+extern fc_port_t *qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t);
extern int qla2x00_loop_resync(scsi_qla_host_t *);
@@ -277,7 +277,7 @@ extern int qla2x00_fdmi_register(scsi_qla_host_t *);
/*
* Global Function Prototypes in qla_rscn.c source file.
*/
-extern fc_port_t *qla2x00_alloc_rscn_fcport(scsi_qla_host_t *, int);
+extern fc_port_t *qla2x00_alloc_rscn_fcport(scsi_qla_host_t *, gfp_t);
extern int qla2x00_handle_port_rscn(scsi_qla_host_t *, uint32_t, fc_port_t *,
int);
extern void qla2x00_process_iodesc(scsi_qla_host_t *, struct mbx_entry *);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 23d095d3817b8c..fbb6feee40cfeb 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1685,7 +1685,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
* Returns a pointer to the allocated fcport, or NULL, if none available.
*/
fc_port_t *
-qla2x00_alloc_fcport(scsi_qla_host_t *ha, int flags)
+qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags)
{
fc_port_t *fcport;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 8982978c42fdfa..7aec93f9d42316 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1325,6 +1325,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->brd_info = brd_info;
sprintf(ha->host_str, "%s_%ld", ha->brd_info->drv_name, ha->host_no);
+ ha->dpc_pid = -1;
+
/* Configure PCI I/O space */
ret = qla2x00_iospace_config(ha);
if (ret)
@@ -1448,7 +1450,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
*/
spin_lock_init(&ha->mbx_reg_lock);
- ha->dpc_pid = -1;
init_completion(&ha->dpc_inited);
init_completion(&ha->dpc_exited);
diff --git a/drivers/scsi/qla2xxx/qla_rscn.c b/drivers/scsi/qla2xxx/qla_rscn.c
index 1eba988286360e..7534efcc891860 100644
--- a/drivers/scsi/qla2xxx/qla_rscn.c
+++ b/drivers/scsi/qla2xxx/qla_rscn.c
@@ -1066,7 +1066,7 @@ qla2x00_send_login_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
* Returns a pointer to the allocated RSCN fcport, or NULL, if none available.
*/
fc_port_t *
-qla2x00_alloc_rscn_fcport(scsi_qla_host_t *ha, int flags)
+qla2x00_alloc_rscn_fcport(scsi_qla_host_t *ha, gfp_t flags)
{
fc_port_t *fcport;
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index ea76fe44585e8f..422e0b6f603ac5 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -35,7 +35,7 @@
#include <asm/io.h>
#define DRV_NAME "sata_mv"
-#define DRV_VERSION "0.12"
+#define DRV_VERSION "0.25"
enum {
/* BAR's are enumerated in terms of pci_resource_start() terms */
@@ -55,31 +55,61 @@ enum {
MV_SATAHC_ARBTR_REG_SZ = MV_MINOR_REG_AREA_SZ, /* arbiter */
MV_PORT_REG_SZ = MV_MINOR_REG_AREA_SZ,
- MV_Q_CT = 32,
- MV_CRQB_SZ = 32,
- MV_CRPB_SZ = 8,
+ MV_USE_Q_DEPTH = ATA_DEF_QUEUE,
- MV_DMA_BOUNDARY = 0xffffffffU,
- SATAHC_MASK = (~(MV_SATAHC_REG_SZ - 1)),
+ MV_MAX_Q_DEPTH = 32,
+ MV_MAX_Q_DEPTH_MASK = MV_MAX_Q_DEPTH - 1,
+
+ /* CRQB needs alignment on a 1KB boundary. Size == 1KB
+ * CRPB needs alignment on a 256B boundary. Size == 256B
+ * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB
+ * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B
+ */
+ MV_CRQB_Q_SZ = (32 * MV_MAX_Q_DEPTH),
+ MV_CRPB_Q_SZ = (8 * MV_MAX_Q_DEPTH),
+ MV_MAX_SG_CT = 176,
+ MV_SG_TBL_SZ = (16 * MV_MAX_SG_CT),
+ MV_PORT_PRIV_DMA_SZ = (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ),
+
+ /* Our DMA boundary is determined by an ePRD being unable to handle
+ * anything larger than 64KB
+ */
+ MV_DMA_BOUNDARY = 0xffffU,
MV_PORTS_PER_HC = 4,
/* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
MV_PORT_HC_SHIFT = 2,
- /* == (port % MV_PORTS_PER_HC) to determine port from 0-7 port */
+ /* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
MV_PORT_MASK = 3,
/* Host Flags */
MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */
MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */
- MV_FLAG_BDMA = (1 << 28), /* Basic DMA */
+ MV_FLAG_GLBL_SFT_RST = (1 << 28), /* Global Soft Reset support */
+ MV_COMMON_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO),
+ MV_6XXX_FLAGS = (MV_FLAG_IRQ_COALESCE |
+ MV_FLAG_GLBL_SFT_RST),
chip_504x = 0,
chip_508x = 1,
chip_604x = 2,
chip_608x = 3,
+ CRQB_FLAG_READ = (1 << 0),
+ CRQB_TAG_SHIFT = 1,
+ CRQB_CMD_ADDR_SHIFT = 8,
+ CRQB_CMD_CS = (0x2 << 11),
+ CRQB_CMD_LAST = (1 << 15),
+
+ CRPB_FLAG_STATUS_SHIFT = 8,
+
+ EPRD_FLAG_END_OF_TBL = (1 << 31),
+
/* PCI interface registers */
+ PCI_COMMAND_OFS = 0xc00,
+
PCI_MAIN_CMD_STS_OFS = 0xd30,
STOP_PCI_MASTER = (1 << 2),
PCI_MASTER_EMPTY = (1 << 3),
@@ -111,20 +141,13 @@ enum {
HC_CFG_OFS = 0,
HC_IRQ_CAUSE_OFS = 0x14,
- CRBP_DMA_DONE = (1 << 0), /* shift by port # */
+ CRPB_DMA_DONE = (1 << 0), /* shift by port # */
HC_IRQ_COAL = (1 << 4), /* IRQ coalescing */
DEV_IRQ = (1 << 8), /* shift by port # */
/* Shadow block registers */
- SHD_PIO_DATA_OFS = 0x100,
- SHD_FEA_ERR_OFS = 0x104,
- SHD_SECT_CNT_OFS = 0x108,
- SHD_LBA_L_OFS = 0x10C,
- SHD_LBA_M_OFS = 0x110,
- SHD_LBA_H_OFS = 0x114,
- SHD_DEV_HD_OFS = 0x118,
- SHD_CMD_STA_OFS = 0x11C,
- SHD_CTL_AST_OFS = 0x120,
+ SHD_BLK_OFS = 0x100,
+ SHD_CTL_AST_OFS = 0x20, /* ofs from SHD_BLK_OFS */
/* SATA registers */
SATA_STATUS_OFS = 0x300, /* ctrl, err regs follow status */
@@ -132,6 +155,11 @@ enum {
/* Port registers */
EDMA_CFG_OFS = 0,
+ EDMA_CFG_Q_DEPTH = 0, /* queueing disabled */
+ EDMA_CFG_NCQ = (1 << 5),
+ EDMA_CFG_NCQ_GO_ON_ERR = (1 << 14), /* continue on error */
+ EDMA_CFG_RD_BRST_EXT = (1 << 11), /* read burst 512B */
+ EDMA_CFG_WR_BUFF_LEN = (1 << 13), /* write buffer 512B */
EDMA_ERR_IRQ_CAUSE_OFS = 0x8,
EDMA_ERR_IRQ_MASK_OFS = 0xc,
@@ -161,33 +189,85 @@ enum {
EDMA_ERR_LNK_DATA_TX |
EDMA_ERR_TRANS_PROTO),
+ EDMA_REQ_Q_BASE_HI_OFS = 0x10,
+ EDMA_REQ_Q_IN_PTR_OFS = 0x14, /* also contains BASE_LO */
+ EDMA_REQ_Q_BASE_LO_MASK = 0xfffffc00U,
+
+ EDMA_REQ_Q_OUT_PTR_OFS = 0x18,
+ EDMA_REQ_Q_PTR_SHIFT = 5,
+
+ EDMA_RSP_Q_BASE_HI_OFS = 0x1c,
+ EDMA_RSP_Q_IN_PTR_OFS = 0x20,
+ EDMA_RSP_Q_OUT_PTR_OFS = 0x24, /* also contains BASE_LO */
+ EDMA_RSP_Q_BASE_LO_MASK = 0xffffff00U,
+ EDMA_RSP_Q_PTR_SHIFT = 3,
+
EDMA_CMD_OFS = 0x28,
EDMA_EN = (1 << 0),
EDMA_DS = (1 << 1),
ATA_RST = (1 << 2),
- /* BDMA is 6xxx part only */
- BDMA_CMD_OFS = 0x224,
- BDMA_START = (1 << 0),
+ /* Host private flags (hp_flags) */
+ MV_HP_FLAG_MSI = (1 << 0),
- MV_UNDEF = 0,
+ /* Port private flags (pp_flags) */
+ MV_PP_FLAG_EDMA_EN = (1 << 0),
+ MV_PP_FLAG_EDMA_DS_ACT = (1 << 1),
};
-struct mv_port_priv {
+/* Command ReQuest Block: 32B */
+struct mv_crqb {
+ u32 sg_addr;
+ u32 sg_addr_hi;
+ u16 ctrl_flags;
+ u16 ata_cmd[11];
+};
+/* Command ResPonse Block: 8B */
+struct mv_crpb {
+ u16 id;
+ u16 flags;
+ u32 tmstmp;
};
-struct mv_host_priv {
+/* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */
+struct mv_sg {
+ u32 addr;
+ u32 flags_size;
+ u32 addr_hi;
+ u32 reserved;
+};
+struct mv_port_priv {
+ struct mv_crqb *crqb;
+ dma_addr_t crqb_dma;
+ struct mv_crpb *crpb;
+ dma_addr_t crpb_dma;
+ struct mv_sg *sg_tbl;
+ dma_addr_t sg_tbl_dma;
+
+ unsigned req_producer; /* cp of req_in_ptr */
+ unsigned rsp_consumer; /* cp of rsp_out_ptr */
+ u32 pp_flags;
+};
+
+struct mv_host_priv {
+ u32 hp_flags;
};
static void mv_irq_clear(struct ata_port *ap);
static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
+static u8 mv_check_err(struct ata_port *ap);
static void mv_phy_reset(struct ata_port *ap);
-static int mv_master_reset(void __iomem *mmio_base);
+static void mv_host_stop(struct ata_host_set *host_set);
+static int mv_port_start(struct ata_port *ap);
+static void mv_port_stop(struct ata_port *ap);
+static void mv_qc_prep(struct ata_queued_cmd *qc);
+static int mv_qc_issue(struct ata_queued_cmd *qc);
static irqreturn_t mv_interrupt(int irq, void *dev_instance,
struct pt_regs *regs);
+static void mv_eng_timeout(struct ata_port *ap);
static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static Scsi_Host_Template mv_sht = {
@@ -196,13 +276,13 @@ static Scsi_Host_Template mv_sht = {
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.eh_strategy_handler = ata_scsi_error,
- .can_queue = ATA_DEF_QUEUE,
+ .can_queue = MV_USE_Q_DEPTH,
.this_id = ATA_SHT_THIS_ID,
- .sg_tablesize = MV_UNDEF,
+ .sg_tablesize = MV_MAX_SG_CT,
.max_sectors = ATA_MAX_SECTORS,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED,
- .use_clustering = MV_UNDEF,
+ .use_clustering = ATA_SHT_USE_CLUSTERING,
.proc_name = DRV_NAME,
.dma_boundary = MV_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
@@ -210,21 +290,22 @@ static Scsi_Host_Template mv_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations mv_ops = {
+static const struct ata_port_operations mv_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
.check_status = ata_check_status,
+ .check_err = mv_check_err,
.exec_command = ata_exec_command,
.dev_select = ata_std_dev_select,
.phy_reset = mv_phy_reset,
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
+ .qc_prep = mv_qc_prep,
+ .qc_issue = mv_qc_issue,
- .eng_timeout = ata_eng_timeout,
+ .eng_timeout = mv_eng_timeout,
.irq_handler = mv_interrupt,
.irq_clear = mv_irq_clear,
@@ -232,46 +313,39 @@ static struct ata_port_operations mv_ops = {
.scr_read = mv_scr_read,
.scr_write = mv_scr_write,
- .port_start = ata_port_start,
- .port_stop = ata_port_stop,
- .host_stop = ata_host_stop,
+ .port_start = mv_port_start,
+ .port_stop = mv_port_stop,
+ .host_stop = mv_host_stop,
};
static struct ata_port_info mv_port_info[] = {
{ /* chip_504x */
.sht = &mv_sht,
- .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO),
- .pio_mask = 0x1f, /* pio4-0 */
- .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */
+ .host_flags = MV_COMMON_FLAGS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = 0, /* 0x7f (udma0-6 disabled for now) */
.port_ops = &mv_ops,
},
{ /* chip_508x */
.sht = &mv_sht,
- .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
- MV_FLAG_DUAL_HC),
- .pio_mask = 0x1f, /* pio4-0 */
- .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */
+ .host_flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = 0, /* 0x7f (udma0-6 disabled for now) */
.port_ops = &mv_ops,
},
{ /* chip_604x */
.sht = &mv_sht,
- .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
- MV_FLAG_IRQ_COALESCE | MV_FLAG_BDMA),
- .pio_mask = 0x1f, /* pio4-0 */
- .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */
+ .host_flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = 0x7f, /* udma0-6 */
.port_ops = &mv_ops,
},
{ /* chip_608x */
.sht = &mv_sht,
- .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
- MV_FLAG_IRQ_COALESCE | MV_FLAG_DUAL_HC |
- MV_FLAG_BDMA),
- .pio_mask = 0x1f, /* pio4-0 */
- .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */
+ .host_flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS |
+ MV_FLAG_DUAL_HC),
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = 0x7f, /* udma0-6 */
.port_ops = &mv_ops,
},
};
@@ -306,12 +380,6 @@ static inline void writelfl(unsigned long data, void __iomem *addr)
(void) readl(addr); /* flush to avoid PCI posted write */
}
-static inline void __iomem *mv_port_addr_to_hc_base(void __iomem *port_mmio)
-{
- return ((void __iomem *)((unsigned long)port_mmio &
- (unsigned long)SATAHC_MASK));
-}
-
static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
{
return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
@@ -329,24 +397,150 @@ static inline void __iomem *mv_ap_base(struct ata_port *ap)
return mv_port_base(ap->host_set->mmio_base, ap->port_no);
}
-static inline int mv_get_hc_count(unsigned long flags)
+static inline int mv_get_hc_count(unsigned long hp_flags)
{
- return ((flags & MV_FLAG_DUAL_HC) ? 2 : 1);
+ return ((hp_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
}
-static inline int mv_is_edma_active(struct ata_port *ap)
+static void mv_irq_clear(struct ata_port *ap)
+{
+}
+
+/**
+ * mv_start_dma - Enable eDMA engine
+ * @base: port base address
+ * @pp: port private data
+ *
+ * Verify the local cache of the eDMA state is accurate with an
+ * assert.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_start_dma(void __iomem *base, struct mv_port_priv *pp)
+{
+ if (!(MV_PP_FLAG_EDMA_EN & pp->pp_flags)) {
+ writelfl(EDMA_EN, base + EDMA_CMD_OFS);
+ pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
+ }
+ assert(EDMA_EN & readl(base + EDMA_CMD_OFS));
+}
+
+/**
+ * mv_stop_dma - Disable eDMA engine
+ * @ap: ATA channel to manipulate
+ *
+ * Verify the local cache of the eDMA state is accurate with an
+ * assert.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_stop_dma(struct ata_port *ap)
{
void __iomem *port_mmio = mv_ap_base(ap);
- return (EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
+ struct mv_port_priv *pp = ap->private_data;
+ u32 reg;
+ int i;
+
+ if (MV_PP_FLAG_EDMA_EN & pp->pp_flags) {
+ /* Disable EDMA if active. The disable bit auto clears.
+ */
+ writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
+ pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+ } else {
+ assert(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)));
+ }
+
+ /* now properly wait for the eDMA to stop */
+ for (i = 1000; i > 0; i--) {
+ reg = readl(port_mmio + EDMA_CMD_OFS);
+ if (!(EDMA_EN & reg)) {
+ break;
+ }
+ udelay(100);
+ }
+
+ if (EDMA_EN & reg) {
+ printk(KERN_ERR "ata%u: Unable to stop eDMA\n", ap->id);
+ /* FIXME: Consider doing a reset here to recover */
+ }
}
-static inline int mv_port_bdma_capable(struct ata_port *ap)
+#ifdef ATA_DEBUG
+static void mv_dump_mem(void __iomem *start, unsigned bytes)
{
- return (ap->flags & MV_FLAG_BDMA);
+ int b, w;
+ for (b = 0; b < bytes; ) {
+ DPRINTK("%p: ", start + b);
+ for (w = 0; b < bytes && w < 4; w++) {
+ printk("%08x ",readl(start + b));
+ b += sizeof(u32);
+ }
+ printk("\n");
+ }
}
+#endif
-static void mv_irq_clear(struct ata_port *ap)
+static void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
+{
+#ifdef ATA_DEBUG
+ int b, w;
+ u32 dw;
+ for (b = 0; b < bytes; ) {
+ DPRINTK("%02x: ", b);
+ for (w = 0; b < bytes && w < 4; w++) {
+ (void) pci_read_config_dword(pdev,b,&dw);
+ printk("%08x ",dw);
+ b += sizeof(u32);
+ }
+ printk("\n");
+ }
+#endif
+}
+static void mv_dump_all_regs(void __iomem *mmio_base, int port,
+ struct pci_dev *pdev)
{
+#ifdef ATA_DEBUG
+ void __iomem *hc_base = mv_hc_base(mmio_base,
+ port >> MV_PORT_HC_SHIFT);
+ void __iomem *port_base;
+ int start_port, num_ports, p, start_hc, num_hcs, hc;
+
+ if (0 > port) {
+ start_hc = start_port = 0;
+ num_ports = 8; /* shld be benign for 4 port devs */
+ num_hcs = 2;
+ } else {
+ start_hc = port >> MV_PORT_HC_SHIFT;
+ start_port = port;
+ num_ports = num_hcs = 1;
+ }
+ DPRINTK("All registers for port(s) %u-%u:\n", start_port,
+ num_ports > 1 ? num_ports - 1 : start_port);
+
+ if (NULL != pdev) {
+ DPRINTK("PCI config space regs:\n");
+ mv_dump_pci_cfg(pdev, 0x68);
+ }
+ DPRINTK("PCI regs:\n");
+ mv_dump_mem(mmio_base+0xc00, 0x3c);
+ mv_dump_mem(mmio_base+0xd00, 0x34);
+ mv_dump_mem(mmio_base+0xf00, 0x4);
+ mv_dump_mem(mmio_base+0x1d00, 0x6c);
+ for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
+ hc_base = mv_hc_base(mmio_base, port >> MV_PORT_HC_SHIFT);
+ DPRINTK("HC regs (HC %i):\n", hc);
+ mv_dump_mem(hc_base, 0x1c);
+ }
+ for (p = start_port; p < start_port + num_ports; p++) {
+ port_base = mv_port_base(mmio_base, p);
+ DPRINTK("EDMA regs (port %i):\n",p);
+ mv_dump_mem(port_base, 0x54);
+ DPRINTK("SATA regs (port %i):\n",p);
+ mv_dump_mem(port_base+0x300, 0x60);
+ }
+#endif
}
static unsigned int mv_scr_offset(unsigned int sc_reg_in)
@@ -389,30 +583,37 @@ static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
}
}
-static int mv_master_reset(void __iomem *mmio_base)
+/**
+ * mv_global_soft_reset - Perform the 6xxx global soft reset
+ * @mmio_base: base address of the HBA
+ *
+ * This routine only applies to 6xxx parts.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static int mv_global_soft_reset(void __iomem *mmio_base)
{
void __iomem *reg = mmio_base + PCI_MAIN_CMD_STS_OFS;
int i, rc = 0;
u32 t;
- VPRINTK("ENTER\n");
-
/* Following procedure defined in PCI "main command and status
* register" table.
*/
t = readl(reg);
writel(t | STOP_PCI_MASTER, reg);
- for (i = 0; i < 100; i++) {
- msleep(10);
+ for (i = 0; i < 1000; i++) {
+ udelay(1);
t = readl(reg);
if (PCI_MASTER_EMPTY & t) {
break;
}
}
if (!(PCI_MASTER_EMPTY & t)) {
- printk(KERN_ERR DRV_NAME "PCI master won't flush\n");
- rc = 1; /* broken HW? */
+ printk(KERN_ERR DRV_NAME ": PCI master won't flush\n");
+ rc = 1;
goto done;
}
@@ -425,39 +626,399 @@ static int mv_master_reset(void __iomem *mmio_base)
} while (!(GLOB_SFT_RST & t) && (i-- > 0));
if (!(GLOB_SFT_RST & t)) {
- printk(KERN_ERR DRV_NAME "can't set global reset\n");
- rc = 1; /* broken HW? */
+ printk(KERN_ERR DRV_NAME ": can't set global reset\n");
+ rc = 1;
goto done;
}
- /* clear reset */
+ /* clear reset and *reenable the PCI master* (not mentioned in spec) */
i = 5;
do {
- writel(t & ~GLOB_SFT_RST, reg);
+ writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg);
t = readl(reg);
udelay(1);
} while ((GLOB_SFT_RST & t) && (i-- > 0));
if (GLOB_SFT_RST & t) {
- printk(KERN_ERR DRV_NAME "can't clear global reset\n");
- rc = 1; /* broken HW? */
+ printk(KERN_ERR DRV_NAME ": can't clear global reset\n");
+ rc = 1;
}
-
- done:
- VPRINTK("EXIT, rc = %i\n", rc);
+done:
return rc;
}
-static void mv_err_intr(struct ata_port *ap)
+/**
+ * mv_host_stop - Host specific cleanup/stop routine.
+ * @host_set: host data structure
+ *
+ * Disable ints, cleanup host memory, call general purpose
+ * host_stop.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_host_stop(struct ata_host_set *host_set)
{
- void __iomem *port_mmio;
- u32 edma_err_cause, serr = 0;
+ struct mv_host_priv *hpriv = host_set->private_data;
+ struct pci_dev *pdev = to_pci_dev(host_set->dev);
+
+ if (hpriv->hp_flags & MV_HP_FLAG_MSI) {
+ pci_disable_msi(pdev);
+ } else {
+ pci_intx(pdev, 0);
+ }
+ kfree(hpriv);
+ ata_host_stop(host_set);
+}
+
+/**
+ * mv_port_start - Port specific init/start routine.
+ * @ap: ATA channel to manipulate
+ *
+ * Allocate and point to DMA memory, init port private memory,
+ * zero indices.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static int mv_port_start(struct ata_port *ap)
+{
+ struct device *dev = ap->host_set->dev;
+ struct mv_port_priv *pp;
+ void __iomem *port_mmio = mv_ap_base(ap);
+ void *mem;
+ dma_addr_t mem_dma;
+
+ pp = kmalloc(sizeof(*pp), GFP_KERNEL);
+ if (!pp) {
+ return -ENOMEM;
+ }
+ memset(pp, 0, sizeof(*pp));
+
+ mem = dma_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma,
+ GFP_KERNEL);
+ if (!mem) {
+ kfree(pp);
+ return -ENOMEM;
+ }
+ memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
+
+ /* First item in chunk of DMA memory:
+ * 32-slot command request table (CRQB), 32 bytes each in size
+ */
+ pp->crqb = mem;
+ pp->crqb_dma = mem_dma;
+ mem += MV_CRQB_Q_SZ;
+ mem_dma += MV_CRQB_Q_SZ;
+
+ /* Second item:
+ * 32-slot command response table (CRPB), 8 bytes each in size
+ */
+ pp->crpb = mem;
+ pp->crpb_dma = mem_dma;
+ mem += MV_CRPB_Q_SZ;
+ mem_dma += MV_CRPB_Q_SZ;
+
+ /* Third item:
+ * Table of scatter-gather descriptors (ePRD), 16 bytes each
+ */
+ pp->sg_tbl = mem;
+ pp->sg_tbl_dma = mem_dma;
+
+ writelfl(EDMA_CFG_Q_DEPTH | EDMA_CFG_RD_BRST_EXT |
+ EDMA_CFG_WR_BUFF_LEN, port_mmio + EDMA_CFG_OFS);
+
+ writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
+ writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK,
+ port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+
+ writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
+ writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
+
+ writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
+ writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK,
+ port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+
+ pp->req_producer = pp->rsp_consumer = 0;
+
+ /* Don't turn on EDMA here...do it before DMA commands only. Else
+ * we'll be unable to send non-data, PIO, etc due to restricted access
+ * to shadow regs.
+ */
+ ap->private_data = pp;
+ return 0;
+}
+
+/**
+ * mv_port_stop - Port specific cleanup/stop routine.
+ * @ap: ATA channel to manipulate
+ *
+ * Stop DMA, cleanup port memory.
+ *
+ * LOCKING:
+ * This routine uses the host_set lock to protect the DMA stop.
+ */
+static void mv_port_stop(struct ata_port *ap)
+{
+ struct device *dev = ap->host_set->dev;
+ struct mv_port_priv *pp = ap->private_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ mv_stop_dma(ap);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+ ap->private_data = NULL;
+ dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma);
+ kfree(pp);
+}
+
+/**
+ * mv_fill_sg - Fill out the Marvell ePRD (scatter gather) entries
+ * @qc: queued command whose SG list to source from
+ *
+ * Populate the SG list and mark the last entry.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_fill_sg(struct ata_queued_cmd *qc)
+{
+ struct mv_port_priv *pp = qc->ap->private_data;
+ unsigned int i;
+
+ for (i = 0; i < qc->n_elem; i++) {
+ u32 sg_len;
+ dma_addr_t addr;
+
+ addr = sg_dma_address(&qc->sg[i]);
+ sg_len = sg_dma_len(&qc->sg[i]);
+
+ pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff);
+ pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16);
+ assert(0 == (sg_len & ~MV_DMA_BOUNDARY));
+ pp->sg_tbl[i].flags_size = cpu_to_le32(sg_len);
+ }
+ if (0 < qc->n_elem) {
+ pp->sg_tbl[qc->n_elem - 1].flags_size |=
+ cpu_to_le32(EPRD_FLAG_END_OF_TBL);
+ }
+}
+
+static inline unsigned mv_inc_q_index(unsigned *index)
+{
+ *index = (*index + 1) & MV_MAX_Q_DEPTH_MASK;
+ return *index;
+}
+
+static inline void mv_crqb_pack_cmd(u16 *cmdw, u8 data, u8 addr, unsigned last)
+{
+ *cmdw = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
+ (last ? CRQB_CMD_LAST : 0);
+}
- /* bug here b/c we got an err int on a port we don't know about,
- * so there's no way to clear it
+/**
+ * mv_qc_prep - Host specific command preparation.
+ * @qc: queued command to prepare
+ *
+ * This routine simply redirects to the general purpose routine
+ * if command is not DMA. Else, it handles prep of the CRQB
+ * (command request block), does some sanity checking, and calls
+ * the SG load routine.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_qc_prep(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct mv_port_priv *pp = ap->private_data;
+ u16 *cw;
+ struct ata_taskfile *tf;
+ u16 flags = 0;
+
+ if (ATA_PROT_DMA != qc->tf.protocol) {
+ return;
+ }
+
+ /* the req producer index should be the same as we remember it */
+ assert(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >>
+ EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
+ pp->req_producer);
+
+ /* Fill in command request block
*/
- BUG_ON(NULL == ap);
- port_mmio = mv_ap_base(ap);
+ if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
+ flags |= CRQB_FLAG_READ;
+ }
+ assert(MV_MAX_Q_DEPTH > qc->tag);
+ flags |= qc->tag << CRQB_TAG_SHIFT;
+
+ pp->crqb[pp->req_producer].sg_addr =
+ cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
+ pp->crqb[pp->req_producer].sg_addr_hi =
+ cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
+ pp->crqb[pp->req_producer].ctrl_flags = cpu_to_le16(flags);
+
+ cw = &pp->crqb[pp->req_producer].ata_cmd[0];
+ tf = &qc->tf;
+
+ /* Sadly, the CRQB cannot accomodate all registers--there are
+ * only 11 bytes...so we must pick and choose required
+ * registers based on the command. So, we drop feature and
+ * hob_feature for [RW] DMA commands, but they are needed for
+ * NCQ. NCQ will drop hob_nsect.
+ */
+ switch (tf->command) {
+ case ATA_CMD_READ:
+ case ATA_CMD_READ_EXT:
+ case ATA_CMD_WRITE:
+ case ATA_CMD_WRITE_EXT:
+ mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
+ break;
+#ifdef LIBATA_NCQ /* FIXME: remove this line when NCQ added */
+ case ATA_CMD_FPDMA_READ:
+ case ATA_CMD_FPDMA_WRITE:
+ mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0);
+ mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0);
+ break;
+#endif /* FIXME: remove this line when NCQ added */
+ default:
+ /* The only other commands EDMA supports in non-queued and
+ * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none
+ * of which are defined/used by Linux. If we get here, this
+ * driver needs work.
+ *
+ * FIXME: modify libata to give qc_prep a return value and
+ * return error here.
+ */
+ BUG_ON(tf->command);
+ break;
+ }
+ mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0);
+ mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0);
+ mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0);
+ mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0);
+ mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0);
+ mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0);
+ mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0);
+ mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0);
+ mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1); /* last */
+
+ if (!(qc->flags & ATA_QCFLAG_DMAMAP)) {
+ return;
+ }
+ mv_fill_sg(qc);
+}
+
+/**
+ * mv_qc_issue - Initiate a command to the host
+ * @qc: queued command to start
+ *
+ * This routine simply redirects to the general purpose routine
+ * if command is not DMA. Else, it sanity checks our local
+ * caches of the request producer/consumer indices then enables
+ * DMA and bumps the request producer index.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static int mv_qc_issue(struct ata_queued_cmd *qc)
+{
+ void __iomem *port_mmio = mv_ap_base(qc->ap);
+ struct mv_port_priv *pp = qc->ap->private_data;
+ u32 in_ptr;
+
+ if (ATA_PROT_DMA != qc->tf.protocol) {
+ /* We're about to send a non-EDMA capable command to the
+ * port. Turn off EDMA so there won't be problems accessing
+ * shadow block, etc registers.
+ */
+ mv_stop_dma(qc->ap);
+ return ata_qc_issue_prot(qc);
+ }
+
+ in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+
+ /* the req producer index should be the same as we remember it */
+ assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
+ pp->req_producer);
+ /* until we do queuing, the queue should be empty at this point */
+ assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
+ ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >>
+ EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
+
+ mv_inc_q_index(&pp->req_producer); /* now incr producer index */
+
+ mv_start_dma(port_mmio, pp);
+
+ /* and write the request in pointer to kick the EDMA to life */
+ in_ptr &= EDMA_REQ_Q_BASE_LO_MASK;
+ in_ptr |= pp->req_producer << EDMA_REQ_Q_PTR_SHIFT;
+ writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+
+ return 0;
+}
+
+/**
+ * mv_get_crpb_status - get status from most recently completed cmd
+ * @ap: ATA channel to manipulate
+ *
+ * This routine is for use when the port is in DMA mode, when it
+ * will be using the CRPB (command response block) method of
+ * returning command completion information. We assert indices
+ * are good, grab status, and bump the response consumer index to
+ * prove that we're up to date.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static u8 mv_get_crpb_status(struct ata_port *ap)
+{
+ void __iomem *port_mmio = mv_ap_base(ap);
+ struct mv_port_priv *pp = ap->private_data;
+ u32 out_ptr;
+
+ out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+
+ /* the response consumer index should be the same as we remember it */
+ assert(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
+ pp->rsp_consumer);
+
+ /* increment our consumer index... */
+ pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer);
+
+ /* and, until we do NCQ, there should only be 1 CRPB waiting */
+ assert(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >>
+ EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
+ pp->rsp_consumer);
+
+ /* write out our inc'd consumer index so EDMA knows we're caught up */
+ out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
+ out_ptr |= pp->rsp_consumer << EDMA_RSP_Q_PTR_SHIFT;
+ writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+
+ /* Return ATA status register for completed CRPB */
+ return (pp->crpb[pp->rsp_consumer].flags >> CRPB_FLAG_STATUS_SHIFT);
+}
+
+/**
+ * mv_err_intr - Handle error interrupts on the port
+ * @ap: ATA channel to manipulate
+ *
+ * In most cases, just clear the interrupt and move on. However,
+ * some cases require an eDMA reset, which is done right before
+ * the COMRESET in mv_phy_reset(). The SERR case requires a
+ * clear of pending errors in the SATA SERROR register. Finally,
+ * if the port disabled DMA, update our cached copy to match.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_err_intr(struct ata_port *ap)
+{
+ void __iomem *port_mmio = mv_ap_base(ap);
+ u32 edma_err_cause, serr = 0;
edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
@@ -465,8 +1026,12 @@ static void mv_err_intr(struct ata_port *ap)
serr = scr_read(ap, SCR_ERROR);
scr_write_flush(ap, SCR_ERROR, serr);
}
- DPRINTK("port %u error; EDMA err cause: 0x%08x SERR: 0x%08x\n",
- ap->port_no, edma_err_cause, serr);
+ if (EDMA_ERR_SELF_DIS & edma_err_cause) {
+ struct mv_port_priv *pp = ap->private_data;
+ pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+ }
+ DPRINTK(KERN_ERR "ata%u: port error; EDMA err cause: 0x%08x "
+ "SERR: 0x%08x\n", ap->id, edma_err_cause, serr);
/* Clear EDMA now that SERR cleanup done */
writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
@@ -477,7 +1042,21 @@ static void mv_err_intr(struct ata_port *ap)
}
}
-/* Handle any outstanding interrupts in a single SATAHC
+/**
+ * mv_host_intr - Handle all interrupts on the given host controller
+ * @host_set: host specific structure
+ * @relevant: port error bits relevant to this host controller
+ * @hc: which host controller we're to look at
+ *
+ * Read then write clear the HC interrupt status then walk each
+ * port connected to the HC and see if it needs servicing. Port
+ * success ints are reported in the HC interrupt status reg, the
+ * port error ints are reported in the higher level main
+ * interrupt status register and thus are passed in via the
+ * 'relevant' argument.
+ *
+ * LOCKING:
+ * Inherited from caller.
*/
static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
unsigned int hc)
@@ -487,8 +1066,8 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
struct ata_port *ap;
struct ata_queued_cmd *qc;
u32 hc_irq_cause;
- int shift, port, port0, hard_port;
- u8 ata_status;
+ int shift, port, port0, hard_port, handled;
+ u8 ata_status = 0;
if (hc == 0) {
port0 = 0;
@@ -499,7 +1078,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
/* we'll need the HC success int register in most cases */
hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
if (hc_irq_cause) {
- writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
+ writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
}
VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
@@ -508,35 +1087,38 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
ap = host_set->ports[port];
hard_port = port & MV_PORT_MASK; /* range 0-3 */
- ata_status = 0xffU;
+ handled = 0; /* ensure ata_status is set if handled++ */
- if (((CRBP_DMA_DONE | DEV_IRQ) << hard_port) & hc_irq_cause) {
- BUG_ON(NULL == ap);
- /* rcv'd new resp, basic DMA complete, or ATA IRQ */
- /* This is needed to clear the ATA INTRQ.
- * FIXME: don't read the status reg in EDMA mode!
+ if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
+ /* new CRPB on the queue; just one at a time until NCQ
+ */
+ ata_status = mv_get_crpb_status(ap);
+ handled++;
+ } else if ((DEV_IRQ << hard_port) & hc_irq_cause) {
+ /* received ATA IRQ; read the status reg to clear INTRQ
*/
ata_status = readb((void __iomem *)
ap->ioaddr.status_addr);
+ handled++;
}
- shift = port * 2;
+ shift = port << 1; /* (port * 2) */
if (port >= MV_PORTS_PER_HC) {
shift++; /* skip bit 8 in the HC Main IRQ reg */
}
if ((PORT0_ERR << shift) & relevant) {
mv_err_intr(ap);
- /* FIXME: smart to OR in ATA_ERR? */
+ /* OR in ATA_ERR to ensure libata knows we took one */
ata_status = readb((void __iomem *)
ap->ioaddr.status_addr) | ATA_ERR;
+ handled++;
}
- if (ap) {
+ if (handled && ap) {
qc = ata_qc_from_tag(ap, ap->active_tag);
if (NULL != qc) {
VPRINTK("port %u IRQ found for qc, "
"ata_status 0x%x\n", port,ata_status);
- BUG_ON(0xffU == ata_status);
/* mark qc status appropriately */
ata_qc_complete(qc, ata_status);
}
@@ -545,17 +1127,30 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
VPRINTK("EXIT\n");
}
+/**
+ * mv_interrupt -
+ * @irq: unused
+ * @dev_instance: private data; in this case the host structure
+ * @regs: unused
+ *
+ * Read the read only register to determine if any host
+ * controllers have pending interrupts. If so, call lower level
+ * routine to handle. Also check for PCI errors which are only
+ * reported here.
+ *
+ * LOCKING:
+ * This routine holds the host_set lock while processing pending
+ * interrupts.
+ */
static irqreturn_t mv_interrupt(int irq, void *dev_instance,
struct pt_regs *regs)
{
struct ata_host_set *host_set = dev_instance;
unsigned int hc, handled = 0, n_hcs;
- void __iomem *mmio;
+ void __iomem *mmio = host_set->mmio_base;
u32 irq_stat;
- mmio = host_set->mmio_base;
irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
- n_hcs = mv_get_hc_count(host_set->ports[0]->flags);
/* check the cases where we either have nothing pending or have read
* a bogus register value which can indicate HW removal or PCI fault
@@ -564,64 +1159,105 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance,
return IRQ_NONE;
}
+ n_hcs = mv_get_hc_count(host_set->ports[0]->flags);
spin_lock(&host_set->lock);
for (hc = 0; hc < n_hcs; hc++) {
u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
if (relevant) {
mv_host_intr(host_set, relevant, hc);
- handled = 1;
+ handled++;
}
}
if (PCI_ERR & irq_stat) {
- /* FIXME: these are all masked by default, but still need
- * to recover from them properly.
- */
- }
+ printk(KERN_ERR DRV_NAME ": PCI ERROR; PCI IRQ cause=0x%08x\n",
+ readl(mmio + PCI_IRQ_CAUSE_OFS));
+ DPRINTK("All regs @ PCI error\n");
+ mv_dump_all_regs(mmio, -1, to_pci_dev(host_set->dev));
+
+ writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
+ handled++;
+ }
spin_unlock(&host_set->lock);
return IRQ_RETVAL(handled);
}
+/**
+ * mv_check_err - Return the error shadow register to caller.
+ * @ap: ATA channel to manipulate
+ *
+ * Marvell requires DMA to be stopped before accessing shadow
+ * registers. So we do that, then return the needed register.
+ *
+ * LOCKING:
+ * Inherited from caller. FIXME: protect mv_stop_dma with lock?
+ */
+static u8 mv_check_err(struct ata_port *ap)
+{
+ mv_stop_dma(ap); /* can't read shadow regs if DMA on */
+ return readb((void __iomem *) ap->ioaddr.error_addr);
+}
+
+/**
+ * mv_phy_reset - Perform eDMA reset followed by COMRESET
+ * @ap: ATA channel to manipulate
+ *
+ * Part of this is taken from __sata_phy_reset and modified to
+ * not sleep since this routine gets called from interrupt level.
+ *
+ * LOCKING:
+ * Inherited from caller. This is coded to safe to call at
+ * interrupt level, i.e. it does not sleep.
+ */
static void mv_phy_reset(struct ata_port *ap)
{
void __iomem *port_mmio = mv_ap_base(ap);
struct ata_taskfile tf;
struct ata_device *dev = &ap->device[0];
- u32 edma = 0, bdma;
+ unsigned long timeout;
VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
- edma = readl(port_mmio + EDMA_CMD_OFS);
- if (EDMA_EN & edma) {
- /* disable EDMA if active */
- edma &= ~EDMA_EN;
- writelfl(edma | EDMA_DS, port_mmio + EDMA_CMD_OFS);
- udelay(1);
- } else if (mv_port_bdma_capable(ap) &&
- (bdma = readl(port_mmio + BDMA_CMD_OFS)) & BDMA_START) {
- /* disable BDMA if active */
- writelfl(bdma & ~BDMA_START, port_mmio + BDMA_CMD_OFS);
- }
+ mv_stop_dma(ap);
- writelfl(edma | ATA_RST, port_mmio + EDMA_CMD_OFS);
+ writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
udelay(25); /* allow reset propagation */
/* Spec never mentions clearing the bit. Marvell's driver does
* clear the bit, however.
*/
- writelfl(edma & ~ATA_RST, port_mmio + EDMA_CMD_OFS);
+ writelfl(0, port_mmio + EDMA_CMD_OFS);
- VPRINTK("Done. Now calling __sata_phy_reset()\n");
+ VPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
+ "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
+ mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
/* proceed to init communications via the scr_control reg */
- __sata_phy_reset(ap);
+ scr_write_flush(ap, SCR_CONTROL, 0x301);
+ mdelay(1);
+ scr_write_flush(ap, SCR_CONTROL, 0x300);
+ timeout = jiffies + (HZ * 1);
+ do {
+ mdelay(10);
+ if ((scr_read(ap, SCR_STATUS) & 0xf) != 1)
+ break;
+ } while (time_before(jiffies, timeout));
- if (ap->flags & ATA_FLAG_PORT_DISABLED) {
- VPRINTK("Port disabled pre-sig. Exiting.\n");
+ VPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x "
+ "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
+ mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
+
+ if (sata_dev_present(ap)) {
+ ata_port_probe(ap);
+ } else {
+ printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n",
+ ap->id, scr_read(ap, SCR_STATUS));
+ ata_port_disable(ap);
return;
}
+ ap->cbl = ATA_CBL_SATA;
tf.lbah = readb((void __iomem *) ap->ioaddr.lbah_addr);
tf.lbam = readb((void __iomem *) ap->ioaddr.lbam_addr);
@@ -636,37 +1272,118 @@ static void mv_phy_reset(struct ata_port *ap)
VPRINTK("EXIT\n");
}
-static void mv_port_init(struct ata_ioports *port, unsigned long base)
+/**
+ * mv_eng_timeout - Routine called by libata when SCSI times out I/O
+ * @ap: ATA channel to manipulate
+ *
+ * Intent is to clear all pending error conditions, reset the
+ * chip/bus, fail the command, and move on.
+ *
+ * LOCKING:
+ * This routine holds the host_set lock while failing the command.
+ */
+static void mv_eng_timeout(struct ata_port *ap)
+{
+ struct ata_queued_cmd *qc;
+ unsigned long flags;
+
+ printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id);
+ DPRINTK("All regs @ start of eng_timeout\n");
+ mv_dump_all_regs(ap->host_set->mmio_base, ap->port_no,
+ to_pci_dev(ap->host_set->dev));
+
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+ printk(KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n",
+ ap->host_set->mmio_base, ap, qc, qc->scsicmd,
+ &qc->scsicmd->cmnd);
+
+ mv_err_intr(ap);
+ mv_phy_reset(ap);
+
+ if (!qc) {
+ printk(KERN_ERR "ata%u: BUG: timeout without command\n",
+ ap->id);
+ } else {
+ /* hack alert! We cannot use the supplied completion
+ * function from inside the ->eh_strategy_handler() thread.
+ * libata is the only user of ->eh_strategy_handler() in
+ * any kernel, so the default scsi_done() assumes it is
+ * not being called from the SCSI EH.
+ */
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ qc->scsidone = scsi_finish_command;
+ ata_qc_complete(qc, ATA_ERR);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+ }
+}
+
+/**
+ * mv_port_init - Perform some early initialization on a single port.
+ * @port: libata data structure storing shadow register addresses
+ * @port_mmio: base address of the port
+ *
+ * Initialize shadow register mmio addresses, clear outstanding
+ * interrupts on the port, and unmask interrupts for the future
+ * start of the port.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_port_init(struct ata_ioports *port, void __iomem *port_mmio)
{
- /* PIO related setup */
- port->data_addr = base + SHD_PIO_DATA_OFS;
- port->error_addr = port->feature_addr = base + SHD_FEA_ERR_OFS;
- port->nsect_addr = base + SHD_SECT_CNT_OFS;
- port->lbal_addr = base + SHD_LBA_L_OFS;
- port->lbam_addr = base + SHD_LBA_M_OFS;
- port->lbah_addr = base + SHD_LBA_H_OFS;
- port->device_addr = base + SHD_DEV_HD_OFS;
- port->status_addr = port->command_addr = base + SHD_CMD_STA_OFS;
- port->altstatus_addr = port->ctl_addr = base + SHD_CTL_AST_OFS;
- /* unused */
+ unsigned long shd_base = (unsigned long) port_mmio + SHD_BLK_OFS;
+ unsigned serr_ofs;
+
+ /* PIO related setup
+ */
+ port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA);
+ port->error_addr =
+ port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR);
+ port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT);
+ port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL);
+ port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM);
+ port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH);
+ port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE);
+ port->status_addr =
+ port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS);
+ /* special case: control/altstatus doesn't have ATA_REG_ address */
+ port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS;
+
+ /* unused: */
port->cmd_addr = port->bmdma_addr = port->scr_addr = 0;
+ /* Clear any currently outstanding port interrupt conditions */
+ serr_ofs = mv_scr_offset(SCR_ERROR);
+ writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs);
+ writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
/* unmask all EDMA error interrupts */
- writel(~0, (void __iomem *)base + EDMA_ERR_IRQ_MASK_OFS);
+ writelfl(~0, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n",
- readl((void __iomem *)base + EDMA_CFG_OFS),
- readl((void __iomem *)base + EDMA_ERR_IRQ_CAUSE_OFS),
- readl((void __iomem *)base + EDMA_ERR_IRQ_MASK_OFS));
+ readl(port_mmio + EDMA_CFG_OFS),
+ readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS),
+ readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
}
+/**
+ * mv_host_init - Perform some early initialization of the host.
+ * @probe_ent: early data struct representing the host
+ *
+ * If possible, do an early global reset of the host. Then do
+ * our port init and clear/unmask all/relevant host interrupts.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
static int mv_host_init(struct ata_probe_ent *probe_ent)
{
int rc = 0, n_hc, port, hc;
void __iomem *mmio = probe_ent->mmio_base;
void __iomem *port_mmio;
- if (mv_master_reset(probe_ent->mmio_base)) {
+ if ((MV_FLAG_GLBL_SFT_RST & probe_ent->host_flags) &&
+ mv_global_soft_reset(probe_ent->mmio_base)) {
rc = 1;
goto done;
}
@@ -676,17 +1393,27 @@ static int mv_host_init(struct ata_probe_ent *probe_ent)
for (port = 0; port < probe_ent->n_ports; port++) {
port_mmio = mv_port_base(mmio, port);
- mv_port_init(&probe_ent->port[port], (unsigned long)port_mmio);
+ mv_port_init(&probe_ent->port[port], port_mmio);
}
for (hc = 0; hc < n_hc; hc++) {
- VPRINTK("HC%i: HC config=0x%08x HC IRQ cause=0x%08x\n", hc,
- readl(mv_hc_base(mmio, hc) + HC_CFG_OFS),
- readl(mv_hc_base(mmio, hc) + HC_IRQ_CAUSE_OFS));
+ void __iomem *hc_mmio = mv_hc_base(mmio, hc);
+
+ VPRINTK("HC%i: HC config=0x%08x HC IRQ cause "
+ "(before clear)=0x%08x\n", hc,
+ readl(hc_mmio + HC_CFG_OFS),
+ readl(hc_mmio + HC_IRQ_CAUSE_OFS));
+
+ /* Clear any currently outstanding hc interrupt conditions */
+ writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
}
- writel(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
- writel(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
+ /* Clear any currently outstanding host interrupt conditions */
+ writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
+
+ /* and unmask interrupt generation for host regs */
+ writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
+ writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
"PCI int cause/mask=0x%08x/0x%08x\n",
@@ -694,11 +1421,53 @@ static int mv_host_init(struct ata_probe_ent *probe_ent)
readl(mmio + HC_MAIN_IRQ_MASK_OFS),
readl(mmio + PCI_IRQ_CAUSE_OFS),
readl(mmio + PCI_IRQ_MASK_OFS));
-
- done:
+done:
return rc;
}
+/**
+ * mv_print_info - Dump key info to kernel log for perusal.
+ * @probe_ent: early data struct representing the host
+ *
+ * FIXME: complete this.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_print_info(struct ata_probe_ent *probe_ent)
+{
+ struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
+ struct mv_host_priv *hpriv = probe_ent->private_data;
+ u8 rev_id, scc;
+ const char *scc_s;
+
+ /* Use this to determine the HW stepping of the chip so we know
+ * what errata to workaround
+ */
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
+
+ pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc);
+ if (scc == 0)
+ scc_s = "SCSI";
+ else if (scc == 0x01)
+ scc_s = "RAID";
+ else
+ scc_s = "unknown";
+
+ printk(KERN_INFO DRV_NAME
+ "(%s) %u slots %u ports %s mode IRQ via %s\n",
+ pci_name(pdev), (unsigned)MV_MAX_Q_DEPTH, probe_ent->n_ports,
+ scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
+}
+
+/**
+ * mv_init_one - handle a positive probe of a Marvell host
+ * @pdev: PCI device found
+ * @ent: PCI device ID entry for the matched host
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version = 0;
@@ -706,16 +1475,12 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
struct mv_host_priv *hpriv;
unsigned int board_idx = (unsigned int)ent->driver_data;
void __iomem *mmio_base;
- int pci_dev_busy = 0;
- int rc;
+ int pci_dev_busy = 0, rc;
if (!printed_version++) {
- printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+ printk(KERN_INFO DRV_NAME " version " DRV_VERSION "\n");
}
- VPRINTK("ENTER for PCI Bus:Slot.Func=%u:%u.%u\n", pdev->bus->number,
- PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
-
rc = pci_enable_device(pdev);
if (rc) {
return rc;
@@ -727,8 +1492,6 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out;
}
- pci_intx(pdev, 1);
-
probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
if (probe_ent == NULL) {
rc = -ENOMEM;
@@ -739,8 +1502,7 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
probe_ent->dev = pci_dev_to_dev(pdev);
INIT_LIST_HEAD(&probe_ent->node);
- mmio_base = ioremap_nocache(pci_resource_start(pdev, MV_PRIMARY_BAR),
- pci_resource_len(pdev, MV_PRIMARY_BAR));
+ mmio_base = pci_iomap(pdev, MV_PRIMARY_BAR, 0);
if (mmio_base == NULL) {
rc = -ENOMEM;
goto err_out_free_ent;
@@ -769,37 +1531,40 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc) {
goto err_out_hpriv;
}
-/* mv_print_info(probe_ent); */
- {
- int b, w;
- u32 dw[4]; /* hold a line of 16b */
- VPRINTK("PCI config space:\n");
- for (b = 0; b < 0x40; ) {
- for (w = 0; w < 4; w++) {
- (void) pci_read_config_dword(pdev,b,&dw[w]);
- b += sizeof(*dw);
- }
- VPRINTK("%08x %08x %08x %08x\n",
- dw[0],dw[1],dw[2],dw[3]);
- }
+ /* Enable interrupts */
+ if (pci_enable_msi(pdev) == 0) {
+ hpriv->hp_flags |= MV_HP_FLAG_MSI;
+ } else {
+ pci_intx(pdev, 1);
}
- /* FIXME: check ata_device_add return value */
- ata_device_add(probe_ent);
- kfree(probe_ent);
+ mv_dump_pci_cfg(pdev, 0x68);
+ mv_print_info(probe_ent);
+
+ if (ata_device_add(probe_ent) == 0) {
+ rc = -ENODEV; /* No devices discovered */
+ goto err_out_dev_add;
+ }
+ kfree(probe_ent);
return 0;
- err_out_hpriv:
+err_out_dev_add:
+ if (MV_HP_FLAG_MSI & hpriv->hp_flags) {
+ pci_disable_msi(pdev);
+ } else {
+ pci_intx(pdev, 0);
+ }
+err_out_hpriv:
kfree(hpriv);
- err_out_iounmap:
- iounmap(mmio_base);
- err_out_free_ent:
+err_out_iounmap:
+ pci_iounmap(pdev, mmio_base);
+err_out_free_ent:
kfree(probe_ent);
- err_out_regions:
+err_out_regions:
pci_release_regions(pdev);
- err_out:
+err_out:
if (!pci_dev_busy) {
pci_disable_device(pdev);
}
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index cb832b03ec5e0c..1a56d6c79dddfc 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -238,7 +238,7 @@ static Scsi_Host_Template nv_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations nv_ops = {
+static const struct ata_port_operations nv_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
@@ -331,7 +331,7 @@ static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg)
return 0xffffffffU;
if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
- return readl((void*)ap->ioaddr.scr_addr + (sc_reg * 4));
+ return readl((void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4));
else
return inl(ap->ioaddr.scr_addr + (sc_reg * 4));
}
@@ -345,7 +345,7 @@ static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
return;
if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
- writel(val, (void*)ap->ioaddr.scr_addr + (sc_reg * 4));
+ writel(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4));
else
outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
}
@@ -405,7 +405,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
rc = -ENOMEM;
ppi = &nv_port_info;
- probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+ probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
if (!probe_ent)
goto err_out_regions;
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 538ad727bd2eb8..eee93b0016df36 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -87,8 +87,8 @@ static void pdc_port_stop(struct ata_port *ap);
static void pdc_pata_phy_reset(struct ata_port *ap);
static void pdc_sata_phy_reset(struct ata_port *ap);
static void pdc_qc_prep(struct ata_queued_cmd *qc);
-static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
-static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
+static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
static void pdc_irq_clear(struct ata_port *ap);
static int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
@@ -113,7 +113,7 @@ static Scsi_Host_Template pdc_ata_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations pdc_sata_ops = {
+static const struct ata_port_operations pdc_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = pdc_tf_load_mmio,
.tf_read = ata_tf_read,
@@ -136,7 +136,7 @@ static struct ata_port_operations pdc_sata_ops = {
.host_stop = ata_pci_host_stop,
};
-static struct ata_port_operations pdc_pata_ops = {
+static const struct ata_port_operations pdc_pata_ops = {
.port_disable = ata_port_disable,
.tf_load = pdc_tf_load_mmio,
.tf_read = ata_tf_read,
@@ -324,7 +324,7 @@ static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
if (sc_reg > SCR_CONTROL)
return 0xffffffffU;
- return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
@@ -333,7 +333,7 @@ static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
{
if (sc_reg > SCR_CONTROL)
return;
- writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
static void pdc_qc_prep(struct ata_queued_cmd *qc)
@@ -438,11 +438,11 @@ static inline unsigned int pdc_host_intr( struct ata_port *ap,
break;
default:
- ap->stats.idle_irq++;
- break;
+ ap->stats.idle_irq++;
+ break;
}
- return handled;
+ return handled;
}
static void pdc_irq_clear(struct ata_port *ap)
@@ -523,8 +523,8 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc)
pp->pkt[2] = seq;
wmb(); /* flush PRD, pkt writes */
- writel(pp->pkt_dma, (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
- readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
+ writel(pp->pkt_dma, (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+ readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
}
static int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
@@ -546,7 +546,7 @@ static int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
return ata_qc_issue_prot(qc);
}
-static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
tf->protocol == ATA_PROT_NODATA);
@@ -554,7 +554,7 @@ static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
}
-static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
tf->protocol == ATA_PROT_NODATA);
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
index ffcdeb68641cf5..250dafa6bc3637 100644
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -51,8 +51,6 @@ enum {
QS_PRD_BYTES = QS_MAX_PRD * 16,
QS_PKT_BYTES = QS_CPB_BYTES + QS_PRD_BYTES,
- QS_DMA_BOUNDARY = ~0UL,
-
/* global register offsets */
QS_HCF_CNFG3 = 0x0003, /* host configuration offset */
QS_HID_HPHY = 0x0004, /* host physical interface info */
@@ -101,6 +99,10 @@ enum {
board_2068_idx = 0, /* QStor 4-port SATA/RAID */
};
+enum {
+ QS_DMA_BOUNDARY = ~0UL
+};
+
typedef enum { qs_state_idle, qs_state_pkt, qs_state_mmio } qs_state_t;
struct qs_port_priv {
@@ -145,7 +147,7 @@ static Scsi_Host_Template qs_ata_sht = {
.bios_param = ata_std_bios_param,
};
-static struct ata_port_operations qs_ata_ops = {
+static const struct ata_port_operations qs_ata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index ba98a175ee3a8f..3a056173fb95a2 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -150,7 +150,7 @@ static Scsi_Host_Template sil_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations sil_ops = {
+static const struct ata_port_operations sil_ops = {
.port_disable = ata_port_disable,
.dev_config = sil_dev_config,
.tf_load = ata_tf_load,
@@ -289,7 +289,7 @@ static inline unsigned long sil_scr_addr(struct ata_port *ap, unsigned int sc_re
static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
- void *mmio = (void *) sil_scr_addr(ap, sc_reg);
+ void __iomem *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
if (mmio)
return readl(mmio);
return 0xffffffffU;
@@ -297,7 +297,7 @@ static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg)
static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
{
- void *mmio = (void *) sil_scr_addr(ap, sc_reg);
+ void *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
if (mmio)
writel(val, mmio);
}
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
new file mode 100644
index 00000000000000..32d730bd5bb605
--- /dev/null
+++ b/drivers/scsi/sata_sil24.c
@@ -0,0 +1,875 @@
+/*
+ * sata_sil24.c - Driver for Silicon Image 3124/3132 SATA-2 controllers
+ *
+ * Copyright 2005 Tejun Heo
+ *
+ * Based on preview driver from Silicon Image.
+ *
+ * NOTE: No NCQ/ATAPI support yet. The preview driver didn't support
+ * NCQ nor ATAPI, and, unfortunately, I couldn't find out how to make
+ * those work. Enabling those shouldn't be difficult. Basic
+ * structure is all there (in libata-dev tree). If you have any
+ * information about this hardware, please contact me or linux-ide.
+ * Info is needed on...
+ *
+ * - How to issue tagged commands and turn on sactive on issue accordingly.
+ * - Where to put an ATAPI command and how to tell the device to send it.
+ * - How to enable/use 64bit.
+ *
+ * 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, 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <scsi/scsi_host.h>
+#include "scsi.h"
+#include <linux/libata.h>
+#include <asm/io.h>
+
+#define DRV_NAME "sata_sil24"
+#define DRV_VERSION "0.22" /* Silicon Image's preview driver was 0.10 */
+
+/*
+ * Port request block (PRB) 32 bytes
+ */
+struct sil24_prb {
+ u16 ctrl;
+ u16 prot;
+ u32 rx_cnt;
+ u8 fis[6 * 4];
+};
+
+/*
+ * Scatter gather entry (SGE) 16 bytes
+ */
+struct sil24_sge {
+ u64 addr;
+ u32 cnt;
+ u32 flags;
+};
+
+/*
+ * Port multiplier
+ */
+struct sil24_port_multiplier {
+ u32 diag;
+ u32 sactive;
+};
+
+enum {
+ /*
+ * Global controller registers (128 bytes @ BAR0)
+ */
+ /* 32 bit regs */
+ HOST_SLOT_STAT = 0x00, /* 32 bit slot stat * 4 */
+ HOST_CTRL = 0x40,
+ HOST_IRQ_STAT = 0x44,
+ HOST_PHY_CFG = 0x48,
+ HOST_BIST_CTRL = 0x50,
+ HOST_BIST_PTRN = 0x54,
+ HOST_BIST_STAT = 0x58,
+ HOST_MEM_BIST_STAT = 0x5c,
+ HOST_FLASH_CMD = 0x70,
+ /* 8 bit regs */
+ HOST_FLASH_DATA = 0x74,
+ HOST_TRANSITION_DETECT = 0x75,
+ HOST_GPIO_CTRL = 0x76,
+ HOST_I2C_ADDR = 0x78, /* 32 bit */
+ HOST_I2C_DATA = 0x7c,
+ HOST_I2C_XFER_CNT = 0x7e,
+ HOST_I2C_CTRL = 0x7f,
+
+ /* HOST_SLOT_STAT bits */
+ HOST_SSTAT_ATTN = (1 << 31),
+
+ /*
+ * Port registers
+ * (8192 bytes @ +0x0000, +0x2000, +0x4000 and +0x6000 @ BAR2)
+ */
+ PORT_REGS_SIZE = 0x2000,
+ PORT_PRB = 0x0000, /* (32 bytes PRB + 16 bytes SGEs * 6) * 31 (3968 bytes) */
+
+ PORT_PM = 0x0f80, /* 8 bytes PM * 16 (128 bytes) */
+ /* 32 bit regs */
+ PORT_CTRL_STAT = 0x1000, /* write: ctrl-set, read: stat */
+ PORT_CTRL_CLR = 0x1004, /* write: ctrl-clear */
+ PORT_IRQ_STAT = 0x1008, /* high: status, low: interrupt */
+ PORT_IRQ_ENABLE_SET = 0x1010, /* write: enable-set */
+ PORT_IRQ_ENABLE_CLR = 0x1014, /* write: enable-clear */
+ PORT_ACTIVATE_UPPER_ADDR= 0x101c,
+ PORT_EXEC_FIFO = 0x1020, /* command execution fifo */
+ PORT_CMD_ERR = 0x1024, /* command error number */
+ PORT_FIS_CFG = 0x1028,
+ PORT_FIFO_THRES = 0x102c,
+ /* 16 bit regs */
+ PORT_DECODE_ERR_CNT = 0x1040,
+ PORT_DECODE_ERR_THRESH = 0x1042,
+ PORT_CRC_ERR_CNT = 0x1044,
+ PORT_CRC_ERR_THRESH = 0x1046,
+ PORT_HSHK_ERR_CNT = 0x1048,
+ PORT_HSHK_ERR_THRESH = 0x104a,
+ /* 32 bit regs */
+ PORT_PHY_CFG = 0x1050,
+ PORT_SLOT_STAT = 0x1800,
+ PORT_CMD_ACTIVATE = 0x1c00, /* 64 bit cmd activate * 31 (248 bytes) */
+ PORT_EXEC_DIAG = 0x1e00, /* 32bit exec diag * 16 (64 bytes, 0-10 used on 3124) */
+ PORT_PSD_DIAG = 0x1e40, /* 32bit psd diag * 16 (64 bytes, 0-8 used on 3124) */
+ PORT_SCONTROL = 0x1f00,
+ PORT_SSTATUS = 0x1f04,
+ PORT_SERROR = 0x1f08,
+ PORT_SACTIVE = 0x1f0c,
+
+ /* PORT_CTRL_STAT bits */
+ PORT_CS_PORT_RST = (1 << 0), /* port reset */
+ PORT_CS_DEV_RST = (1 << 1), /* device reset */
+ PORT_CS_INIT = (1 << 2), /* port initialize */
+ PORT_CS_IRQ_WOC = (1 << 3), /* interrupt write one to clear */
+ PORT_CS_RESUME = (1 << 6), /* port resume */
+ PORT_CS_32BIT_ACTV = (1 << 10), /* 32-bit activation */
+ PORT_CS_PM_EN = (1 << 13), /* port multiplier enable */
+ PORT_CS_RDY = (1 << 31), /* port ready to accept commands */
+
+ /* PORT_IRQ_STAT/ENABLE_SET/CLR */
+ /* bits[11:0] are masked */
+ PORT_IRQ_COMPLETE = (1 << 0), /* command(s) completed */
+ PORT_IRQ_ERROR = (1 << 1), /* command execution error */
+ PORT_IRQ_PORTRDY_CHG = (1 << 2), /* port ready change */
+ PORT_IRQ_PWR_CHG = (1 << 3), /* power management change */
+ PORT_IRQ_PHYRDY_CHG = (1 << 4), /* PHY ready change */
+ PORT_IRQ_COMWAKE = (1 << 5), /* COMWAKE received */
+ PORT_IRQ_UNK_FIS = (1 << 6), /* Unknown FIS received */
+ PORT_IRQ_SDB_FIS = (1 << 11), /* SDB FIS received */
+
+ /* bits[27:16] are unmasked (raw) */
+ PORT_IRQ_RAW_SHIFT = 16,
+ PORT_IRQ_MASKED_MASK = 0x7ff,
+ PORT_IRQ_RAW_MASK = (0x7ff << PORT_IRQ_RAW_SHIFT),
+
+ /* ENABLE_SET/CLR specific, intr steering - 2 bit field */
+ PORT_IRQ_STEER_SHIFT = 30,
+ PORT_IRQ_STEER_MASK = (3 << PORT_IRQ_STEER_SHIFT),
+
+ /* PORT_CMD_ERR constants */
+ PORT_CERR_DEV = 1, /* Error bit in D2H Register FIS */
+ PORT_CERR_SDB = 2, /* Error bit in SDB FIS */
+ PORT_CERR_DATA = 3, /* Error in data FIS not detected by dev */
+ PORT_CERR_SEND = 4, /* Initial cmd FIS transmission failure */
+ PORT_CERR_INCONSISTENT = 5, /* Protocol mismatch */
+ PORT_CERR_DIRECTION = 6, /* Data direction mismatch */
+ PORT_CERR_UNDERRUN = 7, /* Ran out of SGEs while writing */
+ PORT_CERR_OVERRUN = 8, /* Ran out of SGEs while reading */
+ PORT_CERR_PKT_PROT = 11, /* DIR invalid in 1st PIO setup of ATAPI */
+ PORT_CERR_SGT_BOUNDARY = 16, /* PLD ecode 00 - SGT not on qword boundary */
+ PORT_CERR_SGT_TGTABRT = 17, /* PLD ecode 01 - target abort */
+ PORT_CERR_SGT_MSTABRT = 18, /* PLD ecode 10 - master abort */
+ PORT_CERR_SGT_PCIPERR = 19, /* PLD ecode 11 - PCI parity err while fetching SGT */
+ PORT_CERR_CMD_BOUNDARY = 24, /* ctrl[15:13] 001 - PRB not on qword boundary */
+ PORT_CERR_CMD_TGTABRT = 25, /* ctrl[15:13] 010 - target abort */
+ PORT_CERR_CMD_MSTABRT = 26, /* ctrl[15:13] 100 - master abort */
+ PORT_CERR_CMD_PCIPERR = 27, /* ctrl[15:13] 110 - PCI parity err while fetching PRB */
+ PORT_CERR_XFR_UNDEF = 32, /* PSD ecode 00 - undefined */
+ PORT_CERR_XFR_TGTABRT = 33, /* PSD ecode 01 - target abort */
+ PORT_CERR_XFR_MSGABRT = 34, /* PSD ecode 10 - master abort */
+ PORT_CERR_XFR_PCIPERR = 35, /* PSD ecode 11 - PCI prity err during transfer */
+ PORT_CERR_SENDSERVICE = 36, /* FIS received while sending service */
+
+ /*
+ * Other constants
+ */
+ SGE_TRM = (1 << 31), /* Last SGE in chain */
+ PRB_SOFT_RST = (1 << 7), /* Soft reset request (ign BSY?) */
+
+ /* board id */
+ BID_SIL3124 = 0,
+ BID_SIL3132 = 1,
+ BID_SIL3131 = 2,
+
+ IRQ_STAT_4PORTS = 0xf,
+};
+
+struct sil24_cmd_block {
+ struct sil24_prb prb;
+ struct sil24_sge sge[LIBATA_MAX_PRD];
+};
+
+/*
+ * ap->private_data
+ *
+ * The preview driver always returned 0 for status. We emulate it
+ * here from the previous interrupt.
+ */
+struct sil24_port_priv {
+ struct sil24_cmd_block *cmd_block; /* 32 cmd blocks */
+ dma_addr_t cmd_block_dma; /* DMA base addr for them */
+ struct ata_taskfile tf; /* Cached taskfile registers */
+};
+
+/* ap->host_set->private_data */
+struct sil24_host_priv {
+ void *host_base; /* global controller control (128 bytes @BAR0) */
+ void *port_base; /* port registers (4 * 8192 bytes @BAR2) */
+};
+
+static u8 sil24_check_status(struct ata_port *ap);
+static u8 sil24_check_err(struct ata_port *ap);
+static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg);
+static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val);
+static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+static void sil24_phy_reset(struct ata_port *ap);
+static void sil24_qc_prep(struct ata_queued_cmd *qc);
+static int sil24_qc_issue(struct ata_queued_cmd *qc);
+static void sil24_irq_clear(struct ata_port *ap);
+static void sil24_eng_timeout(struct ata_port *ap);
+static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static int sil24_port_start(struct ata_port *ap);
+static void sil24_port_stop(struct ata_port *ap);
+static void sil24_host_stop(struct ata_host_set *host_set);
+static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+
+static struct pci_device_id sil24_pci_tbl[] = {
+ { 0x1095, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 },
+ { 0x1095, 0x3132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3132 },
+ { 0x1095, 0x3131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
+ { 0x1095, 0x3531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
+ { } /* terminate list */
+};
+
+static struct pci_driver sil24_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = sil24_pci_tbl,
+ .probe = sil24_init_one,
+ .remove = ata_pci_remove_one, /* safe? */
+};
+
+static Scsi_Host_Template sil24_sht = {
+ .module = THIS_MODULE,
+ .name = DRV_NAME,
+ .ioctl = ata_scsi_ioctl,
+ .queuecommand = ata_scsi_queuecmd,
+ .eh_strategy_handler = ata_scsi_error,
+ .can_queue = ATA_DEF_QUEUE,
+ .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = LIBATA_MAX_PRD,
+ .max_sectors = ATA_MAX_SECTORS,
+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+ .emulated = ATA_SHT_EMULATED,
+ .use_clustering = ATA_SHT_USE_CLUSTERING,
+ .proc_name = DRV_NAME,
+ .dma_boundary = ATA_DMA_BOUNDARY,
+ .slave_configure = ata_scsi_slave_config,
+ .bios_param = ata_std_bios_param,
+ .ordered_flush = 1, /* NCQ not supported yet */
+};
+
+static const struct ata_port_operations sil24_ops = {
+ .port_disable = ata_port_disable,
+
+ .check_status = sil24_check_status,
+ .check_altstatus = sil24_check_status,
+ .check_err = sil24_check_err,
+ .dev_select = ata_noop_dev_select,
+
+ .tf_read = sil24_tf_read,
+
+ .phy_reset = sil24_phy_reset,
+
+ .qc_prep = sil24_qc_prep,
+ .qc_issue = sil24_qc_issue,
+
+ .eng_timeout = sil24_eng_timeout,
+
+ .irq_handler = sil24_interrupt,
+ .irq_clear = sil24_irq_clear,
+
+ .scr_read = sil24_scr_read,
+ .scr_write = sil24_scr_write,
+
+ .port_start = sil24_port_start,
+ .port_stop = sil24_port_stop,
+ .host_stop = sil24_host_stop,
+};
+
+/*
+ * Use bits 30-31 of host_flags to encode available port numbers.
+ * Current maxium is 4.
+ */
+#define SIL24_NPORTS2FLAG(nports) ((((unsigned)(nports) - 1) & 0x3) << 30)
+#define SIL24_FLAG2NPORTS(flag) ((((flag) >> 30) & 0x3) + 1)
+
+static struct ata_port_info sil24_port_info[] = {
+ /* sil_3124 */
+ {
+ .sht = &sil24_sht,
+ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
+ ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(4),
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x3f, /* udma0-5 */
+ .port_ops = &sil24_ops,
+ },
+ /* sil_3132 */
+ {
+ .sht = &sil24_sht,
+ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
+ ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(2),
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x3f, /* udma0-5 */
+ .port_ops = &sil24_ops,
+ },
+ /* sil_3131/sil_3531 */
+ {
+ .sht = &sil24_sht,
+ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
+ ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(1),
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x3f, /* udma0-5 */
+ .port_ops = &sil24_ops,
+ },
+};
+
+static inline void sil24_update_tf(struct ata_port *ap)
+{
+ struct sil24_port_priv *pp = ap->private_data;
+ void *port = (void *)ap->ioaddr.cmd_addr;
+ struct sil24_prb *prb = port;
+
+ ata_tf_from_fis(prb->fis, &pp->tf);
+}
+
+static u8 sil24_check_status(struct ata_port *ap)
+{
+ struct sil24_port_priv *pp = ap->private_data;
+ return pp->tf.command;
+}
+
+static u8 sil24_check_err(struct ata_port *ap)
+{
+ struct sil24_port_priv *pp = ap->private_data;
+ return pp->tf.feature;
+}
+
+static int sil24_scr_map[] = {
+ [SCR_CONTROL] = 0,
+ [SCR_STATUS] = 1,
+ [SCR_ERROR] = 2,
+ [SCR_ACTIVE] = 3,
+};
+
+static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg)
+{
+ void *scr_addr = (void *)ap->ioaddr.scr_addr;
+ if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
+ void *addr;
+ addr = scr_addr + sil24_scr_map[sc_reg] * 4;
+ return readl(scr_addr + sil24_scr_map[sc_reg] * 4);
+ }
+ return 0xffffffffU;
+}
+
+static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
+{
+ void *scr_addr = (void *)ap->ioaddr.scr_addr;
+ if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
+ void *addr;
+ addr = scr_addr + sil24_scr_map[sc_reg] * 4;
+ writel(val, scr_addr + sil24_scr_map[sc_reg] * 4);
+ }
+}
+
+static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+ struct sil24_port_priv *pp = ap->private_data;
+ *tf = pp->tf;
+}
+
+static void sil24_phy_reset(struct ata_port *ap)
+{
+ __sata_phy_reset(ap);
+ /*
+ * No ATAPI yet. Just unconditionally indicate ATA device.
+ * If ATAPI device is attached, it will fail ATA_CMD_ID_ATA
+ * and libata core will ignore the device.
+ */
+ if (!(ap->flags & ATA_FLAG_PORT_DISABLED))
+ ap->device[0].class = ATA_DEV_ATA;
+}
+
+static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
+ struct sil24_cmd_block *cb)
+{
+ struct scatterlist *sg = qc->sg;
+ struct sil24_sge *sge = cb->sge;
+ unsigned i;
+
+ for (i = 0; i < qc->n_elem; i++, sg++, sge++) {
+ sge->addr = cpu_to_le64(sg_dma_address(sg));
+ sge->cnt = cpu_to_le32(sg_dma_len(sg));
+ sge->flags = 0;
+ sge->flags = i < qc->n_elem - 1 ? 0 : cpu_to_le32(SGE_TRM);
+ }
+}
+
+static void sil24_qc_prep(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct sil24_port_priv *pp = ap->private_data;
+ struct sil24_cmd_block *cb = pp->cmd_block + qc->tag;
+ struct sil24_prb *prb = &cb->prb;
+
+ switch (qc->tf.protocol) {
+ case ATA_PROT_PIO:
+ case ATA_PROT_DMA:
+ case ATA_PROT_NODATA:
+ break;
+ default:
+ /* ATAPI isn't supported yet */
+ BUG();
+ }
+
+ ata_tf_to_fis(&qc->tf, prb->fis, 0);
+
+ if (qc->flags & ATA_QCFLAG_DMAMAP)
+ sil24_fill_sg(qc, cb);
+}
+
+static int sil24_qc_issue(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ void *port = (void *)ap->ioaddr.cmd_addr;
+ struct sil24_port_priv *pp = ap->private_data;
+ dma_addr_t paddr = pp->cmd_block_dma + qc->tag * sizeof(*pp->cmd_block);
+
+ writel((u32)paddr, port + PORT_CMD_ACTIVATE);
+ return 0;
+}
+
+static void sil24_irq_clear(struct ata_port *ap)
+{
+ /* unused */
+}
+
+static int __sil24_reset_controller(void *port)
+{
+ int cnt;
+ u32 tmp;
+
+ /* Reset controller state. Is this correct? */
+ writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
+ readl(port + PORT_CTRL_STAT); /* sync */
+
+ /* Max ~100ms */
+ for (cnt = 0; cnt < 1000; cnt++) {
+ udelay(100);
+ tmp = readl(port + PORT_CTRL_STAT);
+ if (!(tmp & PORT_CS_DEV_RST))
+ break;
+ }
+
+ if (tmp & PORT_CS_DEV_RST)
+ return -1;
+ return 0;
+}
+
+static void sil24_reset_controller(struct ata_port *ap)
+{
+ printk(KERN_NOTICE DRV_NAME
+ " ata%u: resetting controller...\n", ap->id);
+ if (__sil24_reset_controller((void *)ap->ioaddr.cmd_addr))
+ printk(KERN_ERR DRV_NAME
+ " ata%u: failed to reset controller\n", ap->id);
+}
+
+static void sil24_eng_timeout(struct ata_port *ap)
+{
+ struct ata_queued_cmd *qc;
+
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+ if (!qc) {
+ printk(KERN_ERR "ata%u: BUG: tiemout without command\n",
+ ap->id);
+ return;
+ }
+
+ /*
+ * hack alert! We cannot use the supplied completion
+ * function from inside the ->eh_strategy_handler() thread.
+ * libata is the only user of ->eh_strategy_handler() in
+ * any kernel, so the default scsi_done() assumes it is
+ * not being called from the SCSI EH.
+ */
+ printk(KERN_ERR "ata%u: command timeout\n", ap->id);
+ qc->scsidone = scsi_finish_command;
+ ata_qc_complete(qc, ATA_ERR);
+
+ sil24_reset_controller(ap);
+}
+
+static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
+{
+ struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+ struct sil24_port_priv *pp = ap->private_data;
+ void *port = (void *)ap->ioaddr.cmd_addr;
+ u32 irq_stat, cmd_err, sstatus, serror;
+
+ irq_stat = readl(port + PORT_IRQ_STAT);
+ writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */
+
+ if (!(irq_stat & PORT_IRQ_ERROR)) {
+ /* ignore non-completion, non-error irqs for now */
+ printk(KERN_WARNING DRV_NAME
+ "ata%u: non-error exception irq (irq_stat %x)\n",
+ ap->id, irq_stat);
+ return;
+ }
+
+ cmd_err = readl(port + PORT_CMD_ERR);
+ sstatus = readl(port + PORT_SSTATUS);
+ serror = readl(port + PORT_SERROR);
+ if (serror)
+ writel(serror, port + PORT_SERROR);
+
+ printk(KERN_ERR DRV_NAME " ata%u: error interrupt on port%d\n"
+ " stat=0x%x irq=0x%x cmd_err=%d sstatus=0x%x serror=0x%x\n",
+ ap->id, ap->port_no, slot_stat, irq_stat, cmd_err, sstatus, serror);
+
+ if (cmd_err == PORT_CERR_DEV || cmd_err == PORT_CERR_SDB) {
+ /*
+ * Device is reporting error, tf registers are valid.
+ */
+ sil24_update_tf(ap);
+ } else {
+ /*
+ * Other errors. libata currently doesn't have any
+ * mechanism to report these errors. Just turn on
+ * ATA_ERR.
+ */
+ pp->tf.command = ATA_ERR;
+ }
+
+ if (qc)
+ ata_qc_complete(qc, pp->tf.command);
+
+ sil24_reset_controller(ap);
+}
+
+static inline void sil24_host_intr(struct ata_port *ap)
+{
+ struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+ void *port = (void *)ap->ioaddr.cmd_addr;
+ u32 slot_stat;
+
+ slot_stat = readl(port + PORT_SLOT_STAT);
+ if (!(slot_stat & HOST_SSTAT_ATTN)) {
+ struct sil24_port_priv *pp = ap->private_data;
+ /*
+ * !HOST_SSAT_ATTN guarantees successful completion,
+ * so reading back tf registers is unnecessary for
+ * most commands. TODO: read tf registers for
+ * commands which require these values on successful
+ * completion (EXECUTE DEVICE DIAGNOSTIC, CHECK POWER,
+ * DEVICE RESET and READ PORT MULTIPLIER (any more?).
+ */
+ sil24_update_tf(ap);
+
+ if (qc)
+ ata_qc_complete(qc, pp->tf.command);
+ } else
+ sil24_error_intr(ap, slot_stat);
+}
+
+static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+{
+ struct ata_host_set *host_set = dev_instance;
+ struct sil24_host_priv *hpriv = host_set->private_data;
+ unsigned handled = 0;
+ u32 status;
+ int i;
+
+ status = readl(hpriv->host_base + HOST_IRQ_STAT);
+
+ if (status == 0xffffffff) {
+ printk(KERN_ERR DRV_NAME ": IRQ status == 0xffffffff, "
+ "PCI fault or device removal?\n");
+ goto out;
+ }
+
+ if (!(status & IRQ_STAT_4PORTS))
+ goto out;
+
+ spin_lock(&host_set->lock);
+
+ for (i = 0; i < host_set->n_ports; i++)
+ if (status & (1 << i)) {
+ struct ata_port *ap = host_set->ports[i];
+ if (ap && !(ap->flags & ATA_FLAG_PORT_DISABLED)) {
+ sil24_host_intr(host_set->ports[i]);
+ handled++;
+ } else
+ printk(KERN_ERR DRV_NAME
+ ": interrupt from disabled port %d\n", i);
+ }
+
+ spin_unlock(&host_set->lock);
+ out:
+ return IRQ_RETVAL(handled);
+}
+
+static int sil24_port_start(struct ata_port *ap)
+{
+ struct device *dev = ap->host_set->dev;
+ struct sil24_port_priv *pp;
+ struct sil24_cmd_block *cb;
+ size_t cb_size = sizeof(*cb);
+ dma_addr_t cb_dma;
+
+ pp = kmalloc(sizeof(*pp), GFP_KERNEL);
+ if (!pp)
+ return -ENOMEM;
+ memset(pp, 0, sizeof(*pp));
+
+ pp->tf.command = ATA_DRDY;
+
+ cb = dma_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL);
+ if (!cb) {
+ kfree(pp);
+ return -ENOMEM;
+ }
+ memset(cb, 0, cb_size);
+
+ pp->cmd_block = cb;
+ pp->cmd_block_dma = cb_dma;
+
+ ap->private_data = pp;
+
+ return 0;
+}
+
+static void sil24_port_stop(struct ata_port *ap)
+{
+ struct device *dev = ap->host_set->dev;
+ struct sil24_port_priv *pp = ap->private_data;
+ size_t cb_size = sizeof(*pp->cmd_block);
+
+ dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma);
+ kfree(pp);
+}
+
+static void sil24_host_stop(struct ata_host_set *host_set)
+{
+ struct sil24_host_priv *hpriv = host_set->private_data;
+
+ iounmap(hpriv->host_base);
+ iounmap(hpriv->port_base);
+ kfree(hpriv);
+}
+
+static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ static int printed_version = 0;
+ unsigned int board_id = (unsigned int)ent->driver_data;
+ struct ata_port_info *pinfo = &sil24_port_info[board_id];
+ struct ata_probe_ent *probe_ent = NULL;
+ struct sil24_host_priv *hpriv = NULL;
+ void *host_base = NULL, *port_base = NULL;
+ int i, rc;
+
+ if (!printed_version++)
+ printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+ rc = pci_enable_device(pdev);
+ if (rc)
+ return rc;
+
+ rc = pci_request_regions(pdev, DRV_NAME);
+ if (rc)
+ goto out_disable;
+
+ rc = -ENOMEM;
+ /* ioremap mmio registers */
+ host_base = ioremap(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ if (!host_base)
+ goto out_free;
+ port_base = ioremap(pci_resource_start(pdev, 2),
+ pci_resource_len(pdev, 2));
+ if (!port_base)
+ goto out_free;
+
+ /* allocate & init probe_ent and hpriv */
+ probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+ if (!probe_ent)
+ goto out_free;
+
+ hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
+ if (!hpriv)
+ goto out_free;
+
+ memset(probe_ent, 0, sizeof(*probe_ent));
+ probe_ent->dev = pci_dev_to_dev(pdev);
+ INIT_LIST_HEAD(&probe_ent->node);
+
+ probe_ent->sht = pinfo->sht;
+ probe_ent->host_flags = pinfo->host_flags;
+ probe_ent->pio_mask = pinfo->pio_mask;
+ probe_ent->udma_mask = pinfo->udma_mask;
+ probe_ent->port_ops = pinfo->port_ops;
+ probe_ent->n_ports = SIL24_FLAG2NPORTS(pinfo->host_flags);
+
+ probe_ent->irq = pdev->irq;
+ probe_ent->irq_flags = SA_SHIRQ;
+ probe_ent->mmio_base = port_base;
+ probe_ent->private_data = hpriv;
+
+ memset(hpriv, 0, sizeof(*hpriv));
+ hpriv->host_base = host_base;
+ hpriv->port_base = port_base;
+
+ /*
+ * Configure the device
+ */
+ /*
+ * FIXME: This device is certainly 64-bit capable. We just
+ * don't know how to use it. After fixing 32bit activation in
+ * this function, enable 64bit masks here.
+ */
+ rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (rc) {
+ printk(KERN_ERR DRV_NAME "(%s): 32-bit DMA enable failed\n",
+ pci_name(pdev));
+ goto out_free;
+ }
+ rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (rc) {
+ printk(KERN_ERR DRV_NAME "(%s): 32-bit consistent DMA enable failed\n",
+ pci_name(pdev));
+ goto out_free;
+ }
+
+ /* GPIO off */
+ writel(0, host_base + HOST_FLASH_CMD);
+
+ /* Mask interrupts during initialization */
+ writel(0, host_base + HOST_CTRL);
+
+ for (i = 0; i < probe_ent->n_ports; i++) {
+ void *port = port_base + i * PORT_REGS_SIZE;
+ unsigned long portu = (unsigned long)port;
+ u32 tmp;
+ int cnt;
+
+ probe_ent->port[i].cmd_addr = portu + PORT_PRB;
+ probe_ent->port[i].scr_addr = portu + PORT_SCONTROL;
+
+ ata_std_ports(&probe_ent->port[i]);
+
+ /* Initial PHY setting */
+ writel(0x20c, port + PORT_PHY_CFG);
+
+ /* Clear port RST */
+ tmp = readl(port + PORT_CTRL_STAT);
+ if (tmp & PORT_CS_PORT_RST) {
+ writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
+ readl(port + PORT_CTRL_STAT); /* sync */
+ for (cnt = 0; cnt < 10; cnt++) {
+ msleep(10);
+ tmp = readl(port + PORT_CTRL_STAT);
+ if (!(tmp & PORT_CS_PORT_RST))
+ break;
+ }
+ if (tmp & PORT_CS_PORT_RST)
+ printk(KERN_ERR DRV_NAME
+ "(%s): failed to clear port RST\n",
+ pci_name(pdev));
+ }
+
+ /* Zero error counters. */
+ writel(0x8000, port + PORT_DECODE_ERR_THRESH);
+ writel(0x8000, port + PORT_CRC_ERR_THRESH);
+ writel(0x8000, port + PORT_HSHK_ERR_THRESH);
+ writel(0x0000, port + PORT_DECODE_ERR_CNT);
+ writel(0x0000, port + PORT_CRC_ERR_CNT);
+ writel(0x0000, port + PORT_HSHK_ERR_CNT);
+
+ /* FIXME: 32bit activation? */
+ writel(0, port + PORT_ACTIVATE_UPPER_ADDR);
+ writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_STAT);
+
+ /* Configure interrupts */
+ writel(0xffff, port + PORT_IRQ_ENABLE_CLR);
+ writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | PORT_IRQ_SDB_FIS,
+ port + PORT_IRQ_ENABLE_SET);
+
+ /* Clear interrupts */
+ writel(0x0fff0fff, port + PORT_IRQ_STAT);
+ writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
+
+ /* Clear port multiplier enable and resume bits */
+ writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR);
+
+ /* Reset itself */
+ if (__sil24_reset_controller(port))
+ printk(KERN_ERR DRV_NAME
+ "(%s): failed to reset controller\n",
+ pci_name(pdev));
+ }
+
+ /* Turn on interrupts */
+ writel(IRQ_STAT_4PORTS, host_base + HOST_CTRL);
+
+ pci_set_master(pdev);
+
+ /* FIXME: check ata_device_add return value */
+ ata_device_add(probe_ent);
+
+ kfree(probe_ent);
+ return 0;
+
+ out_free:
+ if (host_base)
+ iounmap(host_base);
+ if (port_base)
+ iounmap(port_base);
+ kfree(probe_ent);
+ kfree(hpriv);
+ pci_release_regions(pdev);
+ out_disable:
+ pci_disable_device(pdev);
+ return rc;
+}
+
+static int __init sil24_init(void)
+{
+ return pci_module_init(&sil24_pci_driver);
+}
+
+static void __exit sil24_exit(void)
+{
+ pci_unregister_driver(&sil24_pci_driver);
+}
+
+MODULE_AUTHOR("Tejun Heo");
+MODULE_DESCRIPTION("Silicon Image 3124/3132 SATA low-level driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, sil24_pci_tbl);
+
+module_init(sil24_init);
+module_exit(sil24_exit);
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index b227e51d12f4c3..057f7b98b6c448 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -102,7 +102,7 @@ static Scsi_Host_Template sis_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations sis_ops = {
+static const struct ata_port_operations sis_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
@@ -263,7 +263,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_regions;
ppi = &sis_port_info;
- probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+ probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
if (!probe_ent) {
rc = -ENOMEM;
goto err_out_regions;
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index d89d968bedace6..e0f9570bc6ddd3 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -102,7 +102,7 @@ static void k2_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
}
-static void k2_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
+static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@@ -297,7 +297,7 @@ static Scsi_Host_Template k2_sata_sht = {
};
-static struct ata_port_operations k2_sata_ops = {
+static const struct ata_port_operations k2_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = k2_sata_tf_load,
.tf_read = k2_sata_tf_read,
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index 540a851911723b..af08f4f650c1ef 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -137,7 +137,7 @@ struct pdc_port_priv {
};
struct pdc_host_priv {
- void *dimm_mmio;
+ void __iomem *dimm_mmio;
unsigned int doing_hdma;
unsigned int hdma_prod;
@@ -157,8 +157,8 @@ static void pdc_20621_phy_reset (struct ata_port *ap);
static int pdc_port_start(struct ata_port *ap);
static void pdc_port_stop(struct ata_port *ap);
static void pdc20621_qc_prep(struct ata_queued_cmd *qc);
-static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
-static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
+static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
static void pdc20621_host_stop(struct ata_host_set *host_set);
static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
@@ -196,7 +196,7 @@ static Scsi_Host_Template pdc_sata_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations pdc_20621_ops = {
+static const struct ata_port_operations pdc_20621_ops = {
.port_disable = ata_port_disable,
.tf_load = pdc_tf_load_mmio,
.tf_read = ata_tf_read,
@@ -247,7 +247,7 @@ static void pdc20621_host_stop(struct ata_host_set *host_set)
{
struct pci_dev *pdev = to_pci_dev(host_set->dev);
struct pdc_host_priv *hpriv = host_set->private_data;
- void *dimm_mmio = hpriv->dimm_mmio;
+ void __iomem *dimm_mmio = hpriv->dimm_mmio;
pci_iounmap(pdev, dimm_mmio);
kfree(hpriv);
@@ -669,8 +669,8 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc)
readl(mmio + PDC_20621_SEQCTL + (seq * 4)); /* flush */
writel(port_ofs + PDC_DIMM_ATA_PKT,
- (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
- readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+ (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+ readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
VPRINTK("submitted ofs 0x%x (%u), seq %u\n",
port_ofs + PDC_DIMM_ATA_PKT,
port_ofs + PDC_DIMM_ATA_PKT,
@@ -747,8 +747,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
readl(mmio + PDC_20621_SEQCTL + (seq * 4));
writel(port_ofs + PDC_DIMM_ATA_PKT,
- (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
- readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+ (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+ readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
}
/* step two - execute ATA command */
@@ -899,7 +899,7 @@ out:
DPRINTK("EXIT\n");
}
-static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
tf->protocol == ATA_PROT_NODATA);
@@ -907,7 +907,7 @@ static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
}
-static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
tf->protocol == ATA_PROT_NODATA);
@@ -1014,7 +1014,7 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
idx++;
dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size :
(long) (window_size - offset);
- memcpy_toio((char *) (dimm_mmio + offset / 4), (char *) psource, dist);
+ memcpy_toio(dimm_mmio + offset / 4, psource, dist);
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
@@ -1023,8 +1023,7 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
for (; (long) size >= (long) window_size ;) {
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
- memcpy_toio((char *) (dimm_mmio), (char *) psource,
- window_size / 4);
+ memcpy_toio(dimm_mmio, psource, window_size / 4);
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
psource += window_size;
@@ -1035,7 +1034,7 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
if (size) {
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
- memcpy_toio((char *) (dimm_mmio), (char *) psource, size / 4);
+ memcpy_toio(dimm_mmio, psource, size / 4);
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
}
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
index 4c9fb8b71be1cb..d68dc7d3422c4c 100644
--- a/drivers/scsi/sata_uli.c
+++ b/drivers/scsi/sata_uli.c
@@ -90,7 +90,7 @@ static Scsi_Host_Template uli_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations uli_ops = {
+static const struct ata_port_operations uli_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
@@ -202,7 +202,7 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_regions;
ppi = &uli_port_info;
- probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+ probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
if (!probe_ent) {
rc = -ENOMEM;
goto err_out_regions;
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
index 128b996b07b701..80e291a909a972 100644
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -109,7 +109,7 @@ static Scsi_Host_Template svia_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations svia_sata_ops = {
+static const struct ata_port_operations svia_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
@@ -212,7 +212,7 @@ static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev)
struct ata_probe_ent *probe_ent;
struct ata_port_info *ppi = &svia_port_info;
- probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+ probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
if (!probe_ent)
return NULL;
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index cf94e0158a8df5..5af05fdf854439 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -86,7 +86,7 @@ static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
if (sc_reg > SCR_CONTROL)
return 0xffffffffU;
- return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
@@ -95,16 +95,16 @@ static void vsc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
{
if (sc_reg > SCR_CONTROL)
return;
- writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl)
{
- unsigned long mask_addr;
+ void __iomem *mask_addr;
u8 mask;
- mask_addr = (unsigned long) ap->host_set->mmio_base +
+ mask_addr = ap->host_set->mmio_base +
VSC_SATA_INT_MASK_OFFSET + ap->port_no;
mask = readb(mask_addr);
if (ctl & ATA_NIEN)
@@ -115,7 +115,7 @@ static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl)
}
-static void vsc_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
+static void vsc_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@@ -231,7 +231,7 @@ static Scsi_Host_Template vsc_sata_sht = {
};
-static struct ata_port_operations vsc_sata_ops = {
+static const struct ata_port_operations vsc_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = vsc_sata_tf_load,
.tf_read = vsc_sata_tf_read,
@@ -283,7 +283,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
struct ata_probe_ent *probe_ent = NULL;
unsigned long base;
int pci_dev_busy = 0;
- void *mmio_base;
+ void __iomem *mmio_base;
int rc;
if (!printed_version++)
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 1f0ebabf6d4766..a5711d545d7135 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -130,7 +130,7 @@ EXPORT_SYMBOL(scsi_device_types);
* Returns: Pointer to request block.
*/
struct scsi_request *scsi_allocate_request(struct scsi_device *sdev,
- int gfp_mask)
+ gfp_t gfp_mask)
{
const int offset = ALIGN(sizeof(struct scsi_request), 4);
const int size = offset + sizeof(struct request);
@@ -196,7 +196,7 @@ struct scsi_host_cmd_pool {
unsigned int users;
char *name;
unsigned int slab_flags;
- unsigned int gfp_mask;
+ gfp_t gfp_mask;
};
static struct scsi_host_cmd_pool scsi_cmd_pool = {
@@ -213,7 +213,7 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = {
static DECLARE_MUTEX(host_cmd_pool_mutex);
static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost,
- int gfp_mask)
+ gfp_t gfp_mask)
{
struct scsi_cmnd *cmd;
@@ -245,7 +245,7 @@ static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost,
*
* Returns: The allocated scsi command structure.
*/
-struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, int gfp_mask)
+struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask)
{
struct scsi_cmnd *cmd;
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index de7f98cc38feb0..6a3f6aae8a976c 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -205,7 +205,8 @@ int scsi_ioctl_send_command(struct scsi_device *sdev,
unsigned int inlen, outlen, cmdlen;
unsigned int needed, buf_needed;
int timeout, retries, result;
- int data_direction, gfp_mask = GFP_KERNEL;
+ int data_direction;
+ gfp_t gfp_mask = GFP_KERNEL;
if (!sic)
return -EINVAL;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 0074f28c37b271..3ff538809786fb 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -677,7 +677,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
return NULL;
}
-static struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, int gfp_mask)
+static struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask)
{
struct scsi_host_sg_pool *sgp;
struct scatterlist *sgl;
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index ad94367df430a8..861e51375d70c5 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -104,8 +104,8 @@ static int sg_allow_dio = SG_ALLOW_DIO_DEF;
#define SG_DEV_ARR_LUMP 32 /* amount to over allocate sg_dev_arr by */
-static int sg_add(struct class_device *);
-static void sg_remove(struct class_device *);
+static int sg_add(struct class_device *, struct class_interface *);
+static void sg_remove(struct class_device *, struct class_interface *);
static Scsi_Request *dummy_cmdp; /* only used for sizeof */
@@ -1506,7 +1506,7 @@ static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
}
static int
-sg_add(struct class_device *cl_dev)
+sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
{
struct scsi_device *scsidp = to_scsi_device(cl_dev->dev);
struct gendisk *disk;
@@ -1550,7 +1550,7 @@ sg_add(struct class_device *cl_dev)
if (sg_sysfs_valid) {
struct class_device * sg_class_member;
- sg_class_member = class_device_create(sg_sysfs_class,
+ sg_class_member = class_device_create(sg_sysfs_class, NULL,
MKDEV(SCSI_GENERIC_MAJOR, k),
cl_dev->dev, "%s",
disk->disk_name);
@@ -1582,7 +1582,7 @@ out:
}
static void
-sg_remove(struct class_device *cl_dev)
+sg_remove(struct class_device *cl_dev, struct class_interface *cl_intf)
{
struct scsi_device *scsidp = to_scsi_device(cl_dev->dev);
Sg_device *sdp = NULL;
@@ -2644,7 +2644,7 @@ static char *
sg_page_malloc(int rqSz, int lowDma, int *retSzp)
{
char *resp = NULL;
- int page_mask;
+ gfp_t page_mask;
int order, a_size;
int resSz = rqSz;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index d001c046551bca..5eb54d8019b46c 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3577,7 +3577,8 @@ static long st_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a
static struct st_buffer *
new_tape_buffer(int from_initialization, int need_dma, int max_sg)
{
- int i, priority, got = 0, segs = 0;
+ int i, got = 0, segs = 0;
+ gfp_t priority;
struct st_buffer *tb;
if (from_initialization)
@@ -3610,7 +3611,8 @@ static struct st_buffer *
/* Try to allocate enough space in the tape buffer */
static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dma)
{
- int segs, nbr, max_segs, b_size, priority, order, got;
+ int segs, nbr, max_segs, b_size, order, got;
+ gfp_t priority;
if (new_size <= STbuffer->buffer_size)
return 1;
@@ -4375,7 +4377,7 @@ static void do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
snprintf(name, 10, "%s%s%s", rew ? "n" : "",
STp->disk->disk_name, st_formats[i]);
st_class_member =
- class_device_create(st_sysfs_class,
+ class_device_create(st_sysfs_class, NULL,
MKDEV(SCSI_TAPE_MAJOR,
TAPE_MINOR(dev_num, mode, rew)),
&STp->device->sdev_gendev, "%s", name);
diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
index 5a51051e31f0e4..b131432c677d67 100644
--- a/drivers/scsi/zalon.c
+++ b/drivers/scsi/zalon.c
@@ -88,7 +88,7 @@ zalon_probe(struct parisc_device *dev)
struct gsc_irq gsc_irq;
u32 zalon_vers;
int error = -ENODEV;
- void __iomem *zalon = ioremap(dev->hpa, 4096);
+ void __iomem *zalon = ioremap(dev->hpa.start, 4096);
void __iomem *io_port = zalon + GSC_SCSI_ZALON_OFFSET;
static int unit = 0;
struct Scsi_Host *host;
@@ -127,7 +127,7 @@ zalon_probe(struct parisc_device *dev)
device.chip = zalon720_chip;
device.host_id = 7;
device.dev = &dev->dev;
- device.slot.base = dev->hpa + GSC_SCSI_ZALON_OFFSET;
+ device.slot.base = dev->hpa.start + GSC_SCSI_ZALON_OFFSET;
device.slot.base_v = io_port;
device.slot.irq = dev->irq;
device.differential = 2;
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 4d75cdfa0a0af0..afb7ddf200e082 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2358,13 +2358,10 @@ static int __devexit serial8250_remove(struct device *dev)
return 0;
}
-static int serial8250_suspend(struct device *dev, pm_message_t state, u32 level)
+static int serial8250_suspend(struct device *dev, pm_message_t state)
{
int i;
- if (level != SUSPEND_DISABLE)
- return 0;
-
for (i = 0; i < UART_NR; i++) {
struct uart_8250_port *up = &serial8250_ports[i];
@@ -2375,13 +2372,10 @@ static int serial8250_suspend(struct device *dev, pm_message_t state, u32 level)
return 0;
}
-static int serial8250_resume(struct device *dev, u32 level)
+static int serial8250_resume(struct device *dev)
{
int i;
- if (level != RESUME_ENABLE)
- return 0;
-
for (i = 0; i < UART_NR; i++) {
struct uart_8250_port *up = &serial8250_ports[i];
diff --git a/drivers/serial/8250_gsc.c b/drivers/serial/8250_gsc.c
index 431aa5761a7a57..8b4947933d9bcf 100644
--- a/drivers/serial/8250_gsc.c
+++ b/drivers/serial/8250_gsc.c
@@ -29,7 +29,6 @@
static int __init
serial_init_chip(struct parisc_device *dev)
{
- static int serial_line_nr;
struct uart_port port;
unsigned long address;
int err;
@@ -42,12 +41,13 @@ serial_init_chip(struct parisc_device *dev)
*/
if (parisc_parent(dev)->id.hw_type != HPHW_IOA) {
printk(KERN_INFO "Serial: device 0x%lx not configured.\n"
- "Enable support for Wax, Lasi, Asp or Dino.\n", dev->hpa);
+ "Enable support for Wax, Lasi, Asp or Dino.\n",
+ dev->hpa.start);
}
return -ENODEV;
}
- address = dev->hpa;
+ address = dev->hpa.start;
if (dev->id.sversion != 0x8d) {
address += 0x800;
}
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 0e21f583690ebd..5c3c03932d6d45 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -152,6 +152,7 @@ static int __devinit pci_hp_diva_init(struct pci_dev *dev)
rc = 4;
break;
case PCI_DEVICE_ID_HP_DIVA_POWERBAR:
+ case PCI_DEVICE_ID_HP_DIVA_HURRICANE:
rc = 1;
break;
}
@@ -226,8 +227,10 @@ static int __devinit pci_plx9050_init(struct pci_dev *dev)
}
irq_config = 0x41;
- if (dev->vendor == PCI_VENDOR_ID_PANACOM)
+ if (dev->vendor == PCI_VENDOR_ID_PANACOM ||
+ dev->subsystem_vendor == PCI_SUBVENDOR_ID_EXSYS) {
irq_config = 0x43;
+ }
if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
(dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) {
/*
@@ -664,6 +667,15 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
{
.vendor = PCI_VENDOR_ID_PLX,
.device = PCI_DEVICE_ID_PLX_9050,
+ .subvendor = PCI_SUBVENDOR_ID_EXSYS,
+ .subdevice = PCI_SUBDEVICE_ID_EXSYS_4055,
+ .init = pci_plx9050_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_plx9050_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_9050,
.subvendor = PCI_SUBVENDOR_ID_KEYSPAN,
.subdevice = PCI_SUBDEVICE_ID_KEYSPAN_SX2,
.init = pci_plx9050_init,
@@ -927,6 +939,7 @@ enum pci_board_num_t {
pbn_panacom,
pbn_panacom2,
pbn_panacom4,
+ pbn_exsys_4055,
pbn_plx_romulus,
pbn_oxsemi,
pbn_intel_i960,
@@ -1292,6 +1305,13 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.reg_shift = 7,
},
+ [pbn_exsys_4055] = {
+ .flags = FL_BASE2,
+ .num_ports = 4,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+
/* I think this entry is broken - the first_offset looks wrong --rmk */
[pbn_plx_romulus] = {
.flags = FL_BASE2,
@@ -1853,6 +1873,10 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_SUBVENDOR_ID_CHASE_PCIRAS,
PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0,
pbn_b2_8_460800 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_SUBVENDOR_ID_EXSYS,
+ PCI_SUBDEVICE_ID_EXSYS_4055, 0, 0,
+ pbn_exsys_4055 },
/*
* Megawolf Romulus PCI Serial Card, from Mike Hudson
* (Exoray@isys.ca)
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 679e678c7e6a15..ddd0307fece232 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -50,6 +50,7 @@
#include <asm/io.h>
#include <asm/irq.h>
+#include <asm/hardware.h>
#include <asm/hardware/amba.h>
#include <asm/hardware/amba_serial.h>
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 1ff629c7475008..938d185841c9ee 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -50,6 +50,7 @@
#include <asm/io.h>
#include <asm/irq.h>
+#include <asm/sizes.h>
#include <asm/hardware/amba.h>
#include <asm/hardware/clock.h>
#include <asm/hardware/amba_serial.h>
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index 87ef368384fb31..6a67e8f585b307 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -408,7 +408,11 @@ static struct uart_port clps711x_ports[UART_NR] = {
{
.iobase = SYSCON1,
.irq = IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */
+#ifdef CONFIG_MP1000_90MHZ
+ .uartclk = 4515840,
+#else
.uartclk = 3686400,
+#endif
.fifosize = 16,
.ops = &clps711x_pops,
.line = 0,
@@ -417,7 +421,11 @@ static struct uart_port clps711x_ports[UART_NR] = {
{
.iobase = SYSCON2,
.irq = IRQ_UTXINT2, /* IRQ_URXINT2 */
+#ifdef CONFIG_MP1000_90MHZ
+ .uartclk = 4515840,
+#else
.uartclk = 3686400,
+#endif
.fifosize = 16,
.ops = &clps711x_pops,
.line = 1,
@@ -551,6 +559,7 @@ console_initcall(clps711xuart_console_init);
static struct uart_driver clps711x_reg = {
.driver_name = "ttyCL",
.dev_name = "ttyCL",
+ .devfs_name = "ttyCL",
.major = SERIAL_CLPS711X_MAJOR,
.minor = SERIAL_CLPS711X_MINOR,
.nr = UART_NR,
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index bdb4e454b8b073..5b3933b0c997f0 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -921,21 +921,21 @@ static struct uart_driver imx_reg = {
.cons = IMX_CONSOLE,
};
-static int serial_imx_suspend(struct device *_dev, pm_message_t state, u32 level)
+static int serial_imx_suspend(struct device *_dev, pm_message_t state)
{
struct imx_port *sport = dev_get_drvdata(_dev);
- if (sport && level == SUSPEND_DISABLE)
+ if (sport)
uart_suspend_port(&imx_reg, &sport->port);
return 0;
}
-static int serial_imx_resume(struct device *_dev, u32 level)
+static int serial_imx_resume(struct device *_dev)
{
struct imx_port *sport = dev_get_drvdata(_dev);
- if (sport && level == RESUME_ENABLE)
+ if (sport)
uart_resume_port(&imx_reg, &sport->port);
return 0;
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 0585ab27ffde7d..8a79968f8ce1f2 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -781,22 +781,22 @@ mpc52xx_uart_remove(struct device *dev)
#ifdef CONFIG_PM
static int
-mpc52xx_uart_suspend(struct device *dev, pm_message_t state, u32 level)
+mpc52xx_uart_suspend(struct device *dev, pm_message_t state)
{
struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev);
- if (sport && level == SUSPEND_DISABLE)
+ if (sport)
uart_suspend_port(&mpc52xx_uart_driver, port);
return 0;
}
static int
-mpc52xx_uart_resume(struct device *dev, u32 level)
+mpc52xx_uart_resume(struct device *dev)
{
struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev);
- if (port && level == RESUME_ENABLE)
+ if (port)
uart_resume_port(&mpc52xx_uart_driver, port);
return 0;
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c
index 189064607709d9..660bae5ba179bf 100644
--- a/drivers/serial/mux.c
+++ b/drivers/serial/mux.c
@@ -27,6 +27,7 @@
#include <linux/delay.h> /* for udelay */
#include <linux/device.h>
#include <asm/io.h>
+#include <asm/irq.h>
#include <asm/parisc-device.h>
#ifdef CONFIG_MAGIC_SYSRQ
@@ -444,7 +445,7 @@ static int __init mux_probe(struct parisc_device *dev)
unsigned long bytecnt;
struct uart_port *port;
- status = pdc_iodc_read(&bytecnt, dev->hpa, 0, iodc_data, 32);
+ status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32);
if(status != PDC_OK) {
printk(KERN_ERR "Serial mux: Unable to read IODC.\n");
return 1;
@@ -469,16 +470,18 @@ static int __init mux_probe(struct parisc_device *dev)
for(i = 0; i < ports; ++i, ++port_cnt) {
port = &mux_ports[port_cnt];
port->iobase = 0;
- port->mapbase = dev->hpa + MUX_OFFSET + (i * MUX_LINE_OFFSET);
+ port->mapbase = dev->hpa.start + MUX_OFFSET +
+ (i * MUX_LINE_OFFSET);
port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET);
port->iotype = SERIAL_IO_MEM;
port->type = PORT_MUX;
- port->irq = SERIAL_IRQ_NONE;
+ port->irq = NO_IRQ;
port->uartclk = 0;
port->fifosize = MUX_FIFO_SIZE;
port->ops = &mux_pops;
port->flags = UPF_BOOT_AUTOCONF;
port->line = port_cnt;
+ spin_lock_init(&port->lock);
status = uart_add_one_port(&mux_driver, port);
BUG_ON(status);
}
@@ -497,7 +500,7 @@ static struct parisc_device_id mux_tbl[] = {
MODULE_DEVICE_TABLE(parisc, mux_tbl);
static struct parisc_driver serial_mux_driver = {
- .name = "Serial MUX",
+ .name = "serial_mux",
.id_table = mux_tbl,
.probe = mux_probe,
};
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index 90c2a86c421b0c..8cc4cedadd9950 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -358,6 +358,9 @@ static int serial_pxa_startup(struct uart_port *port)
unsigned long flags;
int retval;
+ if (port->line == 3) /* HWUART */
+ up->mcr |= UART_MCR_AFE;
+ else
up->mcr = 0;
/*
@@ -481,8 +484,10 @@ serial_pxa_set_termios(struct uart_port *port, struct termios *termios,
if ((up->port.uartclk / quot) < (2400 * 16))
fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
- else
+ else if ((up->port.uartclk / quot) < (230400 * 16))
fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
+ else
+ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
/*
* Ok, we're now changing the port state. Do it with
@@ -772,6 +777,20 @@ static struct uart_pxa_port serial_pxa_ports[] = {
.ops = &serial_pxa_pops,
.line = 2,
},
+ }, { /* HWUART */
+ .name = "HWUART",
+ .cken = CKEN4_HWUART,
+ .port = {
+ .type = PORT_PXA,
+ .iotype = UPIO_MEM,
+ .membase = (void *)&HWUART,
+ .mapbase = __PREG(HWUART),
+ .irq = IRQ_HWUART,
+ .uartclk = 921600 * 16,
+ .fifosize = 64,
+ .ops = &serial_pxa_pops,
+ .line = 3,
+ },
}
};
@@ -786,21 +805,21 @@ static struct uart_driver serial_pxa_reg = {
.cons = PXA_CONSOLE,
};
-static int serial_pxa_suspend(struct device *_dev, pm_message_t state, u32 level)
+static int serial_pxa_suspend(struct device *_dev, pm_message_t state)
{
struct uart_pxa_port *sport = dev_get_drvdata(_dev);
- if (sport && level == SUSPEND_DISABLE)
+ if (sport)
uart_suspend_port(&serial_pxa_reg, &sport->port);
return 0;
}
-static int serial_pxa_resume(struct device *_dev, u32 level)
+static int serial_pxa_resume(struct device *_dev)
{
struct uart_pxa_port *sport = dev_get_drvdata(_dev);
- if (sport && level == RESUME_ENABLE)
+ if (sport)
uart_resume_port(&serial_pxa_reg, &sport->port);
return 0;
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 52692aa345ecfe..06a17dff1a7316 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -1134,23 +1134,22 @@ static int s3c24xx_serial_remove(struct device *_dev)
#ifdef CONFIG_PM
-static int s3c24xx_serial_suspend(struct device *dev, pm_message_t state,
- u32 level)
+static int s3c24xx_serial_suspend(struct device *dev, pm_message_t state)
{
struct uart_port *port = s3c24xx_dev_to_port(dev);
- if (port && level == SUSPEND_DISABLE)
+ if (port)
uart_suspend_port(&s3c24xx_uart_drv, port);
return 0;
}
-static int s3c24xx_serial_resume(struct device *dev, u32 level)
+static int s3c24xx_serial_resume(struct device *dev)
{
struct uart_port *port = s3c24xx_dev_to_port(dev);
struct s3c24xx_uart_port *ourport = to_ourport(port);
- if (port && level == RESUME_ENABLE) {
+ if (port) {
clk_enable(ourport->clk);
s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port));
clk_disable(ourport->clk);
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index dd8aed242357c7..c4a789e6af447f 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -834,21 +834,21 @@ static struct uart_driver sa1100_reg = {
.cons = SA1100_CONSOLE,
};
-static int sa1100_serial_suspend(struct device *_dev, pm_message_t state, u32 level)
+static int sa1100_serial_suspend(struct device *_dev, pm_message_t state)
{
struct sa1100_port *sport = dev_get_drvdata(_dev);
- if (sport && level == SUSPEND_DISABLE)
+ if (sport)
uart_suspend_port(&sa1100_reg, &sport->port);
return 0;
}
-static int sa1100_serial_resume(struct device *_dev, u32 level)
+static int sa1100_serial_resume(struct device *_dev)
{
struct sa1100_port *sport = dev_get_drvdata(_dev);
- if (sport && level == RESUME_ENABLE)
+ if (sport)
uart_resume_port(&sa1100_reg, &sport->port);
return 0;
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
index 0c5d65a08f6e01..2b623ab0e36ec9 100644
--- a/drivers/serial/vr41xx_siu.c
+++ b/drivers/serial/vr41xx_siu.c
@@ -976,14 +976,11 @@ static int siu_remove(struct device *dev)
return 0;
}
-static int siu_suspend(struct device *dev, pm_message_t state, u32 level)
+static int siu_suspend(struct device *dev, pm_message_t state)
{
struct uart_port *port;
int i;
- if (level != SUSPEND_DISABLE)
- return 0;
-
for (i = 0; i < siu_uart_driver.nr; i++) {
port = &siu_uart_ports[i];
if ((port->type == PORT_VR41XX_SIU ||
@@ -995,14 +992,11 @@ static int siu_suspend(struct device *dev, pm_message_t state, u32 level)
return 0;
}
-static int siu_resume(struct device *dev, u32 level)
+static int siu_resume(struct device *dev)
{
struct uart_port *port;
int i;
- if (level != RESUME_ENABLE)
- return 0;
-
for (i = 0; i < siu_uart_driver.nr; i++) {
port = &siu_uart_ports[i];
if ((port->type == PORT_VR41XX_SIU ||
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index fc15b4acc8af33..57e800ac3cee80 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -106,7 +106,7 @@ void hcd_buffer_destroy (struct usb_hcd *hcd)
void *hcd_buffer_alloc (
struct usb_bus *bus,
size_t size,
- unsigned mem_flags,
+ gfp_t mem_flags,
dma_addr_t *dma
)
{
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 487ff672b1045e..befe0c7f63d14d 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1509,7 +1509,7 @@ void usbdev_add(struct usb_device *dev)
{
int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
- dev->class_dev = class_device_create(usb_device_class,
+ dev->class_dev = class_device_create(usb_device_class, NULL,
MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev,
"usbdev%d.%d", dev->bus->busnum, dev->devnum);
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 65ca131cc44cc8..78cb4be9529f02 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -172,7 +172,9 @@ int usb_register_dev(struct usb_interface *intf,
++temp;
else
temp = name;
- intf->class_dev = class_device_create(usb_class, MKDEV(USB_MAJOR, minor), &intf->dev, "%s", temp);
+ intf->class_dev = class_device_create(usb_class, NULL,
+ MKDEV(USB_MAJOR, minor),
+ &intf->dev, "%s", temp);
if (IS_ERR(intf->class_dev)) {
spin_lock (&minor_lock);
usb_minors[intf->minor] = NULL;
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 1017a97a418b11..14c47a10da86d0 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -782,7 +782,8 @@ static int usb_register_bus(struct usb_bus *bus)
return -E2BIG;
}
- bus->class_dev = class_device_create(usb_host_class, MKDEV(0,0), bus->controller, "usb_host%d", busnum);
+ bus->class_dev = class_device_create(usb_host_class, NULL, MKDEV(0,0),
+ bus->controller, "usb_host%d", busnum);
if (IS_ERR(bus->class_dev)) {
clear_bit(busnum, busmap.busmap);
up(&usb_bus_list_lock);
@@ -1112,7 +1113,7 @@ static void urb_unlink (struct urb *urb)
* expects usb_submit_urb() to have sanity checked and conditioned all
* inputs in the urb
*/
-static int hcd_submit_urb (struct urb *urb, unsigned mem_flags)
+static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
{
int status;
struct usb_hcd *hcd = urb->dev->bus->hcpriv;
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index ac451fa7e4d273..1f1ed6211af8a6 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -142,12 +142,12 @@ struct hcd_timeout { /* timeouts we allocate */
struct usb_operations {
int (*get_frame_number) (struct usb_device *usb_dev);
- int (*submit_urb) (struct urb *urb, unsigned mem_flags);
+ int (*submit_urb) (struct urb *urb, gfp_t mem_flags);
int (*unlink_urb) (struct urb *urb, int status);
/* allocate dma-consistent buffer for URB_DMA_NOMAPPING */
void *(*buffer_alloc)(struct usb_bus *bus, size_t size,
- unsigned mem_flags,
+ gfp_t mem_flags,
dma_addr_t *dma);
void (*buffer_free)(struct usb_bus *bus, size_t size,
void *addr, dma_addr_t dma);
@@ -200,7 +200,7 @@ struct hc_driver {
int (*urb_enqueue) (struct usb_hcd *hcd,
struct usb_host_endpoint *ep,
struct urb *urb,
- unsigned mem_flags);
+ gfp_t mem_flags);
int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
/* hw synch, freeing endpoint resources that urb_dequeue can't */
@@ -247,7 +247,7 @@ int hcd_buffer_create (struct usb_hcd *hcd);
void hcd_buffer_destroy (struct usb_hcd *hcd);
void *hcd_buffer_alloc (struct usb_bus *bus, size_t size,
- unsigned mem_flags, dma_addr_t *dma);
+ gfp_t mem_flags, dma_addr_t *dma);
void hcd_buffer_free (struct usb_bus *bus, size_t size,
void *addr, dma_addr_t dma);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index a12cab5314e987..c3e2024c434707 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1020,9 +1020,15 @@ void usb_set_device_state(struct usb_device *udev,
spin_lock_irqsave(&device_state_lock, flags);
if (udev->state == USB_STATE_NOTATTACHED)
; /* do nothing */
- else if (new_state != USB_STATE_NOTATTACHED)
+ else if (new_state != USB_STATE_NOTATTACHED) {
udev->state = new_state;
- else
+ if (new_state == USB_STATE_CONFIGURED)
+ device_init_wakeup(&udev->dev,
+ (udev->actconfig->desc.bmAttributes
+ & USB_CONFIG_ATT_WAKEUP));
+ else if (new_state != USB_STATE_SUSPENDED)
+ device_init_wakeup(&udev->dev, 0);
+ } else
recursively_mark_NOTATTACHED(udev);
spin_unlock_irqrestore(&device_state_lock, flags);
}
@@ -1546,11 +1552,7 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
* NOTE: OTG devices may issue remote wakeup (or SRP) even when
* we don't explicitly enable it here.
*/
- if (udev->actconfig
- // && FIXME (remote wakeup enabled on this bus)
- // ... currently assuming it's always appropriate
- && (udev->actconfig->desc.bmAttributes
- & USB_CONFIG_ATT_WAKEUP) != 0) {
+ if (device_may_wakeup(&udev->dev)) {
status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
USB_DEVICE_REMOTE_WAKEUP, 0,
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index f1fb67fe22a828..f9a81e84dbdf64 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -321,7 +321,7 @@ int usb_sg_init (
struct scatterlist *sg,
int nents,
size_t length,
- unsigned mem_flags
+ gfp_t mem_flags
)
{
int i;
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index c846fefb738620..b32898e0a27d1d 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -60,7 +60,7 @@ void usb_init_urb(struct urb *urb)
*
* The driver must call usb_free_urb() when it is finished with the urb.
*/
-struct urb *usb_alloc_urb(int iso_packets, unsigned mem_flags)
+struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
{
struct urb *urb;
@@ -224,7 +224,7 @@ struct urb * usb_get_urb(struct urb *urb)
* GFP_NOIO, unless b) or c) apply
*
*/
-int usb_submit_urb(struct urb *urb, unsigned mem_flags)
+int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
{
int pipe, temp, max;
struct usb_device *dev;
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 7d131509e41909..4c57f3f649ede7 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -1147,7 +1147,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
void *usb_buffer_alloc (
struct usb_device *dev,
size_t size,
- unsigned mem_flags,
+ gfp_t mem_flags,
dma_addr_t *dma
)
{
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 583db7c38cf192..503201764f6bbc 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -470,7 +470,7 @@ static int dummy_disable (struct usb_ep *_ep)
}
static struct usb_request *
-dummy_alloc_request (struct usb_ep *_ep, unsigned mem_flags)
+dummy_alloc_request (struct usb_ep *_ep, gfp_t mem_flags)
{
struct dummy_ep *ep;
struct dummy_request *req;
@@ -507,7 +507,7 @@ dummy_alloc_buffer (
struct usb_ep *_ep,
unsigned bytes,
dma_addr_t *dma,
- unsigned mem_flags
+ gfp_t mem_flags
) {
char *retval;
struct dummy_ep *ep;
@@ -541,7 +541,7 @@ fifo_complete (struct usb_ep *ep, struct usb_request *req)
static int
dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
- unsigned mem_flags)
+ gfp_t mem_flags)
{
struct dummy_ep *ep;
struct dummy_request *req;
@@ -935,14 +935,10 @@ static int dummy_udc_remove (struct device *dev)
return 0;
}
-static int dummy_udc_suspend (struct device *dev, pm_message_t state,
- u32 level)
+static int dummy_udc_suspend (struct device *dev, pm_message_t state)
{
struct dummy *dum = dev_get_drvdata(dev);
- if (level != SUSPEND_DISABLE)
- return 0;
-
dev_dbg (dev, "%s\n", __FUNCTION__);
spin_lock_irq (&dum->lock);
dum->udc_suspended = 1;
@@ -954,13 +950,10 @@ static int dummy_udc_suspend (struct device *dev, pm_message_t state,
return 0;
}
-static int dummy_udc_resume (struct device *dev, u32 level)
+static int dummy_udc_resume (struct device *dev)
{
struct dummy *dum = dev_get_drvdata(dev);
- if (level != RESUME_ENABLE)
- return 0;
-
dev_dbg (dev, "%s\n", __FUNCTION__);
spin_lock_irq (&dum->lock);
dum->udc_suspended = 0;
@@ -999,7 +992,7 @@ static int dummy_urb_enqueue (
struct usb_hcd *hcd,
struct usb_host_endpoint *ep,
struct urb *urb,
- unsigned mem_flags
+ gfp_t mem_flags
) {
struct dummy *dum;
struct urbp *urbp;
@@ -1936,14 +1929,10 @@ static int dummy_hcd_remove (struct device *dev)
return 0;
}
-static int dummy_hcd_suspend (struct device *dev, pm_message_t state,
- u32 level)
+static int dummy_hcd_suspend (struct device *dev, pm_message_t state)
{
struct usb_hcd *hcd;
- if (level != SUSPEND_DISABLE)
- return 0;
-
dev_dbg (dev, "%s\n", __FUNCTION__);
hcd = dev_get_drvdata (dev);
@@ -1958,13 +1947,10 @@ static int dummy_hcd_suspend (struct device *dev, pm_message_t state,
return 0;
}
-static int dummy_hcd_resume (struct device *dev, u32 level)
+static int dummy_hcd_resume (struct device *dev)
{
struct usb_hcd *hcd;
- if (level != RESUME_ENABLE)
- return 0;
-
dev_dbg (dev, "%s\n", __FUNCTION__);
hcd = dev_get_drvdata (dev);
hcd->state = HC_STATE_RUNNING;
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 49459e33e952a6..f1024e804d5c4a 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -945,11 +945,11 @@ config_buf (enum usb_device_speed speed,
/*-------------------------------------------------------------------------*/
-static void eth_start (struct eth_dev *dev, unsigned gfp_flags);
-static int alloc_requests (struct eth_dev *dev, unsigned n, unsigned gfp_flags);
+static void eth_start (struct eth_dev *dev, gfp_t gfp_flags);
+static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags);
static int
-set_ether_config (struct eth_dev *dev, unsigned gfp_flags)
+set_ether_config (struct eth_dev *dev, gfp_t gfp_flags)
{
int result = 0;
struct usb_gadget *gadget = dev->gadget;
@@ -1081,7 +1081,7 @@ static void eth_reset_config (struct eth_dev *dev)
* that returns config descriptors, and altsetting code.
*/
static int
-eth_set_config (struct eth_dev *dev, unsigned number, unsigned gfp_flags)
+eth_set_config (struct eth_dev *dev, unsigned number, gfp_t gfp_flags)
{
int result = 0;
struct usb_gadget *gadget = dev->gadget;
@@ -1598,7 +1598,7 @@ static void defer_kevent (struct eth_dev *dev, int flag)
static void rx_complete (struct usb_ep *ep, struct usb_request *req);
static int
-rx_submit (struct eth_dev *dev, struct usb_request *req, unsigned gfp_flags)
+rx_submit (struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
{
struct sk_buff *skb;
int retval = -ENOMEM;
@@ -1724,7 +1724,7 @@ clean:
}
static int prealloc (struct list_head *list, struct usb_ep *ep,
- unsigned n, unsigned gfp_flags)
+ unsigned n, gfp_t gfp_flags)
{
unsigned i;
struct usb_request *req;
@@ -1763,7 +1763,7 @@ extra:
return 0;
}
-static int alloc_requests (struct eth_dev *dev, unsigned n, unsigned gfp_flags)
+static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags)
{
int status;
@@ -1779,7 +1779,7 @@ fail:
return status;
}
-static void rx_fill (struct eth_dev *dev, unsigned gfp_flags)
+static void rx_fill (struct eth_dev *dev, gfp_t gfp_flags)
{
struct usb_request *req;
unsigned long flags;
@@ -1962,7 +1962,7 @@ drop:
* normally just one notification will be queued.
*/
-static struct usb_request *eth_req_alloc (struct usb_ep *, unsigned, unsigned);
+static struct usb_request *eth_req_alloc (struct usb_ep *, unsigned, gfp_t);
static void eth_req_free (struct usb_ep *ep, struct usb_request *req);
static void
@@ -2024,7 +2024,7 @@ static int rndis_control_ack (struct net_device *net)
#endif /* RNDIS */
-static void eth_start (struct eth_dev *dev, unsigned gfp_flags)
+static void eth_start (struct eth_dev *dev, gfp_t gfp_flags)
{
DEBUG (dev, "%s\n", __FUNCTION__);
@@ -2092,7 +2092,7 @@ static int eth_stop (struct net_device *net)
/*-------------------------------------------------------------------------*/
static struct usb_request *
-eth_req_alloc (struct usb_ep *ep, unsigned size, unsigned gfp_flags)
+eth_req_alloc (struct usb_ep *ep, unsigned size, gfp_t gfp_flags)
{
struct usb_request *req;
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index eaab26f4ed3712..b0f3cd63e3b911 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -269,7 +269,7 @@ static int goku_ep_disable(struct usb_ep *_ep)
/*-------------------------------------------------------------------------*/
static struct usb_request *
-goku_alloc_request(struct usb_ep *_ep, unsigned gfp_flags)
+goku_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
{
struct goku_request *req;
@@ -327,7 +327,7 @@ goku_free_request(struct usb_ep *_ep, struct usb_request *_req)
*/
static void *
goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
- dma_addr_t *dma, unsigned gfp_flags)
+ dma_addr_t *dma, gfp_t gfp_flags)
{
void *retval;
struct goku_ep *ep;
@@ -789,7 +789,7 @@ finished:
/*-------------------------------------------------------------------------*/
static int
-goku_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
+goku_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
{
struct goku_request *req;
struct goku_ep *ep;
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index 4842577789c93f..012d1e5f152438 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -71,13 +71,13 @@ static char *state_names[] = {
static int lh7a40x_ep_enable(struct usb_ep *ep,
const struct usb_endpoint_descriptor *);
static int lh7a40x_ep_disable(struct usb_ep *ep);
-static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, int);
+static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, gfp_t);
static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *);
static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned, dma_addr_t *,
- int);
+ gfp_t);
static void lh7a40x_free_buffer(struct usb_ep *ep, void *, dma_addr_t,
unsigned);
-static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, int);
+static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, gfp_t);
static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *);
static int lh7a40x_set_halt(struct usb_ep *ep, int);
static int lh7a40x_fifo_status(struct usb_ep *ep);
@@ -1106,7 +1106,7 @@ static int lh7a40x_ep_disable(struct usb_ep *_ep)
}
static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep,
- unsigned gfp_flags)
+ gfp_t gfp_flags)
{
struct lh7a40x_request *req;
@@ -1134,7 +1134,7 @@ static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *_req)
}
static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned bytes,
- dma_addr_t * dma, unsigned gfp_flags)
+ dma_addr_t * dma, gfp_t gfp_flags)
{
char *retval;
@@ -1158,7 +1158,7 @@ static void lh7a40x_free_buffer(struct usb_ep *ep, void *buf, dma_addr_t dma,
* NOTE: Sets INDEX register
*/
static int lh7a40x_queue(struct usb_ep *_ep, struct usb_request *_req,
- unsigned gfp_flags)
+ gfp_t gfp_flags)
{
struct lh7a40x_request *req;
struct lh7a40x_ep *ep;
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 477fab2e74d118..c32e1f7476da46 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -376,7 +376,7 @@ static int net2280_disable (struct usb_ep *_ep)
/*-------------------------------------------------------------------------*/
static struct usb_request *
-net2280_alloc_request (struct usb_ep *_ep, unsigned gfp_flags)
+net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
{
struct net2280_ep *ep;
struct net2280_request *req;
@@ -463,7 +463,7 @@ net2280_alloc_buffer (
struct usb_ep *_ep,
unsigned bytes,
dma_addr_t *dma,
- unsigned gfp_flags
+ gfp_t gfp_flags
)
{
void *retval;
@@ -897,7 +897,7 @@ done (struct net2280_ep *ep, struct net2280_request *req, int status)
/*-------------------------------------------------------------------------*/
static int
-net2280_queue (struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
+net2280_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
{
struct net2280_request *req;
struct net2280_ep *ep;
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index ff5533e6956047..b7885dc0f42f54 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -269,7 +269,7 @@ static int omap_ep_disable(struct usb_ep *_ep)
/*-------------------------------------------------------------------------*/
static struct usb_request *
-omap_alloc_request(struct usb_ep *ep, unsigned gfp_flags)
+omap_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
{
struct omap_req *req;
@@ -298,7 +298,7 @@ omap_alloc_buffer(
struct usb_ep *_ep,
unsigned bytes,
dma_addr_t *dma,
- unsigned gfp_flags
+ gfp_t gfp_flags
)
{
void *retval;
@@ -937,7 +937,7 @@ static void dma_channel_release(struct omap_ep *ep)
/*-------------------------------------------------------------------------*/
static int
-omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
+omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
{
struct omap_ep *ep = container_of(_ep, struct omap_ep, ep);
struct omap_req *req = container_of(_req, struct omap_req, req);
@@ -2909,12 +2909,10 @@ static int __exit omap_udc_remove(struct device *dev)
* may involve talking to an external transceiver (e.g. isp1301).
*/
-static int omap_udc_suspend(struct device *dev, pm_message_t message, u32 level)
+static int omap_udc_suspend(struct device *dev, pm_message_t message)
{
u32 devstat;
- if (level != SUSPEND_POWER_DOWN)
- return 0;
devstat = UDC_DEVSTAT_REG;
/* we're requesting 48 MHz clock if the pullup is enabled
@@ -2931,11 +2929,8 @@ static int omap_udc_suspend(struct device *dev, pm_message_t message, u32 level)
return 0;
}
-static int omap_udc_resume(struct device *dev, u32 level)
+static int omap_udc_resume(struct device *dev)
{
- if (level != RESUME_POWER_ON)
- return 0;
-
DBG("resume + wakeup/SRP\n");
omap_pullup(&udc->gadget, 1);
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 73f8c9404156be..647028590b23c0 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -332,7 +332,7 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep)
* pxa2xx_ep_alloc_request - allocate a request data structure
*/
static struct usb_request *
-pxa2xx_ep_alloc_request (struct usb_ep *_ep, unsigned gfp_flags)
+pxa2xx_ep_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
{
struct pxa2xx_request *req;
@@ -367,7 +367,7 @@ pxa2xx_ep_free_request (struct usb_ep *_ep, struct usb_request *_req)
*/
static void *
pxa2xx_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
- dma_addr_t *dma, unsigned gfp_flags)
+ dma_addr_t *dma, gfp_t gfp_flags)
{
char *retval;
@@ -422,7 +422,7 @@ static inline void ep0_idle (struct pxa2xx_udc *dev)
}
static int
-write_packet(volatile unsigned long *uddr, struct pxa2xx_request *req, unsigned max)
+write_packet(volatile u32 *uddr, struct pxa2xx_request *req, unsigned max)
{
u8 *buf;
unsigned length, count;
@@ -874,7 +874,7 @@ done:
/*-------------------------------------------------------------------------*/
static int
-pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
+pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
{
struct pxa2xx_request *req;
struct pxa2xx_ep *ep;
@@ -2602,24 +2602,23 @@ static int __exit pxa2xx_udc_remove(struct device *_dev)
* VBUS IRQs should probably be ignored so that the PXA device just acts
* "dead" to USB hosts until system resume.
*/
-static int pxa2xx_udc_suspend(struct device *dev, pm_message_t state, u32 level)
+static int pxa2xx_udc_suspend(struct device *dev, pm_message_t state)
{
struct pxa2xx_udc *udc = dev_get_drvdata(dev);
- if (level == SUSPEND_POWER_DOWN) {
- if (!udc->mach->udc_command)
- WARN("USB host won't detect disconnect!\n");
- pullup(udc, 0);
- }
+ if (!udc->mach->udc_command)
+ WARN("USB host won't detect disconnect!\n");
+ pullup(udc, 0);
+
return 0;
}
-static int pxa2xx_udc_resume(struct device *dev, u32 level)
+static int pxa2xx_udc_resume(struct device *dev)
{
struct pxa2xx_udc *udc = dev_get_drvdata(dev);
- if (level == RESUME_POWER_ON)
- pullup(udc, 1);
+ pullup(udc, 1);
+
return 0;
}
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
index a58f3e6e71f1dd..19a883f7d1b8f6 100644
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ b/drivers/usb/gadget/pxa2xx_udc.h
@@ -69,11 +69,11 @@ struct pxa2xx_ep {
* UDDR = UDC Endpoint Data Register (the fifo)
* DRCM = DMA Request Channel Map
*/
- volatile unsigned long *reg_udccs;
- volatile unsigned long *reg_ubcr;
- volatile unsigned long *reg_uddr;
+ volatile u32 *reg_udccs;
+ volatile u32 *reg_ubcr;
+ volatile u32 *reg_uddr;
#ifdef USE_DMA
- volatile unsigned long *reg_drcmr;
+ volatile u32 *reg_drcmr;
#define drcmr(n) .reg_drcmr = & DRCMR ## n ,
#else
#define drcmr(n)
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index c925d9222f53c4..b35ac6d334f8e3 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -300,18 +300,18 @@ static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed,
u8 type, unsigned int index, int is_otg);
static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len,
- unsigned kmalloc_flags);
+ gfp_t kmalloc_flags);
static void gs_free_req(struct usb_ep *ep, struct usb_request *req);
static struct gs_req_entry *gs_alloc_req_entry(struct usb_ep *ep, unsigned len,
- unsigned kmalloc_flags);
+ gfp_t kmalloc_flags);
static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req);
-static int gs_alloc_ports(struct gs_dev *dev, unsigned kmalloc_flags);
+static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags);
static void gs_free_ports(struct gs_dev *dev);
/* circular buffer */
-static struct gs_buf *gs_buf_alloc(unsigned int size, unsigned kmalloc_flags);
+static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags);
static void gs_buf_free(struct gs_buf *gb);
static void gs_buf_clear(struct gs_buf *gb);
static unsigned int gs_buf_data_avail(struct gs_buf *gb);
@@ -2091,7 +2091,7 @@ static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed,
* usb_request or NULL if there is an error.
*/
static struct usb_request *
-gs_alloc_req(struct usb_ep *ep, unsigned int len, unsigned kmalloc_flags)
+gs_alloc_req(struct usb_ep *ep, unsigned int len, gfp_t kmalloc_flags)
{
struct usb_request *req;
@@ -2132,7 +2132,7 @@ static void gs_free_req(struct usb_ep *ep, struct usb_request *req)
* endpoint, buffer len, and kmalloc flags.
*/
static struct gs_req_entry *
-gs_alloc_req_entry(struct usb_ep *ep, unsigned len, unsigned kmalloc_flags)
+gs_alloc_req_entry(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
{
struct gs_req_entry *req;
@@ -2173,7 +2173,7 @@ static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req)
*
* The device lock is normally held when calling this function.
*/
-static int gs_alloc_ports(struct gs_dev *dev, unsigned kmalloc_flags)
+static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags)
{
int i;
struct gs_port *port;
@@ -2255,7 +2255,7 @@ static void gs_free_ports(struct gs_dev *dev)
*
* Allocate a circular buffer and all associated memory.
*/
-static struct gs_buf *gs_buf_alloc(unsigned int size, unsigned kmalloc_flags)
+static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags)
{
struct gs_buf *gb;
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 6890e773b2a2a3..ec9c424f1d9706 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -612,7 +612,7 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req)
}
static struct usb_request *
-source_sink_start_ep (struct usb_ep *ep, unsigned gfp_flags)
+source_sink_start_ep (struct usb_ep *ep, gfp_t gfp_flags)
{
struct usb_request *req;
int status;
@@ -640,7 +640,7 @@ source_sink_start_ep (struct usb_ep *ep, unsigned gfp_flags)
}
static int
-set_source_sink_config (struct zero_dev *dev, unsigned gfp_flags)
+set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags)
{
int result = 0;
struct usb_ep *ep;
@@ -744,7 +744,7 @@ static void loopback_complete (struct usb_ep *ep, struct usb_request *req)
}
static int
-set_loopback_config (struct zero_dev *dev, unsigned gfp_flags)
+set_loopback_config (struct zero_dev *dev, gfp_t gfp_flags)
{
int result = 0;
struct usb_ep *ep;
@@ -845,7 +845,7 @@ static void zero_reset_config (struct zero_dev *dev)
* by limiting configuration choices (like the pxa2xx).
*/
static int
-zero_set_config (struct zero_dev *dev, unsigned number, unsigned gfp_flags)
+zero_set_config (struct zero_dev *dev, unsigned number, gfp_t gfp_flags)
{
int result = 0;
struct usb_gadget *gadget = dev->gadget;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index b948ffd94f4587..f5eb9e7b5b1875 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -983,7 +983,7 @@ static int ehci_urb_enqueue (
struct usb_hcd *hcd,
struct usb_host_endpoint *ep,
struct urb *urb,
- unsigned mem_flags
+ gfp_t mem_flags
) {
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
struct list_head qtd_list;
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index 5c38ad869485e8..91c2ab43cbcc1a 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -45,7 +45,7 @@ static inline void ehci_qtd_init (struct ehci_qtd *qtd, dma_addr_t dma)
INIT_LIST_HEAD (&qtd->qtd_list);
}
-static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, int flags)
+static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, gfp_t flags)
{
struct ehci_qtd *qtd;
dma_addr_t dma;
@@ -79,7 +79,7 @@ static void qh_destroy (struct kref *kref)
dma_pool_free (ehci->qh_pool, qh, qh->qh_dma);
}
-static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags)
+static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
{
struct ehci_qh *qh;
dma_addr_t dma;
@@ -161,7 +161,7 @@ static void ehci_mem_cleanup (struct ehci_hcd *ehci)
}
/* remember to add cleanup code (above) if you add anything here */
-static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
+static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
{
int i;
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 940d38ca7d9178..5bb872c3496d70 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -477,7 +477,7 @@ qh_urb_transaction (
struct ehci_hcd *ehci,
struct urb *urb,
struct list_head *head,
- int flags
+ gfp_t flags
) {
struct ehci_qtd *qtd, *qtd_prev;
dma_addr_t buf;
@@ -629,7 +629,7 @@ static struct ehci_qh *
qh_make (
struct ehci_hcd *ehci,
struct urb *urb,
- int flags
+ gfp_t flags
) {
struct ehci_qh *qh = ehci_qh_alloc (ehci, flags);
u32 info1 = 0, info2 = 0;
@@ -906,7 +906,7 @@ submit_async (
struct usb_host_endpoint *ep,
struct urb *urb,
struct list_head *qtd_list,
- unsigned mem_flags
+ gfp_t mem_flags
) {
struct ehci_qtd *qtd;
int epnum;
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index ccc7300baa6d71..f0c8aa1ccd5dc0 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -589,7 +589,7 @@ static int intr_submit (
struct usb_host_endpoint *ep,
struct urb *urb,
struct list_head *qtd_list,
- unsigned mem_flags
+ gfp_t mem_flags
) {
unsigned epnum;
unsigned long flags;
@@ -634,7 +634,7 @@ done:
/* ehci_iso_stream ops work with both ITD and SITD */
static struct ehci_iso_stream *
-iso_stream_alloc (unsigned mem_flags)
+iso_stream_alloc (gfp_t mem_flags)
{
struct ehci_iso_stream *stream;
@@ -851,7 +851,7 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
/* ehci_iso_sched ops can be ITD-only or SITD-only */
static struct ehci_iso_sched *
-iso_sched_alloc (unsigned packets, unsigned mem_flags)
+iso_sched_alloc (unsigned packets, gfp_t mem_flags)
{
struct ehci_iso_sched *iso_sched;
int size = sizeof *iso_sched;
@@ -924,7 +924,7 @@ itd_urb_transaction (
struct ehci_iso_stream *stream,
struct ehci_hcd *ehci,
struct urb *urb,
- unsigned mem_flags
+ gfp_t mem_flags
)
{
struct ehci_itd *itd;
@@ -1418,7 +1418,7 @@ itd_complete (
/*-------------------------------------------------------------------------*/
static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
- unsigned mem_flags)
+ gfp_t mem_flags)
{
int status = -EINVAL;
unsigned long flags;
@@ -1529,7 +1529,7 @@ sitd_urb_transaction (
struct ehci_iso_stream *stream,
struct ehci_hcd *ehci,
struct urb *urb,
- unsigned mem_flags
+ gfp_t mem_flags
)
{
struct ehci_sitd *sitd;
@@ -1779,7 +1779,7 @@ sitd_complete (
static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
- unsigned mem_flags)
+ gfp_t mem_flags)
{
int status = -EINVAL;
unsigned long flags;
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index e142056b0d2cd5..642f35068ce2c6 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -694,7 +694,7 @@ static int balance(struct isp116x *isp116x, u16 period, u16 load)
static int isp116x_urb_enqueue(struct usb_hcd *hcd,
struct usb_host_endpoint *hep, struct urb *urb,
- unsigned mem_flags)
+ gfp_t mem_flags)
{
struct isp116x *isp116x = hcd_to_isp116x(hcd);
struct usb_device *udev = urb->dev;
@@ -1774,15 +1774,12 @@ static int __init isp116x_probe(struct device *dev)
/*
Suspend of platform device
*/
-static int isp116x_suspend(struct device *dev, pm_message_t state, u32 phase)
+static int isp116x_suspend(struct device *dev, pm_message_t state)
{
int ret = 0;
struct usb_hcd *hcd = dev_get_drvdata(dev);
- VDBG("%s: state %x, phase %x\n", __func__, state, phase);
-
- if (phase != SUSPEND_DISABLE && phase != SUSPEND_POWER_DOWN)
- return 0;
+ VDBG("%s: state %x\n", __func__, state);
ret = usb_suspend_device(hcd->self.root_hub, state);
if (!ret) {
@@ -1797,15 +1794,12 @@ static int isp116x_suspend(struct device *dev, pm_message_t state, u32 phase)
/*
Resume platform device
*/
-static int isp116x_resume(struct device *dev, u32 phase)
+static int isp116x_resume(struct device *dev)
{
int ret = 0;
struct usb_hcd *hcd = dev_get_drvdata(dev);
- VDBG("%s: state %x, phase %x\n", __func__, dev->power.power_state,
- phase);
- if (phase != RESUME_POWER_ON)
- return 0;
+ VDBG("%s: state %x\n", __func__, dev->power.power_state);
ret = usb_resume_device(hcd->self.root_hub);
if (!ret) {
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 67c1aa5eb1c175..f8da8c7af7c66b 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -180,7 +180,7 @@ static int ohci_urb_enqueue (
struct usb_hcd *hcd,
struct usb_host_endpoint *ep,
struct urb *urb,
- unsigned mem_flags
+ gfp_t mem_flags
) {
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
struct ed *ed;
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
index fd3c4d3714bd80..9fb83dfb1eb441 100644
--- a/drivers/usb/host/ohci-mem.c
+++ b/drivers/usb/host/ohci-mem.c
@@ -84,7 +84,7 @@ dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
/* TDs ... */
static struct td *
-td_alloc (struct ohci_hcd *hc, unsigned mem_flags)
+td_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
{
dma_addr_t dma;
struct td *td;
@@ -118,7 +118,7 @@ td_free (struct ohci_hcd *hc, struct td *td)
/* EDs ... */
static struct ed *
-ed_alloc (struct ohci_hcd *hc, unsigned mem_flags)
+ed_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
{
dma_addr_t dma;
struct ed *ed;
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index d8f3ba7ad52e2d..a574216625a03c 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -455,14 +455,11 @@ static int ohci_hcd_omap_drv_remove(struct device *dev)
#ifdef CONFIG_PM
-static int ohci_omap_suspend(struct device *dev, pm_message_t message, u32 level)
+static int ohci_omap_suspend(struct device *dev, pm_message_t message)
{
struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev));
int status = -EINVAL;
- if (level != SUSPEND_POWER_DOWN)
- return 0;
-
down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
status = ohci_hub_suspend(ohci_to_hcd(ohci));
if (status == 0) {
@@ -476,14 +473,11 @@ static int ohci_omap_suspend(struct device *dev, pm_message_t message, u32 level
return status;
}
-static int ohci_omap_resume(struct device *dev, u32 level)
+static int ohci_omap_resume(struct device *dev)
{
struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev));
int status = 0;
- if (level != RESUME_POWER_ON)
- return 0;
-
if (time_before(jiffies, ohci->next_statechange))
msleep(5);
ohci->next_statechange = jiffies;
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 2fdb262d47260a..f042261ecb8e95 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -309,7 +309,7 @@ static int ohci_hcd_pxa27x_drv_remove(struct device *dev)
return 0;
}
-static int ohci_hcd_pxa27x_drv_suspend(struct device *dev, pm_message_t state, u32 level)
+static int ohci_hcd_pxa27x_drv_suspend(struct device *dev, pm_message_t state)
{
// struct platform_device *pdev = to_platform_device(dev);
// struct usb_hcd *hcd = dev_get_drvdata(dev);
@@ -318,7 +318,7 @@ static int ohci_hcd_pxa27x_drv_suspend(struct device *dev, pm_message_t state, u
return 0;
}
-static int ohci_hcd_pxa27x_drv_resume(struct device *dev, u32 level)
+static int ohci_hcd_pxa27x_drv_resume(struct device *dev)
{
// struct platform_device *pdev = to_platform_device(dev);
// struct usb_hcd *hcd = dev_get_drvdata(dev);
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index d42a15d10a462d..b5e7a478bc018f 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -818,7 +818,7 @@ static int sl811h_urb_enqueue(
struct usb_hcd *hcd,
struct usb_host_endpoint *hep,
struct urb *urb,
- unsigned mem_flags
+ gfp_t mem_flags
) {
struct sl811 *sl811 = hcd_to_sl811(hcd);
struct usb_device *udev = urb->dev;
@@ -1784,15 +1784,12 @@ sl811h_probe(struct device *dev)
*/
static int
-sl811h_suspend(struct device *dev, pm_message_t state, u32 phase)
+sl811h_suspend(struct device *dev, pm_message_t state)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct sl811 *sl811 = hcd_to_sl811(hcd);
int retval = 0;
- if (phase != SUSPEND_POWER_DOWN)
- return retval;
-
if (state.event == PM_EVENT_FREEZE)
retval = sl811h_hub_suspend(hcd);
else if (state.event == PM_EVENT_SUSPEND)
@@ -1803,14 +1800,11 @@ sl811h_suspend(struct device *dev, pm_message_t state, u32 phase)
}
static int
-sl811h_resume(struct device *dev, u32 phase)
+sl811h_resume(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct sl811 *sl811 = hcd_to_sl811(hcd);
- if (phase != RESUME_POWER_ON)
- return 0;
-
/* with no "check to see if VBUS is still powered" board hook,
* let's assume it'd only be powered to enable remote wakeup.
*/
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index ea0d168a8c676a..4e0fbe2c1a9ab9 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -1164,7 +1164,7 @@ static struct urb *uhci_find_urb_ep(struct uhci_hcd *uhci, struct urb *urb)
static int uhci_urb_enqueue(struct usb_hcd *hcd,
struct usb_host_endpoint *ep,
- struct urb *urb, unsigned mem_flags)
+ struct urb *urb, gfp_t mem_flags)
{
int ret;
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c
index 74f8760d7c07c0..a32558b4048e5a 100644
--- a/drivers/usb/input/acecad.c
+++ b/drivers/usb/input/acecad.c
@@ -53,7 +53,7 @@ struct usb_acecad {
char name[128];
char phys[64];
struct usb_device *usbdev;
- struct input_dev dev;
+ struct input_dev *input;
struct urb *irq;
signed char *data;
@@ -64,7 +64,7 @@ static void usb_acecad_irq(struct urb *urb, struct pt_regs *regs)
{
struct usb_acecad *acecad = urb->context;
unsigned char *data = acecad->data;
- struct input_dev *dev = &acecad->dev;
+ struct input_dev *dev = acecad->input;
int prox, status;
switch (urb->status) {
@@ -135,8 +135,8 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
struct usb_host_interface *interface = intf->cur_altsetting;
struct usb_endpoint_descriptor *endpoint;
struct usb_acecad *acecad;
+ struct input_dev *input_dev;
int pipe, maxp;
- char path[64];
if (interface->desc.bNumEndpoints != 1)
return -ENODEV;
@@ -153,8 +153,9 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL);
- if (!acecad)
- return -ENOMEM;
+ input_dev = input_allocate_device();
+ if (!acecad || !input_dev)
+ goto fail1;
acecad->data = usb_buffer_alloc(dev, 8, SLAB_KERNEL, &acecad->data_dma);
if (!acecad->data)
@@ -164,6 +165,9 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
if (!acecad->irq)
goto fail2;
+ acecad->usbdev = dev;
+ acecad->input = input_dev;
+
if (dev->manufacturer)
strlcpy(acecad->name, dev->manufacturer, sizeof(acecad->name));
@@ -173,48 +177,48 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
strlcat(acecad->name, dev->product, sizeof(acecad->name));
}
- usb_make_path(dev, path, sizeof(path));
- snprintf(acecad->phys, sizeof(acecad->phys), "%s/input0", path);
+ usb_make_path(dev, acecad->phys, sizeof(acecad->phys));
+ strlcat(acecad->phys, "/input0", sizeof(acecad->phys));
- acecad->usbdev = dev;
+ input_dev->name = acecad->name;
+ input_dev->phys = acecad->phys;
+ usb_to_input_id(dev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
+ input_dev->private = acecad;
- acecad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- acecad->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
- acecad->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
- acecad->dev.keybit[LONG(BTN_DIGI)] = BIT(BTN_TOOL_PEN) |BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2);
+ input_dev->open = usb_acecad_open;
+ input_dev->close = usb_acecad_close;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
+ input_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+ input_dev->keybit[LONG(BTN_DIGI)] = BIT(BTN_TOOL_PEN) |BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2);
switch (id->driver_info) {
case 0:
- acecad->dev.absmax[ABS_X] = 5000;
- acecad->dev.absmax[ABS_Y] = 3750;
- acecad->dev.absmax[ABS_PRESSURE] = 512;
+ input_dev->absmax[ABS_X] = 5000;
+ input_dev->absmax[ABS_Y] = 3750;
+ input_dev->absmax[ABS_PRESSURE] = 512;
if (!strlen(acecad->name))
snprintf(acecad->name, sizeof(acecad->name),
"USB Acecad Flair Tablet %04x:%04x",
- dev->descriptor.idVendor, dev->descriptor.idProduct);
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
break;
case 1:
- acecad->dev.absmax[ABS_X] = 3000;
- acecad->dev.absmax[ABS_Y] = 2250;
- acecad->dev.absmax[ABS_PRESSURE] = 1024;
+ input_dev->absmax[ABS_X] = 3000;
+ input_dev->absmax[ABS_Y] = 2250;
+ input_dev->absmax[ABS_PRESSURE] = 1024;
if (!strlen(acecad->name))
snprintf(acecad->name, sizeof(acecad->name),
"USB Acecad 302 Tablet %04x:%04x",
- dev->descriptor.idVendor, dev->descriptor.idProduct);
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
break;
}
- acecad->dev.absfuzz[ABS_X] = 4;
- acecad->dev.absfuzz[ABS_Y] = 4;
-
- acecad->dev.private = acecad;
- acecad->dev.open = usb_acecad_open;
- acecad->dev.close = usb_acecad_close;
-
- acecad->dev.name = acecad->name;
- acecad->dev.phys = acecad->phys;
- usb_to_input_id(dev, &acecad->dev.id);
- acecad->dev.dev = &intf->dev;
+ input_dev->absfuzz[ABS_X] = 4;
+ input_dev->absfuzz[ABS_Y] = 4;
usb_fill_int_urb(acecad->irq, dev, pipe,
acecad->data, maxp > 8 ? 8 : maxp,
@@ -222,17 +226,15 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
acecad->irq->transfer_dma = acecad->data_dma;
acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- input_register_device(&acecad->dev);
-
- printk(KERN_INFO "input: %s with packet size %d on %s\n",
- acecad->name, maxp, path);
+ input_register_device(acecad->input);
usb_set_intfdata(intf, acecad);
return 0;
fail2: usb_buffer_free(dev, 8, acecad->data, acecad->data_dma);
- fail1: kfree(acecad);
+ fail1: input_free_device(input_dev);
+ kfree(acecad);
return -ENOMEM;
}
@@ -243,7 +245,7 @@ static void usb_acecad_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (acecad) {
usb_kill_urb(acecad->irq);
- input_unregister_device(&acecad->dev);
+ input_unregister_device(acecad->input);
usb_free_urb(acecad->irq);
usb_buffer_free(interface_to_usbdev(intf), 10, acecad->data, acecad->data_dma);
kfree(acecad);
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index cd0cbfe207232a..1c5205321d832a 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -317,7 +317,7 @@ struct aiptek_settings {
};
struct aiptek {
- struct input_dev inputdev; /* input device struct */
+ struct input_dev *inputdev; /* input device struct */
struct usb_device *usbdev; /* usb device struct */
struct urb *urb; /* urb for incoming reports */
dma_addr_t data_dma; /* our dma stuffage */
@@ -402,7 +402,7 @@ static void aiptek_irq(struct urb *urb, struct pt_regs *regs)
{
struct aiptek *aiptek = urb->context;
unsigned char *data = aiptek->data;
- struct input_dev *inputdev = &aiptek->inputdev;
+ struct input_dev *inputdev = aiptek->inputdev;
int jitterable = 0;
int retval, macro, x, y, z, left, right, middle, p, dv, tip, bs, pck;
@@ -955,20 +955,20 @@ static int aiptek_program_tablet(struct aiptek *aiptek)
/* Query getXextension */
if ((ret = aiptek_query(aiptek, 0x01, 0x00)) < 0)
return ret;
- aiptek->inputdev.absmin[ABS_X] = 0;
- aiptek->inputdev.absmax[ABS_X] = ret - 1;
+ aiptek->inputdev->absmin[ABS_X] = 0;
+ aiptek->inputdev->absmax[ABS_X] = ret - 1;
/* Query getYextension */
if ((ret = aiptek_query(aiptek, 0x01, 0x01)) < 0)
return ret;
- aiptek->inputdev.absmin[ABS_Y] = 0;
- aiptek->inputdev.absmax[ABS_Y] = ret - 1;
+ aiptek->inputdev->absmin[ABS_Y] = 0;
+ aiptek->inputdev->absmax[ABS_Y] = ret - 1;
/* Query getPressureLevels */
if ((ret = aiptek_query(aiptek, 0x08, 0x00)) < 0)
return ret;
- aiptek->inputdev.absmin[ABS_PRESSURE] = 0;
- aiptek->inputdev.absmax[ABS_PRESSURE] = ret - 1;
+ aiptek->inputdev->absmin[ABS_PRESSURE] = 0;
+ aiptek->inputdev->absmax[ABS_PRESSURE] = ret - 1;
/* Depending on whether we are in absolute or relative mode, we will
* do a switchToTablet(absolute) or switchToMouse(relative) command.
@@ -1025,8 +1025,8 @@ static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr
return 0;
return snprintf(buf, PAGE_SIZE, "%dx%d\n",
- aiptek->inputdev.absmax[ABS_X] + 1,
- aiptek->inputdev.absmax[ABS_Y] + 1);
+ aiptek->inputdev->absmax[ABS_X] + 1,
+ aiptek->inputdev->absmax[ABS_Y] + 1);
}
/* These structs define the sysfs files, param #1 is the name of the
@@ -1048,7 +1048,7 @@ static ssize_t show_tabletProductId(struct device *dev, struct device_attribute
return 0;
return snprintf(buf, PAGE_SIZE, "0x%04x\n",
- aiptek->inputdev.id.product);
+ aiptek->inputdev->id.product);
}
static DEVICE_ATTR(product_id, S_IRUGO, show_tabletProductId, NULL);
@@ -1063,7 +1063,7 @@ static ssize_t show_tabletVendorId(struct device *dev, struct device_attribute *
if (aiptek == NULL)
return 0;
- return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev.id.vendor);
+ return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev->id.vendor);
}
static DEVICE_ATTR(vendor_id, S_IRUGO, show_tabletVendorId, NULL);
@@ -1977,7 +1977,6 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct input_dev *inputdev;
struct input_handle *inputhandle;
struct list_head *node, *next;
- char path[64 + 1];
int i;
int speeds[] = { 0,
AIPTEK_PROGRAMMABLE_DELAY_50,
@@ -1996,24 +1995,26 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
*/
speeds[0] = programmableDelay;
- if ((aiptek = kmalloc(sizeof(struct aiptek), GFP_KERNEL)) == NULL)
- return -ENOMEM;
- memset(aiptek, 0, sizeof(struct aiptek));
+ aiptek = kzalloc(sizeof(struct aiptek), GFP_KERNEL);
+ inputdev = input_allocate_device();
+ if (!aiptek || !inputdev)
+ goto fail1;
aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH,
SLAB_ATOMIC, &aiptek->data_dma);
- if (aiptek->data == NULL) {
- kfree(aiptek);
- return -ENOMEM;
- }
+ if (!aiptek->data)
+ goto fail1;
aiptek->urb = usb_alloc_urb(0, GFP_KERNEL);
- if (aiptek->urb == NULL) {
- usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
- aiptek->data_dma);
- kfree(aiptek);
- return -ENOMEM;
- }
+ if (!aiptek->urb)
+ goto fail2;
+
+ aiptek->inputdev = inputdev;
+ aiptek->usbdev = usbdev;
+ aiptek->ifnum = intf->altsetting[0].desc.bInterfaceNumber;
+ aiptek->inDelay = 0;
+ aiptek->endDelay = 0;
+ aiptek->previousJitterable = 0;
/* Set up the curSettings struct. Said struct contains the current
* programmable parameters. The newSetting struct contains changes
@@ -2036,31 +2037,48 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
/* Both structs should have equivalent settings
*/
- memcpy(&aiptek->newSetting, &aiptek->curSetting,
- sizeof(struct aiptek_settings));
+ aiptek->newSetting = aiptek->curSetting;
+
+ /* Determine the usb devices' physical path.
+ * Asketh not why we always pretend we're using "../input0",
+ * but I suspect this will have to be refactored one
+ * day if a single USB device can be a keyboard & a mouse
+ * & a tablet, and the inputX number actually will tell
+ * us something...
+ */
+ usb_make_path(usbdev, aiptek->features.usbPath,
+ sizeof(aiptek->features.usbPath));
+ strlcat(aiptek->features.usbPath, "/input0",
+ sizeof(aiptek->features.usbPath));
+
+ /* Set up client data, pointers to open and close routines
+ * for the input device.
+ */
+ inputdev->name = "Aiptek";
+ inputdev->phys = aiptek->features.usbPath;
+ usb_to_input_id(usbdev, &inputdev->id);
+ inputdev->cdev.dev = &intf->dev;
+ inputdev->private = aiptek;
+ inputdev->open = aiptek_open;
+ inputdev->close = aiptek_close;
/* Now program the capacities of the tablet, in terms of being
* an input device.
*/
- aiptek->inputdev.evbit[0] |= BIT(EV_KEY)
+ inputdev->evbit[0] |= BIT(EV_KEY)
| BIT(EV_ABS)
| BIT(EV_REL)
| BIT(EV_MSC);
- aiptek->inputdev.absbit[0] |=
- (BIT(ABS_X) |
- BIT(ABS_Y) |
- BIT(ABS_PRESSURE) |
- BIT(ABS_TILT_X) |
- BIT(ABS_TILT_Y) | BIT(ABS_WHEEL) | BIT(ABS_MISC));
+ inputdev->absbit[0] |= BIT(ABS_MISC);
- aiptek->inputdev.relbit[0] |=
+ inputdev->relbit[0] |=
(BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL) | BIT(REL_MISC));
- aiptek->inputdev.keybit[LONG(BTN_LEFT)] |=
+ inputdev->keybit[LONG(BTN_LEFT)] |=
(BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE));
- aiptek->inputdev.keybit[LONG(BTN_DIGI)] |=
+ inputdev->keybit[LONG(BTN_DIGI)] |=
(BIT(BTN_TOOL_PEN) |
BIT(BTN_TOOL_RUBBER) |
BIT(BTN_TOOL_PENCIL) |
@@ -2070,70 +2088,26 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
BIT(BTN_TOOL_LENS) |
BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2));
- aiptek->inputdev.mscbit[0] = BIT(MSC_SERIAL);
+ inputdev->mscbit[0] = BIT(MSC_SERIAL);
/* Programming the tablet macro keys needs to be done with a for loop
* as the keycodes are discontiguous.
*/
for (i = 0; i < sizeof(macroKeyEvents) / sizeof(macroKeyEvents[0]); ++i)
- set_bit(macroKeyEvents[i], aiptek->inputdev.keybit);
-
- /* Set up client data, pointers to open and close routines
- * for the input device.
- */
- aiptek->inputdev.private = aiptek;
- aiptek->inputdev.open = aiptek_open;
- aiptek->inputdev.close = aiptek_close;
-
- /* Determine the usb devices' physical path.
- * Asketh not why we always pretend we're using "../input0",
- * but I suspect this will have to be refactored one
- * day if a single USB device can be a keyboard & a mouse
- * & a tablet, and the inputX number actually will tell
- * us something...
- */
- if (usb_make_path(usbdev, path, 64) > 0)
- sprintf(aiptek->features.usbPath, "%s/input0", path);
+ set_bit(macroKeyEvents[i], inputdev->keybit);
- /* Program the input device coordinate capacities. We do not yet
+ /*
+ * Program the input device coordinate capacities. We do not yet
* know what maximum X, Y, and Z values are, so we're putting fake
* values in. Later, we'll ask the tablet to put in the correct
* values.
*/
- aiptek->inputdev.absmin[ABS_X] = 0;
- aiptek->inputdev.absmax[ABS_X] = 2999;
- aiptek->inputdev.absmin[ABS_Y] = 0;
- aiptek->inputdev.absmax[ABS_Y] = 2249;
- aiptek->inputdev.absmin[ABS_PRESSURE] = 0;
- aiptek->inputdev.absmax[ABS_PRESSURE] = 511;
- aiptek->inputdev.absmin[ABS_TILT_X] = AIPTEK_TILT_MIN;
- aiptek->inputdev.absmax[ABS_TILT_X] = AIPTEK_TILT_MAX;
- aiptek->inputdev.absmin[ABS_TILT_Y] = AIPTEK_TILT_MIN;
- aiptek->inputdev.absmax[ABS_TILT_Y] = AIPTEK_TILT_MAX;
- aiptek->inputdev.absmin[ABS_WHEEL] = AIPTEK_WHEEL_MIN;
- aiptek->inputdev.absmax[ABS_WHEEL] = AIPTEK_WHEEL_MAX - 1;
- aiptek->inputdev.absfuzz[ABS_X] = 0;
- aiptek->inputdev.absfuzz[ABS_Y] = 0;
- aiptek->inputdev.absfuzz[ABS_PRESSURE] = 0;
- aiptek->inputdev.absfuzz[ABS_TILT_X] = 0;
- aiptek->inputdev.absfuzz[ABS_TILT_Y] = 0;
- aiptek->inputdev.absfuzz[ABS_WHEEL] = 0;
- aiptek->inputdev.absflat[ABS_X] = 0;
- aiptek->inputdev.absflat[ABS_Y] = 0;
- aiptek->inputdev.absflat[ABS_PRESSURE] = 0;
- aiptek->inputdev.absflat[ABS_TILT_X] = 0;
- aiptek->inputdev.absflat[ABS_TILT_Y] = 0;
- aiptek->inputdev.absflat[ABS_WHEEL] = 0;
- aiptek->inputdev.name = "Aiptek";
- aiptek->inputdev.phys = aiptek->features.usbPath;
- usb_to_input_id(usbdev, &aiptek->inputdev.id);
- aiptek->inputdev.dev = &intf->dev;
-
- aiptek->usbdev = usbdev;
- aiptek->ifnum = intf->altsetting[0].desc.bInterfaceNumber;
- aiptek->inDelay = 0;
- aiptek->endDelay = 0;
- aiptek->previousJitterable = 0;
+ input_set_abs_params(inputdev, ABS_X, 0, 2999, 0, 0);
+ input_set_abs_params(inputdev, ABS_X, 0, 2249, 0, 0);
+ input_set_abs_params(inputdev, ABS_PRESSURE, 0, 511, 0, 0);
+ input_set_abs_params(inputdev, ABS_TILT_X, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0);
+ input_set_abs_params(inputdev, ABS_TILT_Y, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0);
+ input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0);
endpoint = &intf->altsetting[0].endpoint[0].desc;
@@ -2150,28 +2124,6 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
aiptek->urb->transfer_dma = aiptek->data_dma;
aiptek->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- /* Register the tablet as an Input Device
- */
- input_register_device(&aiptek->inputdev);
-
- /* We now will look for the evdev device which is mapped to
- * the tablet. The partial name is kept in the link list of
- * input_handles associated with this input device.
- * What identifies an evdev input_handler is that it begins
- * with 'event', continues with a digit, and that in turn
- * is mapped to /{devfs}/input/eventN.
- */
- inputdev = &aiptek->inputdev;
- list_for_each_safe(node, next, &inputdev->h_list) {
- inputhandle = to_handle(node);
- if (strncmp(inputhandle->name, "event", 5) == 0) {
- strcpy(aiptek->features.inputPath, inputhandle->name);
- break;
- }
- }
-
- info("input: Aiptek on %s (%s)\n", path, aiptek->features.inputPath);
-
/* Program the tablet. This sets the tablet up in the mode
* specified in newSetting, and also queries the tablet's
* physical capacities.
@@ -2186,13 +2138,32 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
for (i = 0; i < sizeof(speeds) / sizeof(speeds[0]); ++i) {
aiptek->curSetting.programmableDelay = speeds[i];
(void)aiptek_program_tablet(aiptek);
- if (aiptek->inputdev.absmax[ABS_X] > 0) {
+ if (aiptek->inputdev->absmax[ABS_X] > 0) {
info("input: Aiptek using %d ms programming speed\n",
aiptek->curSetting.programmableDelay);
break;
}
}
+ /* Register the tablet as an Input Device
+ */
+ input_register_device(aiptek->inputdev);
+
+ /* We now will look for the evdev device which is mapped to
+ * the tablet. The partial name is kept in the link list of
+ * input_handles associated with this input device.
+ * What identifies an evdev input_handler is that it begins
+ * with 'event', continues with a digit, and that in turn
+ * is mapped to /{devfs}/input/eventN.
+ */
+ list_for_each_safe(node, next, &inputdev->h_list) {
+ inputhandle = to_handle(node);
+ if (strncmp(inputhandle->name, "event", 5) == 0) {
+ strcpy(aiptek->features.inputPath, inputhandle->name);
+ break;
+ }
+ }
+
/* Associate this driver's struct with the usb interface.
*/
usb_set_intfdata(intf, aiptek);
@@ -2207,6 +2178,12 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
info("aiptek: error loading 'evdev' module");
return 0;
+
+fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
+ aiptek->data_dma);
+fail1: input_free_device(inputdev);
+ kfree(aiptek);
+ return -ENOMEM;
}
/* Forward declaration */
@@ -2234,7 +2211,7 @@ static void aiptek_disconnect(struct usb_interface *intf)
/* Free & unhook everything from the system.
*/
usb_kill_urb(aiptek->urb);
- input_unregister_device(&aiptek->inputdev);
+ input_unregister_device(aiptek->inputdev);
aiptek_delete_files(&intf->dev);
usb_free_urb(aiptek->urb);
usb_buffer_free(interface_to_usbdev(intf),
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
index e03c1c567a1416..15840db092a512 100644
--- a/drivers/usb/input/appletouch.c
+++ b/drivers/usb/input/appletouch.c
@@ -39,7 +39,7 @@
#define APPLE_VENDOR_ID 0x05AC
#define ATP_DEVICE(prod) \
- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
USB_DEVICE_ID_MATCH_INT_CLASS | \
USB_DEVICE_ID_MATCH_INT_PROTOCOL, \
.idVendor = APPLE_VENDOR_ID, \
@@ -78,9 +78,9 @@ MODULE_DEVICE_TABLE (usb, atp_table);
* We try to keep the touchpad aspect ratio while still doing only simple
* arithmetics.
* The factors below give coordinates like:
- * 0 <= x < 960 on 12" and 15" Powerbooks
- * 0 <= x < 1600 on 17" Powerbooks
- * 0 <= y < 646
+ * 0 <= x < 960 on 12" and 15" Powerbooks
+ * 0 <= x < 1600 on 17" Powerbooks
+ * 0 <= y < 646
*/
#define ATP_XFACT 64
#define ATP_YFACT 43
@@ -93,11 +93,12 @@ MODULE_DEVICE_TABLE (usb, atp_table);
/* Structure to hold all of our device specific stuff */
struct atp {
+ char phys[64];
struct usb_device * udev; /* usb device */
struct urb * urb; /* usb request block */
signed char * data; /* transferred data */
int open; /* non-zero if opened */
- struct input_dev input; /* input dev */
+ struct input_dev *input; /* input dev */
int valid; /* are the sensors valid ? */
int x_old; /* last reported x/y, */
int y_old; /* used for smoothing */
@@ -114,11 +115,11 @@ struct atp {
int i; \
printk("appletouch: %s %lld", msg, (long long)jiffies); \
for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) \
- printk(" %02x", tab[i]); \
- printk("\n"); \
+ printk(" %02x", tab[i]); \
+ printk("\n"); \
}
-#define dprintk(format, a...) \
+#define dprintk(format, a...) \
do { \
if (debug) printk(format, ##a); \
} while (0)
@@ -219,8 +220,8 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs)
for (i = 16; i < ATP_XSENSORS; i++)
if (dev->xy_cur[i]) {
printk("appletouch: 17\" model detected.\n");
- input_set_abs_params(&dev->input, ABS_X, 0,
- (ATP_XSENSORS - 1) *
+ input_set_abs_params(dev->input, ABS_X, 0,
+ (ATP_XSENSORS - 1) *
ATP_XFACT - 1,
ATP_FUZZ, 0);
break;
@@ -260,12 +261,12 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs)
"Xz: %3d Yz: %3d\n",
x, y, x_z, y_z);
- input_report_key(&dev->input, BTN_TOUCH, 1);
- input_report_abs(&dev->input, ABS_X, x);
- input_report_abs(&dev->input, ABS_Y, y);
- input_report_abs(&dev->input, ABS_PRESSURE,
+ input_report_key(dev->input, BTN_TOUCH, 1);
+ input_report_abs(dev->input, ABS_X, x);
+ input_report_abs(dev->input, ABS_Y, y);
+ input_report_abs(dev->input, ABS_PRESSURE,
min(ATP_PRESSURE, x_z + y_z));
- atp_report_fingers(&dev->input, max(x_f, y_f));
+ atp_report_fingers(dev->input, max(x_f, y_f));
}
dev->x_old = x;
dev->y_old = y;
@@ -273,17 +274,17 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs)
else if (!x && !y) {
dev->x_old = dev->y_old = -1;
- input_report_key(&dev->input, BTN_TOUCH, 0);
- input_report_abs(&dev->input, ABS_PRESSURE, 0);
- atp_report_fingers(&dev->input, 0);
+ input_report_key(dev->input, BTN_TOUCH, 0);
+ input_report_abs(dev->input, ABS_PRESSURE, 0);
+ atp_report_fingers(dev->input, 0);
/* reset the accumulator on release */
memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
}
- input_report_key(&dev->input, BTN_LEFT, !!dev->data[80]);
+ input_report_key(dev->input, BTN_LEFT, !!dev->data[80]);
- input_sync(&dev->input);
+ input_sync(dev->input);
exit:
retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
@@ -314,21 +315,14 @@ static void atp_close(struct input_dev *input)
static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id)
{
- struct atp *dev = NULL;
+ struct atp *dev;
+ struct input_dev *input_dev;
+ struct usb_device *udev = interface_to_usbdev(iface);
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
int int_in_endpointAddr = 0;
int i, retval = -ENOMEM;
- /* allocate memory for our device state and initialize it */
- dev = kmalloc(sizeof(struct atp), GFP_KERNEL);
- if (dev == NULL) {
- err("Out of memory");
- goto err_kmalloc;
- }
- memset(dev, 0, sizeof(struct atp));
-
- dev->udev = interface_to_usbdev(iface);
/* set up the endpoint information */
/* use only the first interrupt-in endpoint */
@@ -345,70 +339,82 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
}
}
if (!int_in_endpointAddr) {
- retval = -EIO;
err("Could not find int-in endpoint");
- goto err_endpoint;
+ return -EIO;
}
- /* save our data pointer in this interface device */
- usb_set_intfdata(iface, dev);
+ /* allocate memory for our device state and initialize it */
+ dev = kzalloc(sizeof(struct atp), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!dev || !input_dev) {
+ err("Out of memory");
+ goto err_free_devs;
+ }
+
+ dev->udev = udev;
+ dev->input = input_dev;
dev->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->urb) {
retval = -ENOMEM;
- goto err_usballoc;
+ goto err_free_devs;
}
+
dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,
&dev->urb->transfer_dma);
if (!dev->data) {
retval = -ENOMEM;
- goto err_usbbufalloc;
+ goto err_free_urb;
}
- usb_fill_int_urb(dev->urb, dev->udev,
- usb_rcvintpipe(dev->udev, int_in_endpointAddr),
+
+ usb_fill_int_urb(dev->urb, udev,
+ usb_rcvintpipe(udev, int_in_endpointAddr),
dev->data, ATP_DATASIZE, atp_complete, dev, 1);
- init_input_dev(&dev->input);
- dev->input.name = "appletouch";
- dev->input.dev = &iface->dev;
- dev->input.private = dev;
- dev->input.open = atp_open;
- dev->input.close = atp_close;
+ usb_make_path(udev, dev->phys, sizeof(dev->phys));
+ strlcat(dev->phys, "/input0", sizeof(dev->phys));
+
+ input_dev->name = "appletouch";
+ input_dev->phys = dev->phys;
+ usb_to_input_id(dev->udev, &input_dev->id);
+ input_dev->cdev.dev = &iface->dev;
- usb_to_input_id(dev->udev, &dev->input.id);
+ input_dev->private = dev;
+ input_dev->open = atp_open;
+ input_dev->close = atp_close;
- set_bit(EV_ABS, dev->input.evbit);
+ set_bit(EV_ABS, input_dev->evbit);
/*
* 12" and 15" Powerbooks only have 16 x sensors,
* 17" models are detected later.
*/
- input_set_abs_params(&dev->input, ABS_X, 0,
+ input_set_abs_params(input_dev, ABS_X, 0,
(16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
- input_set_abs_params(&dev->input, ABS_Y, 0,
+ input_set_abs_params(input_dev, ABS_Y, 0,
(ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
- input_set_abs_params(&dev->input, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
- set_bit(EV_KEY, dev->input.evbit);
- set_bit(BTN_TOUCH, dev->input.keybit);
- set_bit(BTN_TOOL_FINGER, dev->input.keybit);
- set_bit(BTN_TOOL_DOUBLETAP, dev->input.keybit);
- set_bit(BTN_TOOL_TRIPLETAP, dev->input.keybit);
- set_bit(BTN_LEFT, dev->input.keybit);
+ set_bit(EV_KEY, input_dev->evbit);
+ set_bit(BTN_TOUCH, input_dev->keybit);
+ set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+ set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
+ set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
+ set_bit(BTN_LEFT, input_dev->keybit);
- input_register_device(&dev->input);
+ input_register_device(dev->input);
- printk(KERN_INFO "input: appletouch connected\n");
+ /* save our data pointer in this interface device */
+ usb_set_intfdata(iface, dev);
return 0;
-err_usbbufalloc:
+ err_free_urb:
usb_free_urb(dev->urb);
-err_usballoc:
+ err_free_devs:
usb_set_intfdata(iface, NULL);
-err_endpoint:
kfree(dev);
-err_kmalloc:
+ input_free_device(input_dev);
return retval;
}
@@ -419,7 +425,7 @@ static void atp_disconnect(struct usb_interface *iface)
usb_set_intfdata(iface, NULL);
if (dev) {
usb_kill_urb(dev->urb);
- input_unregister_device(&dev->input);
+ input_unregister_device(dev->input);
usb_free_urb(dev->urb);
usb_buffer_free(dev->udev, ATP_DATASIZE,
dev->data, dev->urb->transfer_dma);
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index fd99681ee48355..9a2a47db9494d6 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -112,7 +112,6 @@
#define NAME_BUFSIZE 80 /* size of product name, path buffers */
#define DATA_BUFSIZE 63 /* size of URB data buffers */
-#define ATI_INPUTNUM 1 /* Which input device to register as */
static unsigned long channel_mask;
module_param(channel_mask, ulong, 0444);
@@ -162,7 +161,7 @@ static char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
static DECLARE_MUTEX(disconnect_sem);
struct ati_remote {
- struct input_dev idev;
+ struct input_dev *idev;
struct usb_device *udev;
struct usb_interface *interface;
@@ -198,15 +197,13 @@ struct ati_remote {
#define KIND_ACCEL 7 /* Directional keypad - left, right, up, down.*/
/* Translation table from hardware messages to input events. */
-static struct
-{
+static struct {
short kind;
unsigned char data1, data2;
int type;
unsigned int code;
int value;
-} ati_remote_tbl[] =
-{
+} ati_remote_tbl[] = {
/* Directional control pad axes */
{KIND_ACCEL, 0x35, 0x70, EV_REL, REL_X, -1}, /* left */
{KIND_ACCEL, 0x36, 0x71, EV_REL, REL_X, 1}, /* right */
@@ -286,7 +283,6 @@ static struct
/* Local function prototypes */
static void ati_remote_dump (unsigned char *data, unsigned int actual_length);
-static void ati_remote_delete (struct ati_remote *dev);
static int ati_remote_open (struct input_dev *inputdev);
static void ati_remote_close (struct input_dev *inputdev);
static int ati_remote_sendpacket (struct ati_remote *ati_remote, u16 cmd, unsigned char *data);
@@ -428,7 +424,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs)
{
struct ati_remote *ati_remote = urb->context;
unsigned char *data= ati_remote->inbuf;
- struct input_dev *dev = &ati_remote->idev;
+ struct input_dev *dev = ati_remote->idev;
int index, acc;
int remote_num;
@@ -587,38 +583,55 @@ static void ati_remote_irq_in(struct urb *urb, struct pt_regs *regs)
}
/*
- * ati_remote_delete
+ * ati_remote_alloc_buffers
*/
-static void ati_remote_delete(struct ati_remote *ati_remote)
+static int ati_remote_alloc_buffers(struct usb_device *udev,
+ struct ati_remote *ati_remote)
{
- if (ati_remote->irq_urb)
- usb_kill_urb(ati_remote->irq_urb);
+ ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
+ &ati_remote->inbuf_dma);
+ if (!ati_remote->inbuf)
+ return -1;
- if (ati_remote->out_urb)
- usb_kill_urb(ati_remote->out_urb);
+ ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
+ &ati_remote->outbuf_dma);
+ if (!ati_remote->outbuf)
+ return -1;
- input_unregister_device(&ati_remote->idev);
+ ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!ati_remote->irq_urb)
+ return -1;
- if (ati_remote->inbuf)
- usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
- ati_remote->inbuf, ati_remote->inbuf_dma);
+ ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!ati_remote->out_urb)
+ return -1;
- if (ati_remote->outbuf)
- usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
- ati_remote->outbuf, ati_remote->outbuf_dma);
+ return 0;
+}
+/*
+ * ati_remote_free_buffers
+ */
+static void ati_remote_free_buffers(struct ati_remote *ati_remote)
+{
if (ati_remote->irq_urb)
usb_free_urb(ati_remote->irq_urb);
if (ati_remote->out_urb)
usb_free_urb(ati_remote->out_urb);
- kfree(ati_remote);
+ if (ati_remote->inbuf)
+ usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
+ ati_remote->inbuf, ati_remote->inbuf_dma);
+
+ if (ati_remote->outbuf)
+ usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
+ ati_remote->inbuf, ati_remote->outbuf_dma);
}
static void ati_remote_input_init(struct ati_remote *ati_remote)
{
- struct input_dev *idev = &(ati_remote->idev);
+ struct input_dev *idev = ati_remote->idev;
int i;
idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
@@ -637,7 +650,7 @@ static void ati_remote_input_init(struct ati_remote *ati_remote)
idev->phys = ati_remote->phys;
usb_to_input_id(ati_remote->udev, &idev->id);
- idev->dev = &ati_remote->udev->dev;
+ idev->cdev.dev = &ati_remote->udev->dev;
}
static int ati_remote_initialize(struct ati_remote *ati_remote)
@@ -674,7 +687,7 @@ static int ati_remote_initialize(struct ati_remote *ati_remote)
(ati_remote_sendpacket(ati_remote, 0x8007, init2))) {
dev_err(&ati_remote->interface->dev,
"Initializing ati_remote hardware failed.\n");
- return 1;
+ return -EIO;
}
return 0;
@@ -686,95 +699,83 @@ static int ati_remote_initialize(struct ati_remote *ati_remote)
static int ati_remote_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(interface);
- struct ati_remote *ati_remote = NULL;
- struct usb_host_interface *iface_host;
- int retval = -ENOMEM;
- char path[64];
-
- /* Allocate and clear an ati_remote struct */
- if (!(ati_remote = kmalloc(sizeof (struct ati_remote), GFP_KERNEL)))
- return -ENOMEM;
- memset(ati_remote, 0x00, sizeof (struct ati_remote));
+ struct usb_host_interface *iface_host = interface->cur_altsetting;
+ struct usb_endpoint_descriptor *endpoint_in, *endpoint_out;
+ struct ati_remote *ati_remote;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
- iface_host = interface->cur_altsetting;
if (iface_host->desc.bNumEndpoints != 2) {
err("%s: Unexpected desc.bNumEndpoints\n", __FUNCTION__);
- retval = -ENODEV;
- goto error;
+ return -ENODEV;
}
- ati_remote->endpoint_in = &(iface_host->endpoint[0].desc);
- ati_remote->endpoint_out = &(iface_host->endpoint[1].desc);
- ati_remote->udev = udev;
- ati_remote->interface = interface;
+ endpoint_in = &iface_host->endpoint[0].desc;
+ endpoint_out = &iface_host->endpoint[1].desc;
- if (!(ati_remote->endpoint_in->bEndpointAddress & 0x80)) {
+ if (!(endpoint_in->bEndpointAddress & USB_DIR_IN)) {
err("%s: Unexpected endpoint_in->bEndpointAddress\n", __FUNCTION__);
- retval = -ENODEV;
- goto error;
+ return -ENODEV;
}
- if ((ati_remote->endpoint_in->bmAttributes & 3) != 3) {
+ if ((endpoint_in->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) {
err("%s: Unexpected endpoint_in->bmAttributes\n", __FUNCTION__);
- retval = -ENODEV;
- goto error;
+ return -ENODEV;
}
- if (le16_to_cpu(ati_remote->endpoint_in->wMaxPacketSize) == 0) {
+ if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) {
err("%s: endpoint_in message size==0? \n", __FUNCTION__);
- retval = -ENODEV;
- goto error;
+ return -ENODEV;
}
- /* Allocate URB buffers, URBs */
- ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
- &ati_remote->inbuf_dma);
- if (!ati_remote->inbuf)
- goto error;
+ ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ati_remote || !input_dev)
+ goto fail1;
- ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
- &ati_remote->outbuf_dma);
- if (!ati_remote->outbuf)
- goto error;
+ /* Allocate URB buffers, URBs */
+ if (ati_remote_alloc_buffers(udev, ati_remote))
+ goto fail2;
- ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!ati_remote->irq_urb)
- goto error;
+ ati_remote->endpoint_in = endpoint_in;
+ ati_remote->endpoint_out = endpoint_out;
+ ati_remote->udev = udev;
+ ati_remote->idev = input_dev;
+ ati_remote->interface = interface;
- ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!ati_remote->out_urb)
- goto error;
+ usb_make_path(udev, ati_remote->phys, sizeof(ati_remote->phys));
+ strlcpy(ati_remote->phys, "/input0", sizeof(ati_remote->phys));
- usb_make_path(udev, path, NAME_BUFSIZE);
- sprintf(ati_remote->phys, "%s/input%d", path, ATI_INPUTNUM);
if (udev->manufacturer)
- strcat(ati_remote->name, udev->manufacturer);
+ strlcpy(ati_remote->name, udev->manufacturer, sizeof(ati_remote->name));
if (udev->product)
- sprintf(ati_remote->name, "%s %s", ati_remote->name, udev->product);
+ snprintf(ati_remote->name, sizeof(ati_remote->name),
+ "%s %s", ati_remote->name, udev->product);
if (!strlen(ati_remote->name))
- sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)",
+ snprintf(ati_remote->name, sizeof(ati_remote->name),
+ DRIVER_DESC "(%04x,%04x)",
le16_to_cpu(ati_remote->udev->descriptor.idVendor),
le16_to_cpu(ati_remote->udev->descriptor.idProduct));
+ ati_remote_input_init(ati_remote);
+
/* Device Hardware Initialization - fills in ati_remote->idev from udev. */
- retval = ati_remote_initialize(ati_remote);
- if (retval)
- goto error;
+ err = ati_remote_initialize(ati_remote);
+ if (err)
+ goto fail3;
/* Set up and register input device */
- ati_remote_input_init(ati_remote);
- input_register_device(&ati_remote->idev);
-
- dev_info(&ati_remote->interface->dev, "Input registered: %s on %s\n",
- ati_remote->name, path);
+ input_register_device(ati_remote->idev);
usb_set_intfdata(interface, ati_remote);
+ return 0;
-error:
- if (retval)
- ati_remote_delete(ati_remote);
-
- return retval;
+fail3: usb_kill_urb(ati_remote->irq_urb);
+ usb_kill_urb(ati_remote->out_urb);
+fail2: ati_remote_free_buffers(ati_remote);
+fail1: input_free_device(input_dev);
+ kfree(ati_remote);
+ return err;
}
/*
@@ -791,7 +792,11 @@ static void ati_remote_disconnect(struct usb_interface *interface)
return;
}
- ati_remote_delete(ati_remote);
+ usb_kill_urb(ati_remote->irq_urb);
+ usb_kill_urb(ati_remote->out_urb);
+ input_unregister_device(ati_remote->idev);
+ ati_remote_free_buffers(ati_remote);
+ kfree(ati_remote);
}
/*
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 41f92b924761a7..411a0645a7a3cd 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1619,8 +1619,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
struct hid_descriptor *hdesc;
struct hid_device *hid;
unsigned quirks = 0, rsize = 0;
- char *buf, *rdesc;
- int n, insize = 0;
+ char *rdesc;
+ int n, len, insize = 0;
for (n = 0; hid_blacklist[n].idVendor; n++)
if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) &&
@@ -1630,10 +1630,11 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if (quirks & HID_QUIRK_IGNORE)
return NULL;
- if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && ((!interface->desc.bNumEndpoints) ||
- usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
- dbg("class descriptor not present\n");
- return NULL;
+ if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
+ (!interface->desc.bNumEndpoints ||
+ usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
+ dbg("class descriptor not present\n");
+ return NULL;
}
for (n = 0; n < hdesc->bNumDescriptors; n++)
@@ -1749,32 +1750,34 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
hid->name[0] = 0;
- if (!(buf = kmalloc(64, GFP_KERNEL)))
- goto fail;
+ if (dev->manufacturer)
+ strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
+
+ if (dev->product) {
+ if (dev->manufacturer)
+ strlcat(hid->name, " ", sizeof(hid->name));
+ strlcat(hid->name, dev->product, sizeof(hid->name));
+ }
+
+ if (!strlen(hid->name))
+ snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
- if (dev->manufacturer) {
- strcat(hid->name, dev->manufacturer);
- if (dev->product)
- snprintf(hid->name, 64, "%s %s", hid->name, dev->product);
- } else if (dev->product) {
- snprintf(hid->name, 128, "%s", dev->product);
- } else
- snprintf(hid->name, 128, "%04x:%04x",
- le16_to_cpu(dev->descriptor.idVendor),
- le16_to_cpu(dev->descriptor.idProduct));
-
- usb_make_path(dev, buf, 64);
- snprintf(hid->phys, 64, "%s/input%d", buf,
- intf->altsetting[0].desc.bInterfaceNumber);
+ usb_make_path(dev, hid->phys, sizeof(hid->phys));
+ strlcat(hid->phys, "/input", sizeof(hid->phys));
+ len = strlen(hid->phys);
+ if (len < sizeof(hid->phys) - 1)
+ snprintf(hid->phys + len, sizeof(hid->phys) - len,
+ "%d", intf->altsetting[0].desc.bInterfaceNumber);
if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
hid->uniq[0] = 0;
- kfree(buf);
-
hid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
if (!hid->urbctrl)
goto fail;
+
usb_fill_control_urb(hid->urbctrl, dev, 0, (void *) hid->cr,
hid->ctrlbuf, 1, hid_ctrl, hid);
hid->urbctrl->setup_dma = hid->cr_dma;
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index 0b6452248a398a..9ff25eb520a6dc 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -76,8 +76,8 @@ static struct {
static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
struct hid_usage *usage)
{
- struct input_dev *input = &hidinput->input;
- struct hid_device *device = hidinput->input.private;
+ struct input_dev *input = hidinput->input;
+ struct hid_device *device = input->private;
int max = 0, code;
unsigned long *bit = NULL;
@@ -461,7 +461,8 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
if (!field->hidinput)
return;
- input = &field->hidinput->input;
+
+ input = field->hidinput->input;
input_regs(input, regs);
@@ -533,13 +534,10 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
void hidinput_report_event(struct hid_device *hid, struct hid_report *report)
{
- struct list_head *lh;
struct hid_input *hidinput;
- list_for_each (lh, &hid->inputs) {
- hidinput = list_entry(lh, struct hid_input, list);
- input_sync(&hidinput->input);
- }
+ list_for_each_entry(hidinput, &hid->inputs, list)
+ input_sync(hidinput->input);
}
static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
@@ -604,6 +602,7 @@ int hidinput_connect(struct hid_device *hid)
struct usb_device *dev = hid->dev;
struct hid_report *report;
struct hid_input *hidinput = NULL;
+ struct input_dev *input_dev;
int i, j, k;
INIT_LIST_HEAD(&hid->inputs);
@@ -624,25 +623,28 @@ int hidinput_connect(struct hid_device *hid)
continue;
if (!hidinput) {
- hidinput = kmalloc(sizeof(*hidinput), GFP_KERNEL);
- if (!hidinput) {
+ hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!hidinput || !input_dev) {
+ kfree(hidinput);
+ input_free_device(input_dev);
err("Out of memory during hid input probe");
return -1;
}
- memset(hidinput, 0, sizeof(*hidinput));
- list_add_tail(&hidinput->list, &hid->inputs);
+ input_dev->private = hid;
+ input_dev->event = hidinput_input_event;
+ input_dev->open = hidinput_open;
+ input_dev->close = hidinput_close;
- hidinput->input.private = hid;
- hidinput->input.event = hidinput_input_event;
- hidinput->input.open = hidinput_open;
- hidinput->input.close = hidinput_close;
+ input_dev->name = hid->name;
+ input_dev->phys = hid->phys;
+ input_dev->uniq = hid->uniq;
+ usb_to_input_id(dev, &input_dev->id);
+ input_dev->cdev.dev = &hid->intf->dev;
- hidinput->input.name = hid->name;
- hidinput->input.phys = hid->phys;
- hidinput->input.uniq = hid->uniq;
- usb_to_input_id(dev, &hidinput->input.id);
- hidinput->input.dev = &hid->intf->dev;
+ hidinput->input = input_dev;
+ list_add_tail(&hidinput->list, &hid->inputs);
}
for (i = 0; i < report->maxfield; i++)
@@ -657,7 +659,7 @@ int hidinput_connect(struct hid_device *hid)
* UGCI) cram a lot of unrelated inputs into the
* same interface. */
hidinput->report = report;
- input_register_device(&hidinput->input);
+ input_register_device(hidinput->input);
hidinput = NULL;
}
}
@@ -667,7 +669,7 @@ int hidinput_connect(struct hid_device *hid)
* only useful in this case, and not for multi-input quirks. */
if (hidinput) {
hid_ff_init(hid);
- input_register_device(&hidinput->input);
+ input_register_device(hidinput->input);
}
return 0;
@@ -675,13 +677,11 @@ int hidinput_connect(struct hid_device *hid)
void hidinput_disconnect(struct hid_device *hid)
{
- struct list_head *lh, *next;
- struct hid_input *hidinput;
+ struct hid_input *hidinput, *next;
- list_for_each_safe(lh, next, &hid->inputs) {
- hidinput = list_entry(lh, struct hid_input, list);
- input_unregister_device(&hidinput->input);
+ list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
list_del(&hidinput->list);
+ input_unregister_device(hidinput->input);
kfree(hidinput);
}
}
diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c
index 0c4c77aa31eac7..f82c9c9e5d519a 100644
--- a/drivers/usb/input/hid-lgff.c
+++ b/drivers/usb/input/hid-lgff.c
@@ -255,22 +255,19 @@ static void hid_lgff_input_init(struct hid_device* hid)
u16 idVendor = le16_to_cpu(hid->dev->descriptor.idVendor);
u16 idProduct = le16_to_cpu(hid->dev->descriptor.idProduct);
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+ struct input_dev *input_dev = hidinput->input;
while (dev->idVendor && (idVendor != dev->idVendor || idProduct != dev->idProduct))
dev++;
- ff = dev->ff;
+ for (ff = dev->ff; *ff >= 0; ff++)
+ set_bit(*ff, input_dev->ffbit);
- while (*ff >= 0) {
- set_bit(*ff, hidinput->input.ffbit);
- ++ff;
- }
-
- hidinput->input.upload_effect = hid_lgff_upload_effect;
- hidinput->input.flush = hid_lgff_flush;
+ input_dev->upload_effect = hid_lgff_upload_effect;
+ input_dev->flush = hid_lgff_flush;
- set_bit(EV_FF, hidinput->input.evbit);
- hidinput->input.ff_effects_max = LGFF_EFFECTS;
+ set_bit(EV_FF, input_dev->evbit);
+ input_dev->ff_effects_max = LGFF_EFFECTS;
}
static void hid_lgff_exit(struct hid_device* hid)
diff --git a/drivers/usb/input/hid-tmff.c b/drivers/usb/input/hid-tmff.c
index 8f6a0a6f94a9bd..023fd5ac31c8ec 100644
--- a/drivers/usb/input/hid-tmff.c
+++ b/drivers/usb/input/hid-tmff.c
@@ -111,6 +111,7 @@ int hid_tmff_init(struct hid_device *hid)
struct tmff_device *private;
struct list_head *pos;
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+ struct input_dev *input_dev = hidinput->input;
private = kmalloc(sizeof(struct tmff_device), GFP_KERNEL);
if (!private)
@@ -155,7 +156,7 @@ int hid_tmff_init(struct hid_device *hid)
private->report = report;
private->rumble = field;
- set_bit(FF_RUMBLE, hidinput->input.ffbit);
+ set_bit(FF_RUMBLE, input_dev->ffbit);
break;
default:
@@ -164,11 +165,11 @@ int hid_tmff_init(struct hid_device *hid)
}
/* Fallthrough to here only when a valid usage is found */
- hidinput->input.upload_effect = hid_tmff_upload_effect;
- hidinput->input.flush = hid_tmff_flush;
+ input_dev->upload_effect = hid_tmff_upload_effect;
+ input_dev->flush = hid_tmff_flush;
- set_bit(EV_FF, hidinput->input.evbit);
- hidinput->input.ff_effects_max = TMFF_EFFECTS;
+ set_bit(EV_FF, input_dev->evbit);
+ input_dev->ff_effects_max = TMFF_EFFECTS;
}
}
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
index ec2412c42f1ea8..ee48a227610420 100644
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -371,7 +371,7 @@ struct hid_control_fifo {
struct hid_input {
struct list_head list;
struct hid_report *report;
- struct input_dev input;
+ struct input_dev *input;
};
struct hid_device { /* device report descriptor */
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c
index becb87efb869f6..3b581853cf101d 100644
--- a/drivers/usb/input/itmtouch.c
+++ b/drivers/usb/input/itmtouch.c
@@ -73,7 +73,7 @@ MODULE_LICENSE( DRIVER_LICENSE );
struct itmtouch_dev {
struct usb_device *usbdev; /* usb device */
- struct input_dev inputdev; /* input device */
+ struct input_dev *inputdev; /* input device */
struct urb *readurb; /* urb */
char rbuf[ITM_BUFSIZE]; /* data */
int users;
@@ -88,9 +88,9 @@ static struct usb_device_id itmtouch_ids [] = {
static void itmtouch_irq(struct urb *urb, struct pt_regs *regs)
{
- struct itmtouch_dev * itmtouch = urb->context;
+ struct itmtouch_dev *itmtouch = urb->context;
unsigned char *data = urb->transfer_buffer;
- struct input_dev *dev = &itmtouch->inputdev;
+ struct input_dev *dev = itmtouch->inputdev;
int retval;
switch (urb->status) {
@@ -156,49 +156,62 @@ static void itmtouch_close(struct input_dev *input)
static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct itmtouch_dev *itmtouch;
+ struct input_dev *input_dev;
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct usb_device *udev = interface_to_usbdev(intf);
unsigned int pipe;
unsigned int maxp;
- char path[PATH_SIZE];
interface = intf->cur_altsetting;
endpoint = &interface->endpoint[0].desc;
- if (!(itmtouch = kzalloc(sizeof(struct itmtouch_dev), GFP_KERNEL))) {
+ itmtouch = kzalloc(sizeof(struct itmtouch_dev), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!itmtouch || !input_dev) {
err("%s - Out of memory.", __FUNCTION__);
- return -ENOMEM;
+ goto fail;
}
itmtouch->usbdev = udev;
+ itmtouch->inputdev = input_dev;
- itmtouch->inputdev.private = itmtouch;
- itmtouch->inputdev.open = itmtouch_open;
- itmtouch->inputdev.close = itmtouch_close;
+ if (udev->manufacturer)
+ strlcpy(itmtouch->name, udev->manufacturer, sizeof(itmtouch->name));
- usb_make_path(udev, path, PATH_SIZE);
-
- itmtouch->inputdev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- itmtouch->inputdev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
- itmtouch->inputdev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-
- itmtouch->inputdev.name = itmtouch->name;
- itmtouch->inputdev.phys = itmtouch->phys;
- usb_to_input_id(udev, &itmtouch->inputdev.id);
- itmtouch->inputdev.dev = &intf->dev;
+ if (udev->product) {
+ if (udev->manufacturer)
+ strlcat(itmtouch->name, " ", sizeof(itmtouch->name));
+ strlcat(itmtouch->name, udev->product, sizeof(itmtouch->name));
+ }
if (!strlen(itmtouch->name))
sprintf(itmtouch->name, "USB ITM touchscreen");
+ usb_make_path(udev, itmtouch->phys, sizeof(itmtouch->phys));
+ strlcpy(itmtouch->phys, "/input0", sizeof(itmtouch->phys));
+
+ input_dev->name = itmtouch->name;
+ input_dev->phys = itmtouch->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
+ input_dev->private = itmtouch;
+
+ input_dev->open = itmtouch_open;
+ input_dev->close = itmtouch_close;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+
/* device limits */
/* as specified by the ITM datasheet, X and Y are 12bit,
* Z (pressure) is 8 bit. However, the fields are defined up
* to 14 bits for future possible expansion.
*/
- input_set_abs_params(&itmtouch->inputdev, ABS_X, 0, 0x0FFF, 2, 0);
- input_set_abs_params(&itmtouch->inputdev, ABS_Y, 0, 0x0FFF, 2, 0);
- input_set_abs_params(&itmtouch->inputdev, ABS_PRESSURE, 0, 0xFF, 2, 0);
+ input_set_abs_params(input_dev, ABS_X, 0, 0x0FFF, 2, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, 0x0FFF, 2, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xFF, 2, 0);
/* initialise the URB so we can read from the transport stream */
pipe = usb_rcvintpipe(itmtouch->usbdev, endpoint->bEndpointAddress);
@@ -208,22 +221,23 @@ static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id
maxp = ITM_BUFSIZE;
itmtouch->readurb = usb_alloc_urb(0, GFP_KERNEL);
-
if (!itmtouch->readurb) {
dbg("%s - usb_alloc_urb failed: itmtouch->readurb", __FUNCTION__);
- kfree(itmtouch);
- return -ENOMEM;
+ goto fail;
}
usb_fill_int_urb(itmtouch->readurb, itmtouch->usbdev, pipe, itmtouch->rbuf,
maxp, itmtouch_irq, itmtouch, endpoint->bInterval);
- input_register_device(&itmtouch->inputdev);
+ input_register_device(itmtouch->inputdev);
- printk(KERN_INFO "itmtouch: %s registered on %s\n", itmtouch->name, path);
usb_set_intfdata(intf, itmtouch);
return 0;
+
+ fail: input_free_device(input_dev);
+ kfree(itmtouch);
+ return -ENOMEM;
}
static void itmtouch_disconnect(struct usb_interface *intf)
@@ -233,7 +247,7 @@ static void itmtouch_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (itmtouch) {
- input_unregister_device(&itmtouch->inputdev);
+ input_unregister_device(itmtouch->inputdev);
usb_kill_urb(itmtouch->readurb);
usb_free_urb(itmtouch->readurb);
kfree(itmtouch);
diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c
index b6f6ac8d9c2f0a..a248664b5d1d01 100644
--- a/drivers/usb/input/kbtab.c
+++ b/drivers/usb/input/kbtab.c
@@ -34,7 +34,7 @@ MODULE_PARM_DESC(kb_pressure_click, "pressure threshold for clicks");
struct kbtab {
signed char *data;
dma_addr_t data_dma;
- struct input_dev dev;
+ struct input_dev *dev;
struct usb_device *usbdev;
struct urb *irq;
int x, y;
@@ -48,7 +48,7 @@ static void kbtab_irq(struct urb *urb, struct pt_regs *regs)
{
struct kbtab *kbtab = urb->context;
unsigned char *data = kbtab->data;
- struct input_dev *dev = &kbtab->dev;
+ struct input_dev *dev = kbtab->dev;
int retval;
switch (urb->status) {
@@ -124,53 +124,43 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_endpoint_descriptor *endpoint;
struct kbtab *kbtab;
- char path[64];
+ struct input_dev *input_dev;
- if (!(kbtab = kmalloc(sizeof(struct kbtab), GFP_KERNEL)))
- return -ENOMEM;
- memset(kbtab, 0, sizeof(struct kbtab));
+ kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!kbtab || !input_dev)
+ goto fail1;
kbtab->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &kbtab->data_dma);
- if (!kbtab->data) {
- kfree(kbtab);
- return -ENOMEM;
- }
+ if (!kbtab->data)
+ goto fail1;
kbtab->irq = usb_alloc_urb(0, GFP_KERNEL);
- if (!kbtab->irq) {
- usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma);
- kfree(kbtab);
- return -ENOMEM;
- }
-
- kbtab->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC);
- kbtab->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
-
- kbtab->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
-
- kbtab->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH);
+ if (!kbtab->irq)
+ goto fail2;
- kbtab->dev.mscbit[0] |= BIT(MSC_SERIAL);
-
- kbtab->dev.absmax[ABS_X] = 0x2000;
- kbtab->dev.absmax[ABS_Y] = 0x1750;
- kbtab->dev.absmax[ABS_PRESSURE] = 0xff;
+ kbtab->usbdev = dev;
+ kbtab->dev = input_dev;
- kbtab->dev.absfuzz[ABS_X] = 4;
- kbtab->dev.absfuzz[ABS_Y] = 4;
+ usb_make_path(dev, kbtab->phys, sizeof(kbtab->phys));
+ strlcat(kbtab->phys, "/input0", sizeof(kbtab->phys));
- kbtab->dev.private = kbtab;
- kbtab->dev.open = kbtab_open;
- kbtab->dev.close = kbtab_close;
+ input_dev->name = "KB Gear Tablet";
+ input_dev->phys = kbtab->phys;
+ usb_to_input_id(dev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
+ input_dev->private = kbtab;
- usb_make_path(dev, path, 64);
- sprintf(kbtab->phys, "%s/input0", path);
+ input_dev->open = kbtab_open;
+ input_dev->close = kbtab_close;
- kbtab->dev.name = "KB Gear Tablet";
- kbtab->dev.phys = kbtab->phys;
- usb_to_input_id(dev, &kbtab->dev.id);
- kbtab->dev.dev = &intf->dev;
- kbtab->usbdev = dev;
+ input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC);
+ input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+ input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH);
+ input_dev->mscbit[0] |= BIT(MSC_SERIAL);
+ input_set_abs_params(input_dev, ABS_X, 0, 0x2000, 4, 0);
+ input_set_abs_params(input_dev, ABS_X, 0, 0x1750, 4, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xff, 0, 0);
endpoint = &intf->cur_altsetting->endpoint[0].desc;
@@ -181,23 +171,25 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
kbtab->irq->transfer_dma = kbtab->data_dma;
kbtab->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- input_register_device(&kbtab->dev);
-
- printk(KERN_INFO "input: KB Gear Tablet on %s\n", path);
+ input_register_device(kbtab->dev);
usb_set_intfdata(intf, kbtab);
-
return 0;
+
+fail2: usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma);
+fail1: input_free_device(input_dev);
+ kfree(kbtab);
+ return -ENOMEM;
}
static void kbtab_disconnect(struct usb_interface *intf)
{
- struct kbtab *kbtab = usb_get_intfdata (intf);
+ struct kbtab *kbtab = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
if (kbtab) {
usb_kill_urb(kbtab->irq);
- input_unregister_device(&kbtab->dev);
+ input_unregister_device(kbtab->dev);
usb_free_urb(kbtab->irq);
usb_buffer_free(interface_to_usbdev(intf), 10, kbtab->data, kbtab->data_dma);
kfree(kbtab);
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c
index 99de1b33c07df3..5b8d65f62abf20 100644
--- a/drivers/usb/input/keyspan_remote.c
+++ b/drivers/usb/input/keyspan_remote.c
@@ -20,6 +20,7 @@
#include <linux/moduleparam.h>
#include <linux/input.h>
#include <linux/usb.h>
+#include <linux/usb_input.h>
#define DRIVER_VERSION "v0.1"
#define DRIVER_AUTHOR "Michael Downey <downey@zymeta.com>"
@@ -75,7 +76,7 @@ struct usb_keyspan {
char name[128];
char phys[64];
struct usb_device* udev;
- struct input_dev input;
+ struct input_dev *input;
struct usb_interface* interface;
struct usb_endpoint_descriptor* in_endpoint;
struct urb* irq_urb;
@@ -136,12 +137,11 @@ static struct usb_driver keyspan_driver;
*/
static void keyspan_print(struct usb_keyspan* dev) /*unsigned char* data)*/
{
- char codes[4*RECV_SIZE];
+ char codes[4 * RECV_SIZE];
int i;
- for (i = 0; i < RECV_SIZE; i++) {
- snprintf(codes+i*3, 4, "%02x ", dev->in_buffer[i]);
- }
+ for (i = 0; i < RECV_SIZE; i++)
+ snprintf(codes + i * 3, 4, "%02x ", dev->in_buffer[i]);
dev_info(&dev->udev->dev, "%s\n", codes);
}
@@ -153,7 +153,7 @@ static void keyspan_print(struct usb_keyspan* dev) /*unsigned char* data)*/
static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed)
{
if (dev->data.bits_left >= bits_needed)
- return(0);
+ return 0;
/*
* Somehow we've missed the last message. The message will be repeated
@@ -162,7 +162,7 @@ static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed)
if (dev->data.pos >= dev->data.len) {
dev_dbg(&dev->udev, "%s - Error ran out of data. pos: %d, len: %d\n",
__FUNCTION__, dev->data.pos, dev->data.len);
- return(-1);
+ return -1;
}
/* Load as much as we can into the tester. */
@@ -172,7 +172,7 @@ static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed)
dev->data.bits_left += 8;
}
- return(0);
+ return 0;
}
/*
@@ -311,10 +311,10 @@ static void keyspan_check_data(struct usb_keyspan *remote, struct pt_regs *regs)
__FUNCTION__, message.system, message.button, message.toggle);
if (message.toggle != remote->toggle) {
- input_regs(&remote->input, regs);
- input_report_key(&remote->input, keyspan_key_table[message.button], 1);
- input_report_key(&remote->input, keyspan_key_table[message.button], 0);
- input_sync(&remote->input);
+ input_regs(remote->input, regs);
+ input_report_key(remote->input, keyspan_key_table[message.button], 1);
+ input_report_key(remote->input, keyspan_key_table[message.button], 0);
+ input_sync(remote->input);
remote->toggle = message.toggle;
}
@@ -397,14 +397,9 @@ static int keyspan_open(struct input_dev *dev)
{
struct usb_keyspan *remote = dev->private;
- if (remote->open++)
- return 0;
-
remote->irq_urb->dev = remote->udev;
- if (usb_submit_urb(remote->irq_urb, GFP_KERNEL)) {
- remote->open--;
+ if (usb_submit_urb(remote->irq_urb, GFP_KERNEL))
return -EIO;
- }
return 0;
}
@@ -413,8 +408,26 @@ static void keyspan_close(struct input_dev *dev)
{
struct usb_keyspan *remote = dev->private;
- if (!--remote->open)
- usb_kill_urb(remote->irq_urb);
+ usb_kill_urb(remote->irq_urb);
+}
+
+static struct usb_endpoint_descriptor *keyspan_get_in_endpoint(struct usb_host_interface *iface)
+{
+
+ struct usb_endpoint_descriptor *endpoint;
+ int i;
+
+ for (i = 0; i < iface->desc.bNumEndpoints; ++i) {
+ endpoint = &iface->endpoint[i].desc;
+
+ if ((endpoint->bEndpointAddress & USB_DIR_IN) &&
+ ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+ /* we found our interrupt in endpoint */
+ return endpoint;
+ }
+ }
+
+ return NULL;
}
/*
@@ -422,110 +435,78 @@ static void keyspan_close(struct input_dev *dev)
*/
static int keyspan_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
- int i;
- int retval = -ENOMEM;
- char path[64];
- char *buf;
- struct usb_keyspan *remote = NULL;
- struct usb_host_interface *iface_desc;
+ struct usb_device *udev = interface_to_usbdev(interface);
struct usb_endpoint_descriptor *endpoint;
- struct usb_device *udev = usb_get_dev(interface_to_usbdev(interface));
+ struct usb_keyspan *remote;
+ struct input_dev *input_dev;
+ int i, retval;
- /* allocate memory for our device state and initialize it */
- remote = kmalloc(sizeof(*remote), GFP_KERNEL);
- if (remote == NULL) {
- err("Out of memory\n");
- goto error;
+ endpoint = keyspan_get_in_endpoint(interface->cur_altsetting);
+ if (!endpoint)
+ return -ENODEV;
+
+ remote = kzalloc(sizeof(*remote), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!remote || !input_dev) {
+ retval = -ENOMEM;
+ goto fail1;
}
- memset(remote, 0x00, sizeof(*remote));
remote->udev = udev;
+ remote->input = input_dev;
remote->interface = interface;
+ remote->in_endpoint = endpoint;
remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */
- /* set up the endpoint information */
- /* use only the first in interrupt endpoint */
- iface_desc = interface->cur_altsetting;
- for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
- endpoint = &iface_desc->endpoint[i].desc;
-
- if (!remote->in_endpoint &&
- (endpoint->bEndpointAddress & USB_DIR_IN) &&
- ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
- /* we found our interrupt in endpoint */
- remote->in_endpoint = endpoint;
-
- remote->in_buffer = usb_buffer_alloc(remote->udev, RECV_SIZE, SLAB_ATOMIC, &remote->in_dma);
- if (!remote->in_buffer) {
- retval = -ENOMEM;
- goto error;
- }
- }
- }
-
- if (!remote->in_endpoint) {
- err("Could not find interrupt input endpoint.\n");
- retval = -ENODEV;
- goto error;
+ remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, SLAB_ATOMIC, &remote->in_dma);
+ if (!remote->in_buffer) {
+ retval = -ENOMEM;
+ goto fail1;
}
remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!remote->irq_urb) {
- err("Failed to allocate urb.\n");
retval = -ENOMEM;
- goto error;
+ goto fail2;
}
- retval = keyspan_setup(remote->udev);
+ retval = keyspan_setup(udev);
if (retval) {
- err("Failed to setup device.\n");
retval = -ENODEV;
- goto error;
- }
-
- /*
- * Setup the input system with the bits we are going to be reporting
- */
- remote->input.evbit[0] = BIT(EV_KEY); /* We will only report KEY events. */
- for (i = 0; i < 32; ++i) {
- if (keyspan_key_table[i] != KEY_RESERVED) {
- set_bit(keyspan_key_table[i], remote->input.keybit);
- }
+ goto fail3;
}
- remote->input.private = remote;
- remote->input.open = keyspan_open;
- remote->input.close = keyspan_close;
-
- usb_make_path(remote->udev, path, 64);
- sprintf(remote->phys, "%s/input0", path);
+ if (udev->manufacturer)
+ strlcpy(remote->name, udev->manufacturer, sizeof(remote->name));
- remote->input.name = remote->name;
- remote->input.phys = remote->phys;
- remote->input.id.bustype = BUS_USB;
- remote->input.id.vendor = le16_to_cpu(remote->udev->descriptor.idVendor);
- remote->input.id.product = le16_to_cpu(remote->udev->descriptor.idProduct);
- remote->input.id.version = le16_to_cpu(remote->udev->descriptor.bcdDevice);
-
- if (!(buf = kmalloc(63, GFP_KERNEL))) {
- usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
- kfree(remote);
- return -ENOMEM;
+ if (udev->product) {
+ if (udev->manufacturer)
+ strlcat(remote->name, " ", sizeof(remote->name));
+ strlcat(remote->name, udev->product, sizeof(remote->name));
}
- if (remote->udev->descriptor.iManufacturer &&
- usb_string(remote->udev, remote->udev->descriptor.iManufacturer, buf, 63) > 0)
- strcat(remote->name, buf);
+ if (!strlen(remote->name))
+ snprintf(remote->name, sizeof(remote->name),
+ "USB Keyspan Remote %04x:%04x",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
- if (remote->udev->descriptor.iProduct &&
- usb_string(remote->udev, remote->udev->descriptor.iProduct, buf, 63) > 0)
- sprintf(remote->name, "%s %s", remote->name, buf);
+ usb_make_path(udev, remote->phys, sizeof(remote->phys));
+ strlcat(remote->phys, "/input0", sizeof(remote->phys));
- if (!strlen(remote->name))
- sprintf(remote->name, "USB Keyspan Remote %04x:%04x",
- remote->input.id.vendor, remote->input.id.product);
+ input_dev->name = remote->name;
+ input_dev->phys = remote->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->cdev.dev = &interface->dev;
- kfree(buf);
+ input_dev->evbit[0] = BIT(EV_KEY); /* We will only report KEY events. */
+ for (i = 0; i < ARRAY_SIZE(keyspan_key_table); i++)
+ if (keyspan_key_table[i] != KEY_RESERVED)
+ set_bit(keyspan_key_table[i], input_dev->keybit);
+
+ input_dev->private = remote;
+ input_dev->open = keyspan_open;
+ input_dev->close = keyspan_close;
/*
* Initialize the URB to access the device. The urb gets sent to the device in keyspan_open()
@@ -538,27 +519,17 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
/* we can register the device now, as it is ready */
- input_register_device(&remote->input);
+ input_register_device(remote->input);
/* save our data pointer in this interface device */
usb_set_intfdata(interface, remote);
- /* let the user know what node this device is now attached to */
- info("connected: %s on %s", remote->name, path);
return 0;
-error:
- /*
- * In case of error we need to clean up any allocated buffers
- */
- if (remote->irq_urb)
- usb_free_urb(remote->irq_urb);
-
- if (remote->in_buffer)
- usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
-
- if (remote)
- kfree(remote);
+ fail3: usb_free_urb(remote->irq_urb);
+ fail2: usb_buffer_free(udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
+ fail1: kfree(remote);
+ input_free_device(input_dev);
return retval;
}
@@ -570,23 +541,16 @@ static void keyspan_disconnect(struct usb_interface *interface)
{
struct usb_keyspan *remote;
- /* prevent keyspan_open() from racing keyspan_disconnect() */
- lock_kernel();
-
remote = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
if (remote) { /* We have a valid driver structure so clean up everything we allocated. */
- input_unregister_device(&remote->input);
+ input_unregister_device(remote->input);
usb_kill_urb(remote->irq_urb);
usb_free_urb(remote->irq_urb);
- usb_buffer_free(interface_to_usbdev(interface), RECV_SIZE, remote->in_buffer, remote->in_dma);
+ usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
kfree(remote);
}
-
- unlock_kernel();
-
- info("USB Keyspan now disconnected");
}
/*
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c
index ff9275057a18f6..7fce526560ca0f 100644
--- a/drivers/usb/input/mtouchusb.c
+++ b/drivers/usb/input/mtouchusb.c
@@ -98,7 +98,7 @@ struct mtouch_usb {
dma_addr_t data_dma;
struct urb *irq;
struct usb_device *udev;
- struct input_dev input;
+ struct input_dev *input;
char name[128];
char phys[64];
};
@@ -135,14 +135,14 @@ static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs)
goto exit;
}
- input_regs(&mtouch->input, regs);
- input_report_key(&mtouch->input, BTN_TOUCH,
+ input_regs(mtouch->input, regs);
+ input_report_key(mtouch->input, BTN_TOUCH,
MTOUCHUSB_GET_TOUCHED(mtouch->data));
- input_report_abs(&mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data));
- input_report_abs(&mtouch->input, ABS_Y,
+ input_report_abs(mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data));
+ input_report_abs(mtouch->input, ABS_Y,
(raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC)
- MTOUCHUSB_GET_YC(mtouch->data));
- input_sync(&mtouch->input);
+ input_sync(mtouch->input);
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -195,10 +195,10 @@ static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *m
static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct mtouch_usb *mtouch;
+ struct input_dev *input_dev;
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct usb_device *udev = interface_to_usbdev(intf);
- char path[64];
int nRet;
dbg("%s - called", __FUNCTION__);
@@ -209,57 +209,55 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
dbg("%s - setting endpoint", __FUNCTION__);
endpoint = &interface->endpoint[0].desc;
- if (!(mtouch = kmalloc(sizeof(struct mtouch_usb), GFP_KERNEL))) {
+ mtouch = kzalloc(sizeof(struct mtouch_usb), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!mtouch || !input_dev) {
err("%s - Out of memory.", __FUNCTION__);
- return -ENOMEM;
+ goto fail1;
}
- memset(mtouch, 0, sizeof(struct mtouch_usb));
- mtouch->udev = udev;
-
dbg("%s - allocating buffers", __FUNCTION__);
- if (mtouchusb_alloc_buffers(udev, mtouch)) {
- mtouchusb_free_buffers(udev, mtouch);
- kfree(mtouch);
- return -ENOMEM;
- }
+ if (mtouchusb_alloc_buffers(udev, mtouch))
+ goto fail2;
- mtouch->input.private = mtouch;
- mtouch->input.open = mtouchusb_open;
- mtouch->input.close = mtouchusb_close;
-
- usb_make_path(udev, path, 64);
- sprintf(mtouch->phys, "%s/input0", path);
-
- mtouch->input.name = mtouch->name;
- mtouch->input.phys = mtouch->phys;
- usb_to_input_id(udev, &mtouch->input.id);
- mtouch->input.dev = &intf->dev;
-
- mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- mtouch->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
- mtouch->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-
- /* Used to Scale Compensated Data and Flip Y */
- mtouch->input.absmin[ABS_X] = MTOUCHUSB_MIN_XC;
- mtouch->input.absmax[ABS_X] = raw_coordinates ?
- MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC;
- mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ;
- mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT;
- mtouch->input.absmin[ABS_Y] = MTOUCHUSB_MIN_YC;
- mtouch->input.absmax[ABS_Y] = raw_coordinates ?
- MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC;
- mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ;
- mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT;
+ mtouch->udev = udev;
+ mtouch->input = input_dev;
if (udev->manufacturer)
- strcat(mtouch->name, udev->manufacturer);
- if (udev->product)
- sprintf(mtouch->name, "%s %s", mtouch->name, udev->product);
+ strlcpy(mtouch->name, udev->manufacturer, sizeof(mtouch->name));
+
+ if (udev->product) {
+ if (udev->manufacturer)
+ strlcat(mtouch->name, " ", sizeof(mtouch->name));
+ strlcat(mtouch->name, udev->product, sizeof(mtouch->name));
+ }
if (!strlen(mtouch->name))
- sprintf(mtouch->name, "USB Touchscreen %04x:%04x",
- mtouch->input.id.vendor, mtouch->input.id.product);
+ snprintf(mtouch->name, sizeof(mtouch->name),
+ "USB Touchscreen %04x:%04x",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
+
+ usb_make_path(udev, mtouch->phys, sizeof(mtouch->phys));
+ strlcpy(mtouch->phys, "/input0", sizeof(mtouch->phys));
+
+ input_dev->name = mtouch->name;
+ input_dev->phys = mtouch->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
+ input_dev->private = mtouch;
+
+ input_dev->open = mtouchusb_open;
+ input_dev->close = mtouchusb_close;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(input_dev, ABS_X, MTOUCHUSB_MIN_XC,
+ raw_coordinates ? MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC,
+ MTOUCHUSB_XC_FUZZ, MTOUCHUSB_XC_FLAT);
+ input_set_abs_params(input_dev, ABS_Y, MTOUCHUSB_MIN_YC,
+ raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC,
+ MTOUCHUSB_YC_FUZZ, MTOUCHUSB_YC_FLAT);
nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0),
MTOUCHUSB_RESET,
@@ -272,9 +270,7 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
mtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!mtouch->irq) {
dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__);
- mtouchusb_free_buffers(udev, mtouch);
- kfree(mtouch);
- return -ENOMEM;
+ goto fail2;
}
dbg("%s - usb_fill_int_urb", __FUNCTION__);
@@ -284,7 +280,7 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
mtouchusb_irq, mtouch, endpoint->bInterval);
dbg("%s - input_register_device", __FUNCTION__);
- input_register_device(&mtouch->input);
+ input_register_device(mtouch->input);
nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0),
MTOUCHUSB_ASYNC_REPORT,
@@ -293,10 +289,13 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
__FUNCTION__, nRet);
- printk(KERN_INFO "input: %s on %s\n", mtouch->name, path);
usb_set_intfdata(intf, mtouch);
-
return 0;
+
+fail2: mtouchusb_free_buffers(udev, mtouch);
+fail1: input_free_device(input_dev);
+ kfree(mtouch);
+ return -ENOMEM;
}
static void mtouchusb_disconnect(struct usb_interface *intf)
@@ -308,7 +307,7 @@ static void mtouchusb_disconnect(struct usb_interface *intf)
if (mtouch) {
dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__);
usb_kill_urb(mtouch->irq);
- input_unregister_device(&mtouch->input);
+ input_unregister_device(mtouch->input);
usb_free_urb(mtouch->irq);
mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch);
kfree(mtouch);
diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c
index acc71ec560e957..a00672c96644a0 100644
--- a/drivers/usb/input/pid.c
+++ b/drivers/usb/input/pid.c
@@ -262,6 +262,7 @@ int hid_pid_init(struct hid_device *hid)
{
struct hid_ff_pid *private;
struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list);
+ struct input_dev *input_dev = hidinput->input;
private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL);
if (!private)
@@ -281,11 +282,12 @@ int hid_pid_init(struct hid_device *hid)
usb_fill_control_urb(private->urbffout, hid->dev, 0,
(void *)&private->ffcr, private->ctrl_buffer, 8,
hid_pid_ctrl_out, hid);
- hidinput->input.upload_effect = hid_pid_upload_effect;
- hidinput->input.flush = hid_pid_flush;
- hidinput->input.ff_effects_max = 8; // A random default
- set_bit(EV_FF, hidinput->input.evbit);
- set_bit(EV_FF_STATUS, hidinput->input.evbit);
+
+ input_dev->upload_effect = hid_pid_upload_effect;
+ input_dev->flush = hid_pid_flush;
+ input_dev->ff_effects_max = 8; // A random default
+ set_bit(EV_FF, input_dev->evbit);
+ set_bit(EV_FF_STATUS, input_dev->evbit);
spin_lock_init(&private->lock);
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c
index ad4afe7e58974f..b7476233ef5d46 100644
--- a/drivers/usb/input/powermate.c
+++ b/drivers/usb/input/powermate.c
@@ -68,7 +68,7 @@ struct powermate_device {
struct usb_ctrlrequest *configcr;
dma_addr_t configcr_dma;
struct usb_device *udev;
- struct input_dev input;
+ struct input_dev *input;
spinlock_t lock;
int static_brightness;
int pulse_speed;
@@ -106,10 +106,10 @@ static void powermate_irq(struct urb *urb, struct pt_regs *regs)
}
/* handle updates to device state */
- input_regs(&pm->input, regs);
- input_report_key(&pm->input, BTN_0, pm->data[0] & 0x01);
- input_report_rel(&pm->input, REL_DIAL, pm->data[1]);
- input_sync(&pm->input);
+ input_regs(pm->input, regs);
+ input_report_key(pm->input, BTN_0, pm->data[0] & 0x01);
+ input_report_rel(pm->input, REL_DIAL, pm->data[1]);
+ input_sync(pm->input);
exit:
retval = usb_submit_urb (urb, GFP_ATOMIC);
@@ -153,10 +153,10 @@ static void powermate_sync_state(struct powermate_device *pm)
Only values of 'arg' quite close to 255 are particularly useful/spectacular.
*/
- if (pm->pulse_speed < 255){
+ if (pm->pulse_speed < 255) {
op = 0; // divide
arg = 255 - pm->pulse_speed;
- } else if (pm->pulse_speed > 255){
+ } else if (pm->pulse_speed > 255) {
op = 2; // multiply
arg = pm->pulse_speed - 255;
} else {
@@ -166,11 +166,11 @@ static void powermate_sync_state(struct powermate_device *pm)
pm->configcr->wValue = cpu_to_le16( (pm->pulse_table << 8) | SET_PULSE_MODE );
pm->configcr->wIndex = cpu_to_le16( (arg << 8) | op );
pm->requires_update &= ~UPDATE_PULSE_MODE;
- }else if (pm->requires_update & UPDATE_STATIC_BRIGHTNESS){
+ } else if (pm->requires_update & UPDATE_STATIC_BRIGHTNESS) {
pm->configcr->wValue = cpu_to_le16( SET_STATIC_BRIGHTNESS );
pm->configcr->wIndex = cpu_to_le16( pm->static_brightness );
pm->requires_update &= ~UPDATE_STATIC_BRIGHTNESS;
- }else{
+ } else {
printk(KERN_ERR "powermate: unknown update required");
pm->requires_update = 0; /* fudge the bug */
return;
@@ -228,19 +228,19 @@ static void powermate_pulse_led(struct powermate_device *pm, int static_brightne
spin_lock_irqsave(&pm->lock, flags);
/* mark state updates which are required */
- if (static_brightness != pm->static_brightness){
+ if (static_brightness != pm->static_brightness) {
pm->static_brightness = static_brightness;
pm->requires_update |= UPDATE_STATIC_BRIGHTNESS;
}
- if (pulse_asleep != pm->pulse_asleep){
+ if (pulse_asleep != pm->pulse_asleep) {
pm->pulse_asleep = pulse_asleep;
pm->requires_update |= (UPDATE_PULSE_ASLEEP | UPDATE_STATIC_BRIGHTNESS);
}
- if (pulse_awake != pm->pulse_awake){
+ if (pulse_awake != pm->pulse_awake) {
pm->pulse_awake = pulse_awake;
pm->requires_update |= (UPDATE_PULSE_AWAKE | UPDATE_STATIC_BRIGHTNESS);
}
- if (pulse_speed != pm->pulse_speed || pulse_table != pm->pulse_table){
+ if (pulse_speed != pm->pulse_speed || pulse_table != pm->pulse_table) {
pm->pulse_speed = pulse_speed;
pm->pulse_table = pulse_table;
pm->requires_update |= UPDATE_PULSE_MODE;
@@ -283,6 +283,7 @@ static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_dev
SLAB_ATOMIC, &pm->data_dma);
if (!pm->data)
return -1;
+
pm->configcr = usb_buffer_alloc(udev, sizeof(*(pm->configcr)),
SLAB_ATOMIC, &pm->configcr_dma);
if (!pm->configcr)
@@ -308,8 +309,9 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct powermate_device *pm;
+ struct input_dev *input_dev;
int pipe, maxp;
- char path[64];
+ int err = -ENOMEM;
interface = intf->cur_altsetting;
endpoint = &interface->endpoint[0].desc;
@@ -323,42 +325,61 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
0, interface->desc.bInterfaceNumber, NULL, 0,
USB_CTRL_SET_TIMEOUT);
- if (!(pm = kmalloc(sizeof(struct powermate_device), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(pm, 0, sizeof(struct powermate_device));
- pm->udev = udev;
+ pm = kzalloc(sizeof(struct powermate_device), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!pm || !input_dev)
+ goto fail1;
- if (powermate_alloc_buffers(udev, pm)) {
- powermate_free_buffers(udev, pm);
- kfree(pm);
- return -ENOMEM;
- }
+ if (powermate_alloc_buffers(udev, pm))
+ goto fail2;
pm->irq = usb_alloc_urb(0, GFP_KERNEL);
- if (!pm->irq) {
- powermate_free_buffers(udev, pm);
- kfree(pm);
- return -ENOMEM;
- }
+ if (!pm->irq)
+ goto fail2;
pm->config = usb_alloc_urb(0, GFP_KERNEL);
- if (!pm->config) {
- usb_free_urb(pm->irq);
- powermate_free_buffers(udev, pm);
- kfree(pm);
- return -ENOMEM;
- }
+ if (!pm->config)
+ goto fail3;
+
+ pm->udev = udev;
+ pm->input = input_dev;
+
+ usb_make_path(udev, pm->phys, sizeof(pm->phys));
+ strlcpy(pm->phys, "/input0", sizeof(pm->phys));
spin_lock_init(&pm->lock);
- init_input_dev(&pm->input);
+
+ switch (le16_to_cpu(udev->descriptor.idProduct)) {
+ case POWERMATE_PRODUCT_NEW:
+ input_dev->name = pm_name_powermate;
+ break;
+ case POWERMATE_PRODUCT_OLD:
+ input_dev->name = pm_name_soundknob;
+ break;
+ default:
+ input_dev->name = pm_name_soundknob;
+ printk(KERN_WARNING "powermate: unknown product id %04x\n",
+ le16_to_cpu(udev->descriptor.idProduct));
+ }
+
+ input_dev->phys = pm->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
+ input_dev->private = pm;
+
+ input_dev->event = powermate_input_event;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_MSC);
+ input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
+ input_dev->relbit[LONG(REL_DIAL)] = BIT(REL_DIAL);
+ input_dev->mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED);
/* get a handle to the interrupt data pipe */
pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
- if(maxp < POWERMATE_PAYLOAD_SIZE_MIN || maxp > POWERMATE_PAYLOAD_SIZE_MAX){
- printk("powermate: Expected payload of %d--%d bytes, found %d bytes!\n",
+ if (maxp < POWERMATE_PAYLOAD_SIZE_MIN || maxp > POWERMATE_PAYLOAD_SIZE_MAX) {
+ printk(KERN_WARNING "powermate: Expected payload of %d--%d bytes, found %d bytes!\n",
POWERMATE_PAYLOAD_SIZE_MIN, POWERMATE_PAYLOAD_SIZE_MAX, maxp);
maxp = POWERMATE_PAYLOAD_SIZE_MAX;
}
@@ -371,35 +392,11 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
/* register our interrupt URB with the USB system */
if (usb_submit_urb(pm->irq, GFP_KERNEL)) {
- powermate_free_buffers(udev, pm);
- kfree(pm);
- return -EIO; /* failure */
+ err = -EIO;
+ goto fail4;
}
- switch (le16_to_cpu(udev->descriptor.idProduct)) {
- case POWERMATE_PRODUCT_NEW: pm->input.name = pm_name_powermate; break;
- case POWERMATE_PRODUCT_OLD: pm->input.name = pm_name_soundknob; break;
- default:
- pm->input.name = pm_name_soundknob;
- printk(KERN_WARNING "powermate: unknown product id %04x\n",
- le16_to_cpu(udev->descriptor.idProduct));
- }
-
- pm->input.private = pm;
- pm->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_MSC);
- pm->input.keybit[LONG(BTN_0)] = BIT(BTN_0);
- pm->input.relbit[LONG(REL_DIAL)] = BIT(REL_DIAL);
- pm->input.mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED);
- usb_to_input_id(udev, &pm->input.id);
- pm->input.event = powermate_input_event;
- pm->input.dev = &intf->dev;
- pm->input.phys = pm->phys;
-
- input_register_device(&pm->input);
-
- usb_make_path(udev, path, 64);
- snprintf(pm->phys, 64, "%s/input0", path);
- printk(KERN_INFO "input: %s on %s\n", pm->input.name, pm->input.phys);
+ input_register_device(pm->input);
/* force an update of everything */
pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS;
@@ -407,6 +404,13 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
usb_set_intfdata(intf, pm);
return 0;
+
+fail4: usb_free_urb(pm->config);
+fail3: usb_free_urb(pm->irq);
+fail2: powermate_free_buffers(udev, pm);
+fail1: input_free_device(input_dev);
+ kfree(pm);
+ return err;
}
/* Called when a USB device we've accepted ownership of is removed */
@@ -418,7 +422,7 @@ static void powermate_disconnect(struct usb_interface *intf)
if (pm) {
pm->requires_update = 0;
usb_kill_urb(pm->irq);
- input_unregister_device(&pm->input);
+ input_unregister_device(pm->input);
usb_free_urb(pm->irq);
usb_free_urb(pm->config);
powermate_free_buffers(interface_to_usbdev(intf), pm);
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c
index 4276c24a50807a..3766ccc271bef6 100644
--- a/drivers/usb/input/touchkitusb.c
+++ b/drivers/usb/input/touchkitusb.c
@@ -68,7 +68,7 @@ struct touchkit_usb {
dma_addr_t data_dma;
struct urb *irq;
struct usb_device *udev;
- struct input_dev input;
+ struct input_dev *input;
char name[128];
char phys[64];
};
@@ -115,12 +115,12 @@ static void touchkit_irq(struct urb *urb, struct pt_regs *regs)
y = TOUCHKIT_GET_Y(touchkit->data);
}
- input_regs(&touchkit->input, regs);
- input_report_key(&touchkit->input, BTN_TOUCH,
+ input_regs(touchkit->input, regs);
+ input_report_key(touchkit->input, BTN_TOUCH,
TOUCHKIT_GET_TOUCHED(touchkit->data));
- input_report_abs(&touchkit->input, ABS_X, x);
- input_report_abs(&touchkit->input, ABS_Y, y);
- input_sync(&touchkit->input);
+ input_report_abs(touchkit->input, ABS_X, x);
+ input_report_abs(touchkit->input, ABS_Y, y);
+ input_sync(touchkit->input);
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -171,87 +171,81 @@ static void touchkit_free_buffers(struct usb_device *udev,
static int touchkit_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- int ret;
struct touchkit_usb *touchkit;
+ struct input_dev *input_dev;
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct usb_device *udev = interface_to_usbdev(intf);
- char path[64];
interface = intf->cur_altsetting;
endpoint = &interface->endpoint[0].desc;
- touchkit = kmalloc(sizeof(struct touchkit_usb), GFP_KERNEL);
- if (!touchkit)
- return -ENOMEM;
-
- memset(touchkit, 0, sizeof(struct touchkit_usb));
- touchkit->udev = udev;
-
- if (touchkit_alloc_buffers(udev, touchkit)) {
- ret = -ENOMEM;
+ touchkit = kzalloc(sizeof(struct touchkit_usb), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!touchkit || !input_dev)
goto out_free;
- }
-
- touchkit->input.private = touchkit;
- touchkit->input.open = touchkit_open;
- touchkit->input.close = touchkit_close;
-
- usb_make_path(udev, path, 64);
- sprintf(touchkit->phys, "%s/input0", path);
-
- touchkit->input.name = touchkit->name;
- touchkit->input.phys = touchkit->phys;
- usb_to_input_id(udev, &touchkit->input.id);
- touchkit->input.dev = &intf->dev;
-
- touchkit->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- touchkit->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
- touchkit->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-
- /* Used to Scale Compensated Data */
- touchkit->input.absmin[ABS_X] = TOUCHKIT_MIN_XC;
- touchkit->input.absmax[ABS_X] = TOUCHKIT_MAX_XC;
- touchkit->input.absfuzz[ABS_X] = TOUCHKIT_XC_FUZZ;
- touchkit->input.absflat[ABS_X] = TOUCHKIT_XC_FLAT;
- touchkit->input.absmin[ABS_Y] = TOUCHKIT_MIN_YC;
- touchkit->input.absmax[ABS_Y] = TOUCHKIT_MAX_YC;
- touchkit->input.absfuzz[ABS_Y] = TOUCHKIT_YC_FUZZ;
- touchkit->input.absflat[ABS_Y] = TOUCHKIT_YC_FLAT;
-
- if (udev->manufacturer)
- strcat(touchkit->name, udev->manufacturer);
- if (udev->product)
- sprintf(touchkit->name, "%s %s", touchkit->name, udev->product);
- if (!strlen(touchkit->name))
- sprintf(touchkit->name, "USB Touchscreen %04x:%04x",
- touchkit->input.id.vendor, touchkit->input.id.product);
+ if (touchkit_alloc_buffers(udev, touchkit))
+ goto out_free;
touchkit->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!touchkit->irq) {
dbg("%s - usb_alloc_urb failed: touchkit->irq", __FUNCTION__);
- ret = -ENOMEM;
goto out_free_buffers;
}
+ touchkit->udev = udev;
+ touchkit->input = input_dev;
+
+ if (udev->manufacturer)
+ strlcpy(touchkit->name, udev->manufacturer, sizeof(touchkit->name));
+
+ if (udev->product) {
+ if (udev->manufacturer)
+ strlcat(touchkit->name, " ", sizeof(touchkit->name));
+ strlcat(touchkit->name, udev->product, sizeof(touchkit->name));
+ }
+
+ if (!strlen(touchkit->name))
+ snprintf(touchkit->name, sizeof(touchkit->name),
+ "USB Touchscreen %04x:%04x",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
+
+ usb_make_path(udev, touchkit->phys, sizeof(touchkit->phys));
+ strlcpy(touchkit->phys, "/input0", sizeof(touchkit->phys));
+
+ input_dev->name = touchkit->name;
+ input_dev->phys = touchkit->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
+ input_dev->private = touchkit;
+ input_dev->open = touchkit_open;
+ input_dev->close = touchkit_close;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(input_dev, ABS_X, TOUCHKIT_MIN_XC, TOUCHKIT_MAX_XC,
+ TOUCHKIT_XC_FUZZ, TOUCHKIT_XC_FLAT);
+ input_set_abs_params(input_dev, ABS_Y, TOUCHKIT_MIN_YC, TOUCHKIT_MAX_YC,
+ TOUCHKIT_YC_FUZZ, TOUCHKIT_YC_FLAT);
+
usb_fill_int_urb(touchkit->irq, touchkit->udev,
- usb_rcvintpipe(touchkit->udev, 0x81),
- touchkit->data, TOUCHKIT_REPORT_DATA_SIZE,
- touchkit_irq, touchkit, endpoint->bInterval);
+ usb_rcvintpipe(touchkit->udev, 0x81),
+ touchkit->data, TOUCHKIT_REPORT_DATA_SIZE,
+ touchkit_irq, touchkit, endpoint->bInterval);
- input_register_device(&touchkit->input);
+ input_register_device(touchkit->input);
- printk(KERN_INFO "input: %s on %s\n", touchkit->name, path);
usb_set_intfdata(intf, touchkit);
-
return 0;
out_free_buffers:
touchkit_free_buffers(udev, touchkit);
out_free:
+ input_free_device(input_dev);
kfree(touchkit);
- return ret;
+ return -ENOMEM;
}
static void touchkit_disconnect(struct usb_interface *intf)
@@ -265,8 +259,8 @@ static void touchkit_disconnect(struct usb_interface *intf)
dbg("%s - touchkit is initialized, cleaning up", __FUNCTION__);
usb_set_intfdata(intf, NULL);
- input_unregister_device(&touchkit->input);
usb_kill_urb(touchkit->irq);
+ input_unregister_device(touchkit->input);
usb_free_urb(touchkit->irq);
touchkit_free_buffers(interface_to_usbdev(intf), touchkit);
kfree(touchkit);
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
index 28987f15eeee9c..226b6f90a9072b 100644
--- a/drivers/usb/input/usbkbd.c
+++ b/drivers/usb/input/usbkbd.c
@@ -66,7 +66,7 @@ static unsigned char usb_kbd_keycode[256] = {
};
struct usb_kbd {
- struct input_dev dev;
+ struct input_dev *dev;
struct usb_device *usbdev;
unsigned char old[8];
struct urb *irq, *led;
@@ -99,29 +99,29 @@ static void usb_kbd_irq(struct urb *urb, struct pt_regs *regs)
goto resubmit;
}
- input_regs(&kbd->dev, regs);
+ input_regs(kbd->dev, regs);
for (i = 0; i < 8; i++)
- input_report_key(&kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
+ input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
for (i = 2; i < 8; i++) {
if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) {
if (usb_kbd_keycode[kbd->old[i]])
- input_report_key(&kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
+ input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
else
info("Unknown key (scancode %#x) released.", kbd->old[i]);
}
if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
if (usb_kbd_keycode[kbd->new[i]])
- input_report_key(&kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
+ input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
else
info("Unknown key (scancode %#x) pressed.", kbd->new[i]);
}
}
- input_sync(&kbd->dev);
+ input_sync(kbd->dev);
memcpy(kbd->old, kbd->new, 8);
@@ -227,12 +227,12 @@ static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd)
static int usb_kbd_probe(struct usb_interface *iface,
const struct usb_device_id *id)
{
- struct usb_device * dev = interface_to_usbdev(iface);
+ struct usb_device *dev = interface_to_usbdev(iface);
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct usb_kbd *kbd;
+ struct input_dev *input_dev;
int i, pipe, maxp;
- char path[64];
interface = iface->cur_altsetting;
@@ -240,37 +240,59 @@ static int usb_kbd_probe(struct usb_interface *iface,
return -ENODEV;
endpoint = &interface->endpoint[0].desc;
- if (!(endpoint->bEndpointAddress & 0x80))
+ if (!(endpoint->bEndpointAddress & USB_DIR_IN))
return -ENODEV;
- if ((endpoint->bmAttributes & 3) != 3)
+ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
return -ENODEV;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
- if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL)))
- return -ENOMEM;
- memset(kbd, 0, sizeof(struct usb_kbd));
+ kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!kbd || !input_dev)
+ goto fail1;
- if (usb_kbd_alloc_mem(dev, kbd)) {
- usb_kbd_free_mem(dev, kbd);
- kfree(kbd);
- return -ENOMEM;
- }
+ if (usb_kbd_alloc_mem(dev, kbd))
+ goto fail2;
kbd->usbdev = dev;
+ kbd->dev = input_dev;
+
+ if (dev->manufacturer)
+ strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name));
+
+ if (dev->product) {
+ if (dev->manufacturer)
+ strlcat(kbd->name, " ", sizeof(kbd->name));
+ strlcat(kbd->name, dev->product, sizeof(kbd->name));
+ }
+
+ if (!strlen(kbd->name))
+ snprintf(kbd->name, sizeof(kbd->name),
+ "USB HIDBP Keyboard %04x:%04x",
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
+
+ usb_make_path(dev, kbd->phys, sizeof(kbd->phys));
+ strlcpy(kbd->phys, "/input0", sizeof(kbd->phys));
- kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
- kbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA);
+ input_dev->name = kbd->name;
+ input_dev->phys = kbd->phys;
+ usb_to_input_id(dev, &input_dev->id);
+ input_dev->cdev.dev = &iface->dev;
+ input_dev->private = kbd;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
+ input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA);
for (i = 0; i < 255; i++)
- set_bit(usb_kbd_keycode[i], kbd->dev.keybit);
- clear_bit(0, kbd->dev.keybit);
+ set_bit(usb_kbd_keycode[i], input_dev->keybit);
+ clear_bit(0, input_dev->keybit);
- kbd->dev.private = kbd;
- kbd->dev.event = usb_kbd_event;
- kbd->dev.open = usb_kbd_open;
- kbd->dev.close = usb_kbd_close;
+ input_dev->event = usb_kbd_event;
+ input_dev->open = usb_kbd_open;
+ input_dev->close = usb_kbd_close;
usb_fill_int_urb(kbd->irq, dev, pipe,
kbd->new, (maxp > 8 ? 8 : maxp),
@@ -284,37 +306,22 @@ static int usb_kbd_probe(struct usb_interface *iface,
kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber);
kbd->cr->wLength = cpu_to_le16(1);
- usb_make_path(dev, path, 64);
- sprintf(kbd->phys, "%s/input0", path);
-
- kbd->dev.name = kbd->name;
- kbd->dev.phys = kbd->phys;
- usb_to_input_id(dev, &kbd->dev.id);
- kbd->dev.dev = &iface->dev;
-
- if (dev->manufacturer)
- strcat(kbd->name, dev->manufacturer);
- if (dev->product)
- sprintf(kbd->name, "%s %s", kbd->name, dev->product);
-
- if (!strlen(kbd->name))
- sprintf(kbd->name, "USB HIDBP Keyboard %04x:%04x",
- kbd->dev.id.vendor, kbd->dev.id.product);
-
usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0),
(void *) kbd->cr, kbd->leds, 1,
usb_kbd_led, kbd);
kbd->led->setup_dma = kbd->cr_dma;
kbd->led->transfer_dma = kbd->leds_dma;
- kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP
- | URB_NO_SETUP_DMA_MAP);
+ kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
- input_register_device(&kbd->dev);
-
- printk(KERN_INFO "input: %s on %s\n", kbd->name, path);
+ input_register_device(kbd->dev);
usb_set_intfdata(iface, kbd);
return 0;
+
+fail2: usb_kbd_free_mem(dev, kbd);
+fail1: input_free_device(input_dev);
+ kfree(kbd);
+ return -ENOMEM;
}
static void usb_kbd_disconnect(struct usb_interface *intf)
@@ -324,7 +331,7 @@ static void usb_kbd_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (kbd) {
usb_kill_urb(kbd->irq);
- input_unregister_device(&kbd->dev);
+ input_unregister_device(kbd->dev);
usb_kbd_free_mem(interface_to_usbdev(intf), kbd);
kfree(kbd);
}
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
index 4104dec847fbad..230f6b1b314a00 100644
--- a/drivers/usb/input/usbmouse.c
+++ b/drivers/usb/input/usbmouse.c
@@ -50,7 +50,7 @@ struct usb_mouse {
char name[128];
char phys[64];
struct usb_device *usbdev;
- struct input_dev dev;
+ struct input_dev *dev;
struct urb *irq;
signed char *data;
@@ -61,7 +61,7 @@ static void usb_mouse_irq(struct urb *urb, struct pt_regs *regs)
{
struct usb_mouse *mouse = urb->context;
signed char *data = mouse->data;
- struct input_dev *dev = &mouse->dev;
+ struct input_dev *dev = mouse->dev;
int status;
switch (urb->status) {
@@ -115,14 +115,14 @@ static void usb_mouse_close(struct input_dev *dev)
usb_kill_urb(mouse->irq);
}
-static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_id * id)
+static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
- struct usb_device * dev = interface_to_usbdev(intf);
+ struct usb_device *dev = interface_to_usbdev(intf);
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct usb_mouse *mouse;
+ struct input_dev *input_dev;
int pipe, maxp;
- char path[64];
interface = intf->cur_altsetting;
@@ -130,59 +130,62 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_
return -ENODEV;
endpoint = &interface->endpoint[0].desc;
- if (!(endpoint->bEndpointAddress & 0x80))
+ if (!(endpoint->bEndpointAddress & USB_DIR_IN))
return -ENODEV;
- if ((endpoint->bmAttributes & 3) != 3)
+ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
return -ENODEV;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
- if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL)))
- return -ENOMEM;
- memset(mouse, 0, sizeof(struct usb_mouse));
+ mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!mouse || !input_dev)
+ goto fail1;
mouse->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &mouse->data_dma);
- if (!mouse->data) {
- kfree(mouse);
- return -ENOMEM;
- }
+ if (!mouse->data)
+ goto fail1;
mouse->irq = usb_alloc_urb(0, GFP_KERNEL);
- if (!mouse->irq) {
- usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
- kfree(mouse);
- return -ENODEV;
- }
+ if (!mouse->irq)
+ goto fail2;
mouse->usbdev = dev;
+ mouse->dev = input_dev;
+
+ if (dev->manufacturer)
+ strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name));
- mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
- mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
- mouse->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
- mouse->dev.relbit[0] |= BIT(REL_WHEEL);
+ if (dev->product) {
+ if (dev->manufacturer)
+ strlcat(mouse->name, " ", sizeof(mouse->name));
+ strlcat(mouse->name, dev->product, sizeof(mouse->name));
+ }
- mouse->dev.private = mouse;
- mouse->dev.open = usb_mouse_open;
- mouse->dev.close = usb_mouse_close;
+ if (!strlen(mouse->name))
+ snprintf(mouse->name, sizeof(mouse->name),
+ "USB HIDBP Mouse %04x:%04x",
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
- usb_make_path(dev, path, 64);
- sprintf(mouse->phys, "%s/input0", path);
+ usb_make_path(dev, mouse->phys, sizeof(mouse->phys));
+ strlcat(mouse->phys, "/input0", sizeof(mouse->phys));
- mouse->dev.name = mouse->name;
- mouse->dev.phys = mouse->phys;
- usb_to_input_id(dev, &mouse->dev.id);
- mouse->dev.dev = &intf->dev;
+ input_dev->name = mouse->name;
+ input_dev->phys = mouse->phys;
+ usb_to_input_id(dev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
- if (dev->manufacturer)
- strcat(mouse->name, dev->manufacturer);
- if (dev->product)
- sprintf(mouse->name, "%s %s", mouse->name, dev->product);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+ input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
+ input_dev->relbit[0] |= BIT(REL_WHEEL);
- if (!strlen(mouse->name))
- sprintf(mouse->name, "USB HIDBP Mouse %04x:%04x",
- mouse->dev.id.vendor, mouse->dev.id.product);
+ input_dev->private = mouse;
+ input_dev->open = usb_mouse_open;
+ input_dev->close = usb_mouse_close;
usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data,
(maxp > 8 ? 8 : maxp),
@@ -190,11 +193,15 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_
mouse->irq->transfer_dma = mouse->data_dma;
mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- input_register_device(&mouse->dev);
- printk(KERN_INFO "input: %s on %s\n", mouse->name, path);
+ input_register_device(mouse->dev);
usb_set_intfdata(intf, mouse);
return 0;
+
+fail2: usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
+fail1: input_free_device(input_dev);
+ kfree(mouse);
+ return -ENOMEM;
}
static void usb_mouse_disconnect(struct usb_interface *intf)
@@ -204,7 +211,7 @@ static void usb_mouse_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (mouse) {
usb_kill_urb(mouse->irq);
- input_unregister_device(&mouse->dev);
+ input_unregister_device(mouse->dev);
usb_free_urb(mouse->irq);
usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma);
kfree(mouse);
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
index 3b266af3048a11..ea0f75773ae1ea 100644
--- a/drivers/usb/input/wacom.c
+++ b/drivers/usb/input/wacom.c
@@ -111,7 +111,7 @@ struct wacom_features {
struct wacom {
signed char *data;
dma_addr_t data_dma;
- struct input_dev dev;
+ struct input_dev *dev;
struct usb_device *usbdev;
struct urb *irq;
struct wacom_features *features;
@@ -135,7 +135,7 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs)
{
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
- struct input_dev *dev = &wacom->dev;
+ struct input_dev *dev = wacom->dev;
int prox, pressure;
int retval;
@@ -225,7 +225,7 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs)
{
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
- struct input_dev *dev = &wacom->dev;
+ struct input_dev *dev = wacom->dev;
int retval;
switch (urb->status) {
@@ -275,7 +275,7 @@ static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs)
{
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
- struct input_dev *dev = &wacom->dev;
+ struct input_dev *dev = wacom->dev;
int retval;
switch (urb->status) {
@@ -318,7 +318,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
{
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
- struct input_dev *dev = &wacom->dev;
+ struct input_dev *dev = wacom->dev;
int x, y;
int retval;
@@ -397,7 +397,7 @@ static int wacom_intuos_inout(struct urb *urb)
{
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
- struct input_dev *dev = &wacom->dev;
+ struct input_dev *dev = wacom->dev;
int idx;
/* tool number */
@@ -479,7 +479,7 @@ static void wacom_intuos_general(struct urb *urb)
{
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
- struct input_dev *dev = &wacom->dev;
+ struct input_dev *dev = wacom->dev;
unsigned int t;
/* general pen packet */
@@ -509,7 +509,7 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
{
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
- struct input_dev *dev = &wacom->dev;
+ struct input_dev *dev = wacom->dev;
unsigned int t;
int idx;
int retval;
@@ -738,95 +738,83 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
{
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_endpoint_descriptor *endpoint;
- char rep_data[2] = {0x02, 0x02};
struct wacom *wacom;
- char path[64];
+ struct input_dev *input_dev;
+ char rep_data[2] = {0x02, 0x02};
- if (!(wacom = kmalloc(sizeof(struct wacom), GFP_KERNEL)))
- return -ENOMEM;
- memset(wacom, 0, sizeof(struct wacom));
+ wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!wacom || !input_dev)
+ goto fail1;
wacom->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma);
- if (!wacom->data) {
- kfree(wacom);
- return -ENOMEM;
- }
+ if (!wacom->data)
+ goto fail1;
wacom->irq = usb_alloc_urb(0, GFP_KERNEL);
- if (!wacom->irq) {
- usb_buffer_free(dev, 10, wacom->data, wacom->data_dma);
- kfree(wacom);
- return -ENOMEM;
- }
+ if (!wacom->irq)
+ goto fail2;
+
+ wacom->usbdev = dev;
+ wacom->dev = input_dev;
+ usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
+ strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
wacom->features = wacom_features + (id - wacom_ids);
+ if (wacom->features->pktlen > 10)
+ BUG();
+
+ input_dev->name = wacom->features->name;
+ usb_to_input_id(dev, &input_dev->id);
- wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS);
- wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
- wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS);
+ input_dev->cdev.dev = &intf->dev;
+ input_dev->private = wacom;
+ input_dev->open = wacom_open;
+ input_dev->close = wacom_close;
+
+ input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS);
+ input_set_abs_params(input_dev, ABS_X, 0, wacom->features->y_max, 4, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, wacom->features->y_max, 4, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0);
switch (wacom->features->type) {
case GRAPHIRE:
- wacom->dev.evbit[0] |= BIT(EV_REL);
- wacom->dev.relbit[0] |= BIT(REL_WHEEL);
- wacom->dev.absbit[0] |= BIT(ABS_DISTANCE);
- wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
- wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2);
+ input_dev->evbit[0] |= BIT(EV_REL);
+ input_dev->relbit[0] |= BIT(REL_WHEEL);
+ input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+ input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2);
+ input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom->features->distance_max, 0, 0);
break;
case INTUOS3:
case CINTIQ:
- wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
- wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
- wacom->dev.absbit[0] |= BIT(ABS_RX) | BIT(ABS_RY);
+ input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
+ input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
+ input_set_abs_params(input_dev, ABS_RX, 0, 4097, 0, 0);
+ input_set_abs_params(input_dev, ABS_RY, 0, 4097, 0, 0);
/* fall through */
case INTUOS:
- wacom->dev.evbit[0] |= BIT(EV_MSC) | BIT(EV_REL);
- wacom->dev.mscbit[0] |= BIT(MSC_SERIAL);
- wacom->dev.relbit[0] |= BIT(REL_WHEEL);
- wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
- wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH)
+ input_dev->evbit[0] |= BIT(EV_MSC) | BIT(EV_REL);
+ input_dev->mscbit[0] |= BIT(MSC_SERIAL);
+ input_dev->relbit[0] |= BIT(REL_WHEEL);
+ input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
+ input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH)
| BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2);
- wacom->dev.absbit[0] |= BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE);
+ input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom->features->distance_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
+ input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0);
+ input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0);
+ input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0);
+ input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0);
break;
case PL:
- wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER);
+ input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER);
break;
}
- wacom->dev.absmax[ABS_X] = wacom->features->x_max;
- wacom->dev.absmax[ABS_Y] = wacom->features->y_max;
- wacom->dev.absmax[ABS_PRESSURE] = wacom->features->pressure_max;
- wacom->dev.absmax[ABS_DISTANCE] = wacom->features->distance_max;
- wacom->dev.absmax[ABS_TILT_X] = 127;
- wacom->dev.absmax[ABS_TILT_Y] = 127;
- wacom->dev.absmax[ABS_WHEEL] = 1023;
-
- wacom->dev.absmax[ABS_RX] = 4097;
- wacom->dev.absmax[ABS_RY] = 4097;
- wacom->dev.absmin[ABS_RZ] = -900;
- wacom->dev.absmax[ABS_RZ] = 899;
- wacom->dev.absmin[ABS_THROTTLE] = -1023;
- wacom->dev.absmax[ABS_THROTTLE] = 1023;
-
- wacom->dev.absfuzz[ABS_X] = 4;
- wacom->dev.absfuzz[ABS_Y] = 4;
-
- wacom->dev.private = wacom;
- wacom->dev.open = wacom_open;
- wacom->dev.close = wacom_close;
-
- usb_make_path(dev, path, 64);
- sprintf(wacom->phys, "%s/input0", path);
-
- wacom->dev.name = wacom->features->name;
- wacom->dev.phys = wacom->phys;
- usb_to_input_id(dev, &wacom->dev.id);
- wacom->dev.dev = &intf->dev;
- wacom->usbdev = dev;
-
endpoint = &intf->cur_altsetting->endpoint[0].desc;
if (wacom->features->pktlen > 10)
@@ -839,18 +827,20 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
wacom->irq->transfer_dma = wacom->data_dma;
wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- input_register_device(&wacom->dev);
+ input_register_device(wacom->dev);
/* ask the tablet to report tablet data */
usb_set_report(intf, 3, 2, rep_data, 2);
/* repeat once (not sure why the first call often fails) */
usb_set_report(intf, 3, 2, rep_data, 2);
- printk(KERN_INFO "input: %s on %s\n", wacom->features->name, path);
-
usb_set_intfdata(intf, wacom);
-
return 0;
+
+fail2: usb_buffer_free(dev, 10, wacom->data, wacom->data_dma);
+fail1: input_free_device(input_dev);
+ kfree(wacom);
+ return -ENOMEM;
}
static void wacom_disconnect(struct usb_interface *intf)
@@ -860,7 +850,7 @@ static void wacom_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (wacom) {
usb_kill_urb(wacom->irq);
- input_unregister_device(&wacom->dev);
+ input_unregister_device(wacom->dev);
usb_free_urb(wacom->irq);
usb_buffer_free(interface_to_usbdev(intf), 10, wacom->data, wacom->data_dma);
kfree(wacom);
diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c
index 18125e0bffa210..43112f040b6de3 100644
--- a/drivers/usb/input/xpad.c
+++ b/drivers/usb/input/xpad.c
@@ -103,7 +103,7 @@ static struct usb_device_id xpad_table [] = {
MODULE_DEVICE_TABLE (usb, xpad_table);
struct usb_xpad {
- struct input_dev dev; /* input device interface */
+ struct input_dev *dev; /* input device interface */
struct usb_device *udev; /* usb device */
struct urb *irq_in; /* urb for interrupt in report */
@@ -125,7 +125,7 @@ struct usb_xpad {
static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data, struct pt_regs *regs)
{
- struct input_dev *dev = &xpad->dev;
+ struct input_dev *dev = xpad->dev;
input_regs(dev, regs);
@@ -214,9 +214,9 @@ static void xpad_close (struct input_dev *dev)
static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev (intf);
- struct usb_xpad *xpad = NULL;
+ struct usb_xpad *xpad;
+ struct input_dev *input_dev;
struct usb_endpoint_descriptor *ep_irq_in;
- char path[64];
int i;
for (i = 0; xpad_device[i].idVendor; i++) {
@@ -225,89 +225,80 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
break;
}
- if ((xpad = kmalloc (sizeof(struct usb_xpad), GFP_KERNEL)) == NULL) {
- err("cannot allocate memory for new pad");
- return -ENOMEM;
- }
- memset(xpad, 0, sizeof(struct usb_xpad));
+ xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!xpad || !input_dev)
+ goto fail1;
xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN,
SLAB_ATOMIC, &xpad->idata_dma);
- if (!xpad->idata) {
- kfree(xpad);
- return -ENOMEM;
- }
+ if (!xpad->idata)
+ goto fail1;
xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL);
- if (!xpad->irq_in) {
- err("cannot allocate memory for new pad irq urb");
- usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
- kfree(xpad);
- return -ENOMEM;
- }
-
- ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
-
- usb_fill_int_urb(xpad->irq_in, udev,
- usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
- xpad->idata, XPAD_PKT_LEN, xpad_irq_in,
- xpad, ep_irq_in->bInterval);
- xpad->irq_in->transfer_dma = xpad->idata_dma;
- xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ if (!xpad->irq_in)
+ goto fail2;
xpad->udev = udev;
+ xpad->dev = input_dev;
+ usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
+ strlcat(xpad->phys, "/input0", sizeof(xpad->phys));
- usb_to_input_id(udev, &xpad->dev.id);
- xpad->dev.dev = &intf->dev;
- xpad->dev.private = xpad;
- xpad->dev.name = xpad_device[i].name;
- xpad->dev.phys = xpad->phys;
- xpad->dev.open = xpad_open;
- xpad->dev.close = xpad_close;
-
- usb_make_path(udev, path, 64);
- snprintf(xpad->phys, 64, "%s/input0", path);
+ input_dev->name = xpad_device[i].name;
+ input_dev->phys = xpad->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
+ input_dev->private = xpad;
+ input_dev->open = xpad_open;
+ input_dev->close = xpad_close;
- xpad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; xpad_btn[i] >= 0; i++)
- set_bit(xpad_btn[i], xpad->dev.keybit);
+ set_bit(xpad_btn[i], input_dev->keybit);
for (i = 0; xpad_abs[i] >= 0; i++) {
signed short t = xpad_abs[i];
- set_bit(t, xpad->dev.absbit);
+ set_bit(t, input_dev->absbit);
switch (t) {
case ABS_X:
case ABS_Y:
case ABS_RX:
case ABS_RY: /* the two sticks */
- xpad->dev.absmax[t] = 32767;
- xpad->dev.absmin[t] = -32768;
- xpad->dev.absflat[t] = 128;
- xpad->dev.absfuzz[t] = 16;
+ input_set_abs_params(input_dev, t, -32768, 32767, 16, 128);
break;
case ABS_Z:
case ABS_RZ: /* the triggers */
- xpad->dev.absmax[t] = 255;
- xpad->dev.absmin[t] = 0;
+ input_set_abs_params(input_dev, t, 0, 255, 0, 0);
break;
case ABS_HAT0X:
case ABS_HAT0Y: /* the d-pad */
- xpad->dev.absmax[t] = 1;
- xpad->dev.absmin[t] = -1;
+ input_set_abs_params(input_dev, t, -1, 1, 0, 0);
break;
}
}
- input_register_device(&xpad->dev);
+ ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
+ usb_fill_int_urb(xpad->irq_in, udev,
+ usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
+ xpad->idata, XPAD_PKT_LEN, xpad_irq_in,
+ xpad, ep_irq_in->bInterval);
+ xpad->irq_in->transfer_dma = xpad->idata_dma;
+ xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- printk(KERN_INFO "input: %s on %s", xpad->dev.name, path);
+ input_register_device(xpad->dev);
usb_set_intfdata(intf, xpad);
return 0;
+
+fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
+fail1: input_free_device(input_dev);
+ kfree(xpad);
+ return -ENOMEM;
+
}
static void xpad_disconnect(struct usb_interface *intf)
@@ -317,7 +308,7 @@ static void xpad_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (xpad) {
usb_kill_urb(xpad->irq_in);
- input_unregister_device(&xpad->dev);
+ input_unregister_device(xpad->dev);
usb_free_urb(xpad->irq_in);
usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
kfree(xpad);
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c
index 58a176ef96a576..f526aebea50225 100644
--- a/drivers/usb/input/yealink.c
+++ b/drivers/usb/input/yealink.c
@@ -54,6 +54,7 @@
#include <linux/module.h>
#include <linux/rwsem.h>
#include <linux/usb.h>
+#include <linux/usb_input.h>
#include "map_to_7segment.h"
#include "yealink.h"
@@ -101,12 +102,12 @@ static const struct lcd_segment_map {
};
struct yealink_dev {
- struct input_dev idev; /* input device */
+ struct input_dev *idev; /* input device */
struct usb_device *udev; /* usb device */
/* irq input channel */
struct yld_ctl_packet *irq_data;
- dma_addr_t irq_dma;
+ dma_addr_t irq_dma;
struct urb *urb_irq;
/* control output channel */
@@ -237,7 +238,7 @@ static int map_p1k_to_key(int scancode)
*/
static void report_key(struct yealink_dev *yld, int key, struct pt_regs *regs)
{
- struct input_dev *idev = &yld->idev;
+ struct input_dev *idev = yld->idev;
input_regs(idev, regs);
if (yld->key_code >= 0) {
@@ -809,8 +810,12 @@ static int usb_cleanup(struct yealink_dev *yld, int err)
}
if (yld->urb_ctl)
usb_free_urb(yld->urb_ctl);
- if (yld->idev.dev)
- input_unregister_device(&yld->idev);
+ if (yld->idev) {
+ if (err)
+ input_free_device(yld->idev);
+ else
+ input_unregister_device(yld->idev);
+ }
if (yld->ctl_req)
usb_buffer_free(yld->udev, sizeof(*(yld->ctl_req)),
yld->ctl_req, yld->ctl_req_dma);
@@ -857,7 +862,7 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct yealink_dev *yld;
- char path[64];
+ struct input_dev *input_dev;
int ret, pipe, i;
i = usb_match(udev);
@@ -866,17 +871,21 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
interface = intf->cur_altsetting;
endpoint = &interface->endpoint[0].desc;
- if (!(endpoint->bEndpointAddress & 0x80))
+ if (!(endpoint->bEndpointAddress & USB_DIR_IN))
return -EIO;
- if ((endpoint->bmAttributes & 3) != 3)
+ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
return -EIO;
- if ((yld = kmalloc(sizeof(struct yealink_dev), GFP_KERNEL)) == NULL)
+ yld = kzalloc(sizeof(struct yealink_dev), GFP_KERNEL);
+ if (!yld)
return -ENOMEM;
- memset(yld, 0, sizeof(*yld));
yld->udev = udev;
+ yld->idev = input_dev = input_allocate_device();
+ if (!input_dev)
+ return usb_cleanup(yld, -ENOMEM);
+
/* allocate usb buffers */
yld->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN,
SLAB_ATOMIC, &yld->irq_dma);
@@ -935,42 +944,37 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
yld->urb_ctl->dev = udev;
/* find out the physical bus location */
- if (usb_make_path(udev, path, sizeof(path)) > 0)
- snprintf(yld->phys, sizeof(yld->phys)-1, "%s/input0", path);
+ usb_make_path(udev, yld->phys, sizeof(yld->phys));
+ strlcat(yld->phys, "/input0", sizeof(yld->phys));
/* register settings for the input device */
- init_input_dev(&yld->idev);
- yld->idev.private = yld;
- yld->idev.id.bustype = BUS_USB;
- yld->idev.id.vendor = le16_to_cpu(udev->descriptor.idVendor);
- yld->idev.id.product = le16_to_cpu(udev->descriptor.idProduct);
- yld->idev.id.version = le16_to_cpu(udev->descriptor.bcdDevice);
- yld->idev.dev = &intf->dev;
- yld->idev.name = yld_device[i].name;
- yld->idev.phys = yld->phys;
- /* yld->idev.event = input_ev; TODO */
- yld->idev.open = input_open;
- yld->idev.close = input_close;
+ input_dev->name = yld_device[i].name;
+ input_dev->phys = yld->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
+
+ input_dev->private = yld;
+ input_dev->open = input_open;
+ input_dev->close = input_close;
+ /* input_dev->event = input_ev; TODO */
/* register available key events */
- yld->idev.evbit[0] = BIT(EV_KEY);
+ input_dev->evbit[0] = BIT(EV_KEY);
for (i = 0; i < 256; i++) {
int k = map_p1k_to_key(i);
if (k >= 0) {
- set_bit(k & 0xff, yld->idev.keybit);
+ set_bit(k & 0xff, input_dev->keybit);
if (k >> 8)
- set_bit(k >> 8, yld->idev.keybit);
+ set_bit(k >> 8, input_dev->keybit);
}
}
- printk(KERN_INFO "input: %s on %s\n", yld->idev.name, path);
-
- input_register_device(&yld->idev);
+ input_register_device(yld->idev);
usb_set_intfdata(intf, yld);
/* clear visible elements */
- for (i=0; i<ARRAY_SIZE(lcdMap); i++)
+ for (i = 0; i < ARRAY_SIZE(lcdMap); i++)
setChar(yld, i, ' ');
/* display driver version on LCD line 3 */
diff --git a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c
index 20ac9e1069d46c..9fe2c2710d13d5 100644
--- a/drivers/usb/media/konicawc.c
+++ b/drivers/usb/media/konicawc.c
@@ -119,7 +119,7 @@ struct konicawc {
int yplanesz; /* Number of bytes in the Y plane */
unsigned int buttonsts:1;
#ifdef CONFIG_INPUT
- struct input_dev input;
+ struct input_dev *input;
char input_physname[64];
#endif
};
@@ -218,6 +218,57 @@ static void konicawc_adjust_picture(struct uvd *uvd)
konicawc_camera_on(uvd);
}
+#ifdef CONFIG_INPUT
+
+static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev)
+{
+ struct input_dev *input_dev;
+
+ usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname));
+ strncat(cam->input_physname, "/input0", sizeof(cam->input_physname));
+
+ cam->input = input_dev = input_allocate_device();
+ if (!input_dev) {
+ warn("Not enough memory for camera's input device\n");
+ return;
+ }
+
+ input_dev->name = "Konicawc snapshot button";
+ input_dev->phys = cam->input_physname;
+ usb_to_input_id(dev, &input_dev->id);
+ input_dev->cdev.dev = &dev->dev;
+
+ input_dev->evbit[0] = BIT(EV_KEY);
+ input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
+
+ input_dev->private = cam;
+
+ input_register_device(cam->input);
+}
+
+static void konicawc_unregister_input(struct konicawc *cam)
+{
+ if (cam->input) {
+ input_unregister_device(cam->input);
+ cam->input = NULL;
+ }
+}
+
+static void konicawc_report_buttonstat(struct konicawc *cam)
+{
+ if (cam->input) {
+ input_report_key(cam->input, BTN_0, cam->buttonsts);
+ input_sync(cam->input);
+ }
+}
+
+#else
+
+static inline void konicawc_register_input(struct konicawc *cam, struct usb_device *dev) { }
+static inline void konicawc_unregister_input(struct konicawc *cam) { }
+static inline void konicawc_report_buttonstat(struct konicawc *cam) { }
+
+#endif /* CONFIG_INPUT */
static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct urb *stsurb)
{
@@ -273,10 +324,7 @@ static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct ur
if(button != cam->buttonsts) {
DEBUG(2, "button: %sclicked", button ? "" : "un");
cam->buttonsts = button;
-#ifdef CONFIG_INPUT
- input_report_key(&cam->input, BTN_0, cam->buttonsts);
- input_sync(&cam->input);
-#endif
+ konicawc_report_buttonstat(cam);
}
if(sts == 0x01) { /* drop frame */
@@ -645,9 +693,9 @@ static int konicawc_set_video_mode(struct uvd *uvd, struct video_window *vw)
RingQueue_Flush(&uvd->dp);
cam->lastframe = -2;
if(uvd->curframe != -1) {
- uvd->frame[uvd->curframe].curline = 0;
- uvd->frame[uvd->curframe].seqRead_Length = 0;
- uvd->frame[uvd->curframe].seqRead_Index = 0;
+ uvd->frame[uvd->curframe].curline = 0;
+ uvd->frame[uvd->curframe].seqRead_Length = 0;
+ uvd->frame[uvd->curframe].seqRead_Index = 0;
}
konicawc_start_data(uvd);
@@ -718,7 +766,6 @@ static void konicawc_configure_video(struct uvd *uvd)
DEBUG(1, "setting initial values");
}
-
static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id *devid)
{
struct usb_device *dev = interface_to_usbdev(intf);
@@ -839,21 +886,8 @@ static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id
err("usbvideo_RegisterVideoDevice() failed.");
uvd = NULL;
}
-#ifdef CONFIG_INPUT
- /* Register input device for button */
- memset(&cam->input, 0, sizeof(struct input_dev));
- cam->input.name = "Konicawc snapshot button";
- cam->input.private = cam;
- cam->input.evbit[0] = BIT(EV_KEY);
- cam->input.keybit[LONG(BTN_0)] = BIT(BTN_0);
- usb_to_input_id(dev, &cam->input.id);
- input_register_device(&cam->input);
-
- usb_make_path(dev, cam->input_physname, 56);
- strcat(cam->input_physname, "/input0");
- cam->input.phys = cam->input_physname;
- info("konicawc: %s on %s\n", cam->input.name, cam->input.phys);
-#endif
+
+ konicawc_register_input(cam, dev);
}
if (uvd) {
@@ -869,10 +903,9 @@ static void konicawc_free_uvd(struct uvd *uvd)
int i;
struct konicawc *cam = (struct konicawc *)uvd->user_data;
-#ifdef CONFIG_INPUT
- input_unregister_device(&cam->input);
-#endif
- for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+ konicawc_unregister_input(cam);
+
+ for (i = 0; i < USBVIDEO_NUMSBUF; i++) {
usb_free_urb(cam->sts_urb[i]);
cam->sts_urb[i] = NULL;
}
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 03fb70ef2eb3ec..0592cb5e6c4d65 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -137,7 +137,7 @@ static void async_complete(struct urb *urb, struct pt_regs *ptregs)
static struct uss720_async_request *submit_async_request(struct parport_uss720_private *priv,
__u8 request, __u8 requesttype, __u16 value, __u16 index,
- unsigned int mem_flags)
+ gfp_t mem_flags)
{
struct usb_device *usbdev;
struct uss720_async_request *rq;
@@ -204,7 +204,7 @@ static unsigned int kill_all_async_requests_priv(struct parport_uss720_private *
/* --------------------------------------------------------------------- */
-static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val, unsigned int mem_flags)
+static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val, gfp_t mem_flags)
{
struct parport_uss720_private *priv;
struct uss720_async_request *rq;
@@ -238,7 +238,7 @@ static int get_1284_register(struct parport *pp, unsigned char reg, unsigned cha
return -EIO;
}
-static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val, unsigned int mem_flags)
+static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val, gfp_t mem_flags)
{
struct parport_uss720_private *priv;
struct uss720_async_request *rq;
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index 861f00a4375010..252a34fbb42cc2 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -753,7 +753,7 @@ static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
}
static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
- unsigned flags)
+ gfp_t flags)
{
int padlen;
int headroom = skb_headroom(skb);
diff --git a/drivers/usb/net/gl620a.c b/drivers/usb/net/gl620a.c
index c8763ae33c737a..c0f263b202a60e 100644
--- a/drivers/usb/net/gl620a.c
+++ b/drivers/usb/net/gl620a.c
@@ -301,7 +301,7 @@ static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
}
static struct sk_buff *
-genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags)
+genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
{
int padlen;
int length = skb->len;
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index e04b0ce3611a3e..c82655d3d448eb 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -477,13 +477,13 @@ static int kaweth_reset(struct kaweth_device *kaweth)
}
static void kaweth_usb_receive(struct urb *, struct pt_regs *regs);
-static int kaweth_resubmit_rx_urb(struct kaweth_device *, unsigned);
+static int kaweth_resubmit_rx_urb(struct kaweth_device *, gfp_t);
/****************************************************************
int_callback
*****************************************************************/
-static void kaweth_resubmit_int_urb(struct kaweth_device *kaweth, int mf)
+static void kaweth_resubmit_int_urb(struct kaweth_device *kaweth, gfp_t mf)
{
int status;
@@ -550,7 +550,7 @@ static void kaweth_resubmit_tl(void *d)
* kaweth_resubmit_rx_urb
****************************************************************/
static int kaweth_resubmit_rx_urb(struct kaweth_device *kaweth,
- unsigned mem_flags)
+ gfp_t mem_flags)
{
int result;
diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c
index a4309c4a491b88..cee55f8cf64fb5 100644
--- a/drivers/usb/net/net1080.c
+++ b/drivers/usb/net/net1080.c
@@ -500,7 +500,7 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
}
static struct sk_buff *
-net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags)
+net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
{
int padlen;
struct sk_buff *skb2;
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c
index 2ed2e5fb77780e..b5a925dc1beb26 100644
--- a/drivers/usb/net/rndis_host.c
+++ b/drivers/usb/net/rndis_host.c
@@ -517,7 +517,7 @@ static int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
}
static struct sk_buff *
-rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags)
+rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
{
struct rndis_data_hdr *hdr;
struct sk_buff *skb2;
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 6c460918d54f53..fce81d73893393 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -288,7 +288,7 @@ EXPORT_SYMBOL_GPL(usbnet_defer_kevent);
static void rx_complete (struct urb *urb, struct pt_regs *regs);
-static void rx_submit (struct usbnet *dev, struct urb *urb, unsigned flags)
+static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
{
struct sk_buff *skb;
struct skb_data *entry;
diff --git a/drivers/usb/net/usbnet.h b/drivers/usb/net/usbnet.h
index 7aa0abd1a9bd2c..89fc4958eecf81 100644
--- a/drivers/usb/net/usbnet.h
+++ b/drivers/usb/net/usbnet.h
@@ -107,7 +107,7 @@ struct driver_info {
/* fixup tx packet (add framing) */
struct sk_buff *(*tx_fixup)(struct usbnet *dev,
- struct sk_buff *skb, unsigned flags);
+ struct sk_buff *skb, gfp_t flags);
/* for new devices, use the descriptor-reading code instead */
int in; /* rx endpoint */
diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c
index ee3b892aeabce2..5d4b7d55b097c8 100644
--- a/drivers/usb/net/zaurus.c
+++ b/drivers/usb/net/zaurus.c
@@ -62,7 +62,7 @@
*/
static struct sk_buff *
-zaurus_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags)
+zaurus_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
{
int padlen;
struct sk_buff *skb2;
diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c
index c4e479ee926aa7..2f52261c7cc13e 100644
--- a/drivers/usb/net/zd1201.c
+++ b/drivers/usb/net/zd1201.c
@@ -521,7 +521,7 @@ static int zd1201_setconfig(struct zd1201 *zd, int rid, void *buf, int len, int
int reqlen;
char seq=0;
struct urb *urb;
- unsigned int gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC;
+ gfp_t gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC;
len += 4; /* first 4 are for header */
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index 2c9402dc702be4..89401a59f95273 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -5,7 +5,7 @@
* Copyright (c) 2005 Nick Sillik <n.sillik@temple.edu>
*
* Initial work by:
- * Copyright (c) 2003 Erik Thyren <erth7411@student.uu.se>
+ * Copyright (c) 2003 Erik Thyren <erth7411@student.uu.se>
*
* Based on usbmouse.c (Vojtech Pavlik) and xpad.c (Marko Friedemann)
*
@@ -46,7 +46,7 @@ void onetouch_release_input(void *onetouch_);
struct usb_onetouch {
char name[128];
char phys[64];
- struct input_dev dev; /* input device interface */
+ struct input_dev *dev; /* input device interface */
struct usb_device *udev; /* usb device */
struct urb *irq; /* urb for interrupt in report */
@@ -58,7 +58,7 @@ static void usb_onetouch_irq(struct urb *urb, struct pt_regs *regs)
{
struct usb_onetouch *onetouch = urb->context;
signed char *data = onetouch->data;
- struct input_dev *dev = &onetouch->dev;
+ struct input_dev *dev = onetouch->dev;
int status;
switch (urb->status) {
@@ -74,11 +74,9 @@ static void usb_onetouch_irq(struct urb *urb, struct pt_regs *regs)
}
input_regs(dev, regs);
-
- input_report_key(&onetouch->dev, ONETOUCH_BUTTON,
- data[0] & 0x02);
-
+ input_report_key(dev, ONETOUCH_BUTTON, data[0] & 0x02);
input_sync(dev);
+
resubmit:
status = usb_submit_urb (urb, SLAB_ATOMIC);
if (status)
@@ -113,8 +111,8 @@ int onetouch_connect_input(struct us_data *ss)
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct usb_onetouch *onetouch;
+ struct input_dev *input_dev;
int pipe, maxp;
- char path[64];
interface = ss->pusb_intf->cur_altsetting;
@@ -122,62 +120,62 @@ int onetouch_connect_input(struct us_data *ss)
return -ENODEV;
endpoint = &interface->endpoint[2].desc;
- if(!(endpoint->bEndpointAddress & USB_DIR_IN))
+ if (!(endpoint->bEndpointAddress & USB_DIR_IN))
return -ENODEV;
- if((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
!= USB_ENDPOINT_XFER_INT)
return -ENODEV;
pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
- if (!(onetouch = kcalloc(1, sizeof(struct usb_onetouch), GFP_KERNEL)))
- return -ENOMEM;
+ onetouch = kzalloc(sizeof(struct usb_onetouch), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!onetouch || !input_dev)
+ goto fail1;
onetouch->data = usb_buffer_alloc(udev, ONETOUCH_PKT_LEN,
SLAB_ATOMIC, &onetouch->data_dma);
- if (!onetouch->data){
- kfree(onetouch);
- return -ENOMEM;
- }
+ if (!onetouch->data)
+ goto fail1;
onetouch->irq = usb_alloc_urb(0, GFP_KERNEL);
- if (!onetouch->irq){
- kfree(onetouch);
- usb_buffer_free(udev, ONETOUCH_PKT_LEN,
- onetouch->data, onetouch->data_dma);
- return -ENODEV;
- }
-
+ if (!onetouch->irq)
+ goto fail2;
onetouch->udev = udev;
+ onetouch->dev = input_dev;
- set_bit(EV_KEY, onetouch->dev.evbit);
- set_bit(ONETOUCH_BUTTON, onetouch->dev.keybit);
- clear_bit(0, onetouch->dev.keybit);
+ if (udev->manufacturer)
+ strlcpy(onetouch->name, udev->manufacturer,
+ sizeof(onetouch->name));
+ if (udev->product) {
+ if (udev->manufacturer)
+ strlcat(onetouch->name, " ", sizeof(onetouch->name));
+ strlcat(onetouch->name, udev->product, sizeof(onetouch->name));
+ }
- onetouch->dev.private = onetouch;
- onetouch->dev.open = usb_onetouch_open;
- onetouch->dev.close = usb_onetouch_close;
+ if (!strlen(onetouch->name))
+ snprintf(onetouch->name, sizeof(onetouch->name),
+ "Maxtor Onetouch %04x:%04x",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
- usb_make_path(udev, path, sizeof(path));
- sprintf(onetouch->phys, "%s/input0", path);
+ usb_make_path(udev, onetouch->phys, sizeof(onetouch->phys));
+ strlcat(onetouch->phys, "/input0", sizeof(onetouch->phys));
- onetouch->dev.name = onetouch->name;
- onetouch->dev.phys = onetouch->phys;
+ input_dev->name = onetouch->name;
+ input_dev->phys = onetouch->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->cdev.dev = &udev->dev;
- usb_to_input_id(udev, &onetouch->dev.id);
+ set_bit(EV_KEY, input_dev->evbit);
+ set_bit(ONETOUCH_BUTTON, input_dev->keybit);
+ clear_bit(0, input_dev->keybit);
- onetouch->dev.dev = &udev->dev;
-
- if (udev->manufacturer)
- strcat(onetouch->name, udev->manufacturer);
- if (udev->product)
- sprintf(onetouch->name, "%s %s", onetouch->name,
- udev->product);
- if (!strlen(onetouch->name))
- sprintf(onetouch->name, "Maxtor Onetouch %04x:%04x",
- onetouch->dev.id.vendor, onetouch->dev.id.product);
+ input_dev->private = onetouch;
+ input_dev->open = usb_onetouch_open;
+ input_dev->close = usb_onetouch_close;
usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data,
(maxp > 8 ? 8 : maxp),
@@ -188,10 +186,15 @@ int onetouch_connect_input(struct us_data *ss)
ss->extra_destructor = onetouch_release_input;
ss->extra = onetouch;
- input_register_device(&onetouch->dev);
- printk(KERN_INFO "usb-input: %s on %s\n", onetouch->dev.name, path);
+ input_register_device(onetouch->dev);
return 0;
+
+ fail2: usb_buffer_free(udev, ONETOUCH_PKT_LEN,
+ onetouch->data, onetouch->data_dma);
+ fail1: kfree(onetouch);
+ input_free_device(input_dev);
+ return -ENOMEM;
}
void onetouch_release_input(void *onetouch_)
@@ -200,11 +203,9 @@ void onetouch_release_input(void *onetouch_)
if (onetouch) {
usb_kill_urb(onetouch->irq);
- input_unregister_device(&onetouch->dev);
+ input_unregister_device(onetouch->dev);
usb_free_urb(onetouch->irq);
usb_buffer_free(onetouch->udev, ONETOUCH_PKT_LEN,
onetouch->data, onetouch->data_dma);
- printk(KERN_INFO "usb-input: deregistering %s\n",
- onetouch->dev.name);
}
}
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index 321dbe91dc14e2..cde6fd8eb390a6 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -22,6 +22,7 @@
#include <linux/ioport.h>
#include <linux/list.h>
+#include <asm/sizes.h>
#include <asm/hardware/amba.h>
#include <asm/hardware/clock.h>
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c
index 3c72c627e65e99..1991fdb32dfbc7 100644
--- a/drivers/video/backlight/corgi_bl.c
+++ b/drivers/video/backlight/corgi_bl.c
@@ -73,17 +73,15 @@ static void corgibl_blank(int blank)
}
#ifdef CONFIG_PM
-static int corgibl_suspend(struct device *dev, pm_message_t state, u32 level)
+static int corgibl_suspend(struct device *dev, pm_message_t state)
{
- if (level == SUSPEND_POWER_DOWN)
- corgibl_blank(FB_BLANK_POWERDOWN);
+ corgibl_blank(FB_BLANK_POWERDOWN);
return 0;
}
-static int corgibl_resume(struct device *dev, u32 level)
+static int corgibl_resume(struct device *dev)
{
- if (level == RESUME_POWER_ON)
- corgibl_blank(FB_BLANK_UNBLANK);
+ corgibl_blank(FB_BLANK_UNBLANK);
return 0;
}
#else
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index eb83a7874c7150..7e731691e2a914 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -110,7 +110,7 @@ config STI_CONSOLE
config FONTS
bool "Select compiled-in fonts"
- depends on FRAMEBUFFER_CONSOLE
+ depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
help
Say Y here if you would like to use fonts other than the default
your frame buffer console usually use.
@@ -123,7 +123,7 @@ config FONTS
config FONT_8x8
bool "VGA 8x8 font" if FONTS
- depends on FRAMEBUFFER_CONSOLE
+ depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
default y if !SPARC32 && !SPARC64 && !FONTS
help
This is the "high resolution" font for the VGA frame buffer (the one
@@ -137,7 +137,7 @@ config FONT_8x8
config FONT_8x16
bool "VGA 8x16 font" if FONTS
- depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y || USB_SISUSBVGA_CON
+ depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y || STI_CONSOLE || USB_SISUSBVGA_CON
default y if !SPARC32 && !SPARC64 && !FONTS
help
This is the "high resolution" font for the VGA frame buffer (the one
@@ -147,7 +147,7 @@ config FONT_8x16
config FONT_6x11
bool "Mac console 6x11 font (not supported by all drivers)" if FONTS
- depends on FRAMEBUFFER_CONSOLE
+ depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
default y if !SPARC32 && !SPARC64 && !FONTS && MAC
help
Small console font with Macintosh-style high-half glyphs. Some Mac
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index d940f605acb684..a7bcd17112c088 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -511,12 +511,12 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name )
struct sti_cooked_font *cooked_font;
if (!fbfont_name || !strlen(fbfont_name))
- return NULL;
+ return NULL;
fbfont = find_font(fbfont_name);
if (!fbfont)
- fbfont = get_default_font(1024,768);
+ fbfont = get_default_font(1024,768);
if (!fbfont)
- return NULL;
+ return NULL;
DPRINTK((KERN_DEBUG "selected %dx%d fb-font %s\n",
fbfont->width, fbfont->height, fbfont->name));
@@ -527,7 +527,7 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name )
nf = kmalloc(size, GFP_KERNEL);
if (!nf)
- return NULL;
+ return NULL;
memset(nf, 0, size);
nf->first_char = 0;
@@ -546,8 +546,8 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name )
cooked_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL);
if (!cooked_font) {
- kfree(nf);
- return NULL;
+ kfree(nf);
+ return NULL;
}
cooked_font->raw = nf;
@@ -595,7 +595,7 @@ sti_select_font(struct sti_cooked_rom *rom,
static void __init
sti_dump_rom(struct sti_rom *rom)
{
- printk(KERN_INFO " id %04x-%04x, conforms to spec rev. %d.%02x\n",
+ printk(KERN_INFO " id %04x-%04x, conforms to spec rev. %d.%02x\n",
rom->graphics_id[0],
rom->graphics_id[1],
rom->revno[0] >> 4,
@@ -651,15 +651,16 @@ sti_search_font(struct sti_cooked_rom *rom, int height, int width)
struct sti_cooked_font *font;
int i = 0;
- for(font = rom->font_start; font; font = font->next_font, i++) {
- if((font->raw->width == width) && (font->raw->height == height))
+ for (font = rom->font_start; font; font = font->next_font, i++) {
+ if ((font->raw->width == width) &&
+ (font->raw->height == height))
return i;
}
return 0;
}
-#define BMODE_RELOCATE(offset) offset = (offset) / 4;
-#define BMODE_LAST_ADDR_OFFS 0x50
+#define BMODE_RELOCATE(offset) offset = (offset) / 4;
+#define BMODE_LAST_ADDR_OFFS 0x50
static void * __init
sti_bmode_font_raw(struct sti_cooked_font *f)
@@ -700,35 +701,35 @@ sti_get_bmode_rom (unsigned long address)
{
struct sti_rom *raw;
u32 size;
- struct sti_rom_font *raw_font, *font_start;
-
+ struct sti_rom_font *raw_font, *font_start;
+
sti_bmode_rom_copy(address + BMODE_LAST_ADDR_OFFS, sizeof(size), &size);
-
- size = (size+3) / 4;
+
+ size = (size+3) / 4;
raw = kmalloc(size, GFP_KERNEL);
if (raw) {
- sti_bmode_rom_copy(address, size, raw);
- memmove (&raw->res004, &raw->type[0], 0x3c);
- raw->type[3] = raw->res004;
+ sti_bmode_rom_copy(address, size, raw);
+ memmove (&raw->res004, &raw->type[0], 0x3c);
+ raw->type[3] = raw->res004;
- BMODE_RELOCATE (raw->region_list);
- BMODE_RELOCATE (raw->font_start);
+ BMODE_RELOCATE (raw->region_list);
+ BMODE_RELOCATE (raw->font_start);
- BMODE_RELOCATE (raw->init_graph);
- BMODE_RELOCATE (raw->state_mgmt);
- BMODE_RELOCATE (raw->font_unpmv);
- BMODE_RELOCATE (raw->block_move);
- BMODE_RELOCATE (raw->inq_conf);
+ BMODE_RELOCATE (raw->init_graph);
+ BMODE_RELOCATE (raw->state_mgmt);
+ BMODE_RELOCATE (raw->font_unpmv);
+ BMODE_RELOCATE (raw->block_move);
+ BMODE_RELOCATE (raw->inq_conf);
- raw_font = ((void *)raw) + raw->font_start;
- font_start = raw_font;
+ raw_font = ((void *)raw) + raw->font_start;
+ font_start = raw_font;
- while (raw_font->next_font) {
- BMODE_RELOCATE (raw_font->next_font);
- raw_font = ((void *)font_start) + raw_font->next_font;
- }
+ while (raw_font->next_font) {
+ BMODE_RELOCATE (raw_font->next_font);
+ raw_font = ((void *)font_start) + raw_font->next_font;
+ }
}
- return raw;
+ return raw;
}
struct sti_rom * __init
@@ -736,15 +737,15 @@ sti_get_wmode_rom (unsigned long address)
{
struct sti_rom *raw;
unsigned long size;
-
+
/* read the ROM size directly from the struct in ROM */
size = gsc_readl(address + offsetof(struct sti_rom,last_addr));
raw = kmalloc(size, GFP_KERNEL);
- if(raw)
- sti_rom_copy(address, size, raw);
+ if (raw)
+ sti_rom_copy(address, size, raw);
- return raw;
+ return raw;
}
int __init
@@ -757,14 +758,14 @@ sti_read_rom(int wordmode, struct sti_struct *sti, unsigned long address)
if (!cooked)
goto out_err;
- if (wordmode)
- raw = sti_get_wmode_rom (address);
- else
- raw = sti_get_bmode_rom (address);
+ if (wordmode)
+ raw = sti_get_wmode_rom (address);
+ else
+ raw = sti_get_bmode_rom (address);
+
+ if (!raw)
+ goto out_err;
- if (!raw)
- goto out_err;
-
if (!sti_cook_fonts(cooked, raw)) {
printk(KERN_ERR "No font found for STI at %08lx\n", address);
goto out_err;
@@ -787,7 +788,7 @@ sti_read_rom(int wordmode, struct sti_struct *sti, unsigned long address)
sti->font_width = sti->font->raw->width;
sti->font_height = sti->font->raw->height;
if (!wordmode)
- sti->font->raw = sti_bmode_font_raw(sti->font);
+ sti->font->raw = sti_bmode_font_raw(sti->font);
sti->sti_mem_request = raw->sti_mem_req;
sti->graphics_id[0] = raw->graphics_id[0];
@@ -811,16 +812,16 @@ sti_try_rom_generic(unsigned long address, unsigned long hpa, struct pci_dev *pd
u32 sig;
if (num_sti_roms >= MAX_STI_ROMS) {
- printk(KERN_WARNING "maximum number of STI ROMS reached !\n");
- return NULL;
+ printk(KERN_WARNING "maximum number of STI ROMS reached !\n");
+ return NULL;
}
sti = kmalloc(sizeof(*sti), GFP_KERNEL);
if (!sti) {
- printk(KERN_ERR "Not enough memory !\n");
- return NULL;
+ printk(KERN_ERR "Not enough memory !\n");
+ return NULL;
}
-
+
memset(sti, 0, sizeof(*sti));
spin_lock_init(&sti->lock);
@@ -932,28 +933,21 @@ static void __init sticore_check_for_default_sti(struct sti_struct *sti, char *p
*/
static int __init sticore_pa_init(struct parisc_device *dev)
{
- unsigned long rom = 0;
char pa_path[21];
struct sti_struct *sti = NULL;
-
- if(dev->num_addrs) {
- rom = dev->addr[0];
- }
- if (!rom) {
- rom = dev->hpa;
- DPRINTK((KERN_DEBUG "Trying STI ROM at %08lx, hpa at %08lx\n", rom, dev->hpa));
- sti = sti_try_rom_generic(rom, dev->hpa, NULL);
- rom = PAGE0->proc_sti;
- }
- if (!sti) {
- DPRINTK((KERN_DEBUG "Trying STI ROM at %08lx, hpa at %08lx\n", rom, dev->hpa));
- sti = sti_try_rom_generic(rom, dev->hpa, NULL);
- }
+ int hpa = dev->hpa.start;
+
+ if (dev->num_addrs && dev->addr[0])
+ sti = sti_try_rom_generic(dev->addr[0], hpa, NULL);
+ if (!sti)
+ sti = sti_try_rom_generic(hpa, hpa, NULL);
+ if (!sti)
+ sti = sti_try_rom_generic(PAGE0->proc_sti, hpa, NULL);
if (!sti)
return 1;
-
+
print_pa_hwpath(dev, pa_path);
- sticore_check_for_default_sti (sti, pa_path);
+ sticore_check_for_default_sti(sti, pa_path);
return 0;
}
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 70be7009f8afc6..9073be4221a81d 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1031,7 +1031,7 @@ register_framebuffer(struct fb_info *fb_info)
break;
fb_info->node = i;
- fb_info->class_device = class_device_create(fb_class, MKDEV(FB_MAJOR, i),
+ fb_info->class_device = class_device_create(fb_class, NULL, MKDEV(FB_MAJOR, i),
fb_info->device, "fb%d", i);
if (IS_ERR(fb_info->class_device)) {
/* Not fatal */
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 1147b899f007d7..007c8e9b2b3974 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -242,6 +242,13 @@ static ssize_t show_virtual(struct class_device *class_device, char *buf)
fb_info->var.yres_virtual);
}
+static ssize_t show_stride(struct class_device *class_device, char *buf)
+{
+ struct fb_info *fb_info =
+ (struct fb_info *)class_get_devdata(class_device);
+ return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length);
+}
+
/* Format for cmap is "%02x%c%4x%4x%4x\n" */
/* %02x entry %c transp %4x red %4x blue %4x green \n */
/* 256 rows at 16 chars equals 4096, the normal page size */
@@ -432,6 +439,7 @@ static struct class_device_attribute class_device_attrs[] = {
__ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan),
__ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual),
__ATTR(name, S_IRUGO, show_name, NULL),
+ __ATTR(stride, S_IRUGO, show_stride, NULL),
};
int fb_init_class_device(struct fb_info *fb_info)
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 1d54d3d6960b6f..0b9301facbd356 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -424,23 +424,21 @@ static void imxfb_setup_gpio(struct imxfb_info *fbi)
* Power management hooks. Note that we won't be called from IRQ context,
* unlike the blank functions above, so we may sleep.
*/
-static int imxfb_suspend(struct device *dev, pm_message_t state, u32 level)
+static int imxfb_suspend(struct device *dev, pm_message_t state)
{
struct imxfb_info *fbi = dev_get_drvdata(dev);
pr_debug("%s\n",__FUNCTION__);
- if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN)
- imxfb_disable_controller(fbi);
+ imxfb_disable_controller(fbi);
return 0;
}
-static int imxfb_resume(struct device *dev, u32 level)
+static int imxfb_resume(struct device *dev)
{
struct imxfb_info *fbi = dev_get_drvdata(dev);
pr_debug("%s\n",__FUNCTION__);
- if (level == RESUME_ENABLE)
- imxfb_enable_controller(fbi);
+ imxfb_enable_controller(fbi);
return 0;
}
#else
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 194eed0a238c9a..6206da9dd5dad2 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -981,21 +981,19 @@ pxafb_freq_policy(struct notifier_block *nb, unsigned long val, void *data)
* Power management hooks. Note that we won't be called from IRQ context,
* unlike the blank functions above, so we may sleep.
*/
-static int pxafb_suspend(struct device *dev, pm_message_t state, u32 level)
+static int pxafb_suspend(struct device *dev, pm_message_t state)
{
struct pxafb_info *fbi = dev_get_drvdata(dev);
- if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN)
- set_ctrlr_state(fbi, C_DISABLE_PM);
+ set_ctrlr_state(fbi, C_DISABLE_PM);
return 0;
}
-static int pxafb_resume(struct device *dev, u32 level)
+static int pxafb_resume(struct device *dev)
{
struct pxafb_info *fbi = dev_get_drvdata(dev);
- if (level == RESUME_ENABLE)
- set_ctrlr_state(fbi, C_ENABLE_PM);
+ set_ctrlr_state(fbi, C_ENABLE_PM);
return 0;
}
#else
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index fa98d91c42eb2c..cb2f7a1de94779 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -655,7 +655,7 @@ bail:
}
#ifdef CONFIG_PM
-static int s1d13xxxfb_suspend(struct device *dev, pm_message_t state, u32 level)
+static int s1d13xxxfb_suspend(struct device *dev, pm_message_t state)
{
struct fb_info *info = dev_get_drvdata(dev);
struct s1d13xxxfb_par *s1dfb = info->par;
@@ -702,15 +702,12 @@ static int s1d13xxxfb_suspend(struct device *dev, pm_message_t state, u32 level)
return 0;
}
-static int s1d13xxxfb_resume(struct device *dev, u32 level)
+static int s1d13xxxfb_resume(struct device *dev)
{
struct fb_info *info = dev_get_drvdata(dev);
struct s1d13xxxfb_par *s1dfb = info->par;
struct s1d13xxxfb_pdata *pdata = NULL;
- if (level != RESUME_ENABLE)
- return 0;
-
/* awaken the chip */
s1d13xxxfb_writereg(s1dfb, S1DREG_PS_CNF, 0x10);
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index 5ab79afb53b78b..3862d3cb1fb2d9 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -847,37 +847,32 @@ static int s3c2410fb_remove(struct device *dev)
/* suspend and resume support for the lcd controller */
-static int s3c2410fb_suspend(struct device *dev, pm_message_t state, u32 level)
+static int s3c2410fb_suspend(struct device *dev, pm_message_t state)
{
struct fb_info *fbinfo = dev_get_drvdata(dev);
struct s3c2410fb_info *info = fbinfo->par;
- if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN) {
- s3c2410fb_stop_lcd();
+ s3c2410fb_stop_lcd();
- /* sleep before disabling the clock, we need to ensure
- * the LCD DMA engine is not going to get back on the bus
- * before the clock goes off again (bjd) */
+ /* sleep before disabling the clock, we need to ensure
+ * the LCD DMA engine is not going to get back on the bus
+ * before the clock goes off again (bjd) */
- msleep(1);
- clk_disable(info->clk);
- }
+ msleep(1);
+ clk_disable(info->clk);
return 0;
}
-static int s3c2410fb_resume(struct device *dev, u32 level)
+static int s3c2410fb_resume(struct device *dev)
{
struct fb_info *fbinfo = dev_get_drvdata(dev);
struct s3c2410fb_info *info = fbinfo->par;
- if (level == RESUME_ENABLE) {
- clk_enable(info->clk);
- msleep(1);
-
- s3c2410fb_init_registers(info);
+ clk_enable(info->clk);
+ msleep(1);
- }
+ s3c2410fb_init_registers(info);
return 0;
}
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index 8000890e42711f..78e5f194b0df39 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -1309,21 +1309,19 @@ sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val,
* Power management hooks. Note that we won't be called from IRQ context,
* unlike the blank functions above, so we may sleep.
*/
-static int sa1100fb_suspend(struct device *dev, pm_message_t state, u32 level)
+static int sa1100fb_suspend(struct device *dev, pm_message_t state)
{
struct sa1100fb_info *fbi = dev_get_drvdata(dev);
- if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN)
- set_ctrlr_state(fbi, C_DISABLE_PM);
+ set_ctrlr_state(fbi, C_DISABLE_PM);
return 0;
}
-static int sa1100fb_resume(struct device *dev, u32 level)
+static int sa1100fb_resume(struct device *dev)
{
struct sa1100fb_info *fbi = dev_get_drvdata(dev);
- if (level == RESUME_ENABLE)
- set_ctrlr_state(fbi, C_ENABLE_PM);
+ set_ctrlr_state(fbi, C_ENABLE_PM);
return 0;
}
#else
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index 0030c071da8fd5..752bf88906a9de 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -438,36 +438,34 @@ static void w100fb_restore_vidmem(struct w100fb_par *par)
}
}
-static int w100fb_suspend(struct device *dev, pm_message_t state, uint32_t level)
+static int w100fb_suspend(struct device *dev, pm_message_t state)
{
- if (level == SUSPEND_POWER_DOWN) {
- struct fb_info *info = dev_get_drvdata(dev);
- struct w100fb_par *par=info->par;
- struct w100_tg_info *tg = par->mach->tg;
-
- w100fb_save_vidmem(par);
- if(tg && tg->suspend)
- tg->suspend(par);
- w100_suspend(W100_SUSPEND_ALL);
- par->blanked = 1;
- }
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct w100fb_par *par=info->par;
+ struct w100_tg_info *tg = par->mach->tg;
+
+ w100fb_save_vidmem(par);
+ if(tg && tg->suspend)
+ tg->suspend(par);
+ w100_suspend(W100_SUSPEND_ALL);
+ par->blanked = 1;
+
return 0;
}
-static int w100fb_resume(struct device *dev, uint32_t level)
+static int w100fb_resume(struct device *dev)
{
- if (level == RESUME_POWER_ON) {
- struct fb_info *info = dev_get_drvdata(dev);
- struct w100fb_par *par=info->par;
- struct w100_tg_info *tg = par->mach->tg;
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct w100fb_par *par=info->par;
+ struct w100_tg_info *tg = par->mach->tg;
+
+ w100_hw_init(par);
+ w100fb_activate_var(par);
+ w100fb_restore_vidmem(par);
+ if(tg && tg->resume)
+ tg->resume(par);
+ par->blanked = 0;
- w100_hw_init(par);
- w100fb_activate_var(par);
- w100fb_restore_vidmem(par);
- if(tg && tg->resume)
- tg->resume(par);
- par->blanked = 0;
- }
return 0;
}
#else